#include "system/includes.h" #include "app_config.h" #include "audio_config.h" #include "aec_user.h" #include "media/includes.h" #include "commproc.h" #include "application/audio_eq_drc_apply.h" #include "circular_buf.h" #include "clock_cfg.h" #define LOG_TAG_CONST AEC_USER #define LOG_TAG "[AEC_USER]" #define LOG_ERROR_ENABLE #define LOG_DEBUG_ENABLE #define LOG_INFO_ENABLE /* #define LOG_DUMP_ENABLE */ #define LOG_CLI_ENABLE #include "debug.h" #define AEC_USER_MALLOC_ENABLE 1 #if (TCFG_AEC_ENABLE) #define AEC_TOGGLE 1 #else #define AEC_TOGGLE 0 #endif #if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DONGLE) #undef AEC_TOGGLE #define AEC_TOGGLE 0 #endif #if (TCFG_EQ_ENABLE == 1) #define AEC_DCCS_EN 1 /*mic去直流滤波eq*/ #define AEC_UL_EQ_EN 1 /*mic 普通eq*/ #else #define AEC_DCCS_EN 0 #define AEC_UL_EQ_EN 0 #endif #ifdef CONFIG_FPGA_ENABLE const u8 CONST_AEC_ENABLE = 0; #else const u8 CONST_AEC_ENABLE = 1; #endif /*ANS模式:0 or 1*/ u8 CONST_ANS_MODE = 1; /*丢包修复使能*/ const u8 CONST_PLC_ENABLE = 0; /*通话dac限幅器*/ const int CONST_SOFT_LIMITER = 0;/*-12000 = -12dB,放大1000倍,(-24000参考)*/ #if TCFG_AEC_SIMPLEX /*限幅器-噪声门限*/ const int CONST_NOISE_LIMITER = 1;/*使能*/ const u8 CONST_AEC_SIMPLEX = 1; #else /*限幅器-噪声门限*/ const int CONST_NOISE_LIMITER = 0;/*使能*/ const u8 CONST_AEC_SIMPLEX = 0; #endif /* *延时估计使能 *点烟器/单工模式需要做延时估计 *其他的暂时不需要做 */ #if ((AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) || TCFG_AEC_SIMPLEX) const u8 CONST_AEC_DLY_EST = 1; #else const u8 CONST_AEC_DLY_EST = 0; #endif //////////////////Simplex Parameters(单工调试参数)///////////////////// /*单工连续清0的帧数*/ #define AEC_SIMPLEX_TAIL 15 /* *远端数据大于CONST_AEC_SIMPLEX_THR,即清零近端数据 *越小,回音限制得越好,同时也就越容易卡 */ #define AEC_SIMPLEX_THR 100000 /*default:260000*/ /* *数据输出开头丢掉的数据包数 */ #define AEC_OUT_DUMP_PACKET 10 /* *数据输出开头丢掉的数据包数 */ #define AEC_IN_DUMP_PACKET 1 //////////////////AEC Parameters(通话回声调试参数)///////////////////// /*aec mode select:AEC_MODE_REDUCE or AEC_MODE_ADVANCE */ #define AEC_MODULE_BIT AEC_MODE_ADVANCE /*NLP parameters*/ #define NLP_AGGRESS_FACTOR 4.f /*range:0~35*/ #define NLP_SUPPRESS_FACTOR 5.f /*range:0~10*/ //////////////////////////= EDN =////////////////////////////////////// /* *复用lmp rx buf(一般通话的时候复用) */ //rx_buf概率产生碎片,导致alloc失败,因此默认配0 #define MALLOC_MULTIPLEX_EN 0 extern void *lmp_malloc(int); extern void lmp_free(void *); void *zalloc_mux(int size) { #if MALLOC_MULTIPLEX_EN void *p = NULL; void bredr_rx_bulk_state(); bredr_rx_bulk_state(); do { p = lmp_malloc(size); if (p) { break; } printf("aec_malloc wait...\n"); os_time_dly(2); } while (1); if (p) { memset(p, 0, size); } y_printf("[malloc_mux]p = 0x%x,size = %d\n", p, size); return p; #else return zalloc(size); #endif } void free_mux(void *p) { #if MALLOC_MULTIPLEX_EN y_printf("[free_mux]p = 0x%x\n", p); lmp_free(p); #else free(p); #endif } void aec_param_dump(struct aec_s_attr *param) { log_info("===========dump aec param==================\n"); log_info("toggle:%d\n", param->toggle); log_info("EnableBit:%x\n", param->EnableBit); log_info("ul_eq_en:%x\n", param->ul_eq_en); //log_info("AGC_fade:%d\n", (int)(param->AGC_gain_step * 100)); log_info("AGC_NDT_max_gain:%d\n", (int)(param->AGC_NDT_max_gain * 100)); log_info("AGC_NDT_min_gain:%d\n", (int)(param->AGC_NDT_min_gain * 100)); log_info("AGC_NDT_speech_thr:%d\n", (int)(param->AGC_NDT_speech_thr * 100)); log_info("AGC_DT_max_gain:%d\n", (int)(param->AGC_DT_max_gain * 100)); log_info("AGC_DT_min_gain:%d\n", (int)(param->AGC_DT_min_gain * 100)); log_info("AGC_DT_speech_thr:%d\n", (int)(param->AGC_DT_speech_thr * 100)); log_info("AGC_echo_present_thr:%d\n", (int)(param->AGC_echo_present_thr * 100)); log_info("AEC_DT_AggressiveFactor:%d\n", (int)(param->AEC_DT_AggressiveFactor * 100)); log_info("AEC_RefEngThr:%d\n", (int)(param->AEC_RefEngThr * 100)); log_info("ES_AggressFactor:%d\n", (int)(param->ES_AggressFactor * 100)); log_info("ES_MinSuppress:%d\n", (int)(param->ES_MinSuppress * 100)); log_info("ANS_AggressFactor:%d\n", (int)(param->ANS_AggressFactor * 100)); log_info("ANS_MinSuppress:%d\n", (int)(param->ANS_MinSuppress * 100)); log_info("=================END=======================\n"); } void aec_cfg_fill(AEC_CONFIG *cfg) { } struct audio_aec_hdl { u8 start; u8 inbuf_clear_cnt; u8 output_fade_in; u8 output_fade_in_gain; #if AEC_UL_EQ_EN struct audio_eq *ul_eq; /* struct hw_eq_ch ul_eq_ch; */ #endif #if AEC_DCCS_EN struct audio_eq *dccs_eq; /* struct hw_eq_ch dccs_eq_ch; */ #endif u16 dump_packet;/*前面如果有杂音,丢掉几包*/ u8 output_buf[1000]; cbuffer_t output_cbuf; struct aec_s_attr attr; }; #if AEC_USER_MALLOC_ENABLE struct audio_aec_hdl *aec_hdl = NULL; #else struct audio_aec_hdl aec_handle; #endif void audio_aec_ref_start(u8 en) { if (aec_hdl) { if (en != aec_hdl->attr.fm_tx_start) { aec_hdl->attr.fm_tx_start = en; y_printf("fm_tx_start:%d\n", en); } } } #if AEC_DCCS_EN const int DCCS_8k_Coeff[5] = { (943718 << 2), -(856687 << 2), (1048576 << 2), (1887437 << 2), -(2097152 << 2) }; const int DCCS_16k_Coeff[5] = { (1006633 << 2), -(967542 << 2), (1048576 << 2), (2013266 << 2), -(2097152 << 2) }; int aec_dccs_eq_filter(struct audio_eq *eq, int sr, struct audio_eq_filter_info *info) { //r_printf("dccs_eq sr:%d\n", sr); if (sr == 16000) { info->L_coeff = (void *)DCCS_16k_Coeff; info->R_coeff = (void *)DCCS_16k_Coeff; } else { info->L_coeff = (void *)DCCS_8k_Coeff; info->R_coeff = (void *)DCCS_8k_Coeff; } info->L_gain = 0; info->R_gain = 0; info->nsection = 1; return 0; } static int dccs_eq_output(void *priv, void *data, u32 len) { return 0; } #endif/*AEC_DCCS_EN*/ #if AEC_UL_EQ_EN static int ul_eq_output(void *priv, void *data, u32 len) { return 0; } #endif/*AEC_UL_EQ_EN*/ static int audio_aec_probe(s16 *data, u16 len) { #if AEC_DCCS_EN if (aec_hdl->dccs_eq) { audio_eq_run(aec_hdl->dccs_eq, data, len); } #endif/*AEC_DCCS_EN*/ return 0; } static int audio_aec_post(s16 *data, u16 len) { #if AEC_UL_EQ_EN if (aec_hdl->ul_eq) { audio_eq_run(aec_hdl->ul_eq, data, len); } #endif/*AEC_UL_EQ_EN*/ return 0; } extern void esco_enc_resume(void); static int audio_aec_output(s16 *data, u16 len) { 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; } } } u16 wlen = cbuf_write(&aec_hdl->output_cbuf, data, len); //printf("wlen:%d-%d\n",len,aec_hdl.output_cbuf.data_len); esco_enc_resume(); #if 1 static u32 aec_output_max = 0; if (aec_output_max < aec_hdl->output_cbuf.data_len) { aec_output_max = aec_hdl->output_cbuf.data_len; y_printf("o_max:%d", aec_output_max); } #endif if (wlen != len) { putchar('F'); } return wlen; } 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; } static void audio_aec_param_read_config(struct aec_s_attr *p) { AEC_CONFIG cfg; int ret = syscfg_read(CFG_AEC_ID, &cfg, sizeof(AEC_CONFIG)); if (ret == sizeof(AEC_CONFIG)) { log_info("audio_aec read config ok\n"); p->AGC_NDT_fade_in_step = cfg.ndt_fade_in; p->AGC_NDT_fade_out_step = cfg.ndt_fade_out; p->AGC_DT_fade_in_step = cfg.dt_fade_in; p->AGC_DT_fade_out_step = cfg.dt_fade_out; p->AGC_NDT_max_gain = cfg.ndt_max_gain; p->AGC_NDT_min_gain = cfg.ndt_min_gain; p->AGC_NDT_speech_thr = cfg.ndt_speech_thr; p->AGC_DT_max_gain = cfg.dt_max_gain; p->AGC_DT_min_gain = cfg.dt_min_gain; p->AGC_DT_speech_thr = cfg.dt_speech_thr; p->AGC_echo_present_thr = cfg.echo_present_thr; p->AEC_DT_AggressiveFactor = cfg.aec_dt_aggress; p->AEC_RefEngThr = cfg.aec_refengthr; p->ES_AggressFactor = cfg.es_aggress_factor; p->ES_MinSuppress = cfg.es_min_suppress; p->ES_Unconverge_OverDrive = cfg.es_min_suppress; p->ANS_AggressFactor = cfg.ans_aggress; p->ANS_MinSuppress = cfg.ans_suppress; if (cfg.aec_mode == 0) { p->toggle = 0; p->EnableBit = 0; } else if (cfg.aec_mode == 1) { p->toggle = 1; p->EnableBit = AEC_MODE_REDUCE; } else if (cfg.aec_mode == 2) { p->toggle = 1; p->EnableBit = AEC_MODE_ADVANCE; } p->ul_eq_en = cfg.ul_eq_en; //aec_param_dump(p); } else { log_error("read audio_aec param err:%x", ret); } } extern struct adc_platform_data adc_data; /* *enablebit >= 0:使用enablebit设置aec模块使能 * 其他:使用读配置 *out_hdl: 自定义回调函数,NULL则用默认回调 */ int audio_aec_open(u16 sample_rate, s16 enablebit, int (*out_hdl)(s16 *data, u16 len)) { struct aec_s_attr *aec_param; #if AEC_USER_MALLOC_ENABLE aec_hdl = zalloc(sizeof(struct audio_aec_hdl)); if (aec_hdl == NULL) { log_error("aec_hdl malloc failed"); return -ENOMEM; } #else aec_hdl = &aec_handle; #endif/*AEC_USER_MALLOC_ENABLE*/ cbuf_init(&aec_hdl->output_cbuf, aec_hdl->output_buf, sizeof(aec_hdl->output_buf)); aec_hdl->start = 1; aec_hdl->dump_packet = AEC_OUT_DUMP_PACKET; aec_hdl->inbuf_clear_cnt = AEC_IN_DUMP_PACKET; aec_hdl->output_fade_in = 1; aec_hdl->output_fade_in_gain = 0; aec_param = &aec_hdl->attr; #if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC) aec_param->output_way = 0; #elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) aec_param->output_way = 1; #endif aec_param->toggle = 1; aec_param->EnableBit = AEC_MODULE_BIT; aec_param->agc_en = 1; aec_param->wideband = 0; aec_param->ul_eq_en = 1; aec_param->packet_dump = 50;/*0~255(u8)*/ aec_param->AGC_NDT_fade_in_step = 1.3f; aec_param->AGC_NDT_fade_out_step = 0.9f; aec_param->AGC_DT_fade_in_step = 1.3f; aec_param->AGC_DT_fade_out_step = 0.9f; aec_param->AGC_NDT_max_gain = 12.f; aec_param->AGC_NDT_min_gain = 0.f; aec_param->AGC_NDT_speech_thr = -50.f; aec_param->AGC_DT_max_gain = 12.f; aec_param->AGC_DT_min_gain = 0.f; aec_param->AGC_DT_speech_thr = -40.f; aec_param->AGC_echo_look_ahead = 0; aec_param->AGC_echo_present_thr = -70.f; aec_param->AGC_echo_hold = 400; /*AEC*/ aec_param->AEC_DT_AggressiveFactor = 1.f; /*范围:1~5,越大追踪越好,但会不稳定,如破音*/ aec_param->AEC_RefEngThr = -70.f; /*范围:-90 ~ -60 dB*/ /*ES*/ aec_param->ES_AggressFactor = -3.0f; /*范围:-1 ~ -5*/ aec_param->ES_MinSuppress = 4.f; /*范围:0 ~ 10*/ aec_param->ES_Unconverge_OverDrive = aec_param->ES_MinSuppress; /*ANS*/ aec_param->ANS_mode = 1; aec_param->ANS_AggressFactor = 1.25f; /*范围:1~2,动态调整,越大越强(1.25f)*/ aec_param->ANS_MinSuppress = 0.04f; /*范围:0~1,静态定死最小调整,越小越强(0.09f)*/ aec_param->ANS_NoiseLevel = 2.2e4f; #if TCFG_AEC_SIMPLEX aec_param->wn_en = 1; #else aec_param->wn_en = 0; #endif aec_param->wn_gain = 331; //aec_param->EchoSupressRateThr = 0.05f;/*范围:0.01f~0.05f*/ aec_param->SimplexTail = AEC_SIMPLEX_TAIL; aec_param->SimplexThr = AEC_SIMPLEX_THR; #if ((AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) || (TCFG_AEC_SIMPLEX)) aec_param->dly_est = 1; #else aec_param->dly_est = 0; #endif aec_param->dst_delay = 50; aec_param->aec_probe = audio_aec_probe; aec_param->aec_post = audio_aec_post; aec_param->output_handle = audio_aec_output; audio_aec_param_read_config(aec_param); if (enablebit >= 0) { aec_param->EnableBit = enablebit; } if (out_hdl) { aec_param->output_handle = out_hdl; } #if TCFG_AEC_SIMPLEX aec_param->EnableBit = AEC_MODE_SIMPLEX; if (sample_rate == 8000) { aec_param->wideband = 0; aec_param->hw_delay_offset = 75; aec_param->SimplexTail = aec_param->SimplexTail / 2; clock_add(AEC8K_SPX_CLK); } else { aec_param->wideband = 1; aec_param->hw_delay_offset = 50; clock_add(AEC16K_SPX_CLK); } if (aec_param->dly_est == 0) { aec_param->dst_delay = 30; } //printf("aec SimplexMode\n"); #else if (sample_rate == 16000) { aec_param->wideband = 1; aec_param->hw_delay_offset = 50; if (aec_param->EnableBit == AEC_MODE_ADVANCE) { clock_add(AEC16K_ADV_CLK); } else { clock_add(AEC16K_CLK); } } else { aec_param->wideband = 0; aec_param->hw_delay_offset = 75; if (aec_param->EnableBit == AEC_MODE_ADVANCE) { clock_add(AEC8K_ADV_CLK); } else { clock_add(AEC8K_CLK); } } #endif/*TCFG_AEC_SIMPLEX*/ #if AEC_UL_EQ_EN if (aec_param->ul_eq_en) { /* memset(&aec_hdl->ul_eq, 0, sizeof(struct audio_eq)); */ /* memset(&aec_hdl->ul_eq_ch, 0, sizeof(struct hw_eq_ch)); */ /* aec_hdl->ul_eq.eq_ch = &aec_hdl->ul_eq_ch; */ 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); /* audio_eq_open(&aec_hdl->ul_eq, &ul_eq_param); */ /* audio_eq_set_samplerate(&aec_hdl->ul_eq, sample_rate); */ /* audio_eq_set_output_handle(&aec_hdl->ul_eq, ul_eq_output, NULL); */ /* audio_eq_start(&aec_hdl->ul_eq); */ } #endif/*AEC_UL_EQ_EN*/ #if AEC_DCCS_EN if (adc_data.mic_capless) { /* memset(&aec_hdl->dccs_eq, 0, sizeof(struct audio_eq)); */ /* memset(&aec_hdl->dccs_eq_ch, 0, sizeof(struct hw_eq_ch)); */ /* .eq_ch = &aec_hdl->dccs_eq_ch; */ struct audio_eq_param dccs_eq_param = {0}; dccs_eq_param.sr = sample_rate; dccs_eq_param.channels = 1; dccs_eq_param.online_en = 0; dccs_eq_param.mode_en = 0; dccs_eq_param.remain_en = 0; dccs_eq_param.max_nsection = EQ_SECTION_MAX; dccs_eq_param.cb = aec_dccs_eq_filter; aec_hdl->dccs_eq = audio_dec_eq_open(&dccs_eq_param); /* audio_eq_open(&aec_hdl->dccs_eq, &dccs_eq_param); */ /* audio_eq_set_samplerate(&aec_hdl->dccs_eq, sample_rate); */ /* audio_eq_set_output_handle(&aec_hdl->dccs_eq, dccs_eq_output, NULL); */ /* audio_eq_start(&aec_hdl->dccs_eq); */ } #endif/*AEC_DCCS_EN*/ //aec_param->toggle = 1; //aec_param->EnableBit = AEC_MODULE_BIT; //aec_param_dump(aec_param); #if AEC_TOGGLE aec_init(aec_param); #endif return 0; } int audio_aec_init(u16 sample_rate) { return audio_aec_open(sample_rate, -1, NULL); } void audio_aec_close(void) { printf("audio_aec_close:%x", aec_hdl); struct aec_s_attr *aec_param; if (aec_hdl) { aec_hdl->start = 0; aec_param = &aec_hdl->attr; #if TCFG_AEC_SIMPLEX if (aec_param->wideband) { clock_remove(AEC16K_SPX_CLK); } else { clock_remove(AEC8K_SPX_CLK); } #else if (aec_param->wideband) { if (aec_param->EnableBit == AEC_MODE_ADVANCE) { clock_remove(AEC16K_ADV_CLK); } else { clock_remove(AEC16K_CLK); } } else { if (aec_param->EnableBit == AEC_MODE_ADVANCE) { clock_remove(AEC8K_ADV_CLK); } else { clock_remove(AEC8K_CLK); } } #endif/*TCFG_AEC_SIMPLEX*/ #if AEC_TOGGLE aec_exit(); #endif/*AEC_TOGGLE*/ #if AEC_DCCS_EN if (aec_hdl->dccs_eq) { audio_dec_eq_close(aec_hdl->dccs_eq); } #endif/*AEC_DCCS_EN*/ #if AEC_UL_EQ_EN if (aec_hdl->ul_eq) { audio_dec_eq_close(aec_hdl->ul_eq); } #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(); } } void audio_aec_inbuf(s16 *buf, u16 len) { if (aec_hdl && aec_hdl->start) { #if AEC_TOGGLE if (aec_hdl->inbuf_clear_cnt) { aec_hdl->inbuf_clear_cnt--; memset(buf, 0, len); } int ret = aec_fill_in_data(buf, len); if (ret == -1) { #if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC) /* log_info("fill dac data\n"); u8 tmp_buf[64] = {0}; for (u8 i = 0; i < 512 / sizeof(tmp_buf); i++) { app_audio_output_write(tmp_buf, sizeof(tmp_buf)); } */ #endif } else if (ret == -2) { log_error("aec inbuf full\n"); } #else if (aec_hdl->attr.output_handle) { aec_hdl->attr.output_handle(buf, len); /* audio_aec_output(buf, len); */ } else { log_error("audio aec no init\n"); } #endif/*AEC_TOGGLE*/ } } void audio_aec_refbuf(s16 *buf, u16 len) { if (aec_hdl && aec_hdl->start) { #if AEC_TOGGLE aec_fill_ref_data(buf, len); #endif/*AEC_TOGGLE*/ } } int audio_aec_refbuf_data_len() { if (aec_hdl && aec_hdl->start) { #if AEC_TOGGLE //aec_ref_total_len(); //aec_ref_data_len(); #endif/*AEC_TOGGLE*/ } return 0; } /* void aec_estimate_dump(int DlyEst) { printf("DlyEst:%d\n",DlyEst); } */ /******************************************************** * * aec parameters debug online * *******************************************************/ #if AEC_DEBUG_ONLINE #include "string.h" #include "asm/crc16.h" #include "app_main.h" enum { AEC_MIC_AGAIN = 0u, AEC_DAC_AGAIN , AEC_NDT_MAX_GAIN , AEC_NDT_MIN_GAIN , AEC_NDT_FADE_SPEED , AEC_NEAREND_THR , AEC_NLP_AGGRESS , AEC_NLP_SUPPRESS , AEC_MODE ,/*0:disable,1:REDUCE,2:ADVANCE*/ AEC_UL_EQ , /*0:disable,1:enable*/ }; struct _AEC_ONLINE { char tag[4];/*AEC:0x41 0x45 0x43 0x00 */ u16 crc; /*crc = crc16(len+cmd+data) */ u16 len; /*data length */ u16 cmd; /*cmd index */ s32 data; /*cmd value */ } __attribute__((packed)); typedef struct _AEC_ONLINE AEC_ONLINE; AEC_ONLINE aec_online; void aec_param_deal(u16 cmd, s32 data) { //log_info(">>>>aec cmd:%d \t data:%d\n", cmd, data); switch (cmd) { case AEC_MIC_AGAIN: app_var.aec_mic_gain = (u16)data; log_info("aec_mic:%d\n", app_var.aec_mic_gain); break; case AEC_DAC_AGAIN: app_var.aec_dac_gain = (u16)data; log_info("aec_dac:%d\n", app_var.aec_dac_gain); break; case AEC_NDT_MAX_GAIN: aec_param.AGC_max_gain = (u16)data; log_info("aec_max_gain:%d\n", aec_param.AGC_max_gain); break; case AEC_NDT_MIN_GAIN: aec_param.AGC_min_gain = (u16)data; log_info("aec_min_gain:%d\n", aec_param.AGC_min_gain); break; case AEC_NDT_FADE_SPEED: aec_param.AGC_fade = (u16)data; log_info("aec_fade_speed:%d\n", aec_param.AGC_fade); break; case AEC_NEAREND_THR: aec_param.AGC_threshold = (u16)data; log_info("aec_neadend_thr:%d\n", aec_param.AGC_threshold); break; case AEC_NLP_AGGRESS: memcpy(&aec_param.ES_AggressFactor, &data, sizeof(float)); aec_param.ES_AggressFactor = -aec_param.ES_AggressFactor; log_info("Aggress:%d\n", (int)aec_param.ES_AggressFactor); break; case AEC_NLP_SUPPRESS: //memcpy(&aec_param.ES_MinSuppress, &data, sizeof(float)); //log_info("Suppress:%d\n", (int)aec_param.ES_MinSuppress); break; case AEC_MODE: /*0:disable,1:REDUCE,2:ADVANCE*/ if (data == 0) { log_info("aec_mode:OFF\n"); aec_param.toggle = 0; } else if (data == 1) { log_info("aec_mode:REDUCE\n"); aec_param.toggle = 1; aec_param.EnableBit = AEC_MODE_REDUCE; } else if (data == 2) { log_info("aec_mode:ADVANCE\n"); aec_param.toggle = 1; aec_param.EnableBit = AEC_MODE_ADVANCE; } break; case AEC_UL_EQ: aec_param.ul_eq_en = (u8)data; log_info("aec_ul_eq:%d\n", aec_param.ul_eq_en); break; default: log_info("unknown AEC cmd\n"); break; } } #include "tone_player.h" s8 aec_debug_online(void *buf, u16 size) { log_info("AEC_rx:%d\n", size); log_info_hexdump(buf, size); memcpy(&aec_online, buf, sizeof(AEC_ONLINE)); if (strcmp(aec_online.tag, "AEC") == 0) { if (aec_online.crc == CRC16(&aec_online.len, aec_online.len + sizeof(aec_online.len))) { log_info("aec_online OK\n"); aec_param_deal(aec_online.cmd, aec_online.data); tone_play_by_path(tone_table[IDEX_TONE_NORMAL], 1); return 0; } else { log_info("aec_online ERROR\n"); return -1; } } else { log_info("unknown data\n"); return -1; } } #endif