芯片型号:AB1565
功能模块:ANC和PassThrough
功能描述:ANC和PassThrough支持动态调整其增益,比如ANC的消噪强度,或者PassThourgh的透传比例;PassThourgh其实就是在FF的ANC类型的基础上实现的,与ANC的消噪模式所不同的是滤波器的实现不同。Airoha官止提供的APP端,提供有接口可以调整这两类开增益,APP上显示的调整值的范围为[-20~0],如图1所示,那么本文讲解如何用物理按钮来实现该操作。
第一步:定义好物理按键的动作;
如下表为笔者物理按钮的定义:
键 | 单击 | 双击 |
Power | 电话接听/挂起/结束 | 电话拒接/HOLD |
音乐暂停/播放 | 进入配对模式 | |
KEY2 | 音量+ | 透传开关 |
KEY8 | 音量- | ANC开关 |
KEY9 | MIC MUTE打开/关闭 |
其中“透传”即为络达的PassThrough;
源SDK中其实并没有定义ANC/PassThrough增益调节的事件码,因此我们可以自己添加,
所在的文件为:
bta_sdk\mcu\project\ab1565_ab1568_evk\apps\headset_design\inc\apps\config\apps_config_event_list.h
在该头文件中结构体“apps_config_key_action_t”中的末尾添加如下定义:
/*------------------add by micmind-----------------*/
KEY_ANC_GAIN_UP = 0xF010,
KEY_ANC_GAIN_DOWN = 0xF011,
} apps_config_key_action_t;
第二步:定义UI;
如下代码为笔者UI中相关的定义:
const apps_config_key_event_map_t temp_key_short_click_configs[] = {
......
{
EINT_KEY_0, //GPIO2---EINT2 --- KEY2
KEY_ANC_GAIN_UP, //KEY_VOICE_UP,
(1 << APP_CONNECTED) | (1 << APP_HFP_INCOMING) | (1 << APP_HFP_OUTGOING) | (1 << APP_HFP_CALLACTIVE)
| (1 << APP_HFP_TWC_INCOMING) | (1 << APP_HFP_TWC_OUTGOING) | (1 << APP_HFP_MULTITPART_CALL) | (1 << APP_A2DP_PLAYING)
| (1 << APP_STATE_HELD_ACTIVE) | (1 << APP_ULTRA_LOW_LATENCY_PLAYING) | (1 << APP_WIRED_MUSIC_PLAY)
},
{
EINT_KEY_1, //GPIO8---EINT8 --- KEY8
KEY_ANC_GAIN_DOWN, //KEY_VOICE_DN,
(1 << APP_CONNECTED) | (1 << APP_HFP_INCOMING) | (1 << APP_HFP_OUTGOING) | (1 << APP_HFP_CALLACTIVE)
| (1 << APP_HFP_TWC_INCOMING) | (1 << APP_HFP_TWC_OUTGOING) | (1 << APP_HFP_MULTITPART_CALL) | (1 << APP_A2DP_PLAYING)
| (1 << APP_STATE_HELD_ACTIVE) | (1 << APP_ULTRA_LOW_LATENCY_PLAYING) | (1 << APP_WIRED_MUSIC_PLAY)
},
};
const apps_config_key_event_map_t temp_key_double_click_configs[] = {
......
{
EINT_KEY_0, //GPIO2---EINT2 --- KEY2
KEY_PASS_THROUGH,//KEY_SWITCH_ANC_AND_PASSTHROUGH,
(1 << APP_DISCONNECTED) | (1 << APP_CONNECTABLE) | (1 << APP_CONNECTED) | (1 << APP_A2DP_PLAYING)
},
{
EINT_KEY_1, //GPIO8---EINT8 --- KEY8
KEY_ANC,//KEY_SWITCH_ANC_AND_PASSTHROUGH,
(1 << APP_DISCONNECTED) | (1 << APP_CONNECTABLE) | (1 << APP_CONNECTED) | (1 << APP_A2DP_PLAYING)
| (1 << APP_ULTRA_LOW_LATENCY_PLAYING) | (1 << APP_WIRED_MUSIC_PLAY)
},
};
第三步:处理增益加和减的事件
那么,如何知道新添加的事件应该在哪里被处理呢?我们可以通过搜索“KEY_ANC”来确定,新添加的事件和该KEY_ANC的处理位置应该是同一个地方。
通过搜索可以知道,其事件处理位置是:
bta_sdk\mcu\project\ab1565_ab1568_evk\apps\headset_design\src\apps\app_idle\app_home_screen_idle_activity.c
中的函数:
static bool _proc_key_event_group(ui_shell_activity_t *self,
uint32_t event_id,
void *extra_data,
size_t data_len)
比葫芦画瓢,我们添加类似的对增益的处理case,如笔者的代码:
#ifdef MTK_ANC_ENABLE
case KEY_PASS_THROUGH:
case KEY_ANC:
case KEY_SWITCH_ANC_AND_PASSTHROUGH:
case KEY_BETWEEN_ANC_PASSTHROUGH:
/* Handle ANC key event. */
ret = app_home_screen_process_anc_and_pass_through(self, action);
break;
case KEY_ANC_GAIN_UP:
case KEY_ANC_GAIN_DOWN:
ret = app_home_screen_process_anc_volumn_change(action);
break;
#endif
笔者在此处添加了一个独立的函数来处理增益,该函数定义如下:
#define ANC_VOLUMN_MAX 0
#define ANC_VOLUMN_MIN -2000
#define ANC_VOLUMN_STEP 200
static bool app_home_screen_process_anc_volumn_change(apps_config_key_action_t key_action)
{
bool ret = false;
uint8_t anc_enable;
audio_anc_control_filter_id_t anc_current_filter_id;
audio_anc_control_type_t anc_current_type;
int16_t anc_runtime_gain, new_gain;
uint8_t support_hybrid_enable=0;
audio_anc_control_get_status(&anc_enable, &anc_current_filter_id, &anc_current_type, &anc_runtime_gain, &support_hybrid_enable, NULL);
GHP_LOG_MSGID_I("volumn:ancEn:%d,anctype:%d,gain:%d,fltId:%d,hyEn:%d",5,anc_enable, anc_current_type,anc_runtime_gain,anc_current_filter_id,support_hybrid_enable);
new_gain = anc_runtime_gain;
if(KEY_ANC_GAIN_UP == key_action)
{
new_gain += ANC_VOLUMN_STEP;
if(new_gain > ANC_VOLUMN_MAX) new_gain = ANC_VOLUMN_MAX;
}
else if(KEY_ANC_GAIN_DOWN == key_action)
{
new_gain -= ANC_VOLUMN_STEP;
if(new_gain < ANC_VOLUMN_MIN) new_gain = ANC_VOLUMN_MIN;
}
if(anc_enable)
{
//ret = app_anc_service_set_runtime_gain(anc_current_type,new_gain);
//GHP_LOG_MSGID_I("KEY_ANC_GAIN_DOWN[%d],oldG:%d, newG:%d",3,ret,anc_runtime_gain, new_gain);
ret = app_anc_service_enable(anc_current_filter_id, anc_current_type, new_gain, NULL);
GHP_LOG_MSGID_I("prev_gain:%d new_gain: %d, ret:%d", 3, anc_runtime_gain, new_gain, ret);
}
else
{
GHP_LOG_MSGID_I("ANC no enabled.",0);
}
return ret;
}
这里有几个事件需要搞清楚:
- 增益用哪个函数来调整;
- 增益调整值的范围是多少
这些我们可以通过日志来分析出来,我们用文章开始提到的APP来调整增益的最大值和最小值,然后分析日志得出它的范围是多少,如下图所示是用APP用ANC Filter1把增益调整为最小值-20时的相关日志:
图中可以看出,增益的值为-2000, type为0表示ANC的类型为Hybrid,其值的定义如下代码:
/** @brief ANC and Pass-through type values. */
typedef enum {
AUDIO_ANC_CONTROL_TYPE_HYBRID = 0, /**< The hybrid anc type. */
AUDIO_ANC_CONTROL_TYPE_FF = 1, /**< The feedforward anc type. */
AUDIO_ANC_CONTROL_TYPE_FB = 2, /**< The feedback anc type. */
AUDIO_ANC_CONTROL_TYPE_USER_DEFINED = 3, /**< The user defined anc type. */
AUDIO_ANC_CONTROL_TYPE_PASSTHRU_FF = 4, /**< The pass-through feedforward anc type. */
AUDIO_ANC_CONTROL_TYPE_DUMMY = 0x7FFFFFFF,
} audio_anc_control_type_t;
并且从中也可以看出来,其调整的RACE_ANC_SET_RUNTIME_VOL,我们在工程是搜索该定义,可以发现:
case RACE_ANC_SET_RUNTIME_VOL:
if (anc_param_length >= 2) {
pEvt->param.runtime_gain = pAnc_cmd->param.runtime_gain;
anc_ret = audio_anc_set_runtime_volume(pAnc_cmd->param.runtime_gain);
}
break;
从中可以看出,调用的是函数audio_anc_set_runtime_volume(),且值按无符号整数为:0xFFFFF830,因此按道理我们只需要把物理按钮的动作关联到该函数即可。 同时,也能看出,通过手机APP调整益所调用的函数为:
void* RACE_DSPREALTIME_ANC_HDR(ptr_race_pkt_t pCmdMsg, uint8_t channel_id)
那么还有另一个问题,用APP写的是绝对 值,但用按钮应该是在当前增益的基础上进行增加或减少固定的偏移,因此就需要知道当前的增益是多少。
通过代码分析可以发现,下面函数是用来获取当前ANC的配置及状态:
audio_anc_control_get_status()
它会返回ANC的开关状态,滤波器的类型,ANC的类型,当前的动态增益,是否支持hybrid;
并且还有一个函数:
bool app_anc_service_enable(audio_anc_control_filter_id_t filter_id,
audio_anc_control_type_t anc_type,
audio_anc_control_gain_t runtime_gain,
audio_anc_control_misc_t *control_misc);
用来在应用层打开或关闭ANC,以ANC的类型的增益等; 因此,笔者采用该函数来对增益进行动态调整。
第三:完成述改造之后,我们可以通过日志来验证;
如处图为用物理按键调整ANC增益的日志,anctype为0,表示ANC工作在hybrid模式下,fltid为1 表示ANC Filter1;
如下图为PassThrough增益的调节时的日志,type为4表示是ANC工作在PassThrough模式下,即:AUDIO_ANC_CONTROL_TYPE_PASSTHRU_FF
fltId为9表示滤波器为:AUDIO_ANC_CONTROL_FILTER_ID_PASS_THRU_1
至此,完成需求的功能,并验证成功;