Files
99_7018_lmx/cpu/br28/audio_anc.c

3529 lines
129 KiB
C
Raw Normal View History

2025-10-29 13:10:02 +08:00
/*
****************************************************************
* AUDIO ANC
* File : audio_anc.c
* By :
* Notes : ref_mic = mic
* err_mic = mic
*
****************************************************************
*/
#include "system/includes.h"
#include "audio_anc.h"
#include "system/task.h"
#include "timer.h"
#include "asm/clock.h"
#include "asm/power/p33.h"
#include "online_db_deal.h"
#include "app_config.h"
#include "tone_player.h"
#include "audio_adc.h"
#include "audio_enc.h"
#include "asm/dac.h"
#include "audio_anc_coeff.h"
#include "btstack/avctp_user.h"
#include "app_main.h"
#include "audio_decoder.h"
#include "adv_adaptive_noise_reduction.h"
#include "audio_codec_clock.h"
#if ANC_MUSIC_DYNAMIC_GAIN_EN
#include "amplitude_statistic.h"
#endif/*ANC_MUSIC_DYNAMIC_GAIN_EN*/
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
#include "icsd_adt.h"
#include "icsd_adt_app.h"
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
#if TCFG_USER_TWS_ENABLE
#include "bt_tws.h"
#endif/*TCFG_USER_TWS_ENABLE*/
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".anc_user_bss")
#pragma data_seg(".anc_user_data")
#pragma const_seg(".anc_user_const")
#pragma code_seg(".anc_user_code")
#endif/*SUPPORT_MS_EXTENSIONS*/
#define AT_VOLATILE_RAM_CODE AT(.volatile_ram_code)
#if INEAR_ANC_UI
extern u8 inear_tws_ancmode;
#endif/*INEAR_ANC_UI*/
#if TCFG_AUDIO_ANC_ENABLE
#if 1
#define user_anc_log printf
#else
#define user_anc_log(...)
#endif/*log_en*/
/*************************ANC增益配置******************************/
#define ANC_DAC_GAIN 13 //ANC Speaker增益
#define ANC_REF_MIC_GAIN 8 //ANC参考Mic增益
#define ANC_ERR_MIC_GAIN 8 //ANC误差Mic增益
#define ANC_FADE_GAIN_DEFAULT 16384 //ANC默认淡入淡出增益16384 = 0dB
/*****************************************************************/
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
const u8 CONST_ANC_ADT_EN = 1;
#else
const u8 CONST_ANC_ADT_EN = 0;
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
#if ANC_EAR_ADAPTIVE_EN
const u8 CONST_ANC_EAR_ADAPTIVE_EN = 1;
#else
const u8 CONST_ANC_EAR_ADAPTIVE_EN = 0;
#endif/*ANC_EAR_ADAPTIVE_EN*/
#if TCFG_ANC_SELF_DUT_GET_SZ
const u8 CONST_ANC_DUT_SZ_EN = 1;
#else
const u8 CONST_ANC_DUT_SZ_EN = 0;
#endif/*TCFG_ANC_SELF_DUT_GET_SZ*/
#if ANC_ADAPTIVE_EN
/*自适应增益等级系数表*/
anc_adap_param_t anc_adap_param[] = {
{
.pow_thr = 0XFFFFFFFF, //当前等级能量高阈值
.default_flag = 1, //默认等级标志
.trigger_cnt = 20, //当前等级检测时间*500ms */
.gain = 1024, //当前等级对应增益 */
.fade_lvl = 10, //当前等级增益淡入时间*100ms */
/*
MIC模拟增益为4, 1.259,
MIC模拟增益为3, = 500*(1.259^(3-4)) = 397
MIC模拟增益为6, = 500*(1.259^(6-4)) = 792
*/
.pow_lthr = 700, //当前等级能量低阈值
},
{
.pow_thr = 200, //此阈值对应模拟增益为4,计算方法如上
.trigger_cnt = 20,
.gain = 350,
.fade_lvl = 10,
.pow_lthr = 0,
},
};
void audio_anc_pow_adap_fade(u16 gain);
#endif/*ANC_ADAPTIVE_EN*/
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
float anc_trans_lfb_gain = 0.0625f;
float anc_trans_rfb_gain = 0.0625f;
const double anc_trans_lfb_coeff[] = {
0.195234751212410628795623779296875,
0.1007948522455990314483642578125,
0.0427739980514161288738250732421875,
-1.02504855208098888397216796875,
0.36385215423069894313812255859375,
/*
0.0508266850956715643405914306640625,
-0.1013386586564593017101287841796875,
0.0505129448720254004001617431640625,
-1.99860572628676891326904296875,
0.9986066981218755245208740234375,
*/
};
const double anc_trans_rfb_coeff[] = {
0.195234751212410628795623779296875,
0.1007948522455990314483642578125,
0.0427739980514161288738250732421875,
-1.02504855208098888397216796875,
0.36385215423069894313812255859375,
};
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
static void anc_mix_out_audio_drc_thr(float thr);
static void anc_fade_in_timeout(void *arg);
static void anc_mode_switch_deal(u8 mode);
static void anc_timer_deal(void *priv);
static int anc_app_online_parse(u8 *packet, u8 size, u8 *ext_data, u16 ext_size);
static anc_coeff_t *anc_cfg_test(u8 coeff_en, u8 gains_en);
static void anc_fade_in_timer_add(audio_anc_t *param);
static void audio_anc_adap_tone_play(int ref_lvl, int err_lvl);
void anc_dmic_io_init(audio_anc_t *param, u8 en);
u8 anc_btspp_train_again(u8 mode, u32 dat);
static void anc_tone_play_and_mode_switch(u8 index, u8 preemption, u8 cb_sel);
void anc_mode_enable_set(u8 mode_enable);
void audio_anc_post_msg_drc(void);
void audio_anc_post_msg_debug(void);
void audio_anc_post_msg_user_train_run(void);
void audio_anc_adc_ch_set(void);
void audio_anc_music_dynamic_gain_process(void);
static void audio_anc_sz_fft_dac_check_slience_cb(void *buf, int len);
void audio_anc_post_msg_sz_fft_run(void);
#if ANC_EAR_ADAPTIVE_EN
int audio_anc_adaptive_data_save(anc_adaptive_iir_t *iir);
int audio_anc_adaptive_data_read(anc_adaptive_iir_t *iir);
void audio_anc_ear_adaptive_param_init(audio_anc_t *param);
void audio_anc_param_map(u8 coeff_en, u8 gain_en);
void audio_anc_adaptive_poweron_catch_data(anc_adaptive_iir_t *iir);
void audio_anc_adaptive_data_format(anc_adaptive_iir_t *iir);
#endif/*ANC_EAR_ADAPTIVE_EN*/
extern u8 bt_phone_dec_is_running();
extern u8 bt_media_is_running(void);
extern void anc_user_train_tone_play_cb();
extern void esco_adc_mic_set_buffs(void);
#define ESCO_MIC_DUMP_CNT 10
extern void esco_mic_dump_set(u16 dump_cnt);
extern struct audio_dac_hdl dac_hdl;
typedef struct {
u8 mode_num; /*模式总数*/
u8 mode_enable; /*使能的模式*/
u8 anc_parse_seq;
u8 suspend; /*挂起*/
u8 ui_mode_sel; /*ui菜单降噪模式选择*/
u8 new_mode; /*记录模式切换最新的目标模式*/
u8 last_mode; /*记录模式切换的上一个模式*/
u8 mic_dy_state; /*动态MIC增益状态*/
char mic_diff_gain; /*动态MIC增益差值*/
u16 scene_id; /*多场景滤波器-场景ID*/
u8 scene_max; /*多场景滤波器-最大场景个数*/
u16 ui_mode_sel_timer;
u16 fade_in_timer;
u16 fade_gain;
u16 mic_resume_timer; /*动态MIC增益恢复定时器id*/
float drc_ratio; /*动态MIC增益对应DRC增益比例*/
volatile u8 state; /*ANC状态*/
volatile u8 mode_switch_lock; /*切模式锁存1表示正在切ANC模式*/
volatile u8 sync_busy;
audio_anc_t param; /*ANC lib句柄*/
audio_adc_mic_mana_t dy_mic_param[4]; /*MIC动态增益参数管理*/
#if ANC_EAR_ADAPTIVE_EN
u8 ear_adaptive_tws_sync; /*耳道自适应-左右耳平衡使能*/
u8 ear_adaptive_seq;
u8 dac_check_slience_flag; /*耳道自适应-DAC静音检测标志*/
u8 ear_adaptive_data_from; /*耳道自适应-滤波器数据来源*/
u8 ear_adaptive; /*耳道自适应-模式标志*/
u8 ear_adaptive_busy; /*耳道自适应-检测繁忙标记*/
u8 ear_adaptive_dec_wait; /*耳道自适应-音乐播放打断标志*/
int last_sys_clk; /*上一次系统时钟*/
anc_adaptive_iir_t adaptive_iir;/*耳道自适应*/
struct audio_res_wait adaptive_wait; /*耳道自适应解码任务hdl*/
#endif/*ANC_EAR_ADAPTIVE_EN*/
#if ANC_MUSIC_DYNAMIC_GAIN_EN
char loud_dB; /*音乐动态增益-当前音乐幅值*/
s16 loud_nowgain; /*音乐动态增益-当前增益*/
s16 loud_targetgain; /*音乐动态增益-目标增益*/
u16 loud_timeid; /*音乐动态增益-定时器ID*/
LOUDNESS_M_STRUCT loud_hdl; /*音乐动态增益-操作句柄*/
#endif/*ANC_MUSIC_DYNAMIC_GAIN_EN*/
} anc_t;
static anc_t *anc_hdl = NULL;
anc_packet_data_t *anc_adaptive_data = NULL;
const u8 anc_tone_tab[3] = {IDEX_TONE_ANC_OFF, IDEX_TONE_ANC_ON, IDEX_TONE_TRANSPARCNCY};
u32 get_anc_gains_sign()
{
if (anc_hdl) {
return anc_hdl->param.gains.gain_sign;
} else {
return 0;
}
}
u32 get_anc_gains_alogm()
{
if (anc_hdl) {
return anc_hdl->param.gains.alogm;
} else {
return 0;
}
}
u32 get_anc_gains_trans_alogm()
{
if (anc_hdl) {
return anc_hdl->param.gains.trans_alogm;
} else {
return 0;
}
}
void *get_anc_lfb_coeff()
{
if (anc_hdl) {
return anc_hdl->param.lfb_coeff;
} else {
return NULL;
}
}
float get_anc_gains_l_fbgain()
{
if (anc_hdl) {
return anc_hdl->param.gains.l_fbgain;
} else {
return 0;
}
}
u8 get_anc_l_fbyorder()
{
if (anc_hdl) {
return anc_hdl->param.lfb_yorder;
} else {
return 0;
}
}
void *get_anc_lff_coeff()
{
if (anc_hdl) {
printf("anc hdl lff coeff:%x\n", (int)anc_hdl->param.lff_coeff);
return anc_hdl->param.lff_coeff;
} else {
printf("anc hdl NULL~~~~~~~~\n");
return NULL;
}
}
float get_anc_gains_l_ffgain()
{
if (anc_hdl) {
return anc_hdl->param.gains.l_ffgain;
} else {
return 0;
}
}
u8 get_anc_l_ffyorder()
{
if (anc_hdl) {
return anc_hdl->param.lff_yorder;
} else {
return 0;
}
}
void *get_anc_ltrans_coeff()
{
if (anc_hdl) {
return anc_hdl->param.ltrans_coeff;
} else {
return NULL;
}
}
float get_anc_gains_l_transgain()
{
if (anc_hdl) {
return anc_hdl->param.gains.l_transgain;
} else {
return 0;
}
}
u8 get_anc_l_transyorder()
{
if (anc_hdl) {
return anc_hdl->param.ltrans_yorder;
} else {
return 0;
}
}
void *get_anc_ltrans_fb_coeff()
{
if (anc_hdl) {
return anc_hdl->param.ltrans_fb_coeff;
} else {
return NULL;
}
}
float get_anc_gains_lfb_transgain()
{
if (anc_hdl) {
return anc_hdl->param.ltrans_fbgain;
} else {
return 0;
}
}
u8 get_anc_lfb_transyorder()
{
if (anc_hdl) {
return anc_hdl->param.ltrans_fb_yorder;
} else {
return 0;
}
}
void set_anc_adt_state(u8 state)
{
if (anc_hdl) {
anc_hdl->param.adt_state = state;
}
}
static void anc_task(void *p)
{
int res;
int anc_ret = 0;
int msg[16];
u8 speak_to_chat_flag = 0;
u8 adt_flag = 0;
u8 cur_anc_mode;
u32 pend_timeout = portMAX_DELAY;
user_anc_log(">>>ANC TASK<<<\n");
while (1) {
res = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
if (res == OS_TASKQ) {
switch (msg[1]) {
case ANC_MSG_TRAIN_OPEN:/*启动训练模式*/
audio_mic_pwr_ctl(MIC_PWR_ON);
anc_dmic_io_init(&anc_hdl->param, 1);
user_anc_log("ANC_MSG_TRAIN_OPEN");
audio_anc_train(&anc_hdl->param, 1);
os_time_dly(1);
anc_train_close();
audio_mic_pwr_ctl(MIC_PWR_OFF);
break;
case ANC_MSG_TRAIN_CLOSE:/*训练关闭模式*/
user_anc_log("ANC_MSG_TRAIN_CLOSE");
anc_train_close();
break;
case ANC_MSG_RUN:
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
if (anc_hdl->param.gains.trans_alogm != 5) {
ASSERT(0, "ERR!!ANC ADT trans_alogm %d != 5\n", anc_hdl->param.gains.trans_alogm);
}
audio_anc_mode_switch_in_adt(anc_hdl->param.mode);
if (get_adt_open_in_anc_state() && anc_hdl->param.mode == ANC_OFF) {
user_anc_log("[ADT] ANC_MSG_RUN:%s \n", anc_mode_str[anc_hdl->param.mode]);
anc_hdl->param.anc_fade_gain = 0;
anc_hdl->param.mode = ANC_ON;
speak_to_chat_flag = 1;
} else {
anc_hdl->param.anc_fade_gain = 16384;
speak_to_chat_flag = 0;
}
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
cur_anc_mode = anc_hdl->param.mode;/*保存当前anc模式防止切换过程anc_hdl->param.mode发生切换改变*/
#if ANC_MULT_ORDER_ENABLE
if (cur_anc_mode != ANC_OFF) {
#if ANC_EAR_ADAPTIVE_EN
if (anc_hdl->param.anc_coeff_mode == ANC_COEFF_MODE_ADAPTIVE) {
audio_anc_coeff_adaptive_set(ANC_COEFF_MODE_ADAPTIVE, 0, 0);
} else {
anc_mult_scene_set(anc_hdl->scene_id);
}
#else
anc_mult_scene_set(anc_hdl->scene_id);
#endif/*ANC_EAR_ADAPTIVE_EN*/
}
#endif/*ANC_MULT_ORDER_ENABLE*/
user_anc_log("ANC_MSG_RUN:%s \n", anc_mode_str[cur_anc_mode]);
#if ANC_MUSIC_DYNAMIC_GAIN_EN
audio_anc_music_dynamic_gain_reset(0); /*音乐动态增益,切模式复位状态*/
#endif/*ANC_MUSIC_DYNAMIC_GAIN_EN*/
#if TCFG_AUDIO_DYNAMIC_ADC_GAIN
if (anc_hdl->mic_resume_timer) {
sys_timer_del(anc_hdl->mic_resume_timer);
anc_hdl->mic_resume_timer = 0;
}
#endif/*TCFG_AUDIO_DYNAMIC_ADC_GAIN*/
#if (TCFG_AUDIO_ADC_MIC_CHA == LADC_CH_PLNK)
esco_mic_dump_set(ESCO_MIC_DUMP_CNT);
#endif/*LADC_CH_PLNK*/
if (anc_hdl->state == ANC_STA_INIT) {
audio_mic_pwr_ctl(MIC_PWR_ON);
anc_dmic_io_init(&anc_hdl->param, 1);
#if ANC_MODE_SYSVDD_EN
clock_set_lowest_voltage(SYSVDD_VOL_SEL_105V); //进入ANC时提高SYSVDD电压
#endif/*ANC_MODE_SYSVDD_EN*/
anc_ret = audio_anc_run(&anc_hdl->param);
if (anc_ret == 0) {
anc_hdl->state = ANC_STA_OPEN;
} else {
/*
*-EPERM(-1):ANC(MIC使4M的flash)
*-EINVAL(-22):(anc_coeff.bin参数为空, )
*/
user_anc_log("audio_anc open Failed:%d\n", anc_ret);
anc_hdl->mode_switch_lock = 0;
anc_hdl->state = ANC_STA_INIT;
anc_hdl->param.mode = ANC_OFF;
anc_hdl->new_mode = ANC_OFF;
/*ANC OFF && esco_dec idle*/
if (bt_phone_dec_is_running() == 0) {
audio_mic_pwr_ctl(MIC_PWR_OFF);
}
break;
}
} else {
audio_anc_run(&anc_hdl->param);
if (cur_anc_mode == ANC_OFF) {
anc_hdl->state = ANC_STA_INIT;
anc_dmic_io_init(&anc_hdl->param, 0);
/*ANC OFF && esco_dec idle*/
if (bt_phone_dec_is_running() == 0) {
audio_mic_pwr_ctl(MIC_PWR_OFF);
}
}
}
if (cur_anc_mode == ANC_OFF) {
#if ANC_MODE_SYSVDD_EN
clock_set_lowest_voltage(SYSVDD_VOL_SEL_084V); //退出ANC恢复普通模式
#endif/*ANC_MODE_SYSVDD_EN*/
/*anc关闭如果没有连接蓝牙倒计时进入自动关机*/
/* extern u8 get_total_connect_dev(void); */
/* if (get_total_connect_dev() == 0) { //已经没有设备连接 */
/* sys_auto_shut_down_enable(); */
/* } */
}
#if TCFG_AUDIO_DYNAMIC_ADC_GAIN
if (bt_phone_dec_is_running() && (anc_hdl->state == ANC_STA_OPEN)) {
if (anc_hdl->mic_dy_state == ANC_MIC_DY_STA_START) {
audio_anc_drc_ctrl(&anc_hdl->param, anc_hdl->drc_ratio);
} else if (anc_hdl->mic_dy_state == ANC_MIC_DY_STA_INIT) {
anc_dynamic_micgain_start(app_var.aec_mic_gain);
}
}
#endif/*TCFG_AUDIO_DYNAMIC_ADC_GAIN*/
anc_hdl->mode_switch_lock = 0;
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
if (speak_to_chat_flag) {
cur_anc_mode = ANC_OFF;
anc_hdl->param.mode = ANC_OFF;
speak_to_chat_flag = 0;
}
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
if ((anc_hdl->param.mode != ANC_OFF) && anc_hdl->param.anc_fade_en) {
os_time_dly(6); //延时避免切模式反馈有哒哒声
}
audio_anc_lvl_set(anc_hdl->param.anc_lvl, 0);
anc_fade_in_timer_add(&anc_hdl->param);
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
audio_icsd_adt_resume();
audio_speak_to_chat_open_in_anc_done();
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
anc_hdl->last_mode = cur_anc_mode;
#if ANC_MULT_ORDER_ENABLE
audio_anc_mult_scene_coeff_free();
#endif/*ANC_MULT_ORDER_ENABLE*/
break;
case ANC_MSG_MODE_SYNC:
user_anc_log("anc_mode_sync:%d", msg[2]);
anc_mode_switch(msg[2], 0);
break;
#if TCFG_USER_TWS_ENABLE
case ANC_MSG_TONE_SYNC:
user_anc_log("anc_tone_sync_play:%d", msg[2]);
#if !ANC_MODE_EN_MODE_NEXT_SW
if (anc_hdl->mode_switch_lock) {
user_anc_log("anc mode switch lock\n");
break;
}
anc_hdl->mode_switch_lock = 1;
#endif/*ANC_MODE_EN_MODE_NEXT_SW*/
if (msg[2] == SYNC_TONE_ANC_OFF) {
anc_hdl->param.mode = ANC_OFF;
} else if (msg[2] == SYNC_TONE_ANC_ON) {
anc_hdl->param.mode = ANC_ON;
} else {
anc_hdl->param.mode = ANC_TRANSPARENCY;
}
if (anc_hdl->suspend) {
anc_hdl->param.tool_enablebit = 0;
}
anc_hdl->new_mode = anc_hdl->param.mode; //确保准备切的新模式,与最后一个提示音播放的模式一致
anc_tone_play_and_mode_switch(anc_tone_tab[anc_hdl->param.mode - 1], ANC_TONE_PREEMPTION, ANC_TONE_END_MODE_SW);
//anc_mode_switch_deal(anc_hdl->param.mode);
anc_hdl->sync_busy = 0;
break;
#endif/*TCFG_USER_TWS_ENABLE*/
case ANC_MSG_FADE_END:
break;
case ANC_MSG_DRC_TIMER:
audio_anc_drc_process();
break;
case ANC_MSG_DEBUG_OUTPUT:
audio_anc_debug_data_output();
break;
#if ANC_ADAPTIVE_EN
case ANC_MSG_ADAPTIVE_SYNC:
user_anc_log("anc_pow_adap_sync:%d %d", msg[2], msg[3]);
audio_anc_adap_tone_play((u8)msg[2], (u8)msg[3]);
break;
#endif/*ANC_ADAPTIVE_EN*/
#if ANC_MUSIC_DYNAMIC_GAIN_EN
case ANC_MSG_MUSIC_DYN_GAIN:
audio_anc_music_dynamic_gain_process();
break;
#endif/*ANC_MUSIC_DYNAMIC_GAIN_EN*/
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
case ANC_MSG_ADT:
icsd_adt_anctask_handle((u8)msg[2]);
break;
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
#if ANC_EAR_ADAPTIVE_EN
case ANC_MSG_ICSD_ANC_CMD:
icsd_anc_anctask_cmd_handle((u8)msg[2]);
break;
case ANC_MSG_USER_TRAIN_INIT:
/* anc_hdl->last_sys_clk = clk_get("sys"); */
/* user_anc_log("sys clk:%d\n", anc_hdl->last_sys_clk); */
/* sys_clk_set(SYS_160M); //自适应跑最高的时钟 */
audio_codec_clock_set(ANC_EAR_ADAPTIVE_MODE, AUDIO_CODING_PCM, 0);
//icsd_anc_init(&anc_hdl->param,0);
if (++anc_hdl->ear_adaptive_seq == 0xff) {
anc_hdl->ear_adaptive_seq = 0;
}
icsd_anc_init(&anc_hdl->param, 1, anc_hdl->ear_adaptive_seq, ANC_ADAPTIVE_TONE_DELAY, anc_hdl->ear_adaptive_tws_sync);
break;
case ANC_MSG_USER_TRAIN_RUN:
icsd_anc_run();
break;
case ANC_MSG_USER_TRAIN_SETPARAM:
icsd_anc_setparam();
break;
case ANC_MSG_USER_TRAIN_TIMEOUT:
icsd_anc_timeout_handler();
break;
case ANC_MSG_USER_TRAIN_END:
icsd_anc_end(&anc_hdl->param);
/* sys_clk_set(anc_hdl->last_sys_clk); //自适应结束恢复时钟 */
audio_codec_clock_del(ANC_EAR_ADAPTIVE_MODE);
break;
#endif/*ANC_EAR_ADAPTIVE_EN*/
case ANC_MSG_MIC_DATA_GET:
/* extern void anc_spp_mic_data_get(audio_anc_t *param); */
/* anc_spp_mic_data_get(&anc_hdl->param); */
break;
case ANC_MSG_RESET:
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
adt_flag = audio_icsd_adt_is_running();
if (adt_flag) { ////免摘挂起
audio_icsd_adt_suspend();
}
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
if (msg[2] && anc_hdl->param.anc_fade_en) {
int alogm = (anc_hdl->param.mode == ANC_TRANSPARENCY) ? anc_hdl->param.gains.trans_alogm : anc_hdl->param.gains.alogm;
int dly = audio_anc_fade_dly_get(anc_hdl->param.anc_fade_gain, alogm);
audio_anc_fade_ctr_set(ANC_FADE_MODE_RESET, AUDIO_ANC_FDAE_CH_ALL, 0);
os_time_dly(dly / 10 + 1);
audio_anc_reset(&anc_hdl->param, 1);
//避免param.anc_fade_gain 被修改,这里使用固定值
audio_anc_fade_ctr_set(ANC_FADE_MODE_RESET, AUDIO_ANC_FDAE_CH_ALL, ANC_FADE_GAIN_DEFAULT);
} else {
audio_anc_reset(&anc_hdl->param, 0);
}
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
if (adt_flag) { //免摘恢复, 更新免摘参数coeff gain
set_icsd_adt_param_updata();
audio_icsd_adt_resume();
}
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
#if ANC_MULT_ORDER_ENABLE
audio_anc_mult_scene_coeff_free(); //释放空间
#endif/*ANC_MULT_ORDER_ENABLE*/
break;
#if TCFG_ANC_SELF_DUT_GET_SZ
case ANC_MSG_SZ_FFT_OPEN:
audio_codec_clock_set(ANC_DUT_SZ_FFT_MODE, AUDIO_CODING_PCM, 0);
anc_hdl->param.mode = ANC_TRAIN;
anc_hdl->new_mode = ANC_TRAIN;
anc_hdl->param.test_type = ANC_TEST_TYPE_FFT; //设置当前的测试类型
anc_hdl->param.sz_fft.alogm = ANC_ALOGM3; //设置当前测试模式采样率
anc_hdl->param.sz_fft.data_sel = msg[2]; //传入目标数据通道
anc_hdl->param.sz_fft.check_flag = 1; //检查DAC有效数据段
audio_anc_train(&anc_hdl->param, 1); //打开训练模式
audio_dac_write_callback_add(&dac_hdl, audio_anc_sz_fft_dac_check_slience_cb); //注册DAC回调接口-静音检测
break;
case ANC_MSG_SZ_FFT_RUN:
audio_anc_sz_fft_run(&anc_hdl->param); //SZ_FFT 频响计算主体
break;
case ANC_MSG_SZ_FFT_CLOSE:
audio_anc_sz_fft_stop(&anc_hdl->param); //SZ_FFT 停止计算
anc_train_close(); //关闭ANC模式设置为ANC_OFF
break;
#endif/*TCFG_ANC_SELF_DUT_GET_SZ*/
case ANC_MSG_MODE_SWITCH_IN_ANCTASK:
user_anc_log("anc_mode_in_anctask:%d, %d", msg[2], msg[3]);
anc_mode_switch(msg[2], msg[3]);
break;
}
} else {
user_anc_log("res:%d,%d", res, msg[1]);
}
}
}
void anc_param_gain_t_printf(u8 cmd)
{
char *str[2] = {
"ANC_CFG_READ",
"ANC_CFG_WRITE"
};
anc_gain_param_t *gains = &anc_hdl->param.gains;
user_anc_log("-------------anc_param anc_gain_t-%s--------------\n", str[cmd - 1]);
user_anc_log("developer_mode %d\n", gains->developer_mode);
user_anc_log("dac_gain %d\n", gains->dac_gain);
user_anc_log("l_ffmic_gain %d\n", gains->l_ffmic_gain);
user_anc_log("l_fbmic_gain %d\n", gains->l_fbmic_gain);
user_anc_log("r_ffmic_gain %d\n", gains->r_ffmic_gain);
user_anc_log("r_fbmic_gain %d\n", gains->r_fbmic_gain);
user_anc_log("cmp_en %d\n", gains->cmp_en);
user_anc_log("drc_en %d\n", gains->drc_en);
user_anc_log("ahs_en %d\n", gains->ahs_en);
user_anc_log("ff_1st_dcc %d\n", gains->ff_1st_dcc);
user_anc_log("fb_1st_dcc %d\n", gains->fb_1st_dcc);
user_anc_log("ff_2nd_dcc %d\n", gains->ff_2nd_dcc);
user_anc_log("fb_2nd_dcc %d\n", gains->fb_2nd_dcc);
user_anc_log("drc_ff_2dcc %d\n", gains->drc_ff_2dcc);
user_anc_log("drc_fb_2dcc %d\n", gains->drc_fb_2dcc);
user_anc_log("drc_dcc_det_time %d\n", gains->drc_dcc_det_time);
user_anc_log("drc_dcc_res_time %d\n", gains->drc_dcc_res_time);
user_anc_log("gain_sign 0X%x\n", gains->gain_sign);
user_anc_log("noise_lvl 0X%x\n", gains->noise_lvl);
user_anc_log("fade_step 0X%x\n", gains->fade_step);
user_anc_log("alogm %d\n", gains->alogm);
user_anc_log("trans_alogm %d\n", gains->trans_alogm);
user_anc_log("ancl_ffgain %d.%d\n", ((int)(gains->l_ffgain * 100.0)) / 100, ((int)(gains->l_ffgain * 100.0)) % 100);
user_anc_log("ancl_fbgain %d.%d\n", ((int)(gains->l_fbgain * 100.0)) / 100, ((int)(gains->l_fbgain * 100.0)) % 100);
user_anc_log("ancl_trans_gain %d.%d\n", ((int)(gains->l_transgain * 100.0)) / 100, ((int)(gains->l_transgain * 100.0)) % 100);
user_anc_log("ancl_cmpgain %d.%d\n", ((int)(gains->l_cmpgain * 100.0)) / 100, ((int)(gains->l_cmpgain * 100.0)) % 100);
user_anc_log("ancr_ffgain %d.%d\n", ((int)(gains->r_ffgain * 100.0)) / 100, ((int)(gains->r_ffgain * 100.0)) % 100);
user_anc_log("ancr_fbgain %d.%d\n", ((int)(gains->r_fbgain * 100.0)) / 100, ((int)(gains->r_fbgain * 100.0)) % 100);
user_anc_log("ancr_trans_gain %d.%d\n", ((int)(gains->r_transgain * 100.0)) / 100, ((int)(gains->r_transgain * 100.0)) % 100);
user_anc_log("ancr_cmpgain %d.%d\n", ((int)(gains->r_cmpgain * 100.0)) / 100, ((int)(gains->r_cmpgain * 100.0)) % 100);
user_anc_log("drcff_zero_det %d\n", gains->drcff_zero_det);
user_anc_log("drcff_dat_mode %d\n", gains->drcff_dat_mode);
user_anc_log("drcff_lpf_sel %d\n", gains->drcff_lpf_sel);
user_anc_log("drcfb_zero_det %d\n", gains->drcfb_zero_det);
user_anc_log("drcfb_dat_mode %d\n", gains->drcfb_dat_mode);
user_anc_log("drcfb_lpf_sel %d\n", gains->drcfb_lpf_sel);
user_anc_log("drcff_low_thr %d\n", gains->drcff_lthr);
user_anc_log("drcff_high_thr %d\n", gains->drcff_hthr);
user_anc_log("drcff_low_gain %d\n", gains->drcff_lgain);
user_anc_log("drcff_high_gain %d\n", gains->drcff_hgain);
user_anc_log("drcff_nor_gain %d\n", gains->drcff_norgain);
user_anc_log("drcfb_low_thr %d\n", gains->drcfb_lthr);
user_anc_log("drcfb_high_thr %d\n", gains->drcfb_hthr);
user_anc_log("drcfb_low_gain %d\n", gains->drcfb_lgain);
user_anc_log("drcfb_high_gain %d\n", gains->drcfb_hgain);
user_anc_log("drcfb_nor_gain %d\n", gains->drcfb_norgain);
user_anc_log("drctrans_low_thr %d\n", gains->drctrans_lthr);
user_anc_log("drctrans_high_thr %d\n", gains->drctrans_hthr);
user_anc_log("drctrans_low_gain %d\n", gains->drctrans_lgain);
user_anc_log("drctrans_high_gain %d\n", gains->drctrans_hgain);
user_anc_log("drctrans_nor_gain %d\n", gains->drctrans_norgain);
user_anc_log("ahs_dly %d\n", gains->ahs_dly);
user_anc_log("ahs_tap %d\n", gains->ahs_tap);
user_anc_log("ahs_wn_shift %d\n", gains->ahs_wn_shift);
user_anc_log("ahs_wn_sub %d\n", gains->ahs_wn_sub);
user_anc_log("ahs_shift %d\n", gains->ahs_shift);
user_anc_log("ahs_u %d\n", gains->ahs_u);
user_anc_log("ahs_gain %d\n", gains->ahs_gain);
user_anc_log("ahs_nlms_sel %d\n", gains->ahs_nlms_sel);
user_anc_log("audio_drc_thr %d/10\n", (int)(gains->audio_drc_thr * 10.0));
user_anc_log("adaptive_ref_en %d\n", gains->adaptive_ref_en);
user_anc_log("adaptive_ref_fb_f %d/10\n", (int)(gains->adaptive_ref_fb_f * 10.0));
user_anc_log("adaptive_ref_fb_g %d/10\n", (int)(gains->adaptive_ref_fb_g * 10.0));
user_anc_log("adaptive_ref_fb_q %d/10\n", (int)(gains->adaptive_ref_fb_q * 10.0));
}
/*ANC配置参数填充*/
void anc_param_fill(u8 cmd, anc_gain_t *cfg)
{
if (cmd == ANC_CFG_READ) {
anc_gain_t *db_gain = (anc_gain_t *)anc_db_get(ANC_DB_GAIN, &anc_hdl->param.gains_size);
cfg->gains = db_gain->gains; //直接读flash区域
/* cfg->gains = anc_hdl->param.gains; */
} else if (cmd == ANC_CFG_WRITE) {
anc_hdl->param.gains = cfg->gains;
anc_hdl->param.gains.hd_en = 0;
anc_hdl->param.gains.hd_corr_thr = 225;
anc_hdl->param.gains.hd_corr_dly = 13;
anc_hdl->param.gains.hd_corr_gain = 256;
anc_hdl->param.gains.hd_pwr_rate = 2;
anc_hdl->param.gains.hd_pwr_ctl_gain_en = 0;
anc_hdl->param.gains.hd_pwr_ctl_ahsrst_en = 0;
anc_hdl->param.gains.hd_pwr_thr = 500;
anc_hdl->param.gains.hd_pwr_ctl_gain = 1638;
anc_hdl->param.gains.hd_pwr_ref_ctl_en = 0;
anc_hdl->param.gains.hd_pwr_ref_ctl_hthr = 2000;
anc_hdl->param.gains.hd_pwr_ref_ctl_lthr1 = 1000;
anc_hdl->param.gains.hd_pwr_ref_ctl_lthr2 = 200;
anc_hdl->param.gains.hd_pwr_err_ctl_en = 0;
anc_hdl->param.gains.hd_pwr_err_ctl_hthr = 2000;
anc_hdl->param.gains.hd_pwr_err_ctl_lthr1 = 1000;
anc_hdl->param.gains.hd_pwr_err_ctl_lthr2 = 200;
anc_hdl->param.gains.developer_mode = anc_hdl->param.developer_mode;
audio_anc_param_normalize(&anc_hdl->param);
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
if (anc_hdl->param.gains.trans_alogm != anc_hdl->param.gains.alogm) {
user_anc_log("===========================\n\n");
// anc_hdl->param.gains.trans_alogm = anc_hdl->param.gains.alogm;
user_anc_log("err : anc_hdl->param.gains.trans_alogm != anc_hdl->param.gains.alogm !!!");
user_anc_log("\n\n===========================");
}
#endif
#if ANC_EAR_ADAPTIVE_EN
audio_anc_param_map(0, 1);
if (anc_hdl->param.anc_coeff_mode == ANC_COEFF_MODE_ADAPTIVE) {
audio_anc_ear_adaptive_param_init(&anc_hdl->param);
}
#endif/*ANC_EAR_ADAPTIVE_EN*/
}
/* anc_param_gain_t_printf(cmd); */
}
//ANC配置文件读取并更新
int audio_anc_db_cfg_read(void)
{
/*读取ANC增益配置*/
anc_gain_t *db_gain = (anc_gain_t *)anc_db_get(ANC_DB_GAIN, &anc_hdl->param.gains_size);
if (db_gain) {
user_anc_log("anc_gain_db get succ,len:%d\n", anc_hdl->param.gains_size);
if (audio_anc_gains_version_verify(&anc_hdl->param, db_gain)) { //检查版本差异
user_anc_log("The anc gains version is older,0X%x\n", db_gain->gains.version);
db_gain = (anc_gain_t *)anc_db_get(ANC_DB_GAIN, &anc_hdl->param.gains_size);
}
anc_param_fill(ANC_CFG_WRITE, db_gain);
} else {
user_anc_log("anc_gain_db get failed");
/* anc_param_gain_t_printf(ANC_CFG_READ); */
return 1;
}
/*读取ANC滤波器系数*/
#if ANC_MULT_ORDER_ENABLE
return audio_anc_mult_coeff_file_read();
#endif/*ANC_MULT_ORDER_ENABLE*/
anc_coeff_t *db_coeff = (anc_coeff_t *)anc_db_get(ANC_DB_COEFF, &anc_hdl->param.coeff_size);
if (!anc_coeff_fill(db_coeff)) {
user_anc_log("anc_coeff_db get succ,len:%d", anc_hdl->param.coeff_size);
} else {
user_anc_log("anc_coeff_db get failed");
return 1;
#if 0 //测试数据写入是否正常,或写入自己想要的滤波器数据
extern anc_coeff_t *anc_cfg_test(audio_anc_t *param, u8 coeff_en, u8 gains_en);
anc_coeff_t *test_coeff = anc_cfg_test(&anc_hdl->param, 1, 1);
if (test_coeff) {
int ret = anc_db_put(&anc_hdl->param, NULL, test_coeff);
if (ret == 0) {
user_anc_log("anc_db put test succ\n");
} else {
user_anc_log("anc_db put test err\n");
}
}
anc_coeff_t *test_coeff1 = (anc_coeff_t *)anc_db_get(ANC_DB_COEFF, &anc_hdl->param.coeff_size);
anc_coeff_fill(test_coeff1);
#endif
}
#if ANC_EAR_ADAPTIVE_EN
audio_anc_param_map(1, 0);
#endif/*ANC_EAR_ADAPTIVE_EN*/
return 0;
}
/*ANC初始化*/
void anc_init(void)
{
anc_hdl = zalloc(sizeof(anc_t));
user_anc_log("anc_hdl size:%lu\n", sizeof(anc_t));
ASSERT(anc_hdl);
audio_anc_param_init(&anc_hdl->param);
anc_debug_init(&anc_hdl->param);
audio_anc_fade_ctr_init();
#if TCFG_ANC_TOOL_DEBUG_ONLINE
app_online_db_register_handle(DB_PKT_TYPE_ANC, anc_app_online_parse);
#endif/*TCFG_ANC_TOOL_DEBUG_ONLINE*/
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
anc_hdl->param.adt = zalloc(sizeof(anc_adt_param_t));
ASSERT(anc_hdl->param.adt);
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
#if ANC_EAR_ADAPTIVE_EN
anc_hdl->param.adaptive = zalloc(sizeof(anc_ear_adaptive_param_t));
ASSERT(anc_hdl->param.adaptive);
#endif/*ANC_EAR_ADAPTIVE_EN*/
#if ANC_MULT_ORDER_ENABLE
anc_mult_init(&anc_hdl->param);
anc_hdl->scene_id = ANC_MULT_ORDER_NORMAL_ID; //默认使用场景1滤波器
anc_hdl->param.mult_gain_set = audio_anc_mult_gains_id_set;
#endif/*ANC_MULT_ORDER_ENABLE*/
anc_hdl->param.post_msg_drc = audio_anc_post_msg_drc;
anc_hdl->param.post_msg_debug = audio_anc_post_msg_debug;
anc_hdl->mode_enable = ANC_MODE_ENABLE;
anc_mode_enable_set(anc_hdl->mode_enable);
anc_hdl->param.cfg_online_deal_cb = anc_cfg_online_deal;
anc_hdl->param.adc_set_buffs_cb = esco_adc_mic_set_buffs;
audio_anc_adc_ch_set();
anc_hdl->param.mode = ANC_OFF;
anc_hdl->new_mode = anc_hdl->param.mode;
anc_hdl->param.production_mode = 0;
anc_hdl->param.developer_mode = ANC_DEVELOPER_MODE_EN;
anc_hdl->param.anc_fade_en = ANC_FADE_EN;/*ANC淡入淡出默认开*/
anc_hdl->param.anc_fade_gain = 16384;/*ANC淡入淡出增益,16384 (0dB) max:32767*/
anc_hdl->param.tool_enablebit = ANC_TRAIN_MODE;
anc_hdl->param.online_busy = 0; //在线调试繁忙标志位
//36
anc_hdl->param.dut_audio_enablebit = ANC_DUT_CLOSE;
anc_hdl->param.fade_time_lvl = ANC_MODE_FADE_LVL;
anc_hdl->param.enablebit = ANC_TRAIN_MODE;
anc_hdl->param.adaptive_mode = ANC_ADAPTIVE_MODE;
anc_hdl->param.ch = ANC_CH;
anc_hdl->param.mic_type[0] = ANCL_FF_MIC;
anc_hdl->param.mic_type[1] = ANCL_FB_MIC;
anc_hdl->param.mic_type[2] = ANCR_FF_MIC;
anc_hdl->param.mic_type[3] = ANCR_FB_MIC;
anc_hdl->param.lff_en = ANC_CONFIG_LFF_EN;
anc_hdl->param.lfb_en = ANC_CONFIG_LFB_EN;
anc_hdl->param.rff_en = ANC_CONFIG_RFF_EN;
anc_hdl->param.rfb_en = ANC_CONFIG_RFB_EN;
anc_hdl->param.trans_default_coeff = (double *)trans_coeff_test; //推荐通透滤波器
anc_hdl->param.debug_sel = 0;
anc_hdl->param.gains.version = ANC_GAINS_VERSION;
anc_hdl->param.gains.dac_gain = 3;
anc_hdl->param.gains.l_ffmic_gain = 4;
anc_hdl->param.gains.l_fbmic_gain = 4;
anc_hdl->param.gains.r_ffmic_gain = 4;
anc_hdl->param.gains.r_fbmic_gain = 4;
anc_hdl->param.gains.cmp_en = 1;
anc_hdl->param.gains.drc_en = 0;
anc_hdl->param.gains.ahs_en = 0;
anc_hdl->param.gains.ff_1st_dcc = 8;
anc_hdl->param.gains.ff_2nd_dcc = 4;
anc_hdl->param.gains.fb_1st_dcc = 8;
anc_hdl->param.gains.fb_2nd_dcc = 1;
anc_hdl->param.gains.gain_sign = 0;
anc_hdl->param.gains.alogm = ANC_ALOGM6;
anc_hdl->param.gains.trans_alogm = ANC_ALOGM4;
anc_hdl->param.gains.l_ffgain = 1.0f;
anc_hdl->param.gains.l_fbgain = 1.0f;
anc_hdl->param.gains.l_cmpgain = 1.0f;
anc_hdl->param.gains.l_transgain = 1.0f;
anc_hdl->param.gains.r_ffgain = 1.0f;
anc_hdl->param.gains.r_fbgain = 1.0f;
anc_hdl->param.gains.r_cmpgain = 1.0f;
anc_hdl->param.gains.r_transgain = 1.0f;
anc_hdl->param.gains.drcff_zero_det = 0;
anc_hdl->param.gains.drcff_dat_mode = 0;//hbit control l_gain, lbit control h_gain
anc_hdl->param.gains.drcff_lpf_sel = 0;
anc_hdl->param.gains.drcfb_zero_det = 0;
anc_hdl->param.gains.drcfb_dat_mode = 0;//hbit control l_gain, lbit control h_gain
anc_hdl->param.gains.drcfb_lpf_sel = 0;
anc_hdl->param.gains.drcff_lthr = 0;
anc_hdl->param.gains.drcff_hthr = 6000 ;
anc_hdl->param.gains.drcff_lgain = 0;
anc_hdl->param.gains.drcff_hgain = 512;
anc_hdl->param.gains.drcff_norgain = 1024 ;
anc_hdl->param.gains.drctrans_lthr = 0;
anc_hdl->param.gains.drctrans_hthr = 32767 ;
anc_hdl->param.gains.drctrans_lgain = 0;
anc_hdl->param.gains.drctrans_hgain = 1024;
anc_hdl->param.gains.drctrans_norgain = 1024 ;
anc_hdl->param.gains.drcfb_lthr = 0;
anc_hdl->param.gains.drcfb_hthr = 6000;
anc_hdl->param.gains.drcfb_lgain = 0;
anc_hdl->param.gains.drcfb_hgain = 512;
anc_hdl->param.gains.drcfb_norgain = 1024;
anc_hdl->param.gains.ahs_dly = 1;
anc_hdl->param.gains.ahs_tap = 100;
anc_hdl->param.gains.ahs_wn_shift = 9;
anc_hdl->param.gains.ahs_wn_sub = 1;
anc_hdl->param.gains.ahs_shift = 210;
anc_hdl->param.gains.ahs_u = 4000;
anc_hdl->param.gains.ahs_gain = -1024;
anc_hdl->param.gains.audio_drc_thr = -6.0f;
anc_hdl->param.gains.ahs_nlms_sel = 0;
anc_hdl->param.gains.drc_ff_2dcc = 0;
anc_hdl->param.gains.drc_fb_2dcc = 0;
anc_hdl->param.gains.drc_dcc_det_time = 300;
anc_hdl->param.gains.drc_dcc_res_time = 20;
anc_hdl->param.gains.hd_en = 0;
anc_hdl->param.gains.hd_corr_thr = 232;
anc_hdl->param.gains.hd_corr_gain = 256;
anc_hdl->param.gains.hd_corr_dly = 13;
anc_hdl->param.gains.hd_pwr_rate = 2;
anc_hdl->param.gains.hd_pwr_ctl_gain_en = 0;
anc_hdl->param.gains.hd_pwr_ctl_ahsrst_en = 0;
anc_hdl->param.gains.hd_pwr_thr = 18000;
anc_hdl->param.gains.hd_pwr_ctl_gain = 1638;
anc_hdl->param.gains.hd_pwr_ref_ctl_en = 0;
anc_hdl->param.gains.hd_pwr_ref_ctl_hthr = 2000;
anc_hdl->param.gains.hd_pwr_ref_ctl_lthr1 = 1000;
anc_hdl->param.gains.hd_pwr_ref_ctl_lthr2 = 200;
anc_hdl->param.gains.hd_pwr_err_ctl_en = 0;
anc_hdl->param.gains.hd_pwr_err_ctl_hthr = 2000;
anc_hdl->param.gains.hd_pwr_err_ctl_lthr1 = 1000;
anc_hdl->param.gains.hd_pwr_err_ctl_lthr2 = 200;
anc_hdl->param.gains.adaptive_ref_en = 0;
anc_hdl->param.gains.adaptive_ref_fb_f = 120.0;
anc_hdl->param.gains.adaptive_ref_fb_g = 15.0;
anc_hdl->param.gains.adaptive_ref_fb_q = 0.4;
#if ANC_COEFF_SAVE_ENABLE
//1.先读取ANC默认参数
anc_db_init();
audio_anc_db_cfg_read(); //读取anc_gains.bin anc_coeff.bin更新ANC参数
#endif/*ANC_COEFF_SAVE_ENABLE*/
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
anc_hdl->param.adt->dma_done_cb = icsd_adt_dma_done;
anc_hdl->param.ltrans_fbgain = anc_trans_lfb_gain;
anc_hdl->param.rtrans_fbgain = anc_trans_rfb_gain;
anc_hdl->param.ltrans_fb_coeff = anc_trans_lfb_coeff;
anc_hdl->param.rtrans_fb_coeff = anc_trans_rfb_coeff;
anc_hdl->param.ltrans_fb_yorder = sizeof(anc_trans_lfb_coeff) / 40;
anc_hdl->param.rtrans_fb_yorder = sizeof(anc_trans_rfb_coeff) / 40;
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
anc_hdl->param.biquad2ab = icsd_biquad2ab_out;
#if ANC_EAR_ADAPTIVE_EN
//2.再读取ANC自适应参数, 若存在则覆盖默认参数
anc_hdl->param.adaptive->ff_yorder = ANC_ADAPTIVE_FF_ORDER;
anc_hdl->param.adaptive->fb_yorder = ANC_ADAPTIVE_FB_ORDER;
anc_hdl->param.adaptive->cmp_yorder = ANC_ADAPTIVE_CMP_ORDER;
anc_hdl->param.adaptive->dma_done_cb = icsd_anc_dma_done;
audio_anc_adaptive_data_read(&anc_hdl->adaptive_iir);
#if ANC_EAR_RECORD_EN
icsd_anc_vmdata_init(anc_hdl->adaptive_iir.record_FL, anc_hdl->adaptive_iir.record_FR, &anc_hdl->adaptive_iir.record_num);
#endif/*ANC_EAR_RECORD_EN*/
#endif/*ANC_EAR_ADAPTIVE_EN*/
/* sys_timer_add(NULL, anc_timer_deal, 5000); */
#if ANC_ADAPTIVE_EN
anc_pow_adap_init(&anc_hdl->param, &anc_adap_param, &anc_adap_param, \
sizeof(anc_adap_param) / sizeof(anc_adap_param_t), \
sizeof(anc_adap_param) / sizeof(anc_adap_param_t));
anc_hdl->param.pow_adap_fade = audio_anc_pow_adap_fade;
#endif/*ANC_ADAPTIVE_EN*/
#if TCFG_ANC_SELF_DUT_GET_SZ
anc_hdl->param.sz_fft.dma_run_hdl = audio_anc_post_msg_sz_fft_run;
#endif/*TCFG_ANC_SELF_DUT_GET_SZ*/
audio_anc_mic_management(&anc_hdl->param);
anc_mix_out_audio_drc_thr(anc_hdl->param.gains.audio_drc_thr);
task_create(anc_task, NULL, "anc");
anc_hdl->state = ANC_STA_INIT;
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
anc_adt_init();
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
user_anc_log("anc_init ok");
}
void anc_train_open(u8 mode, u8 debug_sel)
{
user_anc_log("ANC_Train_Open\n");
local_irq_disable();
if (anc_hdl && (anc_hdl->state == ANC_STA_INIT)) {
/*防止重复打开训练模式*/
if (anc_hdl->param.mode == ANC_TRAIN) {
local_irq_enable();
return;
}
/*anc工作退出sniff*/
user_send_cmd_prepare(USER_CTRL_ALL_SNIFF_EXIT, 0, NULL);
/*anc工作关闭自动关机*/
/* sys_auto_shut_down_disable(); */
anc_hdl->param.debug_sel = debug_sel;
anc_hdl->param.mode = mode;
anc_hdl->new_mode = anc_hdl->param.mode;
anc_hdl->param.test_type = ANC_TEST_TYPE_PCM;
/*训练的时候申请buf用来保存训练参数*/
local_irq_enable();
os_taskq_post_msg("anc", 1, ANC_MSG_TRAIN_OPEN);
user_anc_log("%s ok\n", __FUNCTION__);
return;
}
local_irq_enable();
}
void anc_train_close(void)
{
int ret = 0;
if (anc_hdl == NULL) {
return;
}
if (anc_hdl && (anc_hdl->param.mode == ANC_TRAIN)) {
anc_hdl->param.train_para.train_busy = 0;
anc_hdl->param.mode = ANC_OFF;
anc_hdl->new_mode = anc_hdl->param.mode;
anc_hdl->state = ANC_STA_INIT;
audio_anc_train(&anc_hdl->param, 0);
user_anc_log("anc_train_close ok\n");
}
}
/*查询当前ANC是否处于训练状态*/
int anc_train_open_query(void)
{
if (anc_hdl) {
#if ANC_EAR_ADAPTIVE_EN
if (anc_hdl->ear_adaptive_busy) {
return 1;
}
#endif/*ANC_EAR_ADAPTIVE_EN*/
if (anc_hdl->param.mode == ANC_TRAIN) {
return 1;
}
}
return 0;
}
extern void audio_dump();
static void anc_timer_deal(void *priv)
{
u8 dac_again_l = JL_ADDA->DAA_CON1 & 0xF;
u8 dac_again_r = (JL_ADDA->DAA_CON1 >> 4) & 0xF;
u32 dac_dgain_l = JL_AUDIO->DAC_VL0 & 0xFFFF;
u32 dac_dgain_r = (JL_AUDIO->DAC_VL0 >> 16) & 0xFFFF;
u8 mic0_gain = (JL_ADDA->ADA_CON8) & 0x1F;
u8 mic1_gain = (JL_ADDA->ADA_CON8 >> 5) & 0x1F;
u8 mic2_gain = (JL_ADDA->ADA_CON8 >> 10) & 0x1F;
u8 mic3_gain = (JL_ADDA->ADA_CON8 >> 15) & 0x1F;
user_anc_log("MIC_G:%d,%d,%d,%d,DAC_AG:%d,%d,DAC_DG:%d,%d\n", mic0_gain, mic1_gain, mic2_gain, mic3_gain, dac_again_l, dac_again_r, dac_dgain_l, dac_dgain_r);
/* mem_stats(); */
#if TCFG_USER_TWS_ENABLE
if (tws_api_get_role() == TWS_ROLE_MASTER) {
printf("%c, master\n", bt_tws_get_local_channel());
} else {
printf("%c, slave\n", bt_tws_get_local_channel());
}
#endif/*TCFG_USER_TWS_ENABLE*/
/* audio_dump(); */
}
#if ANC_EAR_ADAPTIVE_EN
static void anc_tone_play_pre(u8 next_mode)
{
user_anc_log("anc_tone_play_pre:%d %d %d\n", anc_hdl->new_mode, next_mode, anc_hdl->ear_adaptive);
/* if (anc_hdl->new_mode == next_mode) { */
if (next_mode == ANC_ON && anc_hdl->ear_adaptive) {
icsd_anc_tone_play_start();
}
/* } */
}
#endif/*ANC_EAR_ADAPTIVE_EN*/
static void anc_tone_play_cb(void *priv, int break_flag)
{
u8 next_mode = (u8)priv;
user_anc_log("anc_tone_play_cb,anc_mode:%d,%d,new_mode:%d, break %d\n", next_mode, anc_hdl->param.mode, anc_hdl->new_mode, break_flag);
/*
*ANC模式和即将切过去的模式一致
*new_mode领先于ANC模式切换实现next_mode
*
*/
if (anc_hdl->new_mode == next_mode) {
#if ANC_EAR_ADAPTIVE_EN
if (next_mode == ANC_ON && anc_hdl->ear_adaptive) {
anc_hdl->ear_adaptive = 0;
if (break_flag) { // 提示音被打断,自适应强制停止
icsd_anc_forced_exit();
}
anc_user_train_tone_play_cb();
} else
#endif/*ANC_EAR_ADAPTIVE_EN*/
{
anc_mode_switch_deal(next_mode);
}
} else {
anc_hdl->mode_switch_lock = 0;
}
}
/*
*********************************************************************
* Audio ANC Tone Play And Mode Switch
* Description: ANC提示音播放和模式切换
* Arguments : index
* preemption
* cb_sel
* Return : None.
* Note(s) : cb_sel选择是在播放提示音切模式
*
*********************************************************************
*/
static void anc_tone_play_and_mode_switch(u8 index, u8 preemption, u8 cb_sel)
{
if (!bt_media_is_running() && !bt_phone_dec_is_running()) { //后台没有音频,提示音默认打断播放
preemption = 1;
}
if (cb_sel) {
#if ANC_EAR_ADAPTIVE_EN
if (anc_hdl->ear_adaptive) { //非ANC模式下切自适应需要提前开MICADC需要稳定时间
audio_mic_pwr_ctl(MIC_PWR_ON);
audio_anc_dac_open(anc_hdl->param.gains.dac_gain, anc_hdl->param.gains.dac_gain);
anc_hdl->param.adc_set_buffs_cb();
audio_anc_mic_open(anc_hdl->param.mic_param, 0, anc_hdl->param.adc_ch);
index = (index == IDEX_TONE_ANC_ON) ? IDEX_TONE_ANC_ADAPTIVE : index;
}
#if ANC_USER_TRAIN_TONE_MODE
anc_tone_play_pre(anc_hdl->param.mode); //播放提示音时,先进行自适应训练
#endif/*ANC_USER_TRAIN_TONE_MODE*/
#endif/*ANC_EAR_ADAPTIVE_EN*/
tone_play_index_with_callback(index, preemption, (void(*)(void *))anc_tone_play_cb, (void *)anc_hdl->param.mode);
/*ANC打开情况下播提示音的同时anc效果淡出*/
if (anc_hdl->state == ANC_STA_OPEN) {
audio_anc_fade_ctr_set(ANC_FADE_MODE_SWITCH, AUDIO_ANC_FDAE_CH_ALL, 0);
}
} else {
tone_play_index(index, preemption);
anc_mode_switch_deal(anc_hdl->param.mode);
}
}
static void anc_tone_stop(void)
{
if (anc_hdl && anc_hdl->mode_switch_lock) {
tone_play_stop();
}
}
/*
*********************************************************************
* anc_fade_in_timer
* Description: ANC增益淡入函数
* Arguments : None.
* Return : None.
* Note(s) :使ANC的淡入增益一点一点叠加
*********************************************************************
*/
static void anc_fade_in_timer(void *arg)
{
anc_hdl->fade_gain += (anc_hdl->param.anc_fade_gain / anc_hdl->param.fade_time_lvl);
if (anc_hdl->fade_gain > anc_hdl->param.anc_fade_gain) {
anc_hdl->fade_gain = anc_hdl->param.anc_fade_gain;
usr_timer_del(anc_hdl->fade_in_timer);
}
audio_anc_fade_ctr_set(ANC_FADE_MODE_SWITCH, AUDIO_ANC_FDAE_CH_ALL, anc_hdl->fade_gain);
}
static void anc_fade_in_timer_add(audio_anc_t *param)
{
u32 alogm, dly;
if (param->anc_fade_en) {
alogm = (param->mode == ANC_TRANSPARENCY) ? param->gains.trans_alogm : param->gains.alogm;
dly = audio_anc_fade_dly_get(param->anc_fade_gain, alogm);
anc_hdl->fade_gain = 0;
if (param->mode == ANC_ON) { //可自定义模式当前仅在ANC模式下使用
user_anc_log("anc_fade_time_lvl %d\n", param->fade_time_lvl);
anc_hdl->fade_gain = (param->anc_fade_gain / param->fade_time_lvl);
audio_anc_fade_ctr_set(ANC_FADE_MODE_SWITCH, AUDIO_ANC_FDAE_CH_ALL, anc_hdl->fade_gain);
if (param->fade_time_lvl > 1) {
anc_hdl->fade_in_timer = usr_timer_add((void *)0, anc_fade_in_timer, dly, 1);
}
} else if (param->mode != ANC_OFF) {
audio_anc_fade_ctr_set(ANC_FADE_MODE_SWITCH, AUDIO_ANC_FDAE_CH_ALL, param->anc_fade_gain);
}
}
}
static void anc_fade_out_timeout(void *arg)
{
os_taskq_post_msg("anc", 1, ANC_MSG_RUN);
}
static void anc_fade(u32 gain)
{
u32 alogm, dly;
if (anc_hdl) {
alogm = (anc_hdl->last_mode == ANC_TRANSPARENCY) ? anc_hdl->param.gains.trans_alogm : anc_hdl->param.gains.alogm;
dly = audio_anc_fade_dly_get(anc_hdl->param.anc_fade_gain, alogm);
user_anc_log("anc_fade:%d,dly:%d", gain, dly);
audio_anc_fade_ctr_set(ANC_FADE_MODE_SWITCH, AUDIO_ANC_FDAE_CH_ALL, gain);
if (anc_hdl->param.anc_fade_en) {
usr_timeout_del(anc_hdl->fade_in_timer);
usr_timeout_add((void *)0, anc_fade_out_timeout, dly, 1);
} else {/*不淡入淡出,则直接切模式*/
os_taskq_post_msg("anc", 1, ANC_MSG_RUN);
}
}
}
/*
*mode://
*tone_play:
*/
static void anc_mode_switch_deal(u8 mode)
{
#if TCFG_ANCLED_ENABLE
if ((mode == ANC_ON) || (mode == ANC_TRANSPARENCY)) {
gpio_set_pull_up(TCFG_ANCLED_PIN, 1);//头戴耳机ANC指示灯
gpio_set_pull_down(TCFG_ANCLED_PIN, 0);
gpio_set_direction(TCFG_ANCLED_PIN, 0);
gpio_set_output_value(TCFG_ANCLED_PIN, 1);
} else {
gpio_set_pull_up(TCFG_ANCLED_PIN, 0);
gpio_set_pull_down(TCFG_ANCLED_PIN, 0);
gpio_set_direction(TCFG_ANCLED_PIN, 1);
gpio_set_die(TCFG_ANCLED_PIN, 0);
}
#endif
user_anc_log("anc switch,state:%s", anc_state_str[anc_hdl->state]);
anc_hdl->mode_switch_lock = 1;
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
audio_anc_mode_switch_in_adt(anc_hdl->param.mode);
#endif
if (anc_hdl->state == ANC_STA_OPEN) {
user_anc_log("anc open now,switch mode:%d", mode);
anc_fade(0);//切模式先fade_out
} else if (anc_hdl->state == ANC_STA_INIT) {
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
if ((anc_hdl->param.mode != ANC_OFF) || get_adt_open_in_anc_state()) {
#else
if (anc_hdl->param.mode != ANC_OFF) {
#endif/*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
/*anc工作关闭自动关机*/
/* sys_auto_shut_down_disable(); */
os_taskq_post_msg("anc", 1, ANC_MSG_RUN);
} else {
user_anc_log("anc close now,new mode is ANC_OFF\n");
anc_hdl->mode_switch_lock = 0;
}
} else {
user_anc_log("anc state err:%d\n", anc_hdl->state);
anc_hdl->mode_switch_lock = 0;
}
}
void anc_gain_app_value_set(int app_value)
{
static int anc_gain_app_value = -1;
if (-1 == app_value && -1 != anc_gain_app_value) {
/* anc_hdl->param.anc_ff_gain = anc_gain_app_value; */
}
anc_gain_app_value = app_value;
}
static void anc_user_train_timeout(void *arg)
{
#if ANC_EAR_ADAPTIVE_EN
anc_user_train_tone_play_cb();
#endif/*ANC_EAR_ADAPTIVE_EN*/
}
#define TWS_ANC_SYNC_TIMEOUT 600 //ms
void anc_mode_switch(u8 mode, u8 tone_play)
{
u8 ignore_same_mode = 0;
u8 tws_sync_en = 1;
if (anc_hdl == NULL) {
return;
}
/*模式切换超出范围*/
if ((mode > ANC_BYPASS) || (mode < ANC_OFF)) {
user_anc_log("anc mode switch err:%d", mode);
return;
}
/*模式切换同一个*/
#if ANC_EAR_ADAPTIVE_EN
if (anc_hdl->ear_adaptive) {
ignore_same_mode = 1;
if (!anc_hdl->ear_adaptive_tws_sync) {
tws_sync_en = 0; //自适应状态关闭左右平衡,则不需要同步切模式
}
}
#endif/*ANC_EAR_ADAPTIVE_EN*/
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
/*判断adt是否在关闭过程中切anc*/
u8 adt_off_state = (audio_icsd_adt_is_running() && !get_icsd_adt_mode()) ? 1 : 0;
/*需要在切anc模式是开adt || adt关闭时切anc off*/
if ((get_adt_open_in_anc_state() && get_icsd_adt_mode()) || (adt_off_state && (mode == ANC_OFF))) {
ignore_same_mode = 1;
}
#endif/*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
if (anc_hdl->param.mode == mode && (!ignore_same_mode)) {
user_anc_log("anc mode switch err:same mode");
return;
}
#if ANC_MODE_EN_MODE_NEXT_SW
if (anc_hdl->mode_switch_lock) {
user_anc_log("anc mode switch lock\n");
return;
}
anc_hdl->mode_switch_lock = 1;
#endif/*ANC_MODE_EN_MODE_NEXT_SW*/
anc_hdl->new_mode = mode;/*记录最新的目标ANC模式*/
#if ANC_TONE_END_MODE_SW && (!ANC_MODE_EN_MODE_NEXT_SW)
anc_tone_stop();
#endif/*ANC_TONE_END_MODE_SW*/
anc_hdl->param.mode = mode;
if (anc_hdl->suspend) {
anc_hdl->param.tool_enablebit = 0;
}
/* anc_gain_app_value_set(-1); */ //没有处理好bypass与ANC_ON的关系
/*
*ANC模式提示音播放规则
*(1)tone_play
*(2)tws连接的时候
*(3)
*/
if (tone_play) {
#if TCFG_USER_TWS_ENABLE
if (get_tws_sibling_connect_state() && tws_sync_en) {
if (tws_api_get_role() == TWS_ROLE_MASTER) {
user_anc_log("[tws_master]anc_tone_sync_play");
anc_hdl->sync_busy = 1;
if (anc_hdl->param.mode == ANC_ON) {
bt_tws_play_tone_at_same_time(SYNC_TONE_ANC_ON, TWS_ANC_SYNC_TIMEOUT);
} else if (anc_hdl->param.mode == ANC_OFF) {
bt_tws_play_tone_at_same_time(SYNC_TONE_ANC_OFF, TWS_ANC_SYNC_TIMEOUT);
} else {
bt_tws_play_tone_at_same_time(SYNC_TONE_ANC_TRANS, TWS_ANC_SYNC_TIMEOUT);
}
}
return;
} else {
user_anc_log("anc_tone_play");
anc_tone_play_and_mode_switch(anc_tone_tab[mode - 1], ANC_TONE_PREEMPTION, ANC_TONE_END_MODE_SW);
}
#else
anc_tone_play_and_mode_switch(anc_tone_tab[mode - 1], ANC_TONE_PREEMPTION, ANC_TONE_END_MODE_SW);
#endif/*TCFG_USER_TWS_ENABLE*/
} else {
#if ANC_EAR_ADAPTIVE_EN // 不播提示音进入自适应流程
if (mode == ANC_ON && anc_hdl->ear_adaptive) {
anc_hdl->ear_adaptive = 0;
if (anc_hdl->param.anc_fade_en) {
u32 dly = audio_anc_fade_dly_get(anc_hdl->param.anc_fade_gain, anc_hdl->param.gains.alogm);
audio_anc_fade_ctr_set(ANC_FADE_MODE_SWITCH, AUDIO_ANC_FDAE_CH_ALL, 0);
usr_timeout_add((void *)0, anc_user_train_timeout, dly, 1);
} else {
anc_user_train_timeout(NULL);
}
} else
#endif/*ANC_EAR_ADAPTIVE_EN*/
{
anc_mode_switch_deal(mode);
}
/* anc_mode_switch_deal(mode); */
}
}
static void anc_ui_mode_sel_timer(void *priv)
{
if (anc_hdl->ui_mode_sel && (anc_hdl->ui_mode_sel != anc_hdl->param.mode)) {
/*
*
*tws提示音同步播放完成
*/
if ((tone_get_status() == 0) && (anc_hdl->sync_busy == 0)) {
user_anc_log("anc_ui_mode_sel_timer:%d,sync_busy:%d", anc_hdl->ui_mode_sel, anc_hdl->sync_busy);
anc_mode_switch(anc_hdl->ui_mode_sel, 1);
sys_timer_del(anc_hdl->ui_mode_sel_timer);
anc_hdl->ui_mode_sel_timer = 0;
}
}
}
/*ANC通过ui菜单选择anc模式,处理快速切换的情景*/
void anc_ui_mode_sel(u8 mode, u8 tone_play)
{
/*
*timer存在表示上个模式还没有完成切换
*
*tws提示音同步播放完成
*/
if ((anc_hdl->ui_mode_sel_timer == 0) && (tone_get_status() == 0) && (anc_hdl->sync_busy == 0)) {
user_anc_log("anc_ui_mode_sel[ok]:%d", mode);
anc_mode_switch(mode, tone_play);
} else {
user_anc_log("anc_ui_mode_sel[dly]:%d,timer:%d,sync_busy:%d", mode, anc_hdl->ui_mode_sel_timer, anc_hdl->sync_busy);
anc_hdl->ui_mode_sel = mode;
if (anc_hdl->ui_mode_sel_timer == 0) {
anc_hdl->ui_mode_sel_timer = sys_timer_add(NULL, anc_ui_mode_sel_timer, 50);
}
}
}
/*tws同步播放模式提示音并且同步进入anc模式*/
void anc_tone_sync_play(int tone_name)
{
#if TCFG_USER_TWS_ENABLE
if (anc_hdl) {
user_anc_log("anc_tone_sync_play:%d", tone_name);
os_taskq_post_msg("anc", 2, ANC_MSG_TONE_SYNC, tone_name);
}
#endif/*TCFG_USER_TWS_ENABLE*/
}
/*ANC模式同步(tws模式)*/
void anc_mode_sync(u8 *data)
{
//data[0] mode;
//data[1] adaptive_seq;
//data[2] scene_id;
if (anc_hdl) {
#if ANC_EAR_ADAPTIVE_EN
anc_hdl->ear_adaptive_seq = data[1];
#endif/*ANC_EAR_ADAPTIVE_EN*/
#if ANC_MULT_ORDER_ENABLE
anc_hdl->scene_id = data[2];
#endif/*ANC_MULT_ORDER_ENABLE*/
os_taskq_post_msg("anc", 2, ANC_MSG_MODE_SYNC, data[0]);
}
}
/*在anc任务里面切换anc模式避免上一次切换没有完成这次切换被忽略的情况*/
void anc_mode_switch_in_anctask(u8 mode, u8 tone_play)
{
if (anc_hdl) {
os_taskq_post_msg("anc", 3, ANC_MSG_MODE_SWITCH_IN_ANCTASK, mode, tone_play);
}
}
/*ANC挂起*/
void anc_suspend(void)
{
if (anc_hdl) {
user_anc_log("anc_suspend\n");
anc_hdl->suspend = 1;
anc_hdl->param.tool_enablebit = 0; //使能设置为0
if (anc_hdl->param.anc_fade_en) { //挂起ANC增益淡出
audio_anc_fade_ctr_set(ANC_FADE_MODE_SUSPEND, AUDIO_ANC_FDAE_CH_ALL, 0);
}
audio_anc_en_set(0);
}
}
/*ANC恢复*/
void anc_resume(void)
{
if (anc_hdl) {
user_anc_log("anc_resume\n");
anc_hdl->suspend = 0;
anc_hdl->param.tool_enablebit = anc_hdl->param.enablebit; //使能恢复
audio_anc_en_set(1);
if (anc_hdl->param.anc_fade_en) { //恢复ANC增益淡入
//避免param.anc_fade_gain 被修改,这里使用固定值
audio_anc_fade_ctr_set(ANC_FADE_MODE_SUSPEND, AUDIO_ANC_FDAE_CH_ALL, ANC_FADE_GAIN_DEFAULT);
}
}
}
/*ANC信息保存*/
void anc_info_save()
{
if (anc_hdl) {
anc_info_t anc_info;
int ret = syscfg_read(CFG_ANC_INFO, &anc_info, sizeof(anc_info));
if (ret == sizeof(anc_info)) {
#if INEAR_ANC_UI
if (anc_info.mode == anc_hdl->param.mode && anc_info.inear_tws_mode == inear_tws_ancmode) {
#else
if (anc_info.mode == anc_hdl->param.mode) {
#endif/*INEAR_ANC_UI*/
user_anc_log("anc info.mode == cur_anc_mode");
return;
}
} else {
user_anc_log("read anc_info err");
}
user_anc_log("save anc_info");
anc_info.mode = anc_hdl->param.mode;
#if INEAR_ANC_UI
anc_info.inear_tws_mode = inear_tws_ancmode;
#endif/*INEAR_ANC_UI*/
ret = syscfg_write(CFG_ANC_INFO, &anc_info, sizeof(anc_info));
if (ret != sizeof(anc_info)) {
user_anc_log("anc info save err!\n");
}
}
}
/*系统上电的时候,根据配置决定是否进入上次的模式*/
void anc_poweron(void)
{
if (anc_hdl) {
#if ANC_INFO_SAVE_ENABLE
anc_info_t anc_info;
int ret = syscfg_read(CFG_ANC_INFO, &anc_info, sizeof(anc_info));
if (ret == sizeof(anc_info)) {
user_anc_log("read anc_info succ,state:%s,mode:%s", anc_state_str[anc_hdl->state], anc_mode_str[anc_info.mode]);
#if INEAR_ANC_UI
inear_tws_ancmode = anc_info.inear_tws_mode;
#endif/*INEAR_ANC_UI*/
if ((anc_hdl->state == ANC_STA_INIT) && (anc_info.mode != ANC_OFF)) {
anc_mode_switch(anc_info.mode, 0);
}
} else {
user_anc_log("read anc_info err");
}
#endif/*ANC_INFO_SAVE_ENABLE*/
}
}
/*ANC poweroff*/
void anc_poweroff(void)
{
if (anc_hdl) {
#if ANC_POWEOFF_SAVE_ADAPTIVE_DATA && ANC_EAR_ADAPTIVE_EN && (!ANC_DEVELOPER_MODE_EN)
if (anc_hdl->ear_adaptive_data_from == ANC_ADAPTIVE_DATA_FROM_ALOGM) { //表示数据已经更新
audio_anc_adaptive_data_save(&anc_hdl->adaptive_iir);
}
#endif/*ANC_POWEOFF_SAVE_ADAPTIVE_DATA*/
user_anc_log("anc_cur_state:%s\n", anc_state_str[anc_hdl->state]);
#if ANC_INFO_SAVE_ENABLE
anc_info_save();
#endif/*ANC_INFO_SAVE_ENABLE*/
if (anc_hdl->state == ANC_STA_OPEN) {
user_anc_log("anc_poweroff\n");
/*close anc module when fade_out timeout*/
anc_hdl->param.mode = ANC_OFF;
anc_hdl->new_mode = anc_hdl->param.mode;
anc_fade(0);
}
}
}
/*模式切换测试demo*/
#define ANC_MODE_NUM 3 /*ANC模式循环切换*/
static const u8 anc_mode_switch_tab[ANC_MODE_NUM] = {
ANC_OFF,
ANC_TRANSPARENCY,
ANC_ON,
};
void anc_mode_next(void)
{
if (anc_hdl) {
if (anc_train_open_query()) {
return;
}
u8 next_mode = 0;
local_irq_disable();
anc_hdl->param.anc_fade_en = ANC_FADE_EN; //防止被其他地方清0
for (u8 i = 0; i < ANC_MODE_NUM; i++) {
if (anc_mode_switch_tab[i] == anc_hdl->param.mode) {
next_mode = i + 1;
if (next_mode >= ANC_MODE_NUM) {
next_mode = 0;
}
if ((anc_hdl->mode_enable & BIT(anc_mode_switch_tab[next_mode])) == 0) {
user_anc_log("anc_mode_filt,next:%d,en:%d", next_mode, anc_hdl->mode_enable);
next_mode++;
if (next_mode >= ANC_MODE_NUM) {
next_mode = 0;
}
}
//g_printf("fine out anc mode:%d,next:%d,i:%d",anc_hdl->param.mode,next_mode,i);
break;
}
}
local_irq_enable();
//user_anc_log("anc_next_mode:%d old:%d,new:%d", next_mode, anc_hdl->param.mode, anc_mode_switch_tab[next_mode]);
u8 new_mode = anc_mode_switch_tab[next_mode];
user_anc_log("new_mode:%s", anc_mode_str[new_mode]);
#if ANC_EAR_ADAPTIVE_EN && ANC_EAR_ADAPTIVE_EVERY_TIME //非通话状态下,每次切模式都自适应
if ((anc_mode_switch_tab[next_mode] == ANC_ON) && (bt_phone_dec_is_running() == 0)) {
anc_hdl->param.mode = ANC_ON;
anc_hdl->new_mode = anc_hdl->param.mode;
audio_anc_mode_ear_adaptive(1);
} else
#endif/*ANC_EAR_ADAPTIVE_EVERY_TIME*/
{
anc_mode_switch(anc_mode_switch_tab[next_mode], 1);
}
}
}
/*设置ANC支持切换的模式*/
void anc_mode_enable_set(u8 mode_enable)
{
if (anc_hdl) {
anc_hdl->mode_enable = mode_enable;
u8 mode_cnt = 0;
for (u8 i = 1; i < 4; i++) {
if (mode_enable & BIT(i)) {
mode_cnt++;
user_anc_log("%s Select", anc_mode_str[i]);
}
}
user_anc_log("anc_mode_enable_set:%d", mode_cnt);
anc_hdl->mode_num = mode_cnt;
}
}
/*获取anc状态0:空闲l:忙*/
u8 anc_status_get(void)
{
u8 status = 0;
if (anc_hdl) {
if (anc_hdl->state == ANC_STA_OPEN) {
status = 1;
}
}
return status;
}
/*获取anc当前模式*/
u8 anc_mode_get(void)
{
if (anc_hdl) {
//user_anc_log("anc_mode_get:%s", anc_mode_str[anc_hdl->param.mode]);
return anc_hdl->param.mode;
}
return 0;
}
/*获取anc记录的最新的目标ANC模式*/
u8 anc_new_target_mode_get(void)
{
if (anc_hdl) {
//user_anc_log("anc_mode_get:%s", anc_mode_str[anc_hdl->new_mode]);
return anc_hdl->new_mode;
}
return 0;
}
/*获取anc模式dac左右声道的增益*/
u8 anc_dac_gain_get(u8 ch)
{
u8 gain = 0;
if (anc_hdl) {
gain = anc_hdl->param.gains.dac_gain;
}
return gain;
}
/*获取anc模式ff_mic的增益*/
u8 audio_anc_ffmic_gain_get(void)
{
u8 gain = 0;
if (anc_hdl) {
if (anc_hdl->param.ch & ANC_L_CH) {
gain = anc_hdl->param.gains.l_ffmic_gain;
} else {
gain = anc_hdl->param.gains.r_ffmic_gain;
}
}
return gain;
}
/*获取anc模式fb_mic的增益*/
u8 audio_anc_fbmic_gain_get(void)
{
u8 gain = 0;
if (anc_hdl) {
if (anc_hdl->param.ch & ANC_L_CH) {
gain = anc_hdl->param.gains.l_fbmic_gain;
} else {
gain = anc_hdl->param.gains.r_fbmic_gain;
}
}
return gain;
}
/*获取anc模式指定mic的增益, mic_sel:目标MIC通道*/
u8 audio_anc_mic_gain_get(u8 mic_sel)
{
return anc_hdl->param.mic_param[mic_sel].gain;
}
/*anc coeff读接口*/
int *anc_coeff_read(void)
{
#if ANC_BOX_READ_COEFF
int *coeff = anc_db_get(ANC_DB_COEFF, &anc_hdl->param.coeff_size);
if (coeff) {
coeff = (int *)((u8 *)coeff);
}
user_anc_log("anc_coeff_read:0x%x", (u32)coeff);
return coeff;
#else
return NULL;
#endif/*ANC_BOX_READ_COEFF*/
}
/*anc coeff写接口*/
int anc_coeff_write(int *coeff, u16 len)
{
int ret = 0;
u8 single_type = 0;
anc_coeff_t *db_coeff = (anc_coeff_t *)coeff;
anc_coeff_t *tmp_coeff = NULL;
#if ANC_MULT_ORDER_ENABLE
return -1;
#endif/**/
user_anc_log("anc_coeff_write:0x%x, len:%d", (u32)coeff, len);
ret = anc_coeff_check(db_coeff, len);
if (ret) {
return ret;
}
if (db_coeff->cnt != 1) {
ret = anc_db_put(&anc_hdl->param, NULL, (anc_coeff_t *)coeff);
} else { //保存对应的单项滤波器
ret = anc_coeff_single_fill(&anc_hdl->param, (anc_coeff_t *)coeff);
}
if (ret) {
user_anc_log("anc_coeff_write err:%d", ret);
return -1;
}
db_coeff = (anc_coeff_t *)anc_db_get(ANC_DB_COEFF, &anc_hdl->param.coeff_size);
user_anc_log("anc_db coeff_size %d\n", anc_hdl->param.coeff_size);
anc_coeff_fill(db_coeff);
#if ANC_EAR_ADAPTIVE_EN
audio_anc_param_map(1, 0);
#endif/*ANC_EAR_ADAPTIVE_EN*/
if (anc_hdl->param.mode != ANC_OFF) { //实时更新填入使用
audio_anc_reset(&anc_hdl->param, 0);
}
return 0;
}
static u8 ANC_idle_query(void)
{
if (anc_hdl) {
/*ANC训练模式不进入低功耗*/
if (anc_train_open_query()) {
return 0;
}
}
return 1;
}
static enum LOW_POWER_LEVEL ANC_level_query(void)
{
if (anc_hdl == NULL) {
return LOW_POWER_MODE_SLEEP;
}
/*根据anc的状态选择sleep等级*/
if (anc_status_get() || anc_hdl->mode_switch_lock) {
/*anc打开进入轻量级低功耗*/
return LOW_POWER_MODE_LIGHT_SLEEP;
}
/*anc关闭进入最优低功耗*/
return LOW_POWER_MODE_DEEP_SLEEP;
}
/* AT_VOLATILE_RAM_CODE */
AT(.volatile_ram_code)
u8 is_lowpower_anc_active()
{
if (anc_hdl->state == ANC_STA_OPEN || anc_hdl->mode_switch_lock) {
/* 若anc 开启则进入轻量级低功耗时保持住ANC对应时钟 */
if ((anc_hdl->param.ch == (ANC_L_CH | ANC_R_CH)) && !anc_hdl->param.lr_lowpower_en) {
return ANC_CLOCK_USE_PLL;
} else {
return ANC_CLOCK_USE_BTOSC;
}
}
return ANC_CLOCK_USE_CLOSE;
}
REGISTER_LP_TARGET(ANC_lp_target) = {
.name = "ANC",
.level = ANC_level_query,
.is_idle = ANC_idle_query,
};
void chargestore_uart_data_deal(u8 *data, u8 len)
{
/* anc_uart_process(data, len); */
}
#if TCFG_ANC_TOOL_DEBUG_ONLINE
//回复包
void anc_ci_send_packet(u32 id, u8 *packet, int size)
{
if (DB_PKT_TYPE_ANC == id) {
app_online_db_ack(anc_hdl->anc_parse_seq, packet, size);
return;
}
/* y_printf("anc_app_spp_tx\n"); */
ci_send_packet(id, packet, size);
}
//接收函数
static int anc_app_online_parse(u8 *packet, u8 size, u8 *ext_data, u16 ext_size)
{
/* y_printf("anc_app_spp_rx\n"); */
anc_hdl->anc_parse_seq = ext_data[1];
anc_spp_rx_packet(packet, size);
return 0;
}
//发送函数
void anc_btspp_packet_tx(u8 *packet, int size)
{
app_online_db_send(DB_PKT_TYPE_ANC, packet, size);
}
#endif/*TCFG_ANC_TOOL_DEBUG_ONLINE*/
u8 anc_btspp_train_again(u8 mode, u32 dat)
{
/* tws_api_detach(TWS_DETACH_BY_POWEROFF); */
//ANC模式下可直接获取REF+ERRMIC的数据
/* if((dat == 3) || (dat == 5)) { */
/* anc_hdl->param.debug_sel = dat; */
/* os_taskq_post_msg("anc", 1, ANC_MSG_MIC_DATA_GET); */
/* return 0; */
/* } */
#if ANC_EAR_ADAPTIVE_EN
if (anc_hdl->ear_adaptive_busy) { //ANC自适应切换时不支持获取DMA
return 0;
}
#if TCFG_USER_TWS_ENABLE
switch (dat) {
case 2:
dat = 4;
break;
case 3:
dat = 5;
break;
case 6:
dat = 7;
break;
}
#endif/*TCFG_USER_TWS_ENABLE*/
#endif/*ANC_EAR_ADAPTIVE_EN*/
user_anc_log("anc_btspp_train_again\n");
audio_anc_close();
anc_hdl->state = ANC_STA_INIT;
anc_train_open(mode, (u8)dat);
return 1;
}
u8 audio_anc_develop_get(void)
{
return anc_hdl->param.developer_mode;
}
void audio_anc_develop_set(u8 mode)
{
#if (!ANC_DEVELOPER_MODE_EN) && ANC_EAR_ADAPTIVE_EN //非强制开发者模式跟随工具设置
if (mode != anc_hdl->param.developer_mode) {
anc_hdl->param.developer_mode = mode;
if (anc_hdl->param.mode != ANC_OFF) {
anc_mode_switch(ANC_OFF, 0); //避免右耳参数异常,让调试者感受不适
}
if (anc_hdl->param.anc_coeff_mode == ANC_COEFF_MODE_ADAPTIVE) {
return; //自适应模式不更新参数
}
if (mode) { //0 -> 1
audio_anc_param_map(1, 1); //映射ANC参数
audio_anc_adaptive_poweron_catch_data(&anc_hdl->adaptive_iir); //打包自适应数据,等待工具读取
} else { //1 -> 0
audio_anc_db_cfg_read(); //读取ANC配置区的数据
if (anc_adaptive_data) {
free_anc_data_packet(anc_adaptive_data);
anc_adaptive_data = NULL;
}
}
}
#endif/*ANC_DEVELOPER_MODE_EN*/
}
/*ANC配置在线读取接口*/
int anc_cfg_online_deal(u8 cmd, anc_gain_t *cfg)
{
/*同步在线更新配置*/
int ret = 0;
anc_gain_param_t *gains = &anc_hdl->param.gains;
anc_param_fill(cmd, cfg);
if (cmd == ANC_CFG_WRITE) {
/*实时更新ANC配置*/
audio_anc_dac_gain(gains->dac_gain, gains->dac_gain);
audio_anc_mic_management(&anc_hdl->param);
audio_anc_mic_gain(anc_hdl->param.mic_param, 0);
anc_mix_out_audio_drc_thr(gains->audio_drc_thr);
if (anc_hdl->param.mode != ANC_OFF) { //实时更新填入使用
#if ANC_MULT_ORDER_ENABLE
anc_mult_scene_set(anc_hdl->scene_id); //覆盖增益以及增益符号
#endif/*ANC_MULT_ORDER_ENABLE*/
audio_anc_reset(&anc_hdl->param, 0); //不可异步因为后面会更新ANCIF区域内容
#if ANC_MULT_ORDER_ENABLE
audio_anc_mult_scene_coeff_free(); //释放空间
#endif/*ANC_MULT_ORDER_ENABLE*/
}
/*仅修改增益配置*/
ret = anc_db_put(&anc_hdl->param, cfg, NULL);
if (ret) {
user_anc_log("ret %d\n", ret);
anc_hdl->param.lff_coeff = NULL;
anc_hdl->param.rff_coeff = NULL;
anc_hdl->param.lfb_coeff = NULL;
anc_hdl->param.rfb_coeff = NULL;
};
}
return 0;
}
#if 0
/*ANC数字MIC IO配置*/
static atomic_t dmic_mux_ref;
#define DMIC_SCLK_FROM_PLNK 0
#define DMIC_SCLK_FROM_ANC 1
void dmic_io_mux_ctl(u8 en, u8 sclk_sel)
{
user_anc_log("dmic_io_mux,en:%d,sclk:%d,ref:%d\n", en, sclk_sel, atomic_read(&dmic_mux_ref));
if (en) {
if (atomic_read(&dmic_mux_ref)) {
user_anc_log("DMIC_IO_MUX open now\n");
if (sclk_sel == DMIC_SCLK_FROM_ANC) {
user_anc_log("plink_sclk -> anc_sclk\n");
gpio_set_fun_output_port(TCFG_AUDIO_PLNK_SCLK_PIN, FO_ANC_MICCK, 0, 1, LOW_POWER_KEEP);
}
atomic_inc_return(&dmic_mux_ref);
return;
}
if (sclk_sel == DMIC_SCLK_FROM_ANC) {
gpio_set_fun_output_port(TCFG_AUDIO_PLNK_SCLK_PIN, FO_ANC_MICCK, 0, 1, LOW_POWER_KEEP);
} else {
gpio_set_fun_output_port(TCFG_AUDIO_PLNK_SCLK_PIN, FO_PLNK_SCLK, 0, 1, LOW_POWER_KEEP);
}
gpio_set_direction(TCFG_AUDIO_PLNK_SCLK_PIN, 0);
gpio_set_die(TCFG_AUDIO_PLNK_SCLK_PIN, 0);
gpio_direction_output(TCFG_AUDIO_PLNK_SCLK_PIN, 1);
#if TCFG_AUDIO_PLNK_DAT0_PIN != NO_CONFIG_PORT
//anc data0 port init
gpio_set_pull_down(TCFG_AUDIO_PLNK_DAT0_PIN, 0);
gpio_set_pull_up(TCFG_AUDIO_PLNK_DAT0_PIN, 1);
gpio_set_direction(TCFG_AUDIO_PLNK_DAT0_PIN, 1);
gpio_set_die(TCFG_AUDIO_PLNK_DAT0_PIN, 1);
gpio_set_fun_input_port(TCFG_AUDIO_PLNK_DAT0_PIN, PFI_PLNK_DAT0, LOW_POWER_KEEP);
#endif/*TCFG_AUDIO_PLNK_DAT0_PIN != NO_CONFIG_PORT*/
#if TCFG_AUDIO_PLNK_DAT1_PIN != NO_CONFIG_PORT
//anc data1 port init
gpio_set_pull_down(TCFG_AUDIO_PLNK_DAT1_PIN, 0);
gpio_set_pull_up(TCFG_AUDIO_PLNK_DAT1_PIN, 1);
gpio_set_direction(TCFG_AUDIO_PLNK_DAT1_PIN, 1);
gpio_set_die(TCFG_AUDIO_PLNK_DAT1_PIN, 1);
gpio_set_fun_input_port(TCFG_AUDIO_PLNK_DAT1_PIN, PFI_PLNK_DAT1, LOW_POWER_KEEP);
#endif/*TCFG_AUDIO_PLNK_DAT1_PIN != NO_CONFIG_PORT*/
atomic_inc_return(&dmic_mux_ref);
} else {
if (atomic_read(&dmic_mux_ref)) {
atomic_dec_return(&dmic_mux_ref);
if (atomic_read(&dmic_mux_ref)) {
if (sclk_sel == DMIC_SCLK_FROM_ANC) {
user_anc_log("anc close now,anc_sclk->plnk_sclk\n");
gpio_set_fun_output_port(TCFG_AUDIO_PLNK_SCLK_PIN, FO_PLNK_SCLK, 0, 1, LOW_POWER_KEEP);
} else {
user_anc_log("plnk close,anc_plnk open\n");
}
} else {
user_anc_log("dmic all close,disable plnk io_mapping output\n");
gpio_disable_fun_output_port(TCFG_AUDIO_PLNK_SCLK_PIN);
#if TCFG_AUDIO_PLNK_DAT0_PIN != NO_CONFIG_PORT
gpio_disable_fun_input_port(TCFG_AUDIO_PLNK_DAT0_PIN);
#endif/*TCFG_AUDIO_PLNK_DAT0_PIN != NO_CONFIG_PORT*/
#if TCFG_AUDIO_PLNK_DAT1_PIN != NO_CONFIG_PORT
gpio_disable_fun_input_port(TCFG_AUDIO_PLNK_DAT1_PIN);
#endif/*TCFG_AUDIO_PLNK_DAT1_PIN != NO_CONFIG_PORT*/
}
} else {
user_anc_log("dmic_mux_ref NULL\n");
}
}
}
void anc_dmic_io_init(audio_anc_t *param, u8 en)
{
if (en) {
int i;
for (i = 0; i < 4; i++) {
if ((param->mic_type[i] > A_MIC1) && (param->mic_type[i] != MIC_NULL)) {
user_anc_log("anc_dmic_io_init %d:%d\n", i, param->mic_type[i]);
dmic_io_mux_ctl(1, DMIC_SCLK_FROM_ANC);
break;
}
}
} else {
dmic_io_mux_ctl(0, DMIC_SCLK_FROM_ANC);
}
}
#else
void anc_dmic_io_init(audio_anc_t *param, u8 en)
{
}
#endif
extern void mix_out_drc_threadhold_update(float threadhold);
static void anc_mix_out_audio_drc_thr(float thr)
{
if (thr > 0.0 || thr < -6.0 || anc_hdl->param.enablebit == ANC_FB_EN) {
thr = 0.0;
}
mix_out_drc_threadhold_update(thr);
}
#if TCFG_AUDIO_DYNAMIC_ADC_GAIN
void anc_dynamic_micgain_start(u8 audio_mic_gain)
{
int anc_mic_gain, i, diff_gain;
u8 flag = 0;
float ffgain;
float multiple = 1.259;
if (!anc_status_get()) {
anc_hdl->mic_dy_state = ANC_MIC_DY_STA_INIT;
return;
}
memcpy(anc_hdl->dy_mic_param, anc_hdl->param.mic_param, sizeof(audio_adc_mic_mana_t) * 4);
for (i = 0; i < 4; i++) { //动态MIC增益调整时忽略FBmic
if ((anc_hdl->dy_mic_param[i].type % 2) == 1) {
anc_hdl->dy_mic_param[i].mult_flag = 0;
printf("clean anc_hdl->dy_mic_param[%d].mult_flag\n", i);
}
}
anc_hdl->drc_ratio = 1.0;
ffgain = (float)(anc_hdl->param.mode == ANC_TRANSPARENCY ? anc_hdl->param.gains.drctrans_norgain : anc_hdl->param.gains.drcff_norgain);
for (i = 0; i < 4; i++) {
if (anc_hdl->dy_mic_param[i].mult_flag) {
anc_mic_gain = anc_hdl->dy_mic_param[i].gain;
anc_hdl->dy_mic_param[i].gain = audio_mic_gain;
flag = 1;
user_anc_log("after mic%d en %d, gain %d, type %d, mult_flag %d\n", i, anc_hdl->dy_mic_param[i].en, \
anc_hdl->dy_mic_param[i].gain, anc_hdl->dy_mic_param[i].type, anc_hdl->dy_mic_param[i].mult_flag);
}
}
if ((!flag) || (!(audio_mic_gain - anc_mic_gain))) {
user_anc_log("There is no common MIC\n");
anc_hdl->mic_dy_state = ANC_MIC_DY_STA_STOP;
return;
}
anc_hdl->mic_dy_state = ANC_MIC_DY_STA_START;
if (anc_hdl->mic_resume_timer) {
sys_timer_del(anc_hdl->mic_resume_timer);
anc_hdl->mic_resume_timer = 0;
}
anc_hdl->mic_diff_gain = audio_mic_gain - anc_mic_gain;
multiple = (anc_hdl->mic_diff_gain < 0) ? (1.0f / multiple) : multiple;
diff_gain = (anc_hdl->mic_diff_gain < 0) ? 0 - anc_hdl->mic_diff_gain : anc_hdl->mic_diff_gain;
for (i = 0; i < diff_gain; i++) {
ffgain /= multiple;
anc_hdl->drc_ratio *= multiple;
}
audio_anc_drc_ctrl(&anc_hdl->param, anc_hdl->drc_ratio);
audio_anc_mic_gain(anc_hdl->dy_mic_param, 1);
g_printf("dynamic mic:audio_g %d,anc_g %d, diff_g %d, ff_gain %d, mult %d/100\n", audio_mic_gain, anc_mic_gain, anc_hdl->mic_diff_gain, (s16)ffgain, (int)(multiple * 100.0f));
}
void anc_dynamic_micgain_resume_timer(void *priv)
{
float multiple = 1.259;
audio_adc_mic_mana_t mic_param[4];
if (anc_hdl->mic_diff_gain > 0) {
anc_hdl->mic_diff_gain--;
anc_hdl->drc_ratio /= multiple;
if (!anc_hdl->mic_diff_gain) {
anc_hdl->drc_ratio = 1.0;
}
for (int i = 0; i < 4; i++) {
if (anc_hdl->dy_mic_param[i].mult_flag) {
anc_hdl->dy_mic_param[i].gain--;
}
}
} else if (anc_hdl->mic_diff_gain < 0) {
anc_hdl->mic_diff_gain++;
anc_hdl->drc_ratio *= multiple;
if (!anc_hdl->mic_diff_gain) {
anc_hdl->drc_ratio = 1.0;
}
for (int i = 0; i < 4; i++) {
if (anc_hdl->dy_mic_param[i].mult_flag) {
anc_hdl->dy_mic_param[i].gain++;
}
}
} else {
sys_timer_del(anc_hdl->mic_resume_timer);
anc_hdl->mic_resume_timer = 0;
}
audio_anc_drc_ctrl(&anc_hdl->param, anc_hdl->drc_ratio);
audio_anc_mic_gain(anc_hdl->dy_mic_param, 1);
}
void anc_dynamic_micgain_stop(void)
{
if ((anc_hdl->mic_dy_state == ANC_MIC_DY_STA_START) && anc_status_get()) {
anc_hdl->mic_dy_state = ANC_MIC_DY_STA_STOP;
anc_hdl->mic_resume_timer = sys_timer_add(NULL, anc_dynamic_micgain_resume_timer, 10);
}
}
#endif/*TCFG_AUDIO_DYNAMIC_ADC_GAIN*/
void audio_anc_post_msg_drc(void)
{
os_taskq_post_msg("anc", 1, ANC_MSG_DRC_TIMER);
}
void audio_anc_post_msg_debug(void)
{
os_taskq_post_msg("anc", 1, ANC_MSG_DEBUG_OUTPUT);
}
void audio_anc_post_msg_icsd_anc_cmd(u8 cmd)
{
os_taskq_post_msg("anc", 2, ANC_MSG_ICSD_ANC_CMD, cmd);
}
void audio_anc_post_msg_user_train_init(u8 mode)
{
if (mode == ANC_ON) {
os_taskq_post_msg("anc", 1, ANC_MSG_USER_TRAIN_INIT);
}
}
void audio_anc_post_msg_user_train_run(void)
{
os_taskq_post_msg("anc", 1, ANC_MSG_USER_TRAIN_RUN);
}
void audio_anc_post_msg_user_train_setparam(void)
{
os_taskq_post_msg("anc", 1, ANC_MSG_USER_TRAIN_SETPARAM);
}
void audio_anc_post_msg_user_train_timeout(void)
{
os_taskq_post_msg("anc", 1, ANC_MSG_USER_TRAIN_TIMEOUT);
}
void audio_anc_post_msg_user_train_end(void)
{
os_taskq_post_msg("anc", 1, ANC_MSG_USER_TRAIN_END);
}
#if TCFG_ANC_SELF_DUT_GET_SZ
void audio_anc_post_msg_sz_fft_open(u8 sel)
{
os_taskq_post_msg("anc", 2, ANC_MSG_SZ_FFT_OPEN, sel);
}
void audio_anc_post_msg_sz_fft_run(void)
{
os_taskq_post_msg("anc", 1, ANC_MSG_SZ_FFT_RUN);
}
void audio_anc_post_msg_sz_fft_close(void)
{
os_taskq_post_msg("anc", 1, ANC_MSG_SZ_FFT_CLOSE);
}
static void audio_anc_sz_fft_dac_check_slience_cb(void *buf, int len)
{
if (anc_hdl->param.sz_fft.check_flag) {
s16 *check_buf = (s16 *)buf;
for (int i = 0; i < len / 2; i++) {
if (check_buf[i]) {
anc_hdl->param.sz_fft.check_flag = 0;
audio_anc_sz_fft_trigger();
audio_dac_write_callback_del(&dac_hdl, audio_anc_sz_fft_dac_check_slience_cb);
break;
}
}
}
}
//SZ_FFT测试函数
void audio_anc_sz_fft_test(void)
{
#if 0
static u8 cnt = 0;
g_printf("cnt %d\n", cnt);
switch (cnt) {
case 0:
audio_anc_post_msg_sz_fft_open(4);
break;
case 1:
audio_anc_sz_fft_trigger();
/* play_tone_file(get_tone_files()->normal); */
break;
case 2:
audio_anc_post_msg_sz_fft_close();
break;
case 3:
audio_anc_sz_fft_outbuf_release();
break;
}
if (++cnt > 3) {
cnt = 0;
}
#endif
}
#endif/* TCFG_ANC_SELF_DUT_GET_SZ*/
void audio_anc_dut_enable_set(u8 enablebit)
{
anc_hdl->param.dut_audio_enablebit = enablebit;
}
/*
ANC结构设置, ANC时生效
param: enablebit ANC结构配置(ANC_FF_EN/ANC_FB_EN/ANC_HYBRID_EN)
update_flag ANC_OFF时: 0 1
*/
void audio_anc_enable_set(u8 enablebit, u8 update_flag)
{
anc_hdl->param.tool_enablebit = enablebit;
if ((anc_hdl->param.mode != ANC_OFF) && update_flag) { //实时更新填入使用
os_taskq_post_msg("anc", 2, ANC_MSG_RESET, 1);
}
}
void audio_anc_post_msg_adt(u8 cmd)
{
os_taskq_post_msg("anc", 2, ANC_MSG_ADT, cmd);
}
void audio_anc_mic_mana_set_gain(audio_anc_t *param, u8 num, u8 type)
{
int i;
switch (type) {
case 0:
param->mic_param[num].gain = param->gains.l_ffmic_gain;
break;
case 1:
param->mic_param[num].gain = param->gains.l_fbmic_gain;
break;
case 2:
param->mic_param[num].gain = param->gains.r_ffmic_gain;
break;
case 3:
param->mic_param[num].gain = param->gains.r_fbmic_gain;
break;
}
if ((param->ch == (ANC_L_CH | ANC_R_CH)) && param->mic_param[num].mult_flag) {
for (i = 0; i < 4; i++) {
if ((param->mic_param[i].type + 1) % 2) {
param->mic_param[i].mult_flag = 1;
}
}
}
}
/*设置fb mic为复用mic*/
void audio_anc_mic_mana_fb_mult_set(u8 mult_flag)
{
if (anc_hdl) {
audio_anc_t *param = &anc_hdl->param;
for (int i = 0; i < 4; i++) {
if ((param->mic_param[i].type == ANC_MIC_TYPE_LFB) || (param->mic_param[i].type == ANC_MIC_TYPE_RFB)) {
param->mic_param[i].mult_flag = mult_flag;
}
}
}
}
void audio_anc_mic_management(audio_anc_t *param)
{
int i;
u8 double_mult_flag = 0;
for (i = 0; i < 4; i++) {
if (param->mic_type[i] == A_MIC0) {
param->mic_param[0].en = 1;
param->mic_param[0].type = i;
#if TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_0
param->mic_param[0].mult_flag = 1;
#endif/*TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_0*/
audio_anc_mic_mana_set_gain(param, 0, i);
}
if (param->mic_type[i] == A_MIC1) {
param->mic_param[1].en = 1;
param->mic_param[1].type = i;
#if TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_1
param->mic_param[1].mult_flag = 1;
#endif/*TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_1*/
audio_anc_mic_mana_set_gain(param, 1, i);
}
if (param->mic_type[i] == A_MIC2) {
param->mic_param[2].en = 1;
param->mic_param[2].type = i;
#if TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_2
param->mic_param[2].mult_flag = 1;
#endif/*TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_2*/
audio_anc_mic_mana_set_gain(param, 2, i);
}
if (param->mic_type[i] == A_MIC3) {
param->mic_param[3].en = 1;
param->mic_param[3].type = i;
#if TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_3
param->mic_param[3].mult_flag = 1;
#endif/*TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_3*/
audio_anc_mic_mana_set_gain(param, 3, i);
}
}
for (i = 0; i < 4; i++) {
printf("mic%d en %d, gain %d, type %d, mult_flag %d\n", i, param->mic_param[i].en, \
param->mic_param[i].gain, param->mic_param[i].type, param->mic_param[i].mult_flag);
}
}
void audio_anc_adc_ch_set(void)
{
#if TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_0
anc_hdl->param.adc_ch = (anc_hdl->param.adc_ch << 1) | 1;
#endif/*TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_0*/
#if TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_1
anc_hdl->param.adc_ch = (anc_hdl->param.adc_ch << 1) | 1;
#endif/*TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_1*/
#if TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_2
anc_hdl->param.adc_ch = (anc_hdl->param.adc_ch << 1) | 1;
#endif/*TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_2*/
#if TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_3
anc_hdl->param.adc_ch = (anc_hdl->param.adc_ch << 1) | 1;
#endif/*TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_3*/
if (!anc_hdl->param.adc_ch) { //通话没有使用模拟MIC则adc_ch默认赋1
anc_hdl->param.adc_ch = 1;
}
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
/* 开免摘功能后根据通话mic和免摘mic个数取最大值来打开ADC的数字通道保证免摘ADC取数正常 */
u8 esco_mic_num = audio_adc_file_get_esco_mic_num();
u8 adt_mic_num = get_icsd_adt_mic_num();
u8 mic_num = esco_mic_num > adt_mic_num ? esco_mic_num : adt_mic_num;
if (mic_num == 2) {
anc_hdl->param.adc_ch = BIT(1) | BIT(0);
} else {
anc_hdl->param.adc_ch = BIT(2) | BIT(1) | BIT(0);
}
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
}
#if ANC_ADAPTIVE_EN
static void audio_anc_adap_tone_play(int ref_lvl, int err_lvl)
{
#if ANC_ADAPTIVE_TONE_EN
if (ref_lvl == 1) {
tone_play(TONE_ANC_ADAPTIVE_LVL1, 1);
} else if (ref_lvl == 0) {
tone_play(TONE_ANC_ADAPTIVE_LVL2, 1);
}
#endif/*ANC_ADAPTIVE_TONE_EN*/
anc_pow_adap_fade_timer_add(ref_lvl, err_lvl);
}
void audio_anc_adap_sync(int ref_lvl, int err_lvl, int err)
{
os_taskq_post_msg("anc", 3, ANC_MSG_ADAPTIVE_SYNC, ref_lvl, err_lvl);
}
extern void bt_tws_anc_adap_sync_send(int ref_lvl, int err_lvl, int msec);
extern int bt_tws_anc_adap_compare_send(int ref_lvl, int err_lvl);
void audio_anc_adap_lvl_compare(int ref_lvl, int err_lvl)
{
#if TCFG_USER_TWS_ENABLE
int ref_lvl_temp, err_lvl_temp;
ref_lvl_temp = anc_pow_adap_lvl_get(ANC_FF_EN);
err_lvl_temp = anc_pow_adap_lvl_get(ANC_FB_EN);
g_printf("compare ref_lvl_temp %d, %d, lvl %d, %d\n", ref_lvl_temp, err_lvl_temp, ref_lvl, err_lvl);
if (ref_lvl_temp >= ref_lvl) {
bt_tws_anc_adap_sync_send(ref_lvl, err_lvl, 150);
}
if (err_lvl_temp >= ref_lvl) {
bt_tws_anc_adap_sync_send(ref_lvl, err_lvl, 150);
}
#endif/*TCFG_USER_TWS_ENABLE*/
}
int audio_anc_pow_adap_deal(int ref_lvl, int err_lvl)
{
#if TCFG_USER_TWS_ENABLE
if (get_tws_sibling_connect_state()) {
if (tws_api_get_role() == TWS_ROLE_MASTER) {
user_anc_log("[master]anc_pow_adap send %d %d\n", ref_lvl, err_lvl);
} else {
user_anc_log("[slave]anc_pow_adap send %d %d\n", ref_lvl, err_lvl);
}
bt_tws_anc_adap_compare_send(ref_lvl, err_lvl);
} else {
user_anc_log("[no tws]anc_pow_adap send %d %d\n", ref_lvl, err_lvl);
audio_anc_adap_tone_play(ref_lvl, err_lvl);
}
#else
user_anc_log("[no tws]anc_pow_adap send %d %d\n", ref_lvl, err_lvl);
audio_anc_adap_tone_play(ref_lvl, err_lvl);
#endif/*TCFG_USER_TWS_ENABLE*/
return 0;
}
/*切换增益模式*/
void audio_anc_adaptive_mode_set(u8 mode, u8 lvl)
{
if (anc_hdl) {
anc_hdl->param.adaptive_mode = mode;
audio_anc_pow_export_en((mode == ANC_ADAPTIVE_GAIN_MODE), 0);
if (anc_hdl->param.mode == ANC_ON) {
switch (mode) {
case ANC_ADAPTIVE_MANUAL_MODE:
user_anc_log("ANC_ADAPTIVE_MANUAL_MODE ,lvl%d\n", lvl);
audio_anc_pow_adap_stop();
anc_hdl->param.anc_lvl = lvl;
audio_anc_lvl_set(lvl, 1);
break;
case ANC_ADAPTIVE_GAIN_MODE:
user_anc_log("ANC_ADAPTIVE_GAIN_MODE\n");
anc_hdl->param.anc_fade_gain = 16384;
audio_anc_pow_adap_start();
break;
}
}
}
}
void audio_anc_pow_adap_fade(u16 gain)
{
audio_anc_fade_ctr_set(ANC_FADE_MODE_SCENE_ADAPTIVE, AUDIO_ANC_FDAE_CH_ALL, gain);
}
#endif/*ANC_ADAPTIVE_EN*/
#if ANC_MUSIC_DYNAMIC_GAIN_EN
#define ANC_MUSIC_DYNAMIC_GAIN_NORGAIN 1024 /*正常默认增益*/
#define ANC_MUSIC_DYNAMIC_GAIN_TRIGGER_INTERVAL 6 /*音乐响度取样间隔*/
#if ANC_MUSIC_DYNAMIC_GAIN_SINGLE_FB
void audio_anc_music_dyn_gain_resume_timer(void *priv)
{
if (anc_hdl->loud_nowgain < anc_hdl->loud_targetgain) {
anc_hdl->loud_nowgain += 5; ///+5耗时194 * 10ms
if (anc_hdl->loud_nowgain >= anc_hdl->loud_targetgain) {
anc_hdl->loud_nowgain = anc_hdl->loud_targetgain;
sys_timer_del(anc_hdl->loud_timeid);
anc_hdl->loud_timeid = 0;
}
} else if (anc_hdl->loud_nowgain > anc_hdl->loud_targetgain) {
anc_hdl->loud_nowgain -= 5; ///-5耗时194 * 10ms
if (anc_hdl->loud_nowgain <= anc_hdl->loud_targetgain) {
anc_hdl->loud_nowgain = anc_hdl->loud_targetgain;
sys_timer_del(anc_hdl->loud_timeid);
anc_hdl->loud_timeid = 0;
}
}
audio_anc_fbgain_set(anc_hdl->loud_nowgain, anc_hdl->loud_nowgain);
/* user_anc_log("fb resume anc_hdl->loud_nowgain %d\n", anc_hdl->loud_nowgain); */
}
#endif/*ANC_MUSIC_DYNAMIC_GAIN_SINGLE_FB*/
void audio_anc_music_dynamic_gain_process(void)
{
if (anc_hdl->loud_nowgain != anc_hdl->loud_targetgain) {
// user_anc_log("low_nowgain %d, targergain %d\n", anc_hdl->loud_nowgain, anc_hdl->loud_targetgain);
#if ANC_MUSIC_DYNAMIC_GAIN_SINGLE_FB
if (!anc_hdl->loud_timeid) {
anc_hdl->loud_timeid = sys_timer_add(NULL, audio_anc_music_dyn_gain_resume_timer, 10);
}
#else
anc_hdl->loud_nowgain = anc_hdl->loud_targetgain;
audio_anc_fade_ctr_set(ANC_FADE_MODE_MUSIC_DYNAMIC, AUDIO_ANC_FDAE_CH_ALL, anc_hdl->loud_targetgain << 4);
#endif/*ANC_MUSIC_DYNAMIC_GAIN_SINGLE_FB*/
}
}
void audio_anc_music_dynamic_gain_reset(u8 effect_reset_en)
{
if (anc_hdl->loud_targetgain != ANC_MUSIC_DYNAMIC_GAIN_NORGAIN) {
/* user_anc_log("audio_anc_music_dynamic_gain_reset\n"); */
anc_hdl->loud_targetgain = ANC_MUSIC_DYNAMIC_GAIN_NORGAIN;
if (anc_hdl->loud_timeid) {
sys_timer_del(anc_hdl->loud_timeid);
anc_hdl->loud_timeid = 0;
}
if (effect_reset_en && anc_hdl->param.mode == ANC_ON) {
os_taskq_post_msg("anc", 1, ANC_MSG_MUSIC_DYN_GAIN);
} else {
anc_hdl->loud_nowgain = ANC_MUSIC_DYNAMIC_GAIN_NORGAIN;
anc_hdl->loud_dB = 1; //清除上次保留的dB值, 避免切模式后不触发的情况
anc_hdl->loud_hdl.peak_val = ANC_MUSIC_DYNAMIC_GAIN_THR;
}
}
}
void audio_anc_music_dynamic_gain_dB_get(int dB)
{
float mult = 1.122f;
float target_mult = 1.0f;
int cnt, i, gain;
#if ANC_MUSIC_DYNAMIC_GAIN_TRIGGER_INTERVAL > 1 //区间变化,避免频繁操作
if (dB > ANC_MUSIC_DYNAMIC_GAIN_THR) {
int temp_dB = dB / ANC_MUSIC_DYNAMIC_GAIN_TRIGGER_INTERVAL;
dB = temp_dB * ANC_MUSIC_DYNAMIC_GAIN_TRIGGER_INTERVAL;
}
#endif/*ANC_MUSIC_DYNAMIC_GAIN_TRIGGER_INTERVAL*/
if (anc_hdl->loud_dB != dB) {
anc_hdl->loud_dB = dB;
if (dB > ANC_MUSIC_DYNAMIC_GAIN_THR) {
cnt = dB - ANC_MUSIC_DYNAMIC_GAIN_THR;
for (i = 0; i < cnt; i++) {
target_mult *= mult;
}
gain = (int)((float)ANC_MUSIC_DYNAMIC_GAIN_NORGAIN / target_mult);
// user_anc_log("cnt %d, dB %d, gain %d\n", cnt, dB, gain);
anc_hdl->loud_targetgain = gain;
os_taskq_post_msg("anc", 1, ANC_MSG_MUSIC_DYN_GAIN);
} else {
audio_anc_music_dynamic_gain_reset(1);
}
}
}
void audio_anc_music_dynamic_gain_det(s16 *data, int len)
{
/* putchar('l'); */
if (anc_hdl->param.mode == ANC_ON) {
loudness_meter_short(&anc_hdl->loud_hdl, data, len >> 1);
audio_anc_music_dynamic_gain_dB_get(anc_hdl->loud_hdl.peak_val);
}
}
void audio_anc_music_dynamic_gain_init(int sr)
{
/* user_anc_log("audio_anc_music_dynamic_gain_init %d\n", sr); */
anc_hdl->loud_nowgain = ANC_MUSIC_DYNAMIC_GAIN_NORGAIN;
anc_hdl->loud_targetgain = ANC_MUSIC_DYNAMIC_GAIN_NORGAIN;
anc_hdl->loud_dB = 1; //清除上次保留的dB值
loudness_meter_init(&anc_hdl->loud_hdl, sr, 50, 0);
anc_hdl->loud_hdl.peak_val = ANC_MUSIC_DYNAMIC_GAIN_THR;
}
#endif/*ANC_MUSIC_DYNAMIC_GAIN_EN*/
#if ANC_EAR_ADAPTIVE_EN
extern struct audio_decoder_task decode_task;
/* 解码任务回调,执行自适应切换 */
void audio_anc_dac_check_slience_cb(void *buf, int len)
{
if (anc_hdl->dac_check_slience_flag) {
s16 *check_buf = (s16 *)buf;
for (int i = 0; i < len / 2; i++) {
if (check_buf[i]) {
anc_hdl->dac_check_slience_flag = 0;
icsd_anctone_dacon(i, dac_hdl.sample_rate);
audio_dac_write_callback_del(&dac_hdl, audio_anc_dac_check_slience_cb);
break;
}
}
}
}
void audio_anc_ear_adaptive_open(void)
{
#if ANC_MULT_ORDER_ENABLE
//载入场景参数-提供自适应训练过程使用
u8 scene_id = ANC_MULT_ADPTIVE_TRAIN_USE_ID ? ANC_MULT_ADPTIVE_TRAIN_USE_ID : anc_hdl->scene_id;
anc_mult_scene_set(scene_id);
#endif/*ANC_MULT_ORDER_ENABLE*/
anc_hdl->ear_adaptive = 1;
anc_hdl->param.anc_coeff_mode = ANC_COEFF_MODE_ADAPTIVE; //切到自适应的参数
anc_hdl->ear_adaptive_busy = 1;
audio_anc_ear_adaptive_param_init(&anc_hdl->param);
#if ANC_USER_TRAIN_TONE_MODE
anc_hdl->dac_check_slience_flag = 1;
audio_dac_write_callback_add(&dac_hdl, audio_anc_dac_check_slience_cb);
#endif/*ANC_USER_TRAIN_TONE_MODE*/
/*自适应时需要挂起adt*/
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
audio_anc_mode_switch_in_adt(ANC_ON);
#endif
anc_mode_switch(ANC_ON, ANC_USER_TRAIN_TONE_MODE);
}
static int audio_anc_adaptive_wait_handler(struct audio_res_wait *wait, int event)
{
if (event == AUDIO_RES_GET) {
if (anc_hdl->ear_adaptive_dec_wait == ANC_ADAPTIVE_DEC_WAIT_START) {
//避免重复进入
anc_hdl->ear_adaptive_dec_wait = ANC_ADAPTIVE_DEC_WAIT_RUN;
audio_anc_ear_adaptive_open();
}
} else {
g_printf("audio_anc.c AUDIO_RES_PUT\n");
}
return 0;
}
/* 自适应解码任务注册 */
static int audio_anc_decoder_task_add(int parm)
{
anc_hdl->adaptive_wait.priority = 2; //优先级
anc_hdl->adaptive_wait.preemption = 1; //打断方式
anc_hdl->adaptive_wait.handler = audio_anc_adaptive_wait_handler;//解码任务回调
anc_hdl->ear_adaptive_dec_wait = ANC_ADAPTIVE_DEC_WAIT_START;
audio_decoder_task_add_wait(&decode_task, &anc_hdl->adaptive_wait);
return 0;
}
/*
-
param: tws_sync_en 1 TWS同步自适应TWS降噪平衡
0 , TWS降噪平衡TWS状态下单耳自适应
*/
int audio_anc_mode_ear_adaptive(u8 tws_sync_en)
{
//不支持重入自适应模式仅在ANC模式非通话下进入自适应模式
anc_hdl->ear_adaptive_tws_sync = tws_sync_en;
if (anc_hdl->param.mode == ANC_ON && !anc_hdl->ear_adaptive_busy \
&& (bt_phone_dec_is_running() == 0) && !anc_hdl->mode_switch_lock
) {
if (bt_media_is_running()) { //当前处于音乐播放状态, 注册解码任务打断,进入自适应
/* if (0) { //当前处于音乐播放状态, 注册解码任务打断,进入自适应 */
if (strcmp(os_current_task(), "app_core") != 0) {
int *ptr = malloc(2 * sizeof(int));
ptr[0] = 0;
ptr[1] = 0;
OS_SEM *sem = malloc(sizeof(OS_SEM) + 4);
int *err = (int *)(sem + 1);
ASSERT(sem);
int msg[8];
msg[0] = (int)audio_anc_decoder_task_add;
msg[1] = 1 | BIT(8) | BIT(9);
msg[2] = (int)ptr;
msg[3] = (int)err;
msg[4] = (int)sem;
os_sem_create(sem, 0);
int ret_err;
while (1) {
int ret_err = os_taskq_post_type("app_core", Q_CALLBACK, 5, msg);
if (ret_err == OS_ERR_NONE) {
os_sem_pend(sem, 0);
ret_err = *err;
break;
}
if (ret_err != OS_Q_FULL) {
break;
}
os_time_dly(2);
}
free(sem);
free(ptr);
g_printf("switch to app_core paly tone ok\n");
return 0;
} else {
audio_anc_decoder_task_add(0);
return 0;
}
}
audio_anc_ear_adaptive_open();
return 0;
}
#if (RCSP_ADV_EN && RCSP_ADV_ANC_VOICE && RCSP_ADV_ADAPTIVE_NOISE_REDUCTION)
set_adaptive_noise_reduction_reset_callback(0); // 无法进入自适应,返回失败结果
#endif
return 1;
}
/*自适应结束回调函数*/
void anc_user_train_cb(u8 mode, u8 result, u8 forced_exit)
{
user_anc_log("anc_adaptive end result 0x%x , coeff_use 0x%x\n", result, anc_hdl->adaptive_iir.result);
audio_anc_t *param = &anc_hdl->param;
anc_hdl->ear_adaptive_busy = 0;
if (forced_exit == 1) {
//强制打断,自适应定义为失败,使用默认参数
anc_hdl->adaptive_iir.result = 0;
//删除自适应DAC回调接口
audio_dac_write_callback_del(&dac_hdl, audio_anc_dac_check_slience_cb);
}
if (anc_hdl->adaptive_iir.result) { //自适应成功或部分成功
if (anc_hdl->ear_adaptive_data_from == ANC_ADAPTIVE_DATA_FROM_VM) { //释放掉原来VM使用的资源
if (anc_hdl->param.adaptive->lff_coeff) {
free(anc_hdl->param.adaptive->lff_coeff);
};
if (anc_hdl->param.adaptive->lfb_coeff) {
free(anc_hdl->param.adaptive->lfb_coeff);
};
if (anc_hdl->param.adaptive->lcmp_coeff) {
free(anc_hdl->param.adaptive->lcmp_coeff);
};
if (anc_hdl->param.adaptive->rff_coeff) {
free(anc_hdl->param.adaptive->rff_coeff);
};
if (anc_hdl->param.adaptive->rfb_coeff) {
free(anc_hdl->param.adaptive->rfb_coeff);
};
if (anc_hdl->param.adaptive->rcmp_coeff) {
free(anc_hdl->param.adaptive->rcmp_coeff);
};
}
anc_hdl->ear_adaptive_data_from = ANC_ADAPTIVE_DATA_FROM_ALOGM; //自适应参数更新
#if (ANC_CH & ANC_L_CH)
param->adaptive->lff_coeff = param->lff_coeff;
param->adaptive->lfb_coeff = param->lfb_coeff;
#if ANC_EAR_ADAPTIVE_CMP_EN
param->adaptive->lcmp_coeff = param->lcmp_coeff;
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
#endif/*(ANC_CH & ANC_L_CH)*/
#if (ANC_CH & ANC_R_CH)
param->adaptive->rff_coeff = param->rff_coeff;
param->adaptive->rfb_coeff = param->rfb_coeff;
#if ANC_EAR_ADAPTIVE_CMP_EN
param->adaptive->rcmp_coeff = param->rcmp_coeff;
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
#endif/*(ANC_CH & ANC_R_CH)*/
if (result != ANC_SUCCESS) { //非FF+FB同时成功
g_printf("no all success");
audio_anc_coeff_adaptive_set(ANC_COEFF_MODE_NORMAL, 0, 0); //先覆盖默认参数
audio_anc_coeff_adaptive_set(ANC_COEFF_MODE_ADAPTIVE, 0, 0); //根据自适应结果选择覆盖参数
}
#if (!ANC_POWEOFF_SAVE_ADAPTIVE_DATA) || ANC_DEVELOPER_MODE_EN
audio_anc_adaptive_data_save(&anc_hdl->adaptive_iir);
#endif/*ANC_POWEOFF_SAVE_ADAPTIVE_DATA*/
} else { //自适应失败使用默认的参数
audio_anc_coeff_adaptive_set(ANC_COEFF_MODE_NORMAL, 0, 0);
}
if (anc_hdl->ear_adaptive_dec_wait) {
anc_hdl->ear_adaptive_dec_wait = ANC_ADAPTIVE_DEC_WAIT_STOP;
audio_decoder_task_del_wait(&decode_task, &anc_hdl->adaptive_wait);
}
anc_mode_switch_deal(mode);
}
/*ANC滤波器模式循环切换*/
int audio_anc_coeff_adaptive_switch()
{
if (anc_hdl->param.mode == ANC_ON && !anc_hdl->ear_adaptive_busy && !anc_hdl->mode_switch_lock) {
anc_hdl->param.anc_coeff_mode ^= 1;
audio_anc_coeff_adaptive_set(anc_hdl->param.anc_coeff_mode, 1, 1);
}
return 0;
}
/*当前ANC滤波器模式获取 0:普通参数 1:自适应参数*/
int audio_anc_coeff_mode_get(void)
{
if (!anc_hdl) {
return 0;
}
return anc_hdl->param.anc_coeff_mode;
}
/*
/
param: mode 0 使; 1 使
tone_play 0 1
update_flag 0 1
*/
int audio_anc_coeff_adaptive_set(u32 mode, u8 tone_play, u8 update_flag)
{
audio_anc_t *param = &anc_hdl->param;
u8 result = anc_hdl->adaptive_iir.result;
if (anc_hdl->ear_adaptive_busy) {
return 0;
}
anc_hdl->param.anc_coeff_mode = mode;
switch (mode) {
case 0:
if (tone_play) {
tone_play_index(IDEX_TONE_ANC_NORMAL_COEFF, ANC_TONE_PREEMPTION);
}
#if ANC_COEFF_SAVE_ENABLE
#if ANC_MULT_ORDER_ENABLE
//自适应切默认参数,回到当前场景
anc_mult_scene_set(anc_hdl->scene_id);
#else
if (audio_anc_db_cfg_read()) {
return 1;
}
#endif/*ANC_MULT_ORDER_ENABLE*/
#endif/*ANC_COEFF_SAVE_ENABLE*/
break;
case 1:
if (((!anc_hdl->param.adaptive->lff_coeff) && anc_hdl->param.lff_en) || \
((!anc_hdl->param.adaptive->lfb_coeff) && anc_hdl->param.lfb_en) || \
((!anc_hdl->param.adaptive->rff_coeff) && anc_hdl->param.rff_en) || \
((!anc_hdl->param.adaptive->rfb_coeff) && anc_hdl->param.rfb_en)) {
g_printf("anc no adaptive data\n");
return 1;
}
if (tone_play) {
tone_play_index(IDEX_TONE_ANC_ADAPTIVE_COEFF, ANC_TONE_PREEMPTION);
}
#if ANC_MULT_ORDER_ENABLE
//载入场景参数-提供自适应部分成功时,匹配使用。
u8 scene_id = ANC_MULT_ADPTIVE_MATCH_USE_ID ? ANC_MULT_ADPTIVE_MATCH_USE_ID : anc_hdl->scene_id;
anc_mult_scene_set(scene_id);
#endif/*ANC_MULT_ORDER_ENABLE*/
audio_anc_ear_adaptive_param_init(&anc_hdl->param); //初始化自适应固定配置参数
#if ANC_CH & ANC_L_CH
if (result & ANC_ADAPTIVE_RESULT_LFF) {
user_anc_log("adaptive coeff set lff\n");
anc_hdl->param.gains.l_ffgain = (anc_hdl->adaptive_iir.lff_gain < 0) ? (0 - anc_hdl->adaptive_iir.lff_gain) : anc_hdl->adaptive_iir.lff_gain;
anc_hdl->param.lff_yorder = ANC_ADAPTIVE_FF_ORDER;
anc_hdl->param.lff_coeff = anc_hdl->param.adaptive->lff_coeff;
}
if (result & ANC_ADAPTIVE_RESULT_LFB) {
user_anc_log("adaptive coeff set lfb\n");
anc_hdl->param.gains.l_fbgain = (anc_hdl->adaptive_iir.lfb_gain < 0) ? (0 - anc_hdl->adaptive_iir.lfb_gain) : anc_hdl->adaptive_iir.lfb_gain;
anc_hdl->param.lfb_yorder = ANC_ADAPTIVE_FB_ORDER;
anc_hdl->param.lfb_coeff = anc_hdl->param.adaptive->lfb_coeff;
}
#if ANC_EAR_ADAPTIVE_CMP_EN
if (result & ANC_ADAPTIVE_RESULT_LCMP) {
user_anc_log("adaptive coeff set lcmp\n");
anc_hdl->param.gains.l_cmpgain = (anc_hdl->adaptive_iir.lcmp_gain < 0) ? (0 - anc_hdl->adaptive_iir.lcmp_gain) : anc_hdl->adaptive_iir.lcmp_gain;
anc_hdl->param.lcmp_coeff = anc_hdl->param.adaptive->lcmp_coeff;
anc_hdl->param.lcmp_yorder = ANC_ADAPTIVE_CMP_ORDER;
}
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
#endif/*ANC_CH*/
#if ANC_CH & ANC_R_CH
if (result & ANC_ADAPTIVE_RESULT_RFF) {
user_anc_log("adaptive coeff set rff\n");
anc_hdl->param.gains.r_ffgain = (anc_hdl->adaptive_iir.rff_gain < 0) ? (0 - anc_hdl->adaptive_iir.rff_gain) : anc_hdl->adaptive_iir.rff_gain;
anc_hdl->param.rff_yorder = ANC_ADAPTIVE_FF_ORDER;
anc_hdl->param.rff_coeff = anc_hdl->param.adaptive->rff_coeff;
}
if (result & ANC_ADAPTIVE_RESULT_RFB) {
user_anc_log("adaptive coeff set rfb\n");
anc_hdl->param.gains.r_fbgain = (anc_hdl->adaptive_iir.rfb_gain < 0) ? (0 - anc_hdl->adaptive_iir.rfb_gain) : anc_hdl->adaptive_iir.rfb_gain;
anc_hdl->param.rfb_yorder = ANC_ADAPTIVE_FB_ORDER;
anc_hdl->param.rfb_coeff = anc_hdl->param.adaptive->rfb_coeff;
}
#if ANC_EAR_ADAPTIVE_CMP_EN
if (result & ANC_ADAPTIVE_RESULT_RCMP) {
user_anc_log("adaptive coeff set rcmp\n");
anc_hdl->param.gains.r_cmpgain = (anc_hdl->adaptive_iir.rcmp_gain < 0) ? (0 - anc_hdl->adaptive_iir.rcmp_gain) : anc_hdl->adaptive_iir.rcmp_gain;
anc_hdl->param.rcmp_coeff = anc_hdl->param.adaptive->rcmp_coeff;
anc_hdl->param.rcmp_yorder = ANC_ADAPTIVE_CMP_ORDER;
}
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
#endif/*ANC_CH*/
break;
default:
return 1;
}
if ((anc_hdl->param.mode == ANC_ON) && update_flag) { //实时更新填入使用
os_taskq_post_msg("anc", 2, ANC_MSG_RESET, 1);
/* audio_anc_reset(&anc_hdl->param); */
}
//put_buf(param->lff_coeff, ANC_ADAPTIVE_FF_ORDER * 5 * 8);
//put_buf(param->lfb_coeff, ANC_ADAPTIVE_FB_ORDER * 5 * 8);
//put_buf(param->lcmp_coeff, ANC_ADAPTIVE_CMP_ORDER * 5 * 8);
return 0;
}
void audio_anc_adaptive_data_format(anc_adaptive_iir_t *iir)
{
if (anc_hdl->ear_adaptive_data_from == ANC_ADAPTIVE_DATA_EMPTY) {
anc_hdl->ear_adaptive_data_from = ANC_ADAPTIVE_DATA_FROM_VM;
if (anc_hdl->param.lff_en) {
anc_hdl->param.adaptive->lff_coeff = malloc(ANC_ADAPTIVE_FF_ORDER * sizeof(double) * 5);
}
if (anc_hdl->param.lfb_en) {
anc_hdl->param.adaptive->lfb_coeff = malloc(ANC_ADAPTIVE_FB_ORDER * sizeof(double) * 5);
#if ANC_EAR_ADAPTIVE_CMP_EN
anc_hdl->param.adaptive->lcmp_coeff = malloc(ANC_ADAPTIVE_CMP_ORDER * sizeof(double) * 5);
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
}
if (anc_hdl->param.rff_en) {
anc_hdl->param.adaptive->rff_coeff = malloc(ANC_ADAPTIVE_FF_ORDER * sizeof(double) * 5);
}
if (anc_hdl->param.rfb_en) {
anc_hdl->param.adaptive->rfb_coeff = malloc(ANC_ADAPTIVE_FB_ORDER * sizeof(double) * 5);
#if ANC_EAR_ADAPTIVE_CMP_EN
anc_hdl->param.adaptive->rcmp_coeff = malloc(ANC_ADAPTIVE_CMP_ORDER * sizeof(double) * 5);
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
}
anc_iir_t iir_lib; // 库与外部指针分离
#if ANC_CONFIG_LFF_EN
iir_lib.lff = anc_hdl->adaptive_iir.lff;
#endif/*ANC_CONFIG_LFF_EN*/
#if ANC_CONFIG_LFB_EN
iir_lib.lfb = anc_hdl->adaptive_iir.lfb;
#if ANC_EAR_ADAPTIVE_CMP_EN
iir_lib.lcmp = anc_hdl->adaptive_iir.lcmp;
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
#endif/*ANC_CONFIG_LFB_EN*/
#if ANC_CONFIG_RFF_EN
iir_lib.rff = anc_hdl->adaptive_iir.rff;
#endif/*ANC_CONFIG_RFF_EN*/
#if ANC_CONFIG_RFB_EN
iir_lib.rfb = anc_hdl->adaptive_iir.rfb;
#if ANC_EAR_ADAPTIVE_CMP_EN
iir_lib.rcmp = anc_hdl->adaptive_iir.rcmp;
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
#endif/*ANC_CONFIG_RFB_EN*/
audio_anc_adaptive_data_analsis(&iir_lib);
}
}
int audio_anc_adaptive_data_save(anc_adaptive_iir_t *iir)
{
printf("%s\n", __func__);
#if ANC_DEVELOPER_MODE_EN
//保存前做数据格式处理,避免数据异常导致上电转换数据死机
anc_hdl->ear_adaptive_data_from = ANC_ADAPTIVE_DATA_EMPTY;
audio_anc_adaptive_data_format(iir);
#endif/*ANC_DEVELOPER_MODE_EN*/
int ret = syscfg_write(CFG_ANC_ADAPTIVE_DATA_ID, (u8 *)iir, sizeof(anc_adaptive_iir_t));
/* printf("vmdata_num %d\n", *vmdata_num); */
/* put_buf((u8*)vmdata_FL, EAR_RECORD_MAX*25*4); */
/* put_buf((u8*)vmdata_FR, EAR_RECORD_MAX*25*4); */
g_printf("ret %d, %d\n", ret, sizeof(anc_adaptive_iir_t));
return ret;
}
int audio_anc_adaptive_data_read(anc_adaptive_iir_t *iir)
{
int ret = syscfg_read(CFG_ANC_ADAPTIVE_DATA_ID, (u8 *)iir, sizeof(anc_adaptive_iir_t));
if (ret == sizeof(anc_adaptive_iir_t)) { //能读取到参数, 则默认进入自适应
if (!CRC16((u8 *)iir, sizeof(anc_adaptive_iir_t))) { //读到的数全为0
r_printf("adaptive data is emtpy!!!\n");
return -1;
}
g_printf("do adaptive, ret %d\n", ret);
} else {
return -1;
//给予自适应默认参数
}
audio_anc_adaptive_poweron_catch_data(iir); //开机需确认左右耳
audio_anc_adaptive_data_format(iir);
audio_anc_coeff_adaptive_set(ANC_COEFF_MODE_ADAPTIVE, 0, 0);
return 0;
}
/*判断当前是否处于训练中*/
u8 audio_anc_adaptive_busy_get(void)
{
return anc_hdl->ear_adaptive_busy;
}
/* 自适应默认参数更新 */
void audio_anc_ear_adaptive_param_init(audio_anc_t *param)
{
param->gains.ff_1st_dcc = icsd_dcc[0];
param->gains.ff_2nd_dcc = icsd_dcc[1];
param->gains.fb_1st_dcc = icsd_dcc[2];
param->gains.fb_2nd_dcc = icsd_dcc[3];
}
void audio_anc_adaptive_fr_fail_fill(u8 *dat, u8 order, u8 result)
{
u8 fr_fail[13] = {0x2, 0x0, 0x0, 0xc8, 0x42, \
0x0, 0x0, 0x0, 0x0, \
0x0, 0x0, 0x80, 0x3f
};
if (!result) {
for (int i = 0; i < order; i++) {
memcpy(dat + 4 + i * 13, fr_fail, 13);
}
}
}
extern void anc_packet_show(anc_packet_data_t *packet);
void audio_anc_adaptive_data_packet(struct icsd_anc_tool_data *TOOL_DATA)
{
int len = TOOL_DATA->h_len;
int fb_yorder = TOOL_DATA->yorderb;
int ff_yorder = TOOL_DATA->yorderf;
int cmp_yorder = TOOL_DATA->yorderc;
int ff_dat_len = sizeof(anc_fr_t) * ff_yorder + 4;
int fb_dat_len = sizeof(anc_fr_t) * fb_yorder + 4;
int cmp_dat_len = sizeof(anc_fr_t) * cmp_yorder + 4;
anc_adaptive_iir_t *iir = &anc_hdl->adaptive_iir;
u8 *ff_dat, *fb_dat, *cmp_dat, *rff_dat, *rfb_dat, *rcmp_dat;
u8 result = icsd_anc_train_result_get(TOOL_DATA);
anc_hdl->adaptive_iir.result = result; //记录当前参数的保存结果;
#if ANC_CONFIG_LFF_EN
ff_dat = (u8 *)&iir->lff_gain;
audio_anc_fr_format(ff_dat, TOOL_DATA->data_out5, ff_yorder, ff_iir_type);
audio_anc_adaptive_fr_fail_fill(ff_dat, ff_yorder, (result & ANC_ADAPTIVE_RESULT_LFF));
#endif/*ANC_CONFIG_LFF_EN*/
#if ANC_CONFIG_LFB_EN
fb_dat = (u8 *)&iir->lfb_gain;
audio_anc_fr_format(fb_dat, TOOL_DATA->data_out4, fb_yorder, fb_iir_type);
audio_anc_adaptive_fr_fail_fill(fb_dat, fb_yorder, (result & ANC_ADAPTIVE_RESULT_LFB));
#if ANC_EAR_ADAPTIVE_CMP_EN
cmp_dat = (u8 *)&iir->lcmp_gain;
audio_anc_fr_format(cmp_dat, TOOL_DATA->data_out11, cmp_yorder, cmp_iir_type);
audio_anc_adaptive_fr_fail_fill(cmp_dat, cmp_yorder, (result & ANC_ADAPTIVE_RESULT_LCMP));
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
#endif/*ANC_CONFIG_LFB_EN*/
#if ANC_CONFIG_RFF_EN
rff_dat = (u8 *)&iir->rff_gain;
if (!ANC_CONFIG_LFF_EN) { //TWS 单R声道使用
ff_dat = rff_dat;
audio_anc_fr_format(ff_dat, TOOL_DATA->data_out5, ff_yorder, ff_iir_type);
audio_anc_adaptive_fr_fail_fill(ff_dat, ff_yorder, (result & ANC_ADAPTIVE_RESULT_LFF));
} else {
audio_anc_fr_format(rff_dat, TOOL_DATA->data_out10, ff_yorder, ff_iir_type);
audio_anc_adaptive_fr_fail_fill(rff_dat, ff_yorder, (result & ANC_ADAPTIVE_RESULT_RFF));
}
#endif/*ANC_CONFIG_RFF_EN*/
#if ANC_CONFIG_RFB_EN
rfb_dat = (u8 *)&iir->rfb_gain;
if (!ANC_CONFIG_LFB_EN) { //TWS 单R声道使用
fb_dat = rfb_dat;
audio_anc_fr_format(fb_dat, TOOL_DATA->data_out4, fb_yorder, fb_iir_type);
audio_anc_adaptive_fr_fail_fill(fb_dat, fb_yorder, (result & ANC_ADAPTIVE_RESULT_LFB));
} else {
audio_anc_fr_format(rfb_dat, TOOL_DATA->data_out9, fb_yorder, fb_iir_type);
audio_anc_adaptive_fr_fail_fill(rfb_dat, fb_yorder, (result & ANC_ADAPTIVE_RESULT_RFB));
}
#if ANC_EAR_ADAPTIVE_CMP_EN
rcmp_dat = (u8 *)&iir->rcmp_gain;
if (!ANC_CONFIG_LFB_EN) { //TWS 单R声道使用
cmp_dat = rcmp_dat;
audio_anc_fr_format(cmp_dat, TOOL_DATA->data_out11, cmp_yorder, cmp_iir_type);
audio_anc_adaptive_fr_fail_fill(cmp_dat, cmp_yorder, (result & ANC_ADAPTIVE_RESULT_LCMP));
} else {
audio_anc_fr_format(rcmp_dat, TOOL_DATA->data_out12, cmp_yorder, cmp_iir_type);
audio_anc_adaptive_fr_fail_fill(rcmp_dat, cmp_yorder, (result & ANC_ADAPTIVE_RESULT_RCMP));
}
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
#endif/*ANC_CONFIG_RFB_EN*/
if (anc_hdl->param.developer_mode) {
printf("-- len = %d\n", len);
printf("-- ff_yorder = %d\n", ff_yorder);
printf("-- fb_yorder = %d\n", fb_yorder);
printf("-- cmp_yorder = %d\n", cmp_yorder);
/* 先统一申请空间,因为下面不知道什么情况下调用函数 anc_data_catch 时令参数 init_flag 为1 */
anc_adaptive_data = anc_data_catch(anc_adaptive_data, NULL, 0, 0, 1);
#if (ANC_CH == (ANC_L_CH | ANC_R_CH)) //头戴式
r_printf("ANC ear-adaptive send data\n");
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->h_freq, len * 4, ANC_R_ADAP_FRE, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out6, len * 8, ANC_R_ADAP_SZPZ, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out7, len * 8, ANC_R_ADAP_PZ, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out8, len * 8, ANC_R_ADAP_TARGET, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out14, len * 8, ANC_R_ADAP_TARGET_CMP, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)rff_dat, ff_dat_len, ANC_R_FF_IIR, 0); //R_ff
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)rfb_dat, fb_dat_len, ANC_R_FB_IIR, 0); //R_fb
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->h_freq, len * 4, ANC_L_ADAP_FRE, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out1, len * 8, ANC_L_ADAP_SZPZ, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out2, len * 8, ANC_L_ADAP_PZ, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out3, len * 8, ANC_L_ADAP_TARGET, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out13, len * 8, ANC_L_ADAP_TARGET_CMP, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)ff_dat, ff_dat_len, ANC_L_FF_IIR, 0); //L_ff
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)fb_dat, fb_dat_len, ANC_L_FB_IIR, 0); //L_fb
#if ANC_EAR_ADAPTIVE_CMP_EN
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)cmp_dat, cmp_dat_len, ANC_L_CMP_IIR, 0); //L_cmp
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)rcmp_dat, cmp_dat_len, ANC_R_CMP_IIR, 0); //R_cmp
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
#else //入耳式
#if TCFG_USER_TWS_ENABLE
extern char bt_tws_get_local_channel(void);
if (bt_tws_get_local_channel() == 'R') {
r_printf("ANC ear-adaptive send data, ch:R\n");
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->h_freq, len * 4, ANC_R_ADAP_FRE, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out1, len * 8, ANC_R_ADAP_SZPZ, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out2, len * 8, ANC_R_ADAP_PZ, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out3, len * 8, ANC_R_ADAP_TARGET, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out13, len * 8, ANC_R_ADAP_TARGET_CMP, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)ff_dat, ff_dat_len, ANC_R_FF_IIR, 0); //R_ff
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)fb_dat, fb_dat_len, ANC_R_FB_IIR, 0); //R_fb
#if ANC_EAR_ADAPTIVE_CMP_EN
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)cmp_dat, cmp_dat_len, ANC_R_CMP_IIR, 0); //R_cmp
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
} else
#endif/*TCFG_USER_TWS_ENABLE*/
{
r_printf("ANC ear-adaptive send data, ch:L\n");
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->h_freq, len * 4, ANC_L_ADAP_FRE, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out1, len * 8, ANC_L_ADAP_SZPZ, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out2, len * 8, ANC_L_ADAP_PZ, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out3, len * 8, ANC_L_ADAP_TARGET, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)TOOL_DATA->data_out13, len * 8, ANC_L_ADAP_TARGET_CMP, 0);
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)ff_dat, ff_dat_len, ANC_L_FF_IIR, 0); //L_ff
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)fb_dat, fb_dat_len, ANC_L_FB_IIR, 0); //L_fb
#if ANC_EAR_ADAPTIVE_CMP_EN
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)cmp_dat, cmp_dat_len, ANC_L_CMP_IIR, 0); //L_cmp
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
}
#endif /* ANC_CH == (ANC_L_CH | ANC_R_CH) */
}
}
//开机自适应数据拼包,预备工具读取
void audio_anc_adaptive_poweron_catch_data(anc_adaptive_iir_t *iir)
{
if (anc_hdl->param.developer_mode) {
int i;
int ff_dat_len = sizeof(anc_fr_t) * ANC_ADAPTIVE_FF_ORDER + 4;
int fb_dat_len = sizeof(anc_fr_t) * ANC_ADAPTIVE_FB_ORDER + 4;
int cmp_dat_len = sizeof(anc_fr_t) * ANC_ADAPTIVE_CMP_ORDER + 4;
u8 *ff_dat, *fb_dat, *cmp_dat, *rff_dat, *rfb_dat, *rcmp_dat;
audio_anc_t *param = &anc_hdl->param;
#if ANC_CONFIG_LFF_EN
ff_dat = (u8 *)&iir->lff_gain;
#endif/*ANC_CONFIG_LFF_EN*/
#if ANC_CONFIG_LFB_EN
fb_dat = (u8 *)&iir->lfb_gain;
#if ANC_EAR_ADAPTIVE_CMP_EN
cmp_dat = (u8 *)&iir->lcmp_gain;
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
#endif/*ANC_CONFIG_LFB_EN*/
#if ANC_CONFIG_RFF_EN
rff_dat = (u8 *)&iir->rff_gain;
if (ff_dat == NULL) { //TWS ANC_R_CH使用
ff_dat = rff_dat;
}
#endif/*ANC_CONFIG_RFF_EN*/
#if ANC_CONFIG_RFB_EN
rfb_dat = (u8 *)&iir->rfb_gain;
if (fb_dat == NULL) { //TWS ANC_R_CH使用
fb_dat = rfb_dat;
}
#if ANC_EAR_ADAPTIVE_CMP_EN
rcmp_dat = (u8 *)&iir->rcmp_gain;
if (cmp_dat == NULL) { //TWS ANC_R_CH使用
cmp_dat = rcmp_dat;
}
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
#endif/*ANC_CONFIG_RFB_EN*/
/* 先统一申请空间,因为下面不知道什么情况下调用函数 anc_data_catch 时令参数 init_flag 为1 */
anc_adaptive_data = anc_data_catch(anc_adaptive_data, NULL, 0, 0, 1);
#if (ANC_CH == (ANC_L_CH | ANC_R_CH)) //头戴式的耳机
r_printf("ANC ear-adaptive send data\n");
if (param->lff_en && param->rff_en) {
if (iir->result & ANC_ADAPTIVE_RESULT_LFF) {
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)ff_dat, ff_dat_len, ANC_L_FF_IIR, 0); //L_ff
}
if (iir->result & ANC_ADAPTIVE_RESULT_RFF) {
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)rff_dat, ff_dat_len, ANC_R_FF_IIR, 0); //R_ff
}
}
if (iir->result & ANC_ADAPTIVE_RESULT_LFB) {
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)fb_dat, fb_dat_len, ANC_L_FB_IIR, 0); //L_fb
}
if (iir->result & ANC_ADAPTIVE_RESULT_RFB) {
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)rfb_dat, fb_dat_len, ANC_R_FB_IIR, 0); //R_fb
}
#if ANC_EAR_ADAPTIVE_CMP_EN
if (iir->result & ANC_ADAPTIVE_RESULT_LCMP) {
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)cmp_dat, cmp_dat_len, ANC_L_CMP_IIR, 0); //L_cmp
}
if (iir->result & ANC_ADAPTIVE_RESULT_RCMP) {
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)rcmp_dat, cmp_dat_len, ANC_R_CMP_IIR, 0); //R_cmp
}
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
#else //入耳式的
#if TCFG_USER_TWS_ENABLE
extern char bt_tws_get_local_channel(void);
if (bt_tws_get_local_channel() == 'R') {
r_printf("ANC ear-adaptive send data, ch:R\n");
if (param->lff_en || param->rff_en) {
if (iir->result & ANC_ADAPTIVE_RESULT_RFF) {
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)ff_dat, ff_dat_len, ANC_R_FF_IIR, 0); //R_ff
}
}
if (iir->result & ANC_ADAPTIVE_RESULT_RFB) {
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)fb_dat, fb_dat_len, ANC_R_FB_IIR, 0); //R_fb
}
#if ANC_EAR_ADAPTIVE_CMP_EN
if (iir->result & ANC_ADAPTIVE_RESULT_RCMP) {
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)cmp_dat, cmp_dat_len, ANC_R_CMP_IIR, 0); //R_cmp
}
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
} else
#endif/*TCFG_USER_TWS_ENABLE*/
{
r_printf("ANC ear-adaptive send data, ch:L\n");
if (param->lff_en || param->rff_en) {
if (iir->result & ANC_ADAPTIVE_RESULT_LFF) {
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)ff_dat, ff_dat_len, ANC_L_FF_IIR, 0); //L_ff
}
}
if (iir->result & ANC_ADAPTIVE_RESULT_LFB) {
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)fb_dat, fb_dat_len, ANC_L_FB_IIR, 0); //L_fb
}
#if ANC_EAR_ADAPTIVE_CMP_EN
if (iir->result & ANC_ADAPTIVE_RESULT_LCMP) {
anc_adaptive_data = anc_data_catch(anc_adaptive_data, (u8 *)cmp_dat, cmp_dat_len, ANC_L_CMP_IIR, 0); //L_cmp
}
#endif/*ANC_EAR_ADAPTIVE_CMP_EN*/
}
#endif /* ANC_CH == (ANC_L_CH | ANC_R_CH) */
}
}
//左右参数映射
void audio_anc_param_map(u8 coeff_en, u8 gain_en)
{
#if TCFG_USER_TWS_ENABLE && (ANC_CH != (ANC_L_CH | ANC_R_CH))
if (anc_hdl->param.developer_mode) { //开发者模式左右耳区分使用参数
if (coeff_en && (!anc_hdl->param.lff_coeff || !anc_hdl->param.rff_coeff || \
!anc_hdl->param.lfb_coeff || !anc_hdl->param.rfb_coeff)) {
#if ANC_DEVELOPER_MODE_EN
ASSERT(0, "(ERROR)ANC adaptive coeff map %x, %x, %x, %x, Maybe anc_coeff.bin is ERR!", \
anc_hdl->param.lff_coeff, anc_hdl->param.rff_coeff, \
anc_hdl->param.lfb_coeff, anc_hdl->param.rfb_coeff);
#else
user_anc_log("(ERROR)ANC adaptive coeff map %x, %x, %x, %x, Maybe anc_coeff.bin is ERR!", \
anc_hdl->param.lff_coeff, anc_hdl->param.rff_coeff, \
anc_hdl->param.lfb_coeff, anc_hdl->param.rfb_coeff);
#endif/*ANC_DEVELOPER_MODE_EN*/
}
if ((ANC_CH == ANC_L_CH) && (bt_tws_get_local_channel() == 'R')) {
user_anc_log("ANC MAP TWS_RIGHT_CHANNEL\n");
if (gain_en) {
anc_hdl->param.gains.l_ffgain = anc_hdl->param.gains.r_ffgain;
anc_hdl->param.gains.l_fbgain = anc_hdl->param.gains.r_fbgain;
anc_hdl->param.gains.l_transgain = anc_hdl->param.gains.r_transgain;
anc_hdl->param.gains.l_cmpgain = anc_hdl->param.gains.r_cmpgain;
anc_hdl->param.gains.l_ffmic_gain = anc_hdl->param.gains.r_ffmic_gain;
anc_hdl->param.gains.l_fbmic_gain = anc_hdl->param.gains.r_fbmic_gain;
anc_hdl->param.gains.gain_sign = (anc_hdl->param.gains.gain_sign >> 4);
}
if (coeff_en) {
anc_hdl->param.lff_coeff = anc_hdl->param.rff_coeff;
anc_hdl->param.lfb_coeff = anc_hdl->param.rfb_coeff;
anc_hdl->param.ltrans_coeff = anc_hdl->param.rtrans_coeff;
anc_hdl->param.lcmp_coeff = anc_hdl->param.rcmp_coeff;
anc_hdl->param.lff_yorder = anc_hdl->param.rff_yorder;
anc_hdl->param.lfb_yorder = anc_hdl->param.rfb_yorder;
anc_hdl->param.ltrans_yorder = anc_hdl->param.rtrans_yorder;
anc_hdl->param.lcmp_yorder = anc_hdl->param.rcmp_yorder;
}
} else if ((ANC_CH == ANC_R_CH) && (bt_tws_get_local_channel() == 'L')) {
user_anc_log("ANC MAP TWS_LEFT_CHANNEL\n");
if (gain_en) {
anc_hdl->param.gains.r_ffgain = anc_hdl->param.gains.l_ffgain;
anc_hdl->param.gains.r_fbgain = anc_hdl->param.gains.l_fbgain;
anc_hdl->param.gains.r_transgain = anc_hdl->param.gains.l_transgain;
anc_hdl->param.gains.r_cmpgain = anc_hdl->param.gains.l_cmpgain;
anc_hdl->param.gains.r_ffmic_gain = anc_hdl->param.gains.l_ffmic_gain;
anc_hdl->param.gains.r_fbmic_gain = anc_hdl->param.gains.l_fbmic_gain;
anc_hdl->param.gains.gain_sign = (anc_hdl->param.gains.gain_sign << 4);
}
if (coeff_en) {
anc_hdl->param.rff_coeff = anc_hdl->param.lff_coeff;
anc_hdl->param.rfb_coeff = anc_hdl->param.lfb_coeff;
anc_hdl->param.rtrans_coeff = anc_hdl->param.ltrans_coeff;
anc_hdl->param.rcmp_coeff = anc_hdl->param.lcmp_coeff;
anc_hdl->param.rff_yorder = anc_hdl->param.lff_yorder;
anc_hdl->param.rfb_yorder = anc_hdl->param.lfb_yorder;
anc_hdl->param.rtrans_yorder = anc_hdl->param.ltrans_yorder;
anc_hdl->param.rcmp_yorder = anc_hdl->param.lcmp_yorder;
}
}
}
#endif/*TCFG_USER_TWS_ENABLE*/
}
//临时接口
void icsd_audio_adc_mic_open(u8 mic_idx, u8 gain, u16 sr, u8 mic_2_dac)
{
}
u8 anc_ear_adaptive_seq_get(void)
{
if (anc_hdl) {
return anc_hdl->ear_adaptive_seq;
}
return 0;
}
void anc_ear_adaptive_forced_exit(void)
{
if (anc_hdl) {
if (anc_hdl->ear_adaptive_busy) {
icsd_anc_forced_exit();
anc_tone_stop();
}
}
}
//ANC自适应训练失败处理回调函数
void audio_anc_adaptive_fail_callback(u8 anc_err)
{
#if (RCSP_ADV_EN && RCSP_ADV_ANC_VOICE && RCSP_ADV_ADAPTIVE_NOISE_REDUCTION)
extern void set_adaptive_noise_reduction_reset_callback(u8 result);
set_adaptive_noise_reduction_reset_callback(!anc_err);
#endif
if (anc_err == 0) {
/* user_anc_log("ANC_ADAPTIVE SUCCESS==========================\n"); */
}
if (anc_err & ANC_ERR_LR_BALANCE) {
user_anc_log("ANC_ERR_LR_BALANCE==========================\n");
}
if (anc_err & ANC_ERR_SOUND_PRESSURE) {
user_anc_log("ANC_ERR_SOUND_PRESSURE==========================\n");
}
if (anc_err & ANC_ERR_SHAKE) {
user_anc_log("ANC_ERR_SHAKE==========================\n");
}
}
#endif/*ANC_EAR_ADAPTIVE_EN*/
#if ANC_MULT_ORDER_ENABLE
void audio_anc_mult_scene_set(u16 scene_id, u8 update_flag)
{
user_anc_log(" audio_anc_mult scene_id set %d\n", scene_id);
if (audio_anc_mult_scene_id_check(scene_id)) {
user_anc_log("anc_mult_scene id set err id = %d", scene_id);
return;
}
anc_hdl->scene_id = scene_id;
#if ANC_EAR_ADAPTIVE_EN
if (anc_hdl->ear_adaptive_busy) {
anc_ear_adaptive_forced_exit();
return;
}
//非自适应训练状态,切场景自动切回普通参数
anc_hdl->param.anc_coeff_mode = ANC_COEFF_MODE_NORMAL;
#endif/*ANC_EAR_ADAPTIVE_EN*/
if ((anc_hdl->param.mode != ANC_OFF) && update_flag && \
!anc_hdl->mode_switch_lock) { //实时更新填入使用
anc_mult_scene_set(scene_id);
os_taskq_post_msg("anc", 2, ANC_MSG_RESET, 1);
}
}
u8 audio_anc_mult_scene_get(void)
{
return anc_hdl->scene_id;
}
void audio_anc_mult_scene_max_set(u8 scene_cnt)
{
anc_hdl->scene_max = scene_cnt;
}
u8 audio_anc_mult_scene_max_get(void)
{
return anc_hdl->scene_max;
}
void audio_anc_mult_scene_switch(u8 tone_flag)
{
static u8 cnt = 1;
if (cnt < audio_anc_mult_scene_max_get()) {
cnt++;
} else {
cnt = 1;
}
if (tone_flag) {
tone_play_index(IDEX_TONE_NUM_0 + cnt, 0);
}
audio_anc_mult_scene_set(cnt, 1);
}
#endif/*ANC_MULT_ORDER_ENABLE*/
//ANC产测/调试模式
extern struct adc_platform_data adc_data;
void audio_anc_prodution_mode_set(u8 mode)
{
//产测 or 调试模式 关闭非必要的流程
if (mode && (!anc_hdl->param.production_mode)) { //0->1
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
/*关闭ACOUSTIC_DETECTOR所有模块*/
if (audio_icsd_adt_is_running()) {
audio_icsd_adt_close_all();
}
adc_data.anc_adt_en = 0; //关闭adc_ch绑定否则产测使用ADC中断数据会异常
#endif/* TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
} else if (!mode && (anc_hdl->param.production_mode)) { //1->0
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
adc_data.anc_adt_en = 1; //恢复adc_ch绑定
#endif/* TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
}
anc_hdl->param.production_mode = mode;
}
#endif/*TCFG_AUDIO_ANC_ENABLE*/