first
This commit is contained in:
1356
apps/earphone/aec/br28/audio_aec.c
Normal file
1356
apps/earphone/aec/br28/audio_aec.c
Normal file
File diff suppressed because it is too large
Load Diff
239
apps/earphone/aec/br28/audio_aec_debug.c
Normal file
239
apps/earphone/aec/br28/audio_aec_debug.c
Normal file
@ -0,0 +1,239 @@
|
||||
#define ModuleEnable_Max 6
|
||||
static const char *ModuleEnable_Name[ModuleEnable_Max] = {
|
||||
"AEC", "NLP", "ANS", "ENC", "AGC", "WNC"
|
||||
};
|
||||
|
||||
#if TCFG_AUDIO_TRIPLE_MIC_ENABLE
|
||||
void aec_param_dump(struct tms_attr *param)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_ENABLE
|
||||
printf("===========dump dms param==================\n");
|
||||
printf("EnableBit:%x\n", param->EnableBit);
|
||||
for (u8 i = 0; i < ModuleEnable_Max; i++) {
|
||||
if (param->EnableBit & BIT(i)) {
|
||||
printf("%s ON", ModuleEnable_Name[i]);
|
||||
} else {
|
||||
printf("%s OFF", ModuleEnable_Name[i]);
|
||||
}
|
||||
}
|
||||
printf("ul_eq_en:%x\n", param->ul_eq_en);
|
||||
extern void put_float(double fv);
|
||||
printf("******************* AGC ********************");
|
||||
printf("agc_type : %d", param->agc_type);
|
||||
if (param->agc_type == AGC_EXTERNAL) {
|
||||
puts("AGC_NDT_fade_in_step:");
|
||||
put_float(param->AGC_NDT_fade_in_step);
|
||||
puts("AGC_NDT_fade_out_step:");
|
||||
put_float(param->AGC_NDT_fade_out_step);
|
||||
puts("AGC_DT_fade_in_step:");
|
||||
put_float(param->AGC_DT_fade_in_step);
|
||||
puts("AGC_DT_fade_out_step:");
|
||||
put_float(param->AGC_DT_fade_out_step);
|
||||
puts("AGC_NDT_max_gain:");
|
||||
put_float(param->AGC_NDT_max_gain);
|
||||
puts("AGC_NDT_min_gain:");
|
||||
put_float(param->AGC_NDT_min_gain);
|
||||
puts("AGC_NDT_speech_thr:");
|
||||
put_float(param->AGC_NDT_speech_thr);
|
||||
puts("AGC_DT_max_gain:");
|
||||
put_float(param->AGC_DT_max_gain);
|
||||
puts("AGC_DT_min_gain:");
|
||||
put_float(param->AGC_DT_min_gain);
|
||||
puts("AGC_DT_speech_thr:");
|
||||
put_float(param->AGC_DT_speech_thr);
|
||||
puts("AGC_echo_present_thr:");
|
||||
put_float(param->AGC_echo_present_thr);
|
||||
} else {
|
||||
printf("min_mag_db_level : %d", param->min_mag_db_level);
|
||||
printf("max_mag_db_level : %d", param->max_mag_db_level);
|
||||
printf("addition_mag_db_level : %d", param->addition_mag_db_level);
|
||||
printf("clip_mag_db_level : %d", param->clip_mag_db_level);
|
||||
printf("floor_mag_db_level : %d", param->floor_mag_db_level);
|
||||
}
|
||||
|
||||
printf("******************* AEC ********************");
|
||||
puts("aec_process_maxfrequency:");
|
||||
put_float(param->aec_process_maxfrequency);
|
||||
puts("aec_process_minfrequency:");
|
||||
put_float(param->aec_process_minfrequency);
|
||||
puts("aec_af_length:");
|
||||
put_float(param->af_length);
|
||||
|
||||
printf("******************* NLP ********************");
|
||||
puts("nlp_process_maxfrequency");
|
||||
put_float(param->nlp_process_maxfrequency);
|
||||
puts("nlp_process_minfrequency:");
|
||||
put_float(param->nlp_process_minfrequency);
|
||||
puts("nlp_overdrive:");
|
||||
put_float(param->overdrive);
|
||||
|
||||
printf("******************* DNS ********************");
|
||||
puts("DNS_AggressFactor:");
|
||||
put_float(param->aggressfactor);
|
||||
puts("DNS_MinSuppress:");
|
||||
put_float(param->minsuppress);
|
||||
puts("DNC_init_noise_lvl:");
|
||||
put_float(param->init_noise_lvl);
|
||||
puts("DNS_highGain:");
|
||||
put_float(param->DNS_highGain);
|
||||
puts("DNS_rbRate:");
|
||||
put_float(param->DNS_rbRate);
|
||||
printf("enhance_flag:%d", param->enhance_flag);
|
||||
|
||||
printf("******************* ENC ********************");
|
||||
printf("Tri_CutTh:%d", param->Tri_CutTh);
|
||||
puts("Tri_SnrThreshold0:");
|
||||
put_float(param->Tri_SnrThreshold0);
|
||||
puts("Tri_SnrThreshold1:");
|
||||
put_float(param->Tri_SnrThreshold1);
|
||||
puts("Tri_FbCompenDb:");
|
||||
put_float(param->Tri_FbCompenDb);
|
||||
printf("Tri_TfEqSel:%d", param->Tri_TfEqSel);
|
||||
printf("enc_process_maxfreq:%d", param->enc_process_maxfreq);
|
||||
printf("enc_process_minfreq:%d", param->enc_process_minfreq);
|
||||
printf("sir_maxfreq:%d", param->sir_maxfreq);
|
||||
puts("mic_distance:");
|
||||
put_float(param->mic_distance);
|
||||
puts("target_signal_degradation:");
|
||||
put_float(param->target_signal_degradation);
|
||||
puts("enc_aggressfactor:");
|
||||
put_float(param->enc_aggressfactor);
|
||||
puts("enc_minsuppress:");
|
||||
put_float(param->enc_minsuppress);
|
||||
puts("Tri_CompenDb:");
|
||||
put_float(param->Tri_CompenDb);
|
||||
printf("Tri_Bf_Enhance:%d", param->Tri_Bf_Enhance);
|
||||
|
||||
|
||||
printf("******************* WNC ********************");
|
||||
puts("wn_msc_th:");
|
||||
put_float(param->wn_msc_th);
|
||||
puts("ms_th:");
|
||||
put_float(param->ms_th);
|
||||
puts("wn_gain_offset:");
|
||||
put_float(param->wn_gain_offset);
|
||||
|
||||
printf("===============End==================\n");
|
||||
#endif/*CONFIG_DEBUG_ENABLE*/
|
||||
}
|
||||
#elif TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
void aec_param_dump(struct dms_attr *param)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_ENABLE
|
||||
printf("===========dump dms param==================\n");
|
||||
printf("EnableBit:%x\n", param->EnableBit);
|
||||
for (u8 i = 0; i < ModuleEnable_Max; i++) {
|
||||
if (param->EnableBit & BIT(i)) {
|
||||
printf("%s ON", ModuleEnable_Name[i]);
|
||||
} else {
|
||||
printf("%s OFF", ModuleEnable_Name[i]);
|
||||
}
|
||||
}
|
||||
printf("ul_eq_en:%x\n", param->ul_eq_en);
|
||||
extern void put_float(double fv);
|
||||
puts("AGC_NDT_fade_in_step:");
|
||||
put_float(param->AGC_NDT_fade_in_step);
|
||||
puts("AGC_NDT_fade_out_step:");
|
||||
put_float(param->AGC_NDT_fade_out_step);
|
||||
puts("AGC_DT_fade_in_step:");
|
||||
put_float(param->AGC_DT_fade_in_step);
|
||||
puts("AGC_DT_fade_out_step:");
|
||||
put_float(param->AGC_DT_fade_out_step);
|
||||
puts("AGC_NDT_max_gain:");
|
||||
put_float(param->AGC_NDT_max_gain);
|
||||
puts("AGC_NDT_min_gain:");
|
||||
put_float(param->AGC_NDT_min_gain);
|
||||
puts("AGC_NDT_speech_thr:");
|
||||
put_float(param->AGC_NDT_speech_thr);
|
||||
puts("AGC_DT_max_gain:");
|
||||
put_float(param->AGC_DT_max_gain);
|
||||
puts("AGC_DT_min_gain:");
|
||||
put_float(param->AGC_DT_min_gain);
|
||||
puts("AGC_DT_speech_thr:");
|
||||
put_float(param->AGC_DT_speech_thr);
|
||||
puts("AGC_echo_present_thr:");
|
||||
put_float(param->AGC_echo_present_thr);
|
||||
|
||||
puts("aec_process_maxfrequency:");
|
||||
put_float(param->aec_process_maxfrequency);
|
||||
puts("aec_process_minfrequency:");
|
||||
put_float(param->aec_process_minfrequency);
|
||||
puts("aec_af_length:");
|
||||
put_float(param->af_length);
|
||||
|
||||
puts("nlp_process_maxfrequency");
|
||||
put_float(param->nlp_process_maxfrequency);
|
||||
puts("nlp_process_minfrequency:");
|
||||
put_float(param->nlp_process_minfrequency);
|
||||
puts("nlp_overdrive:");
|
||||
put_float(param->overdrive);
|
||||
|
||||
puts("ANS_AggressFactor:");
|
||||
put_float(param->aggressfactor);
|
||||
puts("ANS_MinSuppress:");
|
||||
put_float(param->minsuppress);
|
||||
puts("ANC_init_noise_lvl:");
|
||||
put_float(param->init_noise_lvl);
|
||||
|
||||
printf("enc_process_maxfreq:%d", param->enc_process_maxfreq);
|
||||
printf("enc_process_minfreq:%d", param->enc_process_minfreq);
|
||||
printf("sir_maxfreq:%d", param->sir_maxfreq);
|
||||
puts("mic_distance:");
|
||||
put_float(param->mic_distance);
|
||||
puts("target_signal_degradation:");
|
||||
put_float(param->target_signal_degradation);
|
||||
puts("enc_aggressfactor:");
|
||||
put_float(param->enc_aggressfactor);
|
||||
puts("enc_minsuppress:");
|
||||
put_float(param->enc_minsuppress);
|
||||
|
||||
puts("GloabalMinSuppress:"), put_float(param->global_minsuppress);
|
||||
printf("===============End==================\n");
|
||||
#endif/*CONFIG_DEBUG_ENABLE*/
|
||||
}
|
||||
#else
|
||||
void aec_param_dump(struct aec_s_attr *param)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_ENABLE
|
||||
printf("===========dump sms param==================\n");
|
||||
printf("toggle:%d\n", param->toggle);
|
||||
printf("EnableBit:%x\n", param->EnableBit);
|
||||
printf("ul_eq_en:%x\n", param->ul_eq_en);
|
||||
extern void put_float(double fv);
|
||||
puts("AGC_NDT_fade_in_step:");
|
||||
put_float(param->AGC_NDT_fade_in_step);
|
||||
puts("AGC_NDT_fade_out_step:");
|
||||
put_float(param->AGC_NDT_fade_out_step);
|
||||
puts("AGC_DT_fade_in_step:");
|
||||
put_float(param->AGC_DT_fade_in_step);
|
||||
puts("AGC_DT_fade_out_step:");
|
||||
put_float(param->AGC_DT_fade_out_step);
|
||||
puts("AGC_NDT_max_gain:");
|
||||
put_float(param->AGC_NDT_max_gain);
|
||||
puts("AGC_NDT_min_gain:");
|
||||
put_float(param->AGC_NDT_min_gain);
|
||||
puts("AGC_NDT_speech_thr:");
|
||||
put_float(param->AGC_NDT_speech_thr);
|
||||
puts("AGC_DT_max_gain:");
|
||||
put_float(param->AGC_DT_max_gain);
|
||||
puts("AGC_DT_min_gain:");
|
||||
put_float(param->AGC_DT_min_gain);
|
||||
puts("AGC_DT_speech_thr:");
|
||||
put_float(param->AGC_DT_speech_thr);
|
||||
puts("AGC_echo_present_thr:");
|
||||
put_float(param->AGC_echo_present_thr);
|
||||
puts("AEC_DT_AggressiveFactor:");
|
||||
put_float(param->AEC_DT_AggressiveFactor);
|
||||
puts("AEC_RefEngThr:");
|
||||
put_float(param->AEC_RefEngThr);
|
||||
puts("ES_AggressFactor:");
|
||||
put_float(param->ES_AggressFactor);
|
||||
puts("ES_MinSuppress:");
|
||||
put_float(param->ES_MinSuppress);
|
||||
puts("ANS_AggressFactor:");
|
||||
put_float(param->ANS_AggressFactor);
|
||||
puts("ANS_MinSuppress:");
|
||||
put_float(param->ANS_MinSuppress);
|
||||
#endif/*CONFIG_DEBUG_ENABLE*/
|
||||
}
|
||||
#endif/*CONFIG_DEBUG_ENABLE*/
|
||||
632
apps/earphone/aec/br28/audio_aec_demo.c
Normal file
632
apps/earphone/aec/br28/audio_aec_demo.c
Normal file
@ -0,0 +1,632 @@
|
||||
/*
|
||||
***************************************************************************
|
||||
* AUDIO AEC DEMO
|
||||
* File : audio_aec_demo.c
|
||||
* By : GZR
|
||||
* Notes : 1.可用内存
|
||||
* (1)aec_hdl_mem: 静态变量
|
||||
* (2)free_ram: 动态内存(mem_stats:physics memory size xxxx bytes)
|
||||
* 2.demo默认将输入数据copy到输出,相关处理只需在运算函数
|
||||
* audio_aec_run()实现即可
|
||||
* 3.双mic ENC开发,只需打开对应板级以下配置即可:
|
||||
* #define TCFG_AUDIO_DUAL_MIC_ENABLE ENABLE_THIS_MOUDLE
|
||||
* 4.建议算法开发者使用宏定义将自己的代码模块包起来
|
||||
* 5.算法处理完的数据,如有需要,可以增加EQ处理:AEC_UL_EQ_EN
|
||||
* 6.开发阶段,默认使用芯片最高主频160MHz,可以通过修改AEC_CLK来修改
|
||||
运行频率。
|
||||
***************************************************************************
|
||||
*/
|
||||
#include "aec_user.h"
|
||||
#include "system/includes.h"
|
||||
#include "media/includes.h"
|
||||
#include "application/eq_config.h"
|
||||
#include "circular_buf.h"
|
||||
#include "overlay_code.h"
|
||||
#include "audio_config.h"
|
||||
#include "debug.h"
|
||||
#if TCFG_AUDIO_CVP_DUT_ENABLE
|
||||
#include "audio_cvp_dut.h"
|
||||
#endif // TCFG_AUDIO_CVP_DUT_ENABLE
|
||||
|
||||
#if defined(TCFG_CVP_DEVELOP_ENABLE) && (TCFG_CVP_DEVELOP_ENABLE == CVP_CFG_USER_DEFINED)
|
||||
|
||||
#define AEC_CLK (160 * 1000000L) /*模块运行时钟(MaxFre:160MHz)*/
|
||||
#define AEC_FRAME_POINTS 256 /*AEC处理帧长,跟mic采样长度关联*/
|
||||
#define AEC_FRAME_SIZE (AEC_FRAME_POINTS << 1)
|
||||
#if TCFG_AUDIO_TRIPLE_MIC_ENABLE
|
||||
#define AEC_MIC_NUM 3 /*3 mic*/
|
||||
#elif TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
#define AEC_MIC_NUM 2 /*双mic*/
|
||||
#else
|
||||
#define AEC_MIC_NUM 1 /*单mic*/
|
||||
#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/
|
||||
|
||||
/*上行数据eq*/
|
||||
#define AEC_UL_EQ_EN 0
|
||||
|
||||
#define AEC_USER_MALLOC_ENABLE 1 /*是否使用动态内存*/
|
||||
|
||||
#ifdef AUDIO_PCM_DEBUG
|
||||
/*AEC串口数据导出*/
|
||||
const u8 CONST_AEC_EXPORT = 1;
|
||||
#else
|
||||
const u8 CONST_AEC_EXPORT = 0;
|
||||
#endif/*AUDIO_PCM_DEBUG*/
|
||||
|
||||
extern int audio_dac_read_reset(void);
|
||||
extern int audio_dac_read(s16 points_offset, void *data, int len, u8 read_channel);
|
||||
extern void esco_enc_resume(void);
|
||||
extern int aec_uart_init();
|
||||
extern int aec_uart_open(u8 nch, u16 single_size);
|
||||
extern int aec_uart_fill(u8 ch, void *buf, u16 size);
|
||||
extern void aec_uart_write(void);
|
||||
extern int aec_uart_close(void);
|
||||
|
||||
/*AEC输入buf复用mic_adc采样buf*/
|
||||
#define MIC_BULK_MAX 3
|
||||
struct mic_bulk {
|
||||
struct list_head entry;
|
||||
s16 *addr;
|
||||
u16 len;
|
||||
u16 used;
|
||||
};
|
||||
|
||||
struct audio_aec_hdl {
|
||||
volatile u8 start; //aec模块状态
|
||||
volatile u8 busy;
|
||||
u8 output_sel; //数据输出通道选择
|
||||
u8 output_buf[1000]; //aec数据输出缓存
|
||||
cbuffer_t output_cbuf;
|
||||
s16 *mic; /*主mic数据地址*/
|
||||
s16 *mic_ref; /*参考mic数据地址*/
|
||||
s16 *mic_ref_1; /*参考mic数据地址*/
|
||||
s16 spk_ref[AEC_FRAME_POINTS]; /*扬声器参考数据*/
|
||||
s16 out[AEC_FRAME_POINTS]; /*运算输出地址*/
|
||||
OS_SEM sem;
|
||||
/*数据复用相关数据结构*/
|
||||
struct mic_bulk in_bulk[MIC_BULK_MAX];
|
||||
struct mic_bulk inref_bulk[MIC_BULK_MAX];
|
||||
struct mic_bulk inref_1_bulk[MIC_BULK_MAX];
|
||||
struct list_head in_head;
|
||||
struct list_head inref_head;
|
||||
struct list_head inref_1_head;
|
||||
#if AEC_UL_EQ_EN
|
||||
struct audio_eq *ul_eq;
|
||||
#endif/*AEC_UL_EQ_EN*/
|
||||
int (*output_handle)(s16 *dat, u16 len);
|
||||
};
|
||||
#if AEC_USER_MALLOC_ENABLE
|
||||
struct audio_aec_hdl *aec_hdl = NULL;
|
||||
#else
|
||||
struct audio_aec_hdl aec_handle;
|
||||
struct audio_aec_hdl *aec_hdl = &aec_handle;
|
||||
#endif /*AEC_USER_MALLOC_ENABLE*/
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Output Read
|
||||
* Description: 读取aec模块的输出数据
|
||||
* Arguments : buf 读取数据存放地址
|
||||
* len 读取数据长度
|
||||
* Return : 数据读取长度
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_aec_output_read(s16 *buf, u16 len)
|
||||
{
|
||||
//printf("rlen:%d-%d\n",len,aec_hdl.output_cbuf.data_len);
|
||||
local_irq_disable();
|
||||
if (!aec_hdl || !aec_hdl->start) {
|
||||
printf("audio_aec close now");
|
||||
local_irq_enable();
|
||||
return -EINVAL;
|
||||
}
|
||||
u16 rlen = cbuf_read(&aec_hdl->output_cbuf, buf, len);
|
||||
if (rlen == 0) {
|
||||
//putchar('N');
|
||||
}
|
||||
local_irq_enable();
|
||||
return rlen;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Output Handle
|
||||
* Description: AEC模块数据输出回调
|
||||
* Arguments : data 输出数据地址
|
||||
* len 输出数据长度
|
||||
* Return : 数据输出消耗长度
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int audio_aec_output(s16 *data, u16 len)
|
||||
{
|
||||
u16 wlen = 0;
|
||||
if (aec_hdl && aec_hdl->start) {
|
||||
wlen = cbuf_write(&aec_hdl->output_cbuf, data, len);
|
||||
//printf("wlen:%d-%d\n",len,aec_hdl.output_cbuf.data_len);
|
||||
if (wlen != len) {
|
||||
printf("aec_out_full:%d,%d\n", len, wlen);
|
||||
}
|
||||
esco_enc_resume();
|
||||
}
|
||||
return wlen;
|
||||
}
|
||||
|
||||
/*
|
||||
*跟踪系统内存使用情况:physics memory size xxxx bytes
|
||||
*正常的系统运行过程,应该至少有3k bytes的剩余空间给到系统调度开销
|
||||
*/
|
||||
static void sys_memory_trace(void)
|
||||
{
|
||||
static int cnt = 0;
|
||||
if (cnt++ > 200) {
|
||||
cnt = 0;
|
||||
mem_stats();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC RUN
|
||||
* Description: AEC数据处理核心
|
||||
* Arguments : in 主mic数据
|
||||
* inref 参考mic数据(双mic降噪有用)
|
||||
* inref1 参考mic数据(3 mic降噪有用)
|
||||
* ref speaker参考数据
|
||||
* out 数据输出
|
||||
* Return : 数据运算输出长度
|
||||
* Note(s) : 在这里实现AEC_core
|
||||
*********************************************************************
|
||||
*/
|
||||
static int audio_aec_run(s16 *in, s16 *inref, s16 *inref1, s16 *ref, s16 *out, u16 points)
|
||||
{
|
||||
int out_size = 0;
|
||||
putchar('.');
|
||||
memcpy(out, in, (points << 1));
|
||||
//memcpy(out, inref, (points << 1));
|
||||
out_size = points << 1;
|
||||
#if AEC_UL_EQ_EN
|
||||
if (aec_hdl->ul_eq) {
|
||||
audio_eq_run(aec_hdl->ul_eq, out, out_size);
|
||||
}
|
||||
#endif/*AEC_UL_EQ_EN*/
|
||||
|
||||
#if TCFG_AUDIO_CVP_DUT_ENABLE
|
||||
switch (aec_hdl->output_sel) {
|
||||
case CVP_3MIC_OUTPUT_SEL_MASTER:
|
||||
memcpy(out, in, (points << 1));
|
||||
break;
|
||||
case CVP_3MIC_OUTPUT_SEL_SLAVE:
|
||||
memcpy(out, inref, (points << 1));
|
||||
break;
|
||||
case CVP_3MIC_OUTPUT_SEL_FBMIC:
|
||||
memcpy(out, inref1, (points << 1));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif/*TCFG_AUDIO_CVP_DUT_ENABLE*/
|
||||
|
||||
sys_memory_trace();
|
||||
return out_size;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Task
|
||||
* Description: AEC任务
|
||||
* Arguments : priv 私用参数
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static void audio_aec_task(void *priv)
|
||||
{
|
||||
printf("==Audio AEC Task==\n");
|
||||
struct mic_bulk *bulk = NULL;
|
||||
struct mic_bulk *bulk_ref = NULL;
|
||||
struct mic_bulk *bulk_ref_1 = NULL;
|
||||
u8 pend = 1;
|
||||
while (1) {
|
||||
if (pend) {
|
||||
os_sem_pend(&aec_hdl->sem, 0);
|
||||
}
|
||||
pend = 1;
|
||||
if (aec_hdl->start) {
|
||||
if (!list_empty(&aec_hdl->in_head)) {
|
||||
aec_hdl->busy = 1;
|
||||
local_irq_disable();
|
||||
/*1.获取主mic数据*/
|
||||
bulk = list_first_entry(&aec_hdl->in_head, struct mic_bulk, entry);
|
||||
list_del(&bulk->entry);
|
||||
aec_hdl->mic = bulk->addr;
|
||||
#if (AEC_MIC_NUM > 1)
|
||||
/*2.获取参考mic数据*/
|
||||
bulk_ref = list_first_entry(&aec_hdl->inref_head, struct mic_bulk, entry);
|
||||
list_del(&bulk_ref->entry);
|
||||
aec_hdl->mic_ref = bulk_ref->addr;
|
||||
#endif/*Dual_Microphone*/
|
||||
|
||||
#if (AEC_MIC_NUM > 2)
|
||||
/*获取参考mic1数据*/
|
||||
bulk_ref_1 = list_first_entry(&aec_hdl->inref_1_head, struct mic_bulk, entry);
|
||||
list_del(&bulk_ref_1->entry);
|
||||
aec_hdl->mic_ref_1 = bulk_ref_1->addr;
|
||||
#endif/*3_Microphone*/
|
||||
|
||||
local_irq_enable();
|
||||
/*3.获取speaker参考数据*/
|
||||
audio_dac_read(60, aec_hdl->spk_ref, AEC_FRAME_SIZE, 1);
|
||||
|
||||
/*4.算法处理*/
|
||||
int out_len = audio_aec_run(aec_hdl->mic, aec_hdl->mic_ref, aec_hdl->mic_ref_1, aec_hdl->spk_ref, aec_hdl->out, AEC_FRAME_POINTS);
|
||||
|
||||
/*5.结果输出*/
|
||||
if (aec_hdl->output_handle) {
|
||||
aec_hdl->output_handle(aec_hdl->out, out_len);
|
||||
}
|
||||
|
||||
/*6.数据导出*/
|
||||
if (CONST_AEC_EXPORT) {
|
||||
aec_uart_fill(0, aec_hdl->mic, 512); //主mic数据
|
||||
aec_uart_fill(1, aec_hdl->mic_ref, 512); //副mic数据
|
||||
aec_uart_fill(2, aec_hdl->spk_ref, 512); //扬声器数据
|
||||
#if (AEC_MIC_NUM > 2)
|
||||
aec_uart_fill(2, aec_hdl->mic_ref_1, 512); //扬声器数据
|
||||
aec_uart_fill(3, aec_hdl->spk_ref, 512); //扬声器数据
|
||||
aec_uart_fill(4, aec_hdl->out, out_len); //算法运算结果
|
||||
#endif /*3_Microphone*/
|
||||
aec_uart_write();
|
||||
}
|
||||
bulk->used = 0;
|
||||
#if (AEC_MIC_NUM > 1)
|
||||
bulk_ref->used = 0;
|
||||
#endif/*Dual_Microphone*/
|
||||
#if (AEC_MIC_NUM > 2)
|
||||
bulk_ref_1->used = 0;
|
||||
#endif /*3_Microphone*/
|
||||
aec_hdl->busy = 0;
|
||||
pend = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Open
|
||||
* Description: 初始化AEC模块
|
||||
* Arguments : sr 采样率(8000/16000)
|
||||
* enablebit 使能模块(AEC/NLP/AGC/ANS...)
|
||||
* out_hdl 自定义回调函数,NULL则用默认的回调
|
||||
* Return : 0 成功 其他 失败
|
||||
* Note(s) : 该接口是对audio_aec_init的扩展,支持自定义使能模块以及
|
||||
* 数据输出回调函数
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_aec_open(u16 sample_rate, s16 enablebit, int (*out_hdl)(s16 *data, u16 len))
|
||||
{
|
||||
printf("audio_aec_open,sr = %d\n", sample_rate);
|
||||
mem_stats();
|
||||
if (aec_hdl) {
|
||||
printf("audio aec is already open!\n");
|
||||
return -1;
|
||||
}
|
||||
overlay_load_code(OVERLAY_AEC);
|
||||
#if AEC_USER_MALLOC_ENABLE
|
||||
aec_hdl = zalloc(sizeof(struct audio_aec_hdl));
|
||||
if (aec_hdl == NULL) {
|
||||
printf("aec_hdl malloc failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif /*AEC_USER_MALLOC_ENABLE*/
|
||||
|
||||
#if TCFG_AUDIO_CVP_DUT_ENABLE
|
||||
aec_hdl->output_sel = CVP_3MIC_OUTPUT_SEL_DEFAULT;
|
||||
#endif/*TCFG_AUDIO_CVP_DUT_ENABLE*/
|
||||
aec_hdl->output_handle = audio_aec_output;
|
||||
|
||||
printf("aec_hdl size:%d\n", sizeof(struct audio_aec_hdl));
|
||||
clk_set("sys", AEC_CLK);
|
||||
INIT_LIST_HEAD(&aec_hdl->in_head);
|
||||
INIT_LIST_HEAD(&aec_hdl->inref_head);
|
||||
INIT_LIST_HEAD(&aec_hdl->inref_1_head);
|
||||
cbuf_init(&aec_hdl->output_cbuf, aec_hdl->output_buf, sizeof(aec_hdl->output_buf));
|
||||
if (CONST_AEC_EXPORT) {
|
||||
#if (AEC_MIC_NUM > 2)
|
||||
aec_uart_open(5, 512);
|
||||
#elif (AEC_MIC_NUM > 1)
|
||||
aec_uart_open(3, 512);
|
||||
#endif /*AEC_MIC_NUM*/
|
||||
}
|
||||
|
||||
if (out_hdl) {
|
||||
aec_hdl->output_handle = out_hdl;
|
||||
}
|
||||
|
||||
#if AEC_UL_EQ_EN
|
||||
struct audio_eq_param ul_eq_param = {0};
|
||||
ul_eq_param.sr = sample_rate;
|
||||
ul_eq_param.channels = 1;
|
||||
ul_eq_param.online_en = 1;
|
||||
ul_eq_param.mode_en = 0;
|
||||
ul_eq_param.remain_en = 0;
|
||||
ul_eq_param.max_nsection = EQ_SECTION_MAX;
|
||||
ul_eq_param.cb = aec_ul_eq_filter;
|
||||
ul_eq_param.eq_name = aec_eq_mode;
|
||||
aec_hdl->ul_eq = audio_dec_eq_open(&ul_eq_param);
|
||||
#endif/*AEC_UL_EQ_EN*/
|
||||
os_sem_create(&aec_hdl->sem, 0);
|
||||
task_create(audio_aec_task, NULL, "aec");
|
||||
audio_dac_read_reset();
|
||||
aec_hdl->start = 1;
|
||||
|
||||
mem_stats();
|
||||
#ifdef MUX_RX_BULK_TEST_DEMO
|
||||
mux_rx_bulk_test = zalloc_mux_rx_bulk(MUX_RX_BULK_MAX);
|
||||
if (mux_rx_bulk_test) {
|
||||
printf("mux_rx_bulk_test:0x%x\n", mux_rx_bulk_test);
|
||||
free_mux_rx_bulk(mux_rx_bulk_test);
|
||||
mux_rx_bulk_test = NULL;
|
||||
}
|
||||
#endif/*MUX_RX_BULK_TEST_DEMO*/
|
||||
|
||||
printf("audio_aec_open succ\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Open
|
||||
* Description: 初始化AEC模块
|
||||
* Arguments : sr 采样率(8000/16000)
|
||||
* Return : 0 成功 其他 失败
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_aec_init(u16 sample_rate)
|
||||
{
|
||||
return audio_aec_open(sample_rate, -1, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Reboot
|
||||
* Description: AEC模块复位接口
|
||||
* Arguments : reduce 复位/恢复标志
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_reboot(u8 reduce)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Close
|
||||
* Description: 关闭AEC模块
|
||||
* Arguments : None.
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_close(void)
|
||||
{
|
||||
printf("audio_aec_close:%x", (u32)aec_hdl);
|
||||
if (aec_hdl) {
|
||||
aec_hdl->start = 0;
|
||||
while (aec_hdl->busy) {
|
||||
os_time_dly(2);
|
||||
}
|
||||
task_kill("aec");
|
||||
if (CONST_AEC_EXPORT) {
|
||||
aec_uart_close();
|
||||
}
|
||||
|
||||
#if AEC_UL_EQ_EN
|
||||
if (aec_hdl->ul_eq) {
|
||||
audio_dec_eq_close(aec_hdl->ul_eq);
|
||||
aec_hdl->ul_eq = NULL;
|
||||
}
|
||||
#endif/*AEC_UL_EQ_EN*/
|
||||
|
||||
local_irq_disable();
|
||||
#if AEC_USER_MALLOC_ENABLE
|
||||
free(aec_hdl);
|
||||
#endif /*AEC_USER_MALLOC_ENABLE*/
|
||||
aec_hdl = NULL;
|
||||
local_irq_enable();
|
||||
printf("audio_aec_close succ\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Status
|
||||
* Description: AEC模块当前状态
|
||||
* Arguments : None.
|
||||
* Return : 0 关闭 其他 打开
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
u8 audio_aec_status(void)
|
||||
{
|
||||
if (aec_hdl) {
|
||||
return aec_hdl->start;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Input
|
||||
* Description: AEC源数据输入
|
||||
* Arguments : buf 输入源数据地址
|
||||
* len 输入源数据长度
|
||||
* Return : None.
|
||||
* Note(s) : 输入一帧数据,唤醒一次运行任务处理数据,默认帧长256点
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_inbuf(s16 *buf, u16 len)
|
||||
{
|
||||
if (aec_hdl && aec_hdl->start) {
|
||||
int i = 0;
|
||||
for (i = 0; i < MIC_BULK_MAX; i++) {
|
||||
if (aec_hdl->in_bulk[i].used == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if TCFG_AUDIO_CVP_DUT_ENABLE
|
||||
if (cvp_dut_mode_get() == CVP_DUT_MODE_BYPASS) {
|
||||
audio_aec_output(buf, len);
|
||||
return;
|
||||
}
|
||||
#endif/*TCFG_AUDIO_CVP_DUT_ENABLE*/
|
||||
if (i < MIC_BULK_MAX) {
|
||||
aec_hdl->in_bulk[i].addr = buf;
|
||||
aec_hdl->in_bulk[i].used = 0x55;
|
||||
aec_hdl->in_bulk[i].len = len;
|
||||
list_add_tail(&aec_hdl->in_bulk[i].entry, &aec_hdl->in_head);
|
||||
} else {
|
||||
printf(">>>aec_in_full\n");
|
||||
/*align reset*/
|
||||
struct mic_bulk *bulk;
|
||||
list_for_each_entry(bulk, &aec_hdl->in_head, entry) {
|
||||
bulk->used = 0;
|
||||
__list_del_entry(&bulk->entry);
|
||||
}
|
||||
return;
|
||||
}
|
||||
os_sem_set(&aec_hdl->sem, 0);
|
||||
os_sem_post(&aec_hdl->sem);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Input Reference
|
||||
* Description: AEC源参考数据输入
|
||||
* Arguments : buf 输入源数据地址
|
||||
* len 输入源数据长度
|
||||
* Return : None.
|
||||
* Note(s) : 双mic ENC的参考mic数据输入,单mic的无须调用该接口
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_inbuf_ref(s16 *buf, u16 len)
|
||||
{
|
||||
if (aec_hdl && aec_hdl->start) {
|
||||
int i = 0;
|
||||
for (i = 0; i < MIC_BULK_MAX; i++) {
|
||||
if (aec_hdl->inref_bulk[i].used == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < MIC_BULK_MAX) {
|
||||
aec_hdl->inref_bulk[i].addr = buf;
|
||||
aec_hdl->inref_bulk[i].used = 0x55;
|
||||
aec_hdl->inref_bulk[i].len = len;
|
||||
list_add_tail(&aec_hdl->inref_bulk[i].entry, &aec_hdl->inref_head);
|
||||
} else {
|
||||
printf(">>>aec_inref_full\n");
|
||||
/*align reset*/
|
||||
struct mic_bulk *bulk;
|
||||
list_for_each_entry(bulk, &aec_hdl->inref_head, entry) {
|
||||
bulk->used = 0;
|
||||
__list_del_entry(&bulk->entry);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Input Reference
|
||||
* Description: AEC源参考数据输入
|
||||
* Arguments : buf 输入源数据地址
|
||||
* len 输入源数据长度
|
||||
* Return : None.
|
||||
* Note(s) : 双mic ENC的参考mic数据输入,单mic的无须调用该接口
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_inbuf_ref_1(s16 *buf, u16 len)
|
||||
{
|
||||
if (aec_hdl && aec_hdl->start) {
|
||||
int i = 0;
|
||||
for (i = 0; i < MIC_BULK_MAX; i++) {
|
||||
if (aec_hdl->inref_1_bulk[i].used == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < MIC_BULK_MAX) {
|
||||
aec_hdl->inref_1_bulk[i].addr = buf;
|
||||
aec_hdl->inref_1_bulk[i].used = 0x55;
|
||||
aec_hdl->inref_1_bulk[i].len = len;
|
||||
list_add_tail(&aec_hdl->inref_1_bulk[i].entry, &aec_hdl->inref_1_head);
|
||||
} else {
|
||||
printf(">>>aec_inref_1_full\n");
|
||||
/*align reset*/
|
||||
struct mic_bulk *bulk;
|
||||
list_for_each_entry(bulk, &aec_hdl->inref_1_head, entry) {
|
||||
bulk->used = 0;
|
||||
__list_del_entry(&bulk->entry);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Reference
|
||||
* Description: AEC模块参考数据输入
|
||||
* Arguments : buf 输入参考数据地址
|
||||
* len 输入参考数据长度
|
||||
* Return : None.
|
||||
* Note(s) : 声卡设备是DAC,默认不用外部提供参考数据
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_refbuf(s16 *buf, u16 len)
|
||||
{
|
||||
if (aec_hdl && aec_hdl->start) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Output Sel
|
||||
* Description: AEC输出数据选择
|
||||
* Arguments : sel 选择输出/算法输出/talk/ff/fb原始数据
|
||||
* agc NULL
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_output_sel(CVP_OUTPUT_ENUM sel, u8 agc)
|
||||
{
|
||||
if (aec_hdl) {
|
||||
aec_hdl->output_sel = sel;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Toggle Set
|
||||
* Description: AEC模块算法开关使能
|
||||
* Arguments : toggle 0 关闭算法 1 打开算法
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_aec_toggle_set(u8 toggle)
|
||||
{
|
||||
if (aec_hdl) {
|
||||
aec_hdl->output_sel = (toggle) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /*TCFG_CVP_DEVELOP_ENABLE*/
|
||||
1622
apps/earphone/aec/br28/audio_aec_dms.c
Normal file
1622
apps/earphone/aec/br28/audio_aec_dms.c
Normal file
File diff suppressed because it is too large
Load Diff
672
apps/earphone/aec/br28/audio_aec_online.c
Normal file
672
apps/earphone/aec/br28/audio_aec_online.c
Normal file
@ -0,0 +1,672 @@
|
||||
#include "audio_aec_online.h"
|
||||
#include "app_online_cfg.h"
|
||||
#include "config/config_target.h"
|
||||
#include "system/includes.h"
|
||||
#include "online_db_deal.h"
|
||||
#include "timer.h"
|
||||
#include "aec_user.h"
|
||||
#include "audio_adc.h"
|
||||
|
||||
#if 1
|
||||
extern void put_float(double fv);
|
||||
#define AEC_ONLINE_LOG y_printf
|
||||
#define AEC_ONLINE_FLOG put_float
|
||||
#else
|
||||
#define AEC_ONLINE_LOG(...)
|
||||
#define AEC_ONLINE_FLOG(...)
|
||||
#endif
|
||||
|
||||
#if TCFG_AEC_TOOL_ONLINE_ENABLE
|
||||
extern int esco_enc_mic_gain_set(u8 gain);
|
||||
extern int esco_enc_mic1_gain_set(u8 gain);
|
||||
extern int esco_enc_mic2_gain_set(u8 gain);
|
||||
extern int esco_enc_mic3_gain_set(u8 gain);
|
||||
extern int esco_dec_dac_gain_set(u8 gain);
|
||||
enum {
|
||||
AEC_UPDATE_CLOSE,
|
||||
AEC_UPDATE_INIT,
|
||||
AEC_UPDATE_ONLINE,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
u8 update;
|
||||
u8 reserved;
|
||||
u16 timer;
|
||||
#if TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
#if (TCFG_AUDIO_DMS_SEL == DMS_NORMAL)
|
||||
AEC_DMS_CONFIG cfg;
|
||||
#else/*TCFG_AUDIO_DMS_SEL == DMS_FLEXIBLE*/
|
||||
DMS_FLEXIBLE_CONFIG cfg;
|
||||
#endif/*TCFG_AUDIO_DMS_SEL*/
|
||||
#else/*SINGLE MIC*/
|
||||
AEC_CONFIG cfg;
|
||||
u8 agc_en;
|
||||
#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/
|
||||
} aec_update_t;
|
||||
aec_update_t *aec_update = NULL;
|
||||
|
||||
static void aec_update_timer_deal(void *priv)
|
||||
{
|
||||
AEC_ONLINE_LOG("aec_update_timer_deal");
|
||||
#if TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
aec_dms_cfg_update(&aec_update->cfg);
|
||||
#else
|
||||
aec_cfg_update(&aec_update->cfg);
|
||||
#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/
|
||||
sys_timer_del(aec_update->timer);
|
||||
aec_update->timer = 0;
|
||||
}
|
||||
|
||||
int aec_cfg_online_update(int root_cmd, void *packet)
|
||||
{
|
||||
if ((root_cmd != 0x3000) && (root_cmd != 0x3100) &&
|
||||
(root_cmd != 0x3200) && (root_cmd != 0x3300) &&
|
||||
(root_cmd != 0x3400) && (root_cmd != 0x3500)) {
|
||||
return -1;
|
||||
}
|
||||
if (aec_update->update == AEC_UPDATE_CLOSE) {
|
||||
return 0;
|
||||
}
|
||||
u8 update = 1;
|
||||
aec_online_t *cfg = packet;
|
||||
int id = cfg->id;
|
||||
//AEC_ONLINE_LOG("AEC_TYPE[0x30xx:SMS 0x31xx:DMS]:%x",root_cmd);
|
||||
//AEC_ONLINE_LOG("aec_cfg_id:%x,val:%d", cfg->id, (int)cfg->val_int);
|
||||
//AEC_ONLINE_FLOG(cfg->val_float);
|
||||
if (id >= ENC_Process_MaxFreq) {
|
||||
#if TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
AEC_ONLINE_LOG("ENC cfg update\n");
|
||||
switch (id) {
|
||||
#if (TCFG_AUDIO_DMS_SEL == DMS_NORMAL)
|
||||
case ENC_Process_MaxFreq:
|
||||
AEC_ONLINE_LOG("ENC_Process_MaxFreq:%d\n", cfg->val_int);
|
||||
aec_update->cfg.enc_process_maxfreq = cfg->val_int;
|
||||
break;
|
||||
case ENC_Process_MinFreq:
|
||||
AEC_ONLINE_LOG("ENC_Process_MinFreq:%d\n", cfg->val_int);
|
||||
aec_update->cfg.enc_process_minfreq = cfg->val_int;
|
||||
break;
|
||||
case ENC_SIR_MaxFreq:
|
||||
AEC_ONLINE_LOG("ENC_SIR_MaxFreq:%d\n", cfg->val_int);
|
||||
aec_update->cfg.sir_maxfreq = cfg->val_int;
|
||||
break;
|
||||
case ENC_MIC_Distance:
|
||||
AEC_ONLINE_LOG("ENC_MIC_Distance:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.mic_distance = cfg->val_float;
|
||||
break;
|
||||
case ENC_Target_Signal_Degradation:
|
||||
AEC_ONLINE_LOG("ENC_Target_Signal_Degradation:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.target_signal_degradation = cfg->val_float;
|
||||
break;
|
||||
case ENC_AggressFactor:
|
||||
AEC_ONLINE_LOG("ENC_AggressFactor:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.enc_aggressfactor = cfg->val_float;
|
||||
break;
|
||||
case ENC_MinSuppress:
|
||||
AEC_ONLINE_LOG("ENC_MinSuppress:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.enc_minsuppress = cfg->val_float;
|
||||
break;
|
||||
#else/*TCFG_AUDIO_DMS_SEL == DMS_FLEXIBLE*/
|
||||
case ENC_Suppress_Pre:
|
||||
AEC_ONLINE_LOG("ENC_Suppress_Pre:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.enc_suppress_pre = cfg->val_float;
|
||||
break;
|
||||
case ENC_Suppress_Post:
|
||||
AEC_ONLINE_LOG("ENC_Suppress_Post:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.enc_suppress_post = cfg->val_float;
|
||||
break;
|
||||
case ENC_MinSuppress:
|
||||
AEC_ONLINE_LOG("ENC_MinSuppress:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.enc_minsuppress = cfg->val_float;
|
||||
break;
|
||||
case ENC_Disconverge_Thr:
|
||||
AEC_ONLINE_LOG("ENC_Disconverge_Thr:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.enc_disconverge_erle_thr = cfg->val_float;
|
||||
break;
|
||||
|
||||
#endif/*TCFG_AUDIO_DMS_SEL*/
|
||||
default:
|
||||
AEC_ONLINE_LOG("enc param default:%x\n", id, cfg->val_int);
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
break;
|
||||
}
|
||||
#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/
|
||||
} else if (id >= AGC_NDT_FADE_IN) {
|
||||
AEC_ONLINE_LOG("AGC cfg update\n");
|
||||
switch (id) {
|
||||
case AGC_NDT_FADE_IN:
|
||||
AEC_ONLINE_LOG("AGC_NDT_FADE_IN:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.ndt_fade_in = cfg->val_float;
|
||||
break;
|
||||
case AGC_NDT_FADE_OUT:
|
||||
AEC_ONLINE_LOG("AGC_NDT_FADE_OUT:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.ndt_fade_out = cfg->val_float;
|
||||
break;
|
||||
case AGC_DT_FADE_IN:
|
||||
AEC_ONLINE_LOG("AGC_DT_FADE_IN:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.dt_fade_in = cfg->val_float;
|
||||
break;
|
||||
case AGC_DT_FADE_OUT:
|
||||
AEC_ONLINE_LOG("AGC_DT_FADE_OUT:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.dt_fade_out = cfg->val_float;
|
||||
break;
|
||||
case AGC_NDT_MAX_GAIN:
|
||||
AEC_ONLINE_LOG("AGC_NDT_MAX_GAIN:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.ndt_max_gain = cfg->val_float;
|
||||
break;
|
||||
case AGC_NDT_MIN_GAIN:
|
||||
AEC_ONLINE_LOG("AGC_NDT_MIN_GAIN:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.ndt_min_gain = cfg->val_float;
|
||||
break;
|
||||
case AGC_NDT_SPEECH_THR:
|
||||
AEC_ONLINE_LOG("AGC_NDT_SPEECH_THR:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.ndt_speech_thr = cfg->val_float;
|
||||
break;
|
||||
case AGC_DT_MAX_GAIN:
|
||||
AEC_ONLINE_LOG("AGC_DT_MAX_GAIN:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.dt_max_gain = cfg->val_float;
|
||||
break;
|
||||
case AGC_DT_MIN_GAIN:
|
||||
AEC_ONLINE_LOG("AGC_DT_MIN_GAIN:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.dt_min_gain = cfg->val_float;
|
||||
break;
|
||||
case AGC_DT_SPEECH_THR:
|
||||
AEC_ONLINE_LOG("AGC_DT_SPEECH_THR:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.dt_speech_thr = cfg->val_float;
|
||||
break;
|
||||
case AGC_ECHO_PRESENT_THR:
|
||||
AEC_ONLINE_LOG("AGC_ECHO_PRESENT_THR:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.echo_present_thr = cfg->val_float;
|
||||
break;
|
||||
}
|
||||
} else if (id >= ANS_AggressFactor) {
|
||||
AEC_ONLINE_LOG("ANS cfg update\n");
|
||||
switch (id) {
|
||||
#if TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
case ANS_AggressFactor:
|
||||
AEC_ONLINE_LOG("ANS_AggressFactor:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.aggressfactor = cfg->val_float;
|
||||
break;
|
||||
case ANS_MinSuppress:
|
||||
AEC_ONLINE_LOG("ANS_MinSuppress:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.minsuppress = cfg->val_float;
|
||||
break;
|
||||
case ANS_MicNoiseLevel:
|
||||
AEC_ONLINE_LOG("ANS_MicNoiseLevel:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.init_noise_lvl = cfg->val_float;
|
||||
break;
|
||||
#else
|
||||
case ANS_AGGRESS:
|
||||
AEC_ONLINE_LOG("ANS_AGGRESS:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.ans_aggress = cfg->val_float;
|
||||
break;
|
||||
case ANS_SUPPRESS:
|
||||
AEC_ONLINE_LOG("ANS_SUPPRESS:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.ans_suppress = cfg->val_float;
|
||||
break;
|
||||
case DNS_GainFloor:
|
||||
AEC_ONLINE_LOG("DNS_GainFloor:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.ans_suppress = cfg->val_float;
|
||||
break;
|
||||
case DNS_OverDrive:
|
||||
AEC_ONLINE_LOG("DNS_OverDrive:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.ans_aggress = cfg->val_float;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
} else if (id >= NLP_ProcessMaxFreq) {
|
||||
AEC_ONLINE_LOG("NLP cfg update\n");
|
||||
switch (id) {
|
||||
#if TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
case NLP_ProcessMaxFreq:
|
||||
AEC_ONLINE_LOG("NLP_ProcessMaxFreq:%d\n", cfg->val_int);
|
||||
aec_update->cfg.nlp_process_maxfrequency = cfg->val_int;
|
||||
break;
|
||||
case NLP_ProcessMinFreq:
|
||||
AEC_ONLINE_LOG("NLP_ProcessMinFreq:%d\n", cfg->val_int);
|
||||
aec_update->cfg.nlp_process_minfrequency = cfg->val_int;
|
||||
break;
|
||||
case NLP_OverDrive:
|
||||
AEC_ONLINE_LOG("NLP_OverDrive:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.overdrive = cfg->val_float;
|
||||
break;
|
||||
#else/*SINGLE MIC*/
|
||||
case NLP_AGGRESS_FACTOR:
|
||||
AEC_ONLINE_LOG("NLP_AGGRESS_FACTOR:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.es_aggress_factor = cfg->val_float;
|
||||
break;
|
||||
case NLP_MIN_SUPPRESS:
|
||||
AEC_ONLINE_LOG("NLP_MIN_SUPPRESS:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.es_min_suppress = cfg->val_float;
|
||||
break;
|
||||
#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/
|
||||
}
|
||||
} else if (id >= AEC_ProcessMaxFreq) {
|
||||
switch (id) {
|
||||
#if TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
case AEC_ProcessMaxFreq:
|
||||
AEC_ONLINE_LOG("AEC_ProcessMaxFreq:%d\n", cfg->val_int);
|
||||
aec_update->cfg.aec_process_maxfrequency = cfg->val_int;
|
||||
break;
|
||||
case AEC_ProcessMinFreq:
|
||||
AEC_ONLINE_LOG("AEC_ProcessMinFreq:%d\n", cfg->val_int);
|
||||
aec_update->cfg.aec_process_minfrequency = cfg->val_int;
|
||||
break;
|
||||
case AEC_AF_Lenght:
|
||||
AEC_ONLINE_LOG("AEC_AF_Lenght:%d\n", cfg->val_int);
|
||||
aec_update->cfg.af_length = cfg->val_int;
|
||||
break;
|
||||
#else/*SINGLE MIC*/
|
||||
case AEC_DT_AGGRESS:
|
||||
AEC_ONLINE_LOG("AEC_DT_AGGRESS:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.aec_dt_aggress = cfg->val_float;
|
||||
case AEC_REFENGTHR:
|
||||
AEC_ONLINE_LOG("AEC_REFENGTHR:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.aec_refengthr = cfg->val_float;
|
||||
break;
|
||||
#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/
|
||||
}
|
||||
} else {
|
||||
AEC_ONLINE_LOG("General cfg update\n");
|
||||
switch (id) {
|
||||
case GENERAL_DAC:
|
||||
AEC_ONLINE_LOG("DAC_Gain:%d\n", cfg->val_int);
|
||||
aec_update->cfg.dac_again = cfg->val_int;
|
||||
esco_dec_dac_gain_set(cfg->val_int);
|
||||
update = 0;
|
||||
break;
|
||||
case GENERAL_MIC:
|
||||
AEC_ONLINE_LOG("Mic_Gain:%d\n", cfg->val_int);
|
||||
aec_update->cfg.mic_again = cfg->val_int;
|
||||
#if (TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_0)
|
||||
esco_enc_mic_gain_set(cfg->val_int);
|
||||
#endif/*TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_0*/
|
||||
#if (TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_1)
|
||||
esco_enc_mic1_gain_set(cfg->val_int);
|
||||
#endif/*(TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_1)*/
|
||||
#if (TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_2)
|
||||
esco_enc_mic2_gain_set(cfg->val_int);
|
||||
#endif/*(TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_2)*/
|
||||
#if (TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_3)
|
||||
esco_enc_mic3_gain_set(cfg->val_int);
|
||||
#endif/*(TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_3)*/
|
||||
update = 0;
|
||||
break;
|
||||
#if (TCFG_AUDIO_DMS_SEL == DMS_FLEXIBLE)
|
||||
case GENERAL_MIC_1:
|
||||
AEC_ONLINE_LOG("Mic1_Gain:%d\n", cfg->val_int);
|
||||
aec_update->cfg.mic1_again = cfg->val_int;
|
||||
esco_enc_mic1_gain_set(cfg->val_int);
|
||||
update = 0;
|
||||
break;
|
||||
#endif/*TCFG_AUDIO_DMS_SEL*/
|
||||
case GENERAL_ModuleEnable:
|
||||
#if TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
AEC_ONLINE_LOG("DMS EnableBit:%x", cfg->val_int);
|
||||
aec_update->cfg.enable_module = cfg->val_int;
|
||||
#else
|
||||
AEC_ONLINE_LOG("SMS EnableBit:%x", cfg->val_int);
|
||||
aec_update->cfg.aec_mode = cfg->val_int;
|
||||
|
||||
/*使用新配置工具后,兼容app在线调试*/
|
||||
if (aec_update->cfg.aec_mode == 2) {
|
||||
aec_update->cfg.aec_mode &= ~AEC_MODE_ADVANCE;
|
||||
aec_update->cfg.aec_mode |= AEC_MODE_ADVANCE;
|
||||
} else if (aec_update->cfg.aec_mode == 1) {
|
||||
aec_update->cfg.aec_mode &= ~AEC_MODE_ADVANCE;
|
||||
aec_update->cfg.aec_mode |= AEC_MODE_REDUCE;
|
||||
} else {
|
||||
aec_update->cfg.aec_mode &= ~AEC_MODE_ADVANCE;
|
||||
}
|
||||
if (aec_update->cfg.aec_mode) {
|
||||
aec_update->cfg.aec_mode |= AGC_EN;
|
||||
}
|
||||
#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/
|
||||
break;
|
||||
case GENERAL_PC_ModuleEnable:
|
||||
#if TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
AEC_ONLINE_LOG("DMS EnableBit:%x", cfg->val_int);
|
||||
aec_update->cfg.enable_module = cfg->val_int;
|
||||
#else
|
||||
AEC_ONLINE_LOG("SMS EnableBit:%x", cfg->val_int);
|
||||
aec_update->cfg.aec_mode = cfg->val_int;
|
||||
#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/
|
||||
break;
|
||||
case GENERAL_UL_EQ:
|
||||
AEC_ONLINE_LOG("UL_EQ_EN:%d\n", cfg->val_int);
|
||||
aec_update->cfg.ul_eq_en = cfg->val_int;
|
||||
break;
|
||||
#if TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
#if (TCFG_AUDIO_DMS_SEL == DMS_NORMAL)
|
||||
case GENERAL_Global_MinSuppress:
|
||||
AEC_ONLINE_LOG("GlobalMinSuppress:");
|
||||
AEC_ONLINE_FLOG(cfg->val_float);
|
||||
aec_update->cfg.global_minsuppress = cfg->val_float;
|
||||
break;
|
||||
#endif/*TCFG_AUDIO_DMS_SEL*/
|
||||
#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/
|
||||
}
|
||||
}
|
||||
aec_update->update = AEC_UPDATE_ONLINE;
|
||||
if (update && audio_aec_status()) {
|
||||
if (aec_update->timer) {
|
||||
sys_timer_modify(aec_update->timer, 500);
|
||||
} else {
|
||||
aec_update->timer = sys_timer_add(NULL, aec_update_timer_deal, 500);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aec_cfg_online_init()
|
||||
{
|
||||
int ret = 0;
|
||||
aec_update = zalloc(sizeof(aec_update_t));
|
||||
#if TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
#if (TCFG_AUDIO_DMS_SEL == DMS_NORMAL)
|
||||
#if (TCFG_AUDIO_CVP_NS_MODE == CVP_ANS_MODE)
|
||||
ret = syscfg_read(CFG_DMS_ID, &aec_update->cfg, sizeof(AEC_DMS_CONFIG));
|
||||
#else/*CVP_DNS_MODE*/
|
||||
ret = syscfg_read(CFG_DMS_DNS_ID, &aec_update->cfg, sizeof(AEC_DMS_CONFIG));
|
||||
#endif/*TCFG_AUDIO_CVP_NS_MODE*/
|
||||
if (ret == sizeof(AEC_DMS_CONFIG)) {
|
||||
aec_update->update = AEC_UPDATE_INIT;
|
||||
}
|
||||
#else/*TCFG_AUDIO_DMS_SEL == DMS_FLEXIBLE*/
|
||||
#if (TCFG_AUDIO_CVP_NS_MODE == CVP_ANS_MODE)
|
||||
ret = syscfg_read(CFG_DMS_FLEXIBLE_ID, &aec_update->cfg, sizeof(DMS_FLEXIBLE_CONFIG));
|
||||
#else/*CVP_DNS_MODE*/
|
||||
ret = syscfg_read(CFG_DMS_DNS_FLEXIBLE_ID, &aec_update->cfg, sizeof(DMS_FLEXIBLE_CONFIG));
|
||||
#endif/*TCFG_AUDIO_CVP_NS_MODE*/
|
||||
if (ret == sizeof(DMS_FLEXIBLE_CONFIG)) {
|
||||
aec_update->update = AEC_UPDATE_INIT;
|
||||
}
|
||||
#endif/*TCFG_AUDIO_DMS_SEL*/
|
||||
#else/*SINGLE MIC*/
|
||||
#if (TCFG_AUDIO_CVP_NS_MODE == CVP_ANS_MODE)
|
||||
ret = syscfg_read(CFG_AEC_ID, &aec_update->cfg, sizeof(AEC_CONFIG));
|
||||
#else/*CVP_DNS_MODE*/
|
||||
ret = syscfg_read(CFG_SMS_DNS_ID, &aec_update->cfg, sizeof(AEC_CONFIG));
|
||||
#endif/*TCFG_AUDIO_CVP_NS_MODE*/
|
||||
if (ret == sizeof(AEC_CONFIG)) {
|
||||
aec_update->update = AEC_UPDATE_INIT;
|
||||
}
|
||||
#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*return 1:有在线更新数据*/
|
||||
/*return 0:没有在线更新数据*/
|
||||
int aec_cfg_online_update_fill(void *cfg, u16 len)
|
||||
{
|
||||
if (aec_update && aec_update->update) {
|
||||
memcpy(cfg, &aec_update->cfg, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aec_cfg_online_exit()
|
||||
{
|
||||
if (aec_update) {
|
||||
free(aec_update);
|
||||
aec_update = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_aec_config(u8 *buf, int version)
|
||||
{
|
||||
#if 1/*每次获取update的配置*/
|
||||
if (aec_update) {
|
||||
printf("cfg_size:%d\n", sizeof(aec_update->cfg));
|
||||
memcpy(buf, &aec_update->cfg, sizeof(aec_update->cfg));
|
||||
|
||||
#if (TCFG_AUDIO_DUAL_MIC_ENABLE == 0)
|
||||
AEC_CONFIG *cfg = (AEC_CONFIG *)buf;
|
||||
/*单麦aec_mode: app(旧)和pc端(兼容) */
|
||||
if (version == 0x01) {
|
||||
printf("APP version %d", version);
|
||||
if (aec_update->cfg.aec_mode & AGC_EN) {
|
||||
aec_update->agc_en = 1;
|
||||
} else {
|
||||
aec_update->agc_en = 0;
|
||||
}
|
||||
if ((aec_update->cfg.aec_mode & AEC_MODE_ADVANCE) == AEC_MODE_ADVANCE) {
|
||||
cfg->aec_mode = 2;
|
||||
} else if ((aec_update->cfg.aec_mode & AEC_MODE_ADVANCE) == AEC_MODE_REDUCE) {
|
||||
cfg->aec_mode = 1;
|
||||
} else {
|
||||
cfg->aec_mode = 0;
|
||||
}
|
||||
} else if (version == 0x02) {
|
||||
printf("PC version %d", version);
|
||||
}
|
||||
#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/
|
||||
|
||||
return sizeof(aec_update->cfg);
|
||||
}
|
||||
return 0;
|
||||
#else/*每次获取原始配置*/
|
||||
#if TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
AEC_DMS_CONFIG cfg;
|
||||
int ret = syscfg_read(CFG_DMS_ID, &cfg, sizeof(AEC_DMS_CONFIG));
|
||||
if (ret == sizeof(AEC_DMS_CONFIG)) {
|
||||
memcpy(buf, &cfg, sizeof(AEC_DMS_CONFIG));
|
||||
return sizeof(AEC_DMS_CONFIG);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
AEC_CONFIG cfg;
|
||||
int ret = syscfg_read(CFG_AEC_ID, &cfg, sizeof(AEC_CONFIG));
|
||||
if (ret == sizeof(AEC_CONFIG)) {
|
||||
memcpy(buf, &cfg, sizeof(AEC_CONFIG));
|
||||
return sizeof(AEC_CONFIG);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/
|
||||
#endif
|
||||
}
|
||||
#endif /*TCFG_AEC_TOOL_ONLINE_ENABLE*/
|
||||
|
||||
/*
|
||||
***********************************************************************
|
||||
* 导出通话过程的数据
|
||||
*
|
||||
*
|
||||
***********************************************************************
|
||||
*/
|
||||
#if (TCFG_AUDIO_DATA_EXPORT_ENABLE == AUDIO_DATA_EXPORT_USE_SPP)
|
||||
enum {
|
||||
AEC_RECORD_COUNT = 0x200,
|
||||
AEC_RECORD_START,
|
||||
AEC_RECORD_STOP,
|
||||
ONLINE_OP_QUERY_RECORD_PACKAGE_LENGTH,
|
||||
};
|
||||
|
||||
enum {
|
||||
AEC_ST_INIT,
|
||||
AEC_ST_START,
|
||||
AEC_ST_STOP,
|
||||
};
|
||||
|
||||
#define AEC_RECORD_CH 2
|
||||
#define AEC_RECORD_MTU 200
|
||||
#define RECORD_CH0_LENGTH 644
|
||||
#define RECORD_CH1_LENGTH 644
|
||||
#define RECORD_CH2_LENGTH 644
|
||||
|
||||
typedef struct {
|
||||
u8 state;
|
||||
u8 ch; /*export data ch num*/
|
||||
u16 send_timer;
|
||||
u8 packet[256];
|
||||
} aec_record_t;
|
||||
aec_record_t *aec_rec = NULL;
|
||||
|
||||
typedef struct {
|
||||
int cmd;
|
||||
int data;
|
||||
} rec_cmd_t;
|
||||
|
||||
extern int audio_capture_start(void);
|
||||
extern void audio_capture_stop(void);
|
||||
static int aec_online_parse(u8 *packet, u8 size, u8 *ext_data, u16 ext_size)
|
||||
{
|
||||
int res_data = 0;
|
||||
rec_cmd_t rec_cmd;
|
||||
int err = 0;
|
||||
u8 parse_seq = ext_data[1];
|
||||
//AEC_ONLINE_LOG("aec_spp_rx,seq:%d,size:%d\n", parse_seq, size);
|
||||
//put_buf(packet, size);
|
||||
memcpy(&rec_cmd, packet, sizeof(rec_cmd_t));
|
||||
switch (rec_cmd.cmd) {
|
||||
case AEC_RECORD_COUNT:
|
||||
res_data = aec_rec->ch;
|
||||
err = app_online_db_ack(parse_seq, (u8 *)&res_data, 4);
|
||||
AEC_ONLINE_LOG("query record_ch num:%d\n", res_data);
|
||||
break;
|
||||
case AEC_RECORD_START:
|
||||
err = app_online_db_ack(parse_seq, (u8 *)&res_data, 1); //该命令随便ack一个byte即可
|
||||
aec_rec->state = AEC_ST_START;
|
||||
audio_capture_start();
|
||||
AEC_ONLINE_LOG("record_start\n");
|
||||
break;
|
||||
case AEC_RECORD_STOP:
|
||||
AEC_ONLINE_LOG("record_stop\n");
|
||||
audio_capture_stop();
|
||||
aec_rec->state = AEC_ST_STOP;
|
||||
app_online_db_ack(parse_seq, (u8 *)&res_data, 1); //该命令随便ack一个byte即可
|
||||
break;
|
||||
case ONLINE_OP_QUERY_RECORD_PACKAGE_LENGTH:
|
||||
if (rec_cmd.data == 0) {
|
||||
res_data = RECORD_CH0_LENGTH;
|
||||
} else if (rec_cmd.data == 1) {
|
||||
res_data = RECORD_CH1_LENGTH;
|
||||
} else {
|
||||
res_data = RECORD_CH2_LENGTH;
|
||||
}
|
||||
AEC_ONLINE_LOG("query record ch%d packet length:%d\n", rec_cmd.data, res_data);
|
||||
err = app_online_db_ack(parse_seq, (u8 *)&res_data, 4); //回复对应的通道数据长度
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aec_export_timer(void *priv)
|
||||
{
|
||||
int err = 0;
|
||||
if (aec_rec->state) {
|
||||
putchar('.');
|
||||
#if 1
|
||||
static u8 data = 0;
|
||||
memset(aec_rec->packet, data, 128);
|
||||
data++;
|
||||
#endif
|
||||
err = app_online_db_send(DB_PKT_TYPE_DAT_CH0, aec_rec->packet, AEC_RECORD_MTU);
|
||||
if (err) {
|
||||
printf("w0_err:%d", err);
|
||||
}
|
||||
err = app_online_db_send(DB_PKT_TYPE_DAT_CH1, aec_rec->packet, AEC_RECORD_MTU);
|
||||
if (err) {
|
||||
printf("w1_err:%d", err);
|
||||
}
|
||||
} else {
|
||||
//putchar('S');
|
||||
}
|
||||
}
|
||||
|
||||
int spp_data_export(u8 ch, u8 *buf, u16 len)
|
||||
{
|
||||
u8 data_ch;
|
||||
if (aec_rec->state == AEC_ST_START) {
|
||||
putchar('.');
|
||||
if (ch == 0) {
|
||||
data_ch = DB_PKT_TYPE_DAT_CH0;
|
||||
} else if (ch == 1) {
|
||||
data_ch = DB_PKT_TYPE_DAT_CH1;
|
||||
} else {
|
||||
data_ch = DB_PKT_TYPE_DAT_CH2;
|
||||
}
|
||||
int err = app_online_db_send_more(data_ch, buf, len);
|
||||
if (err) {
|
||||
r_printf("tx_err:%d", err);
|
||||
//return -1;
|
||||
}
|
||||
return len;
|
||||
} else {
|
||||
//putchar('x');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int aec_data_export_init(u8 ch)
|
||||
{
|
||||
aec_rec = zalloc(sizeof(aec_record_t));
|
||||
//aec_rec->send_timer = sys_timer_add(NULL, aec_export_timer, 16);
|
||||
aec_rec->ch = ch;
|
||||
app_online_db_register_handle(DB_PKT_TYPE_EXPORT, aec_online_parse);
|
||||
//app_online_db_register_handle(DB_PKT_TYPE_MIC_DUT, mic_dut_online_parse);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aec_data_export_exit()
|
||||
{
|
||||
if (aec_rec) {
|
||||
if (aec_rec->send_timer) {
|
||||
sys_timer_del(aec_rec->send_timer);
|
||||
aec_rec->send_timer = 0;
|
||||
}
|
||||
free(aec_rec);
|
||||
aec_rec = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /*TCFG_AUDIO_DATA_EXPORT_ENABLE*/
|
||||
|
||||
#if 0
|
||||
static u8 aec_online_idle_query(void)
|
||||
{
|
||||
//return ((aec_rec == NULL) ? 1 : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_LP_TARGET(aec_online_lp_target) = {
|
||||
.name = "aec_online",
|
||||
.is_idle = aec_online_idle_query,
|
||||
};
|
||||
#endif
|
||||
118
apps/earphone/aec/br28/audio_aec_online.h
Normal file
118
apps/earphone/aec/br28/audio_aec_online.h
Normal file
@ -0,0 +1,118 @@
|
||||
#ifndef _AUDIO_AEC_ONLINE_H_
|
||||
#define _AUDIO_AEC_ONLINE_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
/*
|
||||
*0x30xx:单mic降噪ANS
|
||||
*0x31xx:双mic降噪ANS
|
||||
*0x32xx:单mic降噪DNS
|
||||
*0x33xx:双mic降噪DNS
|
||||
*0x34xx:双mic话务耳机ANS
|
||||
*0x35xx:双mic话务耳机DNS
|
||||
*如果有版本更新,通过更新后两位来区分,比如:0x3001
|
||||
*/
|
||||
#define AEC_CFG_SMS 0x3000
|
||||
#define AEC_CFG_DMS 0x3100
|
||||
#define AEC_CFG_SMS_DNS 0x3200
|
||||
#define AEC_CFG_DMS_DNS 0x3300
|
||||
#define AEC_CFG_DMS_FLEXIBLE 0x3400
|
||||
#define AEC_CFG_DMS_FLEXIBLE_DNS 0x3500
|
||||
|
||||
//GENERAL_CONFIG:0x0000~0x0FFF
|
||||
enum {
|
||||
GENERAL_DAC = 0x0000,
|
||||
GENERAL_MIC,
|
||||
/*app端在线调试的enablebit;*/
|
||||
GENERAL_ModuleEnable,
|
||||
GENERAL_UL_EQ,
|
||||
GENERAL_Global_MinSuppress,
|
||||
|
||||
GENERAL_MIC_1,
|
||||
|
||||
/*pc端在线调试的enablebit;*/
|
||||
GENERAL_PC_ModuleEnable,
|
||||
};
|
||||
|
||||
//AEC_CONFIG:0x1000~0x2FFF
|
||||
enum {
|
||||
//dms
|
||||
AEC_ProcessMaxFreq = 0x1000,
|
||||
AEC_ProcessMinFreq,
|
||||
AEC_AF_Lenght,
|
||||
//sms
|
||||
AEC_DT_AGGRESS = 0x2000,
|
||||
AEC_REFENGTHR,
|
||||
};
|
||||
|
||||
//NLP_CONFIG:0x3000~0x4FFF
|
||||
enum {
|
||||
//dms
|
||||
NLP_ProcessMaxFreq = 0x3000,
|
||||
NLP_ProcessMinFreq,
|
||||
NLP_OverDrive,
|
||||
//sms
|
||||
NLP_AGGRESS_FACTOR = 0x4000,
|
||||
NLP_MIN_SUPPRESS,
|
||||
};
|
||||
|
||||
//ANS_CONFIG:0x5000~0x6FFF
|
||||
enum {
|
||||
//dms
|
||||
ANS_AggressFactor = 0x5000,
|
||||
ANS_MinSuppress,
|
||||
ANS_MicNoiseLevel,
|
||||
//sms
|
||||
ANS_AGGRESS = 0x6000,
|
||||
ANS_SUPPRESS,
|
||||
//DNS
|
||||
DNS_GainFloor = 0x6100,
|
||||
DNS_OverDrive,
|
||||
};
|
||||
|
||||
//AGC_CONFIG(common):0x7000~0x7FFF
|
||||
enum {
|
||||
AGC_NDT_FADE_IN = 0x7000,
|
||||
AGC_NDT_FADE_OUT,
|
||||
AGC_DT_FADE_IN,
|
||||
AGC_DT_FADE_OUT,
|
||||
AGC_NDT_MAX_GAIN,
|
||||
AGC_NDT_MIN_GAIN,
|
||||
AGC_NDT_SPEECH_THR,
|
||||
AGC_DT_MAX_GAIN,
|
||||
AGC_DT_MIN_GAIN,
|
||||
AGC_DT_SPEECH_THR,
|
||||
AGC_ECHO_PRESENT_THR,
|
||||
};
|
||||
|
||||
//ENC_CONFIG(only dms):0x8000~0x8FFF
|
||||
enum {
|
||||
ENC_Process_MaxFreq = 0x8000,
|
||||
ENC_Process_MinFreq,
|
||||
ENC_SIR_MaxFreq,
|
||||
ENC_MIC_Distance,
|
||||
ENC_Target_Signal_Degradation,
|
||||
ENC_AggressFactor,
|
||||
|
||||
ENC_MinSuppress,
|
||||
|
||||
ENC_Suppress_Pre,
|
||||
ENC_Suppress_Post,
|
||||
ENC_Disconverge_Thr,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int id; //参数id号
|
||||
union {//参数值(整形或者浮点)
|
||||
float val_float;
|
||||
int val_int;
|
||||
};
|
||||
} aec_online_t;
|
||||
|
||||
int aec_cfg_online_init();
|
||||
int aec_cfg_online_exit();
|
||||
int aec_cfg_online_update(int root_cmd, void *cfg);
|
||||
int aec_cfg_online_update_fill(void *cfg, u16 len);
|
||||
int get_aec_config(u8 *buf, int version);
|
||||
|
||||
#endif/*_AUDIO_AEC_ONLINE_H_*/
|
||||
1330
apps/earphone/aec/br28/audio_cvp_3mic.c
Normal file
1330
apps/earphone/aec/br28/audio_cvp_3mic.c
Normal file
File diff suppressed because it is too large
Load Diff
710
apps/earphone/aec/br28/audio_cvp_ais_3mic.c
Normal file
710
apps/earphone/aec/br28/audio_cvp_ais_3mic.c
Normal file
@ -0,0 +1,710 @@
|
||||
/*
|
||||
***************************************************************************
|
||||
* AISPEECH 3-Mic NR
|
||||
* Brief : 思必驰3mic通话降噪
|
||||
* By : GZR
|
||||
* Notes : 1.可用内存
|
||||
* (1)aec_hdl_mem: 静态变量
|
||||
* (2)free_ram: 动态内存(mem_stats:physics memory size xxxx bytes)
|
||||
* 2.demo默认将输入数据copy到输出,相关处理只需在运算函数
|
||||
* audio_aec_run()实现即可
|
||||
* 3.双mic ENC开发,只需打开对应板级以下配置即可:
|
||||
* #define TCFG_AUDIO_DUAL_MIC_ENABLE ENABLE_THIS_MOUDLE
|
||||
* 4.建议算法开发者使用宏定义将自己的代码模块包起来
|
||||
* 5.算法处理完的数据,如有需要,可以增加EQ处理:AEC_UL_EQ_EN
|
||||
* 6.开发阶段,默认使用芯片最高主频160MHz,可以通过修改AEC_CLK来修改
|
||||
运行频率。
|
||||
***************************************************************************
|
||||
*/
|
||||
#include "aec_user.h"
|
||||
#include "system/includes.h"
|
||||
#include "media/includes.h"
|
||||
#include "application/eq_config.h"
|
||||
#include "circular_buf.h"
|
||||
#include "overlay_code.h"
|
||||
#include "audio_config.h"
|
||||
#include "debug.h"
|
||||
#include "audio_gain_process.h"
|
||||
#ifdef CONFIG_BOARD_AISPEECH_NR
|
||||
#include "aispeech_enc.h"
|
||||
#endif /*CONFIG_BOARD_AISPEECH_NR*/
|
||||
#if TCFG_AUDIO_CVP_DUT_ENABLE
|
||||
#include "audio_cvp_dut.h"
|
||||
#endif // TCFG_AUDIO_CVP_DUT_ENABLE
|
||||
|
||||
#if defined(TCFG_CVP_DEVELOP_ENABLE) && (TCFG_CVP_DEVELOP_ENABLE == CVP_CFG_AIS_3MIC)
|
||||
|
||||
#define AEC_CLK (160 * 1000000L) /*模块运行时钟(MaxFre:160MHz)*/
|
||||
#define AEC_FRAME_POINTS 256 /*AEC处理帧长,跟mic采样长度关联*/
|
||||
#define AEC_FRAME_SIZE (AEC_FRAME_POINTS << 1)
|
||||
#if TCFG_AUDIO_TRIPLE_MIC_ENABLE
|
||||
#define AEC_MIC_NUM 3 /*3 mic*/
|
||||
#elif TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
#define AEC_MIC_NUM 2 /*双mic*/
|
||||
#else
|
||||
#define AEC_MIC_NUM 1 /*单mic*/
|
||||
#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/
|
||||
|
||||
/*上行数据eq*/
|
||||
#define AEC_UL_EQ_EN 0
|
||||
|
||||
#define AEC_USER_MALLOC_ENABLE 1 /*是否使用动态内存*/
|
||||
|
||||
/*数据输出开头丢掉的数据包数*/
|
||||
#define CVP_OUT_DUMP_PACKET 15
|
||||
|
||||
#ifdef AUDIO_PCM_DEBUG
|
||||
/*AEC串口数据导出*/
|
||||
const u8 CONST_AEC_EXPORT = 1;
|
||||
#else
|
||||
const u8 CONST_AEC_EXPORT = 0;
|
||||
#endif/*AUDIO_PCM_DEBUG*/
|
||||
|
||||
//*********************************************************************************//
|
||||
// 预处理配置(Pre-process Config) //
|
||||
//*********************************************************************************//
|
||||
/*预增益配置*/
|
||||
#define CVP_PRE_GAIN_ENABLE 0 //算法处理前预加数字增益放大使能
|
||||
#define CVP_PRE_GAIN 6.f //算法前处理数字增益(Gain = 10^(dB_diff/20))
|
||||
|
||||
extern float usb_audio_mic_get_dig_gain(void);
|
||||
extern int audio_dac_read_reset(void);
|
||||
extern int audio_dac_read(s16 points_offset, void *data, int len, u8 read_channel);
|
||||
extern void esco_enc_resume(void);
|
||||
extern int aec_uart_init();
|
||||
extern int aec_uart_open(u8 nch, u16 single_size);
|
||||
extern int aec_uart_fill(u8 ch, void *buf, u16 size);
|
||||
extern void aec_uart_write(void);
|
||||
extern int aec_uart_close(void);
|
||||
|
||||
/*AEC输入buf复用mic_adc采样buf*/
|
||||
#define MIC_BULK_MAX 3
|
||||
struct mic_bulk {
|
||||
struct list_head entry;
|
||||
s16 *addr;
|
||||
u16 len;
|
||||
u16 used;
|
||||
};
|
||||
|
||||
struct audio_aec_hdl {
|
||||
volatile u8 start; //aec模块状态
|
||||
u8 output_fade_in; //aec输出淡入使能
|
||||
u8 output_fade_in_gain; //aec输出淡入增益
|
||||
u8 output_sel; //数据输出通道选择
|
||||
u16 dump_packet; //前面如果有杂音,丢掉几包
|
||||
volatile u8 busy;
|
||||
u8 output_buf[1000]; //aec数据输出缓存
|
||||
cbuffer_t output_cbuf;
|
||||
s16 *mic; /*主mic数据地址*/
|
||||
s16 *mic_ref; /*参考mic数据地址*/
|
||||
s16 *mic_ref_1; /*参考mic数据地址*/
|
||||
s16 spk_ref[AEC_FRAME_POINTS]; /*扬声器参考数据*/
|
||||
s16 out[AEC_FRAME_POINTS]; /*运算输出地址*/
|
||||
OS_SEM sem;
|
||||
/*数据复用相关数据结构*/
|
||||
struct mic_bulk in_bulk[MIC_BULK_MAX];
|
||||
struct mic_bulk inref_bulk[MIC_BULK_MAX];
|
||||
struct mic_bulk inref_1_bulk[MIC_BULK_MAX];
|
||||
struct list_head in_head;
|
||||
struct list_head inref_head;
|
||||
struct list_head inref_1_head;
|
||||
#if AEC_UL_EQ_EN
|
||||
struct audio_eq *ul_eq;
|
||||
#endif/*AEC_UL_EQ_EN*/
|
||||
int (*output_handle)(s16 *dat, u16 len);
|
||||
s16 *free_ram; /*当前可用内存*/
|
||||
};
|
||||
|
||||
|
||||
|
||||
#if AEC_USER_MALLOC_ENABLE
|
||||
struct audio_aec_hdl *aec_hdl = NULL;
|
||||
#else
|
||||
struct audio_aec_hdl aec_handle;
|
||||
struct audio_aec_hdl *aec_hdl = &aec_handle;
|
||||
#endif /*AEC_USER_MALLOC_ENABLE*/
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Output Read
|
||||
* Description: 读取aec模块的输出数据
|
||||
* Arguments : buf 读取数据存放地址
|
||||
* len 读取数据长度
|
||||
* Return : 数据读取长度
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_aec_output_read(s16 *buf, u16 len)
|
||||
{
|
||||
//printf("rlen:%d-%d\n",len,aec_hdl.output_cbuf.data_len);
|
||||
local_irq_disable();
|
||||
if (!aec_hdl || !aec_hdl->start) {
|
||||
printf("audio_aec close now");
|
||||
local_irq_enable();
|
||||
return -EINVAL;
|
||||
}
|
||||
u16 rlen = cbuf_read(&aec_hdl->output_cbuf, buf, len);
|
||||
if (rlen == 0) {
|
||||
//putchar('N');
|
||||
}
|
||||
local_irq_enable();
|
||||
return rlen;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Output Handle
|
||||
* Description: AEC模块数据输出回调
|
||||
* Arguments : data 输出数据地址
|
||||
* len 输出数据长度
|
||||
* Return : 数据输出消耗长度
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int audio_aec_output(s16 *data, u16 len)
|
||||
{
|
||||
u16 wlen = 0;
|
||||
float dig_gain;
|
||||
if (aec_hdl && aec_hdl->start) {
|
||||
if (aec_hdl->dump_packet) {
|
||||
aec_hdl->dump_packet--;
|
||||
memset(data, 0, len);
|
||||
} else {
|
||||
if (aec_hdl->output_fade_in) {
|
||||
s32 tmp_data;
|
||||
//printf("fade:%d\n",aec_hdl->output_fade_in_gain);
|
||||
for (int i = 0; i < len / 2; i++) {
|
||||
tmp_data = data[i];
|
||||
data[i] = tmp_data * aec_hdl->output_fade_in_gain >> 7;
|
||||
}
|
||||
aec_hdl->output_fade_in_gain += 12;
|
||||
if (aec_hdl->output_fade_in_gain >= 128) {
|
||||
aec_hdl->output_fade_in = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wlen = cbuf_write(&aec_hdl->output_cbuf, data, len);
|
||||
//printf("wlen:%d-%d\n",len,aec_hdl.output_cbuf.data_len);
|
||||
if (wlen != len) {
|
||||
printf("aec_out_full:%d,%d\n", len, wlen);
|
||||
}
|
||||
esco_enc_resume();
|
||||
}
|
||||
return wlen;
|
||||
}
|
||||
|
||||
/*
|
||||
*跟踪系统内存使用情况:physics memory size xxxx bytes
|
||||
*正常的系统运行过程,应该至少有3k bytes的剩余空间给到系统调度开销
|
||||
*/
|
||||
static void sys_memory_trace(void)
|
||||
{
|
||||
static int cnt = 0;
|
||||
if (cnt++ > 200) {
|
||||
cnt = 0;
|
||||
mem_stats();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC RUN
|
||||
* Description: AEC数据处理核心
|
||||
* Arguments : in 主mic数据
|
||||
* inref 参考mic数据(双mic降噪有用)
|
||||
* ref speaker参考数据
|
||||
* out 数据输出
|
||||
* Return : 数据运算输出长度
|
||||
* Note(s) : 在这里实现AEC_core
|
||||
*********************************************************************
|
||||
*/
|
||||
static int audio_aec_run(s16 *in, s16 *inref, s16 *inref1, s16 *ref, s16 *out, u16 points)
|
||||
{
|
||||
int out_size = 0;
|
||||
putchar('.');
|
||||
|
||||
#if CVP_PRE_GAIN_ENABLE
|
||||
GainProcess_16Bit(in, in, CVP_PRE_GAIN, 1, 1, 1, points);
|
||||
GainProcess_16Bit(inref, inref, CVP_PRE_GAIN, 1, 1, 1, points);
|
||||
// GainProcess_16Bit_test(inref1, inref1, 0.f, 1, 1, 1, points);
|
||||
#endif/*CVP_PRE_GAIN_ENABLE*/
|
||||
|
||||
#ifdef CONFIG_BOARD_AISPEECH_NR
|
||||
out_size = Aispeech_NR_run(in, inref, inref1, ref, out, points);
|
||||
#else
|
||||
memcpy(out, in, (points << 1));
|
||||
//memcpy(out, inref, (points << 1));
|
||||
out_size = points << 1;
|
||||
#endif /*CONFIG_BOARD_AISPEECH_NR*/
|
||||
|
||||
#if AEC_UL_EQ_EN
|
||||
if (aec_hdl->ul_eq) {
|
||||
audio_eq_run(aec_hdl->ul_eq, out, out_size);
|
||||
}
|
||||
#endif/*AEC_UL_EQ_EN*/
|
||||
|
||||
#if TCFG_AUDIO_CVP_DUT_ENABLE
|
||||
switch (aec_hdl->output_sel) {
|
||||
case CVP_3MIC_OUTPUT_SEL_MASTER:
|
||||
memcpy(out, in, (points << 1));
|
||||
break;
|
||||
case CVP_3MIC_OUTPUT_SEL_SLAVE:
|
||||
memcpy(out, inref, (points << 1));
|
||||
break;
|
||||
case CVP_3MIC_OUTPUT_SEL_FBMIC:
|
||||
memcpy(out, inref1, (points << 1));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif/*TCFG_AUDIO_CVP_DUT_ENABLE*/
|
||||
sys_memory_trace();
|
||||
return out_size;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Task
|
||||
* Description: AEC任务
|
||||
* Arguments : priv 私用参数
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static void audio_aec_task(void *priv)
|
||||
{
|
||||
printf("==Audio AEC Task==\n");
|
||||
struct mic_bulk *bulk = NULL;
|
||||
struct mic_bulk *bulk_ref = NULL;
|
||||
struct mic_bulk *bulk_ref_1 = NULL;
|
||||
u8 pend = 1;
|
||||
while (1) {
|
||||
if (pend) {
|
||||
os_sem_pend(&aec_hdl->sem, 0);
|
||||
}
|
||||
pend = 1;
|
||||
if (aec_hdl->start) {
|
||||
if (!list_empty(&aec_hdl->in_head)) {
|
||||
aec_hdl->busy = 1;
|
||||
local_irq_disable();
|
||||
/*1.获取主mic数据*/
|
||||
bulk = list_first_entry(&aec_hdl->in_head, struct mic_bulk, entry);
|
||||
list_del(&bulk->entry);
|
||||
aec_hdl->mic = bulk->addr;
|
||||
#if (AEC_MIC_NUM > 1)
|
||||
/*2.获取参考mic数据*/
|
||||
bulk_ref = list_first_entry(&aec_hdl->inref_head, struct mic_bulk, entry);
|
||||
list_del(&bulk_ref->entry);
|
||||
aec_hdl->mic_ref = bulk_ref->addr;
|
||||
#endif/*Dual_Microphone*/
|
||||
|
||||
#if (AEC_MIC_NUM > 2)
|
||||
/*获取参考mic1数据*/
|
||||
bulk_ref_1 = list_first_entry(&aec_hdl->inref_1_head, struct mic_bulk, entry);
|
||||
list_del(&bulk_ref_1->entry);
|
||||
aec_hdl->mic_ref_1 = bulk_ref_1->addr;
|
||||
#endif/*3_Microphone*/
|
||||
|
||||
local_irq_enable();
|
||||
/*3.获取speaker参考数据*/
|
||||
audio_dac_read(60, aec_hdl->spk_ref, AEC_FRAME_SIZE, 1);
|
||||
|
||||
/*4.算法处理*/
|
||||
int out_len = audio_aec_run(aec_hdl->mic, aec_hdl->mic_ref, aec_hdl->mic_ref_1, aec_hdl->spk_ref, aec_hdl->out, AEC_FRAME_POINTS);
|
||||
|
||||
/*5.结果输出*/
|
||||
if (aec_hdl->output_handle) {
|
||||
aec_hdl->output_handle(aec_hdl->out, out_len);
|
||||
}
|
||||
|
||||
/*6.数据导出*/
|
||||
if (CONST_AEC_EXPORT) {
|
||||
aec_uart_fill(0, aec_hdl->mic, 512); //主mic数据
|
||||
aec_uart_fill(1, aec_hdl->mic_ref, 512); //副mic数据
|
||||
aec_uart_fill(2, aec_hdl->spk_ref, 512); //扬声器数据
|
||||
#if (AEC_MIC_NUM > 2)
|
||||
aec_uart_fill(2, aec_hdl->mic_ref_1, 512); //扬声器数据
|
||||
aec_uart_fill(3, aec_hdl->spk_ref, 512); //扬声器数据
|
||||
aec_uart_fill(4, aec_hdl->out, out_len); //算法运算结果
|
||||
#endif /*3_Microphone*/
|
||||
aec_uart_write();
|
||||
}
|
||||
bulk->used = 0;
|
||||
#if (AEC_MIC_NUM > 1)
|
||||
bulk_ref->used = 0;
|
||||
#endif/*Dual_Microphone*/
|
||||
#if (AEC_MIC_NUM > 2)
|
||||
bulk_ref_1->used = 0;
|
||||
#endif /*3_Microphone*/
|
||||
aec_hdl->busy = 0;
|
||||
pend = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Open
|
||||
* Description: 初始化AEC模块
|
||||
* Arguments : sr 采样率(8000/16000)
|
||||
* enablebit 使能模块(AEC/NLP/AGC/ANS...)
|
||||
* out_hdl 自定义回调函数,NULL则用默认的回调
|
||||
* Return : 0 成功 其他 失败
|
||||
* Note(s) : 该接口是对audio_aec_init的扩展,支持自定义使能模块以及
|
||||
* 数据输出回调函数
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_aec_open(u16 sample_rate, s16 enablebit, int (*out_hdl)(s16 *data, u16 len))
|
||||
{
|
||||
printf("audio_aec_open,sr = %d\n", sample_rate);
|
||||
mem_stats();
|
||||
if (aec_hdl) {
|
||||
printf("audio aec is already open!\n");
|
||||
return -1;
|
||||
}
|
||||
overlay_load_code(OVERLAY_AEC);
|
||||
#if AEC_USER_MALLOC_ENABLE
|
||||
aec_hdl = zalloc(sizeof(struct audio_aec_hdl));
|
||||
if (aec_hdl == NULL) {
|
||||
printf("aec_hdl malloc failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif /*AEC_USER_MALLOC_ENABLE*/
|
||||
|
||||
aec_hdl->dump_packet = CVP_OUT_DUMP_PACKET;
|
||||
aec_hdl->output_fade_in = 1;
|
||||
aec_hdl->output_fade_in_gain = 0;
|
||||
#if TCFG_AUDIO_CVP_DUT_ENABLE
|
||||
aec_hdl->output_sel = CVP_3MIC_OUTPUT_SEL_DEFAULT;
|
||||
#endif/*TCFG_AUDIO_CVP_DUT_ENABLE*/
|
||||
aec_hdl->output_handle = audio_aec_output;
|
||||
|
||||
printf("aec_hdl size:%d\n", sizeof(struct audio_aec_hdl));
|
||||
clk_set("sys", AEC_CLK);
|
||||
INIT_LIST_HEAD(&aec_hdl->in_head);
|
||||
INIT_LIST_HEAD(&aec_hdl->inref_head);
|
||||
INIT_LIST_HEAD(&aec_hdl->inref_1_head);
|
||||
cbuf_init(&aec_hdl->output_cbuf, aec_hdl->output_buf, sizeof(aec_hdl->output_buf));
|
||||
if (CONST_AEC_EXPORT) {
|
||||
#if (AEC_MIC_NUM > 2)
|
||||
aec_uart_open(5, 512);
|
||||
#elif (AEC_MIC_NUM > 1)
|
||||
aec_uart_open(3, 512);
|
||||
#endif /*AEC_MIC_NUM*/
|
||||
}
|
||||
|
||||
if (out_hdl) {
|
||||
aec_hdl->output_handle = out_hdl;
|
||||
}
|
||||
|
||||
#if AEC_UL_EQ_EN
|
||||
struct audio_eq_param ul_eq_param = {0};
|
||||
ul_eq_param.sr = sample_rate;
|
||||
ul_eq_param.channels = 1;
|
||||
ul_eq_param.online_en = 1;
|
||||
ul_eq_param.mode_en = 0;
|
||||
ul_eq_param.remain_en = 0;
|
||||
ul_eq_param.max_nsection = EQ_SECTION_MAX;
|
||||
ul_eq_param.cb = aec_ul_eq_filter;
|
||||
ul_eq_param.eq_name = aec_eq_mode;
|
||||
aec_hdl->ul_eq = audio_dec_eq_open(&ul_eq_param);
|
||||
#endif/*AEC_UL_EQ_EN*/
|
||||
os_sem_create(&aec_hdl->sem, 0);
|
||||
task_create(audio_aec_task, NULL, "aec");
|
||||
audio_dac_read_reset();
|
||||
aec_hdl->start = 1;
|
||||
|
||||
mem_stats();
|
||||
#ifdef MUX_RX_BULK_TEST_DEMO
|
||||
mux_rx_bulk_test = zalloc_mux_rx_bulk(MUX_RX_BULK_MAX);
|
||||
if (mux_rx_bulk_test) {
|
||||
printf("mux_rx_bulk_test:0x%x\n", mux_rx_bulk_test);
|
||||
free_mux_rx_bulk(mux_rx_bulk_test);
|
||||
mux_rx_bulk_test = NULL;
|
||||
}
|
||||
#endif/*MUX_RX_BULK_TEST_DEMO*/
|
||||
|
||||
#ifdef CONFIG_BOARD_AISPEECH_NR
|
||||
u32 memPoolLen = Aispeech_NR_getmemsize(sample_rate);
|
||||
printf("ais memPoolLen=%d\r\n", memPoolLen);
|
||||
extern char *SEVC_API_Version();
|
||||
printf("--------------version %s ---\r\n", SEVC_API_Version());
|
||||
|
||||
aec_hdl->free_ram = malloc(memPoolLen);
|
||||
|
||||
char *pcMemPool = (char *)aec_hdl->free_ram;
|
||||
if (NULL == pcMemPool) {
|
||||
printf("ais calloc fail \r\n");
|
||||
return -1;
|
||||
}
|
||||
printf("ais pcMemPool malloc ok\r\n");
|
||||
Aispeech_NR_init(pcMemPool, memPoolLen, sample_rate);
|
||||
#endif /*CONFIG_BOARD_AISPEECH_NR*/
|
||||
|
||||
printf("audio_aec_open succ\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Init
|
||||
* Description: 初始化AEC模块
|
||||
* Arguments : sample_rate 采样率(8000/16000)
|
||||
* Return : 0 成功 其他 失败
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_aec_init(u16 sample_rate)
|
||||
{
|
||||
return audio_aec_open(sample_rate, -1, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Reboot
|
||||
* Description: AEC模块复位接口
|
||||
* Arguments : reduce 复位/恢复标志
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_reboot(u8 reduce)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Close
|
||||
* Description: 关闭AEC模块
|
||||
* Arguments : None.
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_close(void)
|
||||
{
|
||||
printf("audio_aec_close:%x", (u32)aec_hdl);
|
||||
if (aec_hdl) {
|
||||
aec_hdl->start = 0;
|
||||
while (aec_hdl->busy) {
|
||||
os_time_dly(2);
|
||||
}
|
||||
task_kill("aec");
|
||||
if (CONST_AEC_EXPORT) {
|
||||
aec_uart_close();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOARD_AISPEECH_NR
|
||||
Aispeech_NR_deinit();
|
||||
if (aec_hdl->free_ram) {
|
||||
free(aec_hdl->free_ram);
|
||||
}
|
||||
#endif /*CONFIG_BOARD_AISPEECH_NR*/
|
||||
|
||||
#if AEC_UL_EQ_EN
|
||||
if (aec_hdl->ul_eq) {
|
||||
audio_dec_eq_close(aec_hdl->ul_eq);
|
||||
aec_hdl->ul_eq = NULL;
|
||||
}
|
||||
#endif/*AEC_UL_EQ_EN*/
|
||||
|
||||
local_irq_disable();
|
||||
#if AEC_USER_MALLOC_ENABLE
|
||||
free(aec_hdl);
|
||||
#endif /*AEC_USER_MALLOC_ENABLE*/
|
||||
aec_hdl = NULL;
|
||||
local_irq_enable();
|
||||
printf("audio_aec_close succ\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Status
|
||||
* Description: AEC模块当前状态
|
||||
* Arguments : None.
|
||||
* Return : 0 关闭 其他 打开
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
u8 audio_aec_status(void)
|
||||
{
|
||||
if (aec_hdl) {
|
||||
return aec_hdl->start;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Input
|
||||
* Description: AEC源数据输入
|
||||
* Arguments : buf 输入源数据地址
|
||||
* len 输入源数据长度
|
||||
* Return : None.
|
||||
* Note(s) : 输入一帧数据,唤醒一次运行任务处理数据,默认帧长256点
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_inbuf(s16 *buf, u16 len)
|
||||
{
|
||||
if (aec_hdl && aec_hdl->start) {
|
||||
int i = 0;
|
||||
for (i = 0; i < MIC_BULK_MAX; i++) {
|
||||
if (aec_hdl->in_bulk[i].used == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if TCFG_AUDIO_CVP_DUT_ENABLE
|
||||
if (cvp_dut_mode_get() == CVP_DUT_MODE_BYPASS) {
|
||||
audio_aec_output(buf, len);
|
||||
return;
|
||||
}
|
||||
#endif/*TCFG_AUDIO_CVP_DUT_ENABLE*/
|
||||
|
||||
if (i < MIC_BULK_MAX) {
|
||||
aec_hdl->in_bulk[i].addr = buf;
|
||||
aec_hdl->in_bulk[i].used = 0x55;
|
||||
aec_hdl->in_bulk[i].len = len;
|
||||
list_add_tail(&aec_hdl->in_bulk[i].entry, &aec_hdl->in_head);
|
||||
} else {
|
||||
printf(">>>aec_in_full\n");
|
||||
/*align reset*/
|
||||
struct mic_bulk *bulk;
|
||||
list_for_each_entry(bulk, &aec_hdl->in_head, entry) {
|
||||
bulk->used = 0;
|
||||
__list_del_entry(&bulk->entry);
|
||||
}
|
||||
return;
|
||||
}
|
||||
os_sem_set(&aec_hdl->sem, 0);
|
||||
os_sem_post(&aec_hdl->sem);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Input Reference
|
||||
* Description: AEC源参考数据输入
|
||||
* Arguments : buf 输入源数据地址
|
||||
* len 输入源数据长度
|
||||
* Return : None.
|
||||
* Note(s) : 双mic ENC的参考mic数据输入,单mic的无须调用该接口
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_inbuf_ref(s16 *buf, u16 len)
|
||||
{
|
||||
if (aec_hdl && aec_hdl->start) {
|
||||
int i = 0;
|
||||
for (i = 0; i < MIC_BULK_MAX; i++) {
|
||||
if (aec_hdl->inref_bulk[i].used == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < MIC_BULK_MAX) {
|
||||
aec_hdl->inref_bulk[i].addr = buf;
|
||||
aec_hdl->inref_bulk[i].used = 0x55;
|
||||
aec_hdl->inref_bulk[i].len = len;
|
||||
list_add_tail(&aec_hdl->inref_bulk[i].entry, &aec_hdl->inref_head);
|
||||
} else {
|
||||
printf(">>>aec_inref_full\n");
|
||||
/*align reset*/
|
||||
struct mic_bulk *bulk;
|
||||
list_for_each_entry(bulk, &aec_hdl->inref_head, entry) {
|
||||
bulk->used = 0;
|
||||
__list_del_entry(&bulk->entry);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Input Reference
|
||||
* Description: AEC源参考数据输入
|
||||
* Arguments : buf 输入源数据地址
|
||||
* len 输入源数据长度
|
||||
* Return : None.
|
||||
* Note(s) : 双mic ENC的参考mic数据输入,单mic的无须调用该接口
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_inbuf_ref_1(s16 *buf, u16 len)
|
||||
{
|
||||
if (aec_hdl && aec_hdl->start) {
|
||||
int i = 0;
|
||||
for (i = 0; i < MIC_BULK_MAX; i++) {
|
||||
if (aec_hdl->inref_1_bulk[i].used == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < MIC_BULK_MAX) {
|
||||
aec_hdl->inref_1_bulk[i].addr = buf;
|
||||
aec_hdl->inref_1_bulk[i].used = 0x55;
|
||||
aec_hdl->inref_1_bulk[i].len = len;
|
||||
list_add_tail(&aec_hdl->inref_1_bulk[i].entry, &aec_hdl->inref_1_head);
|
||||
} else {
|
||||
printf(">>>aec_inref_1_full\n");
|
||||
/*align reset*/
|
||||
struct mic_bulk *bulk;
|
||||
list_for_each_entry(bulk, &aec_hdl->inref_1_head, entry) {
|
||||
bulk->used = 0;
|
||||
__list_del_entry(&bulk->entry);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Reference
|
||||
* Description: AEC模块参考数据输入
|
||||
* Arguments : buf 输入参考数据地址
|
||||
* len 输入参考数据长度
|
||||
* Return : None.
|
||||
* Note(s) : 声卡设备是DAC,默认不用外部提供参考数据
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_refbuf(s16 *buf, u16 len)
|
||||
{
|
||||
if (aec_hdl && aec_hdl->start) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Output Sel
|
||||
* Description: AEC输出数据选择
|
||||
* Arguments : sel 选择输出/算法输出/talk/ff/fb原始数据
|
||||
* agc NULL
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_aec_output_sel(CVP_OUTPUT_ENUM sel, u8 agc)
|
||||
{
|
||||
if (aec_hdl) {
|
||||
aec_hdl->output_sel = sel;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio AEC Toggle Set
|
||||
* Description: AEC模块算法开关使能
|
||||
* Arguments : toggle 0 关闭算法 1 打开算法
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_aec_toggle_set(u8 toggle)
|
||||
{
|
||||
if (aec_hdl) {
|
||||
aec_hdl->output_sel = (toggle) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*TCFG_CVP_DEVELOP_ENABLE*/
|
||||
Reference in New Issue
Block a user