Files
99_7018_lmx/cpu/br28/audio_anc.c
2025-10-29 13:10:02 +08:00

3529 lines
129 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

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

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