This commit is contained in:
lmx
2025-10-29 13:10:02 +08:00
commit 49a07fa419
2284 changed files with 642060 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View 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*/

View 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*/

File diff suppressed because it is too large Load Diff

View 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

View 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_*/

File diff suppressed because it is too large Load Diff

View 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*/