KT25-1015_AC695x_SDK310/cpu/br23/audio_dec/audio_usb_mic.c
2025-10-15 15:18:43 +08:00

569 lines
15 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "asm/includes.h"
#include "media/includes.h"
#include "system/includes.h"
#include "audio_enc.h"
#include "app_main.h"
#include "app_config.h"
#include "audio_splicing.h"
#include "media/audio_echo_reverb.h"
/*usb mic的数据是否经过AEC,包括里面的ANS模块*/
#define USB_MIC_AEC_EN 0
/*AEC模块只能处理16k数据如果经过aec就需要对输出数据做变采样*/
#define USB_MIC_SRC_ENABLE 1
#if USB_MIC_AEC_EN
#include "aec_user.h"
#endif/*USB_MIC_AEC_EN*/
#if TCFG_APP_PC_EN
#include "device/uac_stream.h"
#define PCM_ENC2USB_OUTBUF_LEN (4 * 1024)
/* #define USB_MIC_BUF_NUM 3 */
/* #define USB_MIC_CH_NUM 1 */
/* #define USB_MIC_IRQ_POINTS 1//256 */
/* #define USB_MIC_BUFS_SIZE (USB_MIC_CH_NUM * USB_MIC_BUF_NUM * USB_MIC_IRQ_POINTS) */
#define USB_MIC_STOP 0x00
#define USB_MIC_START 0x01
extern struct audio_adc_hdl adc_hdl;
extern u16 uac_get_mic_vol(const u8 usb_id);
struct _usb_mic_hdl {
struct audio_adc_output_hdl adc_output;
struct adc_mic_ch mic_ch;
struct audio_adc_ch linein_ch;
#if SOUNDCARD_ENABLE //4取1
s16 *temp_buf;
u32 temp_buf_len;
#endif
enum enc_source source;
cbuffer_t output_cbuf;
u8 *output_buf;//[PCM_ENC2USB_OUTBUF_LEN];
u8 rec_tx_channels;
u8 mic_data_ok;/*mic数据等到一定长度再开始发送*/
u8 status;
u8 mic_busy;
#if TCFG_USB_MIC_ECHO_ENABLE
ECHO_API_STRUCT *p_echo_hdl;
#endif
};
static struct _usb_mic_hdl *usb_mic_hdl = NULL;
#if TCFG_USB_MIC_ECHO_ENABLE
ECHO_PARM_SET usbmic_echo_parm_default = {
.delay = 200, //回声的延时时间 0-300ms
.decayval = 50, // 0-70%
.direct_sound_enable = 1, //直达声使能 0/1
.filt_enable = 1, //发散滤波器使能
};
EF_REVERB_FIX_PARM usbmic_echo_fix_parm_default = {
.wetgain = 2048, ////湿声增益:[0:4096]
.drygain = 4096, ////干声增益: [0:4096]
.sr = MIC_EFFECT_SAMPLERATE, ////采样率
.max_ms = 200, ////所需要的最大延时,影响 need_buf 大小
};
#endif
static int usb_audio_mic_sync(u32 data_size)
{
#if 0
int change_point = 0;
if (data_size > __this->rec_top_size) {
change_point = -1;
} else if (data_size < __this->rec_bottom_size) {
change_point = 1;
}
if (change_point) {
struct audio_pcm_src src;
src.resample = 0;
src.ratio_i = (1024) * 2;
src.ratio_o = (1024 + change_point) * 2;
src.convert = 1;
dev_ioctl(__this->rec_dev, AUDIOC_PCM_RATE_CTL, (u32)&src);
}
#endif
return 0;
}
static int usb_audio_mic_tx_handler(int event, void *data, int len)
{
if (usb_mic_hdl == NULL) {
return 0;
}
if (usb_mic_hdl->status == USB_MIC_STOP) {
return 0;
}
int i = 0;
int r_len = 0;
u8 ch = 0;
u8 double_read = 0;
int rlen = 0;
if (usb_mic_hdl->mic_data_ok == 0) {
if (usb_mic_hdl->output_cbuf.data_len > (PCM_ENC2USB_OUTBUF_LEN / 4)) {
usb_mic_hdl->mic_data_ok = 1;
} else {
//y_printf("mic_tx NULL\n");
memset(data, 0, len);
return 0;
}
}
/* usb_audio_mic_sync(size); */
if (usb_mic_hdl->rec_tx_channels == 2) {
rlen = cbuf_get_data_size(&usb_mic_hdl->output_cbuf);
if (rlen) {
rlen = rlen > (len / 2) ? (len / 2) : rlen;
rlen = cbuf_read(&usb_mic_hdl->output_cbuf, data, rlen);
} else {
/* printf("uac read err1\n"); */
usb_mic_hdl->mic_data_ok = 0;
return 0;
}
len = rlen * 2;
s16 *tx_pcm = (s16 *)data;
int cnt = len / 2;
for (cnt = len / 2; cnt >= 2;) {
tx_pcm[cnt - 1] = tx_pcm[cnt / 2 - 1];
tx_pcm[cnt - 2] = tx_pcm[cnt / 2 - 1];
cnt -= 2;
}
rlen = len;
} else {
rlen = cbuf_get_data_size(&usb_mic_hdl->output_cbuf);
if (rlen) {
rlen = rlen > len ? len : rlen;
rlen = cbuf_read(&usb_mic_hdl->output_cbuf, data, rlen);
} else {
/* printf("uac read err2\n"); */
usb_mic_hdl->mic_data_ok = 0;
return 0;
}
}
return rlen;
}
int usb_audio_mic_write_do(void *data, u16 len)
{
int wlen = len;
if (usb_mic_hdl && usb_mic_hdl->status == USB_MIC_START) {
usb_mic_hdl->mic_busy = 1;
#if SOUNDCARD_ENABLE //4取1
if (usb_mic_hdl->temp_buf) {
if (usb_mic_hdl->temp_buf_len < len / 4) {
free(usb_mic_hdl->temp_buf);
usb_mic_hdl->temp_buf = NULL;
}
}
if (!usb_mic_hdl->temp_buf) {
usb_mic_hdl->temp_buf_len = len / 4;
usb_mic_hdl->temp_buf = (s16 *) zalloc(usb_mic_hdl->temp_buf_len);
}
s16 *temp_pcm = (s16 *)data;
for (int cnt = 0; cnt < len / 8; cnt++) {
usb_mic_hdl->temp_buf[cnt] = temp_pcm[cnt * 4 + 2];//取RL通道
}
len = len / 4;
wlen = cbuf_write(&usb_mic_hdl->output_cbuf, usb_mic_hdl->temp_buf, len);
#else
wlen = cbuf_write(&usb_mic_hdl->output_cbuf, data, len);
#endif //SOUNDCARD_ENABLE
#if 0
static u32 usb_mic_data_max = 0;
if (usb_mic_data_max < usb_mic_hdl->output_cbuf.data_len) {
usb_mic_data_max = usb_mic_hdl->output_cbuf.data_len;
y_printf("usb_mic_max:%d", usb_mic_data_max);
}
#endif
if (wlen != (len)) {
putchar('L');
//r_printf("usb_mic write full:%d-%d\n", wlen, len);
}
usb_mic_hdl->mic_busy = 0;
}
return wlen;
}
int usb_audio_mic_write(void *data, u16 len)
{
pcm_dual_to_single(data, data, len);
int wlen = usb_audio_mic_write_do(data, len / 2);
return wlen;
}
static void adc_output_to_cbuf(void *priv, s16 *data, int len)
{
if (usb_mic_hdl == NULL) {
return ;
}
if (usb_mic_hdl->status == USB_MIC_STOP) {
return ;
}
switch (usb_mic_hdl->source) {
case ENCODE_SOURCE_MIC:
case ENCODE_SOURCE_LINE0_LR:
case ENCODE_SOURCE_LINE1_LR:
case ENCODE_SOURCE_LINE2_LR: {
#if USB_MIC_AEC_EN
audio_aec_inbuf(data, len);
#else
#if TCFG_USB_MIC_ECHO_ENABLE
if (usb_mic_hdl->p_echo_hdl) {
run_echo(usb_mic_hdl->p_echo_hdl, data, data, len);
}
#endif
int wlen = cbuf_write(&usb_mic_hdl->output_cbuf, data, len);
if (wlen != len) {
printf("wlen %d len %d\n", wlen, len);
}
#endif
}
break;
default:
break;
}
}
#if USB_MIC_SRC_ENABLE
#include "common/Resample_api.h"
typedef struct {
u8 start;
u8 busy;
u16 output_rate;
u32 *runbuf;
s16 output[320 * 3 + 16];
RS_STUCT_API *ops;
} usb_mic_sw_src_t;
static usb_mic_sw_src_t *usb_mic_src = NULL;
static int sw_src_init(u32 in_sr, u32 out_sr)
{
usb_mic_src = zalloc(sizeof(usb_mic_sw_src_t));
ASSERT(usb_mic_src);
usb_mic_src->ops = get_rs16_context();
ASSERT(usb_mic_src->ops);
u32 need_buf = usb_mic_src->ops->need_buf();
printf("sw_src need_buf:%d\n", need_buf);
usb_mic_src->runbuf = zalloc(need_buf);
ASSERT(usb_mic_src->runbuf);
RS_PARA_STRUCT rs_para_obj;
rs_para_obj.nch = 1;
rs_para_obj.new_insample = in_sr;
rs_para_obj.new_outsample = out_sr;
printf("sw src,in = %d,out = %d\n", rs_para_obj.new_insample, rs_para_obj.new_outsample);
usb_mic_src->ops->open(usb_mic_src->runbuf, &rs_para_obj);
usb_mic_src->start = 1;
return 0;
}
static int sw_src_exit(void)
{
if (usb_mic_src) {
usb_mic_src->start = 0;
while (usb_mic_src->busy) {
putchar('w');
os_time_dly(2);
}
local_irq_disable();
if (usb_mic_src->runbuf) {
free(usb_mic_src->runbuf);
}
free(usb_mic_src);
local_irq_enable();
printf("sw_src_exit\n");
}
printf("sw_src_exit ok\n");
return 0;
}
#endif/*USB_MIC_SRC_ENABLE*/
static int usb_mic_aec_output(s16 *data, u16 len)
{
//putchar('k');
if (usb_mic_hdl == NULL) {
return len ;
}
if (usb_mic_hdl->status == USB_MIC_STOP) {
return len;
}
u16 olen = len;
s16 *obuf = data;
#if USB_MIC_SRC_ENABLE
if (usb_mic_src && usb_mic_src->start) {
usb_mic_src->busy = 1;
int outlen = usb_mic_src->ops->run(usb_mic_src->runbuf, data, len >> 1, usb_mic_src->output);
usb_mic_src->busy = 0;
ASSERT(outlen <= (sizeof(usb_mic_src->output) >> 1));
/* printf("16->48k:%d,%d,%d\n",len >> 1,outlen,sizeof(sw_src->output)); */
obuf = usb_mic_src->output;
olen = outlen << 1;
}
#endif/*USB_MIC_SRC_ENABLE*/
usb_audio_mic_write_do(obuf, olen);
return len;
}
int uac_mic_vol_switch(int vol)
{
return vol * 14 / 100;
}
int usb_audio_mic_open(void *_info)
{
printf("usb_audio_mic_open -----------------------------------------------------\n");
if (usb_mic_hdl) {
return 0;
}
struct _usb_mic_hdl *hdl = NULL;
hdl = zalloc(sizeof(struct _usb_mic_hdl));
if (!hdl) {
return -EFAULT;
}
local_irq_disable();
usb_mic_hdl = hdl;
local_irq_enable();
hdl->status = USB_MIC_STOP;
#if 0
hdl->adc_buf = zalloc(USB_MIC_BUFS_SIZE * 2);
if (!hdl->adc_buf) {
printf("hdl->adc_buf NULL\n");
if (hdl) {
free(hdl);
hdl = NULL;
}
return -EFAULT;
}
#endif
hdl->output_buf = zalloc(PCM_ENC2USB_OUTBUF_LEN);
if (!hdl->output_buf) {
printf("hdl->output_buf NULL\n");
/* if (hdl->adc_buf) { */
/* free(hdl->adc_buf); */
/* } */
if (hdl) {
free(hdl);
hdl = NULL;
}
return -EFAULT;
}
u32 sample_rate = (u32)_info & 0xFFFFFF;
u32 output_rate = sample_rate;
hdl->rec_tx_channels = (u32)_info >> 24;
hdl->source = ENCODE_SOURCE_MIC;
printf("usb mic sr:%d ch:%d\n", sample_rate, hdl->rec_tx_channels);
#if USB_MIC_AEC_EN
printf("usb mic sr[aec]:%d\n", sample_rate);
sample_rate = 16000;
#if USB_MIC_SRC_ENABLE
sw_src_init(sample_rate, output_rate);
#endif/*USB_MIC_SRC_ENABLE*/
//audio_aec_init(sample_rate);
audio_aec_open(sample_rate, ANS_EN, usb_mic_aec_output);
#endif/*USB_MIC_AEC_EN*/
cbuf_init(&hdl->output_cbuf, hdl->output_buf, PCM_ENC2USB_OUTBUF_LEN);
#if (SOUNDCARD_ENABLE)
///从mix output哪里获取usb mic上行数据
#if(TCFG_USB_MIC_DATA_FROM_DAC)
mic_effect_to_usbmic_onoff(1);
#endif//TCFG_USB_MIC_DATA_FROM_DAC
#else
#if TCFG_MIC_EFFECT_ENABLE
app_var.usb_mic_gain = mic_effect_get_micgain();
#else
app_var.usb_mic_gain = uac_mic_vol_switch(uac_get_mic_vol(0));
#endif//TCFG_MIC_EFFECT_ENABLE
#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT)
mic_effect_to_usbmic_onoff(1);
#else
#if 0
audio_adc_mic_open(&hdl->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl);
audio_adc_mic_set_sample_rate(&hdl->mic_ch, sample_rate);
audio_adc_mic_set_gain(&hdl->mic_ch, app_var.usb_mic_gain);
audio_adc_mic_set_buffs(&hdl->mic_ch, hdl->adc_buf, USB_MIC_IRQ_POINTS * 2, USB_MIC_BUF_NUM);
hdl->adc_output.handler = adc_output_to_cbuf;
audio_adc_add_output_handler(&adc_hdl, &hdl->adc_output);
audio_adc_mic_start(&hdl->mic_ch);
#else
audio_mic_open(&hdl->mic_ch, sample_rate, app_var.usb_mic_gain);
hdl->adc_output.handler = adc_output_to_cbuf;
audio_mic_add_output(&hdl->adc_output);
audio_mic_start(&hdl->mic_ch);
#endif
#endif//TCFG_USB_MIC_DATA_FROM_MICEFFECT
#endif//SOUNDCARD_ENABLE
#if TCFG_USB_MIC_ECHO_ENABLE
hdl->p_echo_hdl = open_echo(&usbmic_echo_parm_default, &usbmic_echo_fix_parm_default);
#endif
set_uac_mic_tx_handler(NULL, usb_audio_mic_tx_handler);
hdl->status = USB_MIC_START;
hdl->mic_busy = 0;
/* __this->rec_begin = 0; */
return 0;
}
u32 usb_mic_is_running()
{
if (usb_mic_hdl) {
return SPK_AUDIO_RATE;
}
return 0;
}
/*
*************************************************************
*
* usb mic gain save
*
*************************************************************
*/
static int usb_mic_gain_save_timer;
static u8 usb_mic_gain_save_cnt;
static void usb_audio_mic_gain_save_do(void *priv)
{
//printf(" usb_audio_mic_gain_save_do %d\n", usb_mic_gain_save_cnt);
local_irq_disable();
if (++usb_mic_gain_save_cnt >= 5) {
sys_hi_timer_del(usb_mic_gain_save_timer);
usb_mic_gain_save_timer = 0;
usb_mic_gain_save_cnt = 0;
local_irq_enable();
printf("USB_GAIN_SAVE\n");
syscfg_write(VM_USB_MIC_GAIN, &app_var.usb_mic_gain, 1);
return;
}
local_irq_enable();
}
static void usb_audio_mic_gain_change(u8 gain)
{
local_irq_disable();
app_var.usb_mic_gain = gain;
usb_mic_gain_save_cnt = 0;
if (usb_mic_gain_save_timer == 0) {
usb_mic_gain_save_timer = sys_hi_timer_add(NULL, usb_audio_mic_gain_save_do, 1000);
}
local_irq_enable();
}
int usb_audio_mic_get_gain(void)
{
return app_var.usb_mic_gain;
}
void usb_audio_mic_set_gain(int gain)
{
#if (SOUNDCARD_ENABLE)
return ;
#endif//SOUNDCARD_ENABLE
if (usb_mic_hdl == NULL) {
r_printf("usb_mic_hdl NULL gain");
return;
}
gain = uac_mic_vol_switch(gain);
audio_adc_mic_set_gain(&usb_mic_hdl->mic_ch, gain);
usb_audio_mic_gain_change(gain);
}
int usb_audio_mic_close(void *arg)
{
if (usb_mic_hdl == NULL) {
r_printf("usb_mic_hdl NULL close");
return 0;
}
printf("usb_mic_hdl->status %x\n", usb_mic_hdl->status);
if (usb_mic_hdl && usb_mic_hdl->status == USB_MIC_START) {
printf("usb_audio_mic_close in\n");
usb_mic_hdl->status = USB_MIC_STOP;
#if USB_MIC_AEC_EN
audio_aec_close();
#endif/*USB_MIC_AEC_EN*/
#if USB_MIC_SRC_ENABLE
sw_src_exit();
#endif/*USB_MIC_SRC_ENABLE*/
#if (SOUNDCARD_ENABLE)
//从声卡输出端获取, 没有打开mic 所以这里不需要关
#if (TCFG_USB_MIC_DATA_FROM_DAC)
mic_effect_to_usbmic_onoff(0);
#endif//TCFG_USB_MIC_DATA_FROM_DAC
#else
#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT)
mic_effect_to_usbmic_onoff(0);
#else
#if 0
audio_adc_mic_close(&usb_mic_hdl->mic_ch);
audio_adc_del_output_handler(&adc_hdl, &usb_mic_hdl->adc_output);
#else
audio_mic_close(&usb_mic_hdl->mic_ch, &usb_mic_hdl->adc_output);
#endif
#endif//TCFG_USB_MIC_DATA_FROM_MICEFFECT
#endif//SOUNDCARD_ENABLE
#if TCFG_USB_MIC_ECHO_ENABLE
if (usb_mic_hdl->p_echo_hdl) {
close_echo(usb_mic_hdl->p_echo_hdl);
}
#endif
cbuf_clear(&usb_mic_hdl->output_cbuf);
if (usb_mic_hdl) {
while (usb_mic_hdl->mic_busy) {
os_time_dly(3);
}
local_irq_disable();
#if SOUNDCARD_ENABLE //4取1
if (usb_mic_hdl->temp_buf) {
free(usb_mic_hdl->temp_buf);
usb_mic_hdl->temp_buf = NULL;
}
usb_mic_hdl->temp_buf_len = 0;
#endif
if (usb_mic_hdl->output_buf) {
free(usb_mic_hdl->output_buf);
usb_mic_hdl->output_buf = NULL;
}
free(usb_mic_hdl);
usb_mic_hdl = NULL;
local_irq_enable();
}
}
printf("usb_audio_mic_close out\n");
return 0;
}
#endif