6. AUDIO 功能
6.1. 概述
HID和SPP_AND_LE 新添加了AUDIO的实现示例代码,需要使用AUDIO功能要在板级配置使能 TCFG_AUDIO_ENABLE ,如下代码所示:
//支持Audio功能,才能使能DAC/ADC模块
#ifdef CONFIG_LITE_AUDIO
#define TCFG_AUDIO_ENABLE ENABLE
#if TCFG_AUDIO_ENABLE
#undef TCFG_AUDIO_ADC_ENABLE
#undef TCFG_AUDIO_DAC_ENABLE
#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE
#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE
- 支持板级:br23、br25、br30、br34
- 支持芯片:AC635N、AC636N、AC673N、AC638N
6.2. Audio的使用
DAC硬件输出参数配置
在板级配置文件里面有如下配置:
/* DAC硬件上的连接方式,可选的配置: DAC_OUTPUT_MONO_L 左声道 DAC_OUTPUT_MONO_R 右声道 DAC_OUTPUT_LR 立体声 DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 */ #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF需要根据具体的硬件接法,配置 TCFG_AUDIO_DAC_CONNECT_MODE 宏。
MIC配置和使用
配置说明:在每个 board.c 文件里都有配置 mic 参数的结构体,如下所示:
/* struct adc_platform_data adc_data = { .mic_channel = TCFG_AUDIO_ADC_MIC_CHA, //MIC通道选择,对于693x,MIC只有一个通道,固定选择右声道 /*MIC LDO电流档位设置: 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, /*MIC 是否省隔直电容: 0: 不省电容 1: 省电容 */ #if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 #else .mic_capless = 0, #endif /*MIC免电容方案需要设置,影响MIC的偏置电压 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ .mic_bias_res = 16, /*MIC LDO电压档位设置,也会影响MIC的偏置电压 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ .mic_ldo_vsel = 2, /*MIC电容隔直模式使用内部mic偏置*/ .mic_bias_inside = 1, /*保持内部mic偏置输出*/ .mic_bias_keep = 0, // ladc 通道 .ladc_num = ARRAY_SIZE(ladc_list), .ladc = ladc_list, };
主要关注以下变量:
mic_capless:0:选用不省电容模式 1:选用省电容模式;
mic_bias_res:选用省电容模式的时候才有效,mic 的上拉偏置电阻,选择范围为:1:16K 2:7.5K 3:5.1K 4:6.8K 5:4.7K 6:3.5K 7:2.9K 8:3K 9:2.5K 10:2.1K 11:1.9K 12:2K 13:1.8K 14:1.6K 15:1.5K 16:1K 31:0.6K;
mic_ldo_vsel:mic_ldo 的偏置电压,与偏置电阻共同决定 mic 的偏置,选择范围为:0:2.3v 1:2.5v 2:2.7v 3:3.0v;
mic_bias_inside:mic 外部电容隔直,芯片内部提供偏置电压,当 mic_bias_inside=1,可以正常使用 mic_bias_res 和 mic_ldo_vsel。
自动校准 MIC 偏置电压
使用省电容模式时,可在 app_config.h 配置 TCFG_MC_BIAS_AUTO_ADJUST,选择 MIC 的自动校准模式,自动选择对应的MIC 偏置电阻和偏置电压。配置如下:(注意:不省电容无法校准)。
/* *省电容mic偏置电压自动调整(因为校准需要时间,所以有不同的方式) *1、烧完程序(完全更新,包括配置区)开机校准一次 *2、上电复位的时候都校准,即断电重新上电就会校准是否有偏差(默认) *3、每次开机都校准,不管有没有断过电,即校准流程每次都跑 */ #define MC_BIAS_ADJUST_DISABLE 0 //省电容mic偏置校准关闭 #define MC_BIAS_ADJUST_ONE 1 //省电容mic偏置只校准一次(跟dac trim一样) #define MC_BIAS_ADJUST_POWER_ON 2 //省电容mic偏置每次上电复位都校准(Power_On_Reset) #define MC_BIAS_ADJUST_ALWAYS 3 //省电容mic偏置每次开机都校准(包括上电复位和其他复位) #define TCFG_MC_BIAS_AUTO_ADJUST MC_BIAS_ADJUST_POWER_ON #define TCFG_MC_CONVERGE_TRACE 0 //省电容mic收敛值跟踪
Mic 的使用示例:可调用 audio_adc_open_demo(void)函数输出 mic 的声音,示例如下:
if (key_type == KEY_EVENT_LONG && key_value == TCFG_ADKEY_VALUE0) { printf(">>>key0:open mic\n"); //br23/25 mic test extern int audio_adc_open_demo(void); audio_adc_open_demo(); //br30 mic test /* extern void audio_adc_mic_demo(u8 mic_idx, u8 gain, u8 mic_2_dac); */ /* audio_adc_mic_demo(1, 1, 1); */ }
6.3. 提示音使用
提示音文件配置
打开SDK对应的cpu/brxx/tools/ACxxxN_config_tool,进入配置工具入口—>选择编译前配置工具—>提示音配置。
打开以上界面按步骤添加自己需要的*.mp3格式的源文件,转换成需要的主要格式。要注意文件的路径,SDK中默认的路径可能和本地保存的路径不同,要改成SDK当前的绝对路径。
在ota的目录download.bat下载项中添加tone.cfg配置选项
播放sin/wtg提示音,要在板级配置文件里面使能TCFG_DEC_G729_ENABLE 和 TCFG_DEC_PCM_ENABLE两个宏,如下所示:
#if TCFG_AUDIO_ENABLE #undef TCFG_AUDIO_ADC_ENABLE #undef TCFG_AUDIO_DAC_ENABLE #define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE #define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE #define TCFG_DEC_G729_ENABLE ENABLE #define TCFG_DEC_PCM_ENABLE ENABLE #define TCFG_ENC_OPUS_ENABLE DISABLE #define TCFG_ENC_SPEEX_ENABLE DISABLE #define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR #else #define TCFG_DEC_PCM_ENABLE DISABLE #endif/*TCFG_AUDIO_ENABLE*/并在tone_player.h文件中定义文件名和路径:文件名和配置工具中第4步添加的提示音的名字要一致。
#define TONE_NUM_0 TONE_RES_ROOT_PATH"tone/0.*"
提示音使用示例
可以调用tone_play()播放提示音,使用示例如下
if (key_type == KEY_EVENT_LONG && key_value == TCFG_ADKEY_VALUE2) { printf(">>>key1:tone_play_test\n"); //br23/25 tone play test /* tone_play_by_path(TONE_NORMAL, 1); */ /* tone_play_by_path(TONE_BT_CONN, 1); */ //br30 tone play test tone_play(TONE_NUM_0, 1); /* tone_play(TONE_SIN_NORMAL, 1); */ }
6.4. opusspeex编码的使用
配置说明:opusspeex编码模块是对mic的数据进行编码,使用给功能,需要在板级配置文件里面使能TCFG_ENC_OPUS_ENABLE和TCFG_ENC_SPEEX_ENABLE这两个宏,配置如下图所示:
#if TCFG_AUDIO_ENABLE #undef TCFG_AUDIO_ADC_ENABLE #undef TCFG_AUDIO_DAC_ENABLE #define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE #define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE #define TCFG_DEC_G729_ENABLE ENABLE #define TCFG_DEC_PCM_ENABLE ENABLE #define TCFG_ENC_OPUS_ENABLE ENABLE #define TCFG_ENC_SPEEX_ENABLE ENABLE #define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR #else #define TCFG_DEC_PCM_ENABLE DISABLE #endif/*TCFG_AUDIO_ENABLE*/
opusspeex编码示例
int audio_mic_enc_open(**int** (*mic_output)(**void** *priv, **void** *buf, **int** len), u32 code_type);
对mic的数据进行opusspeex编码使用audio_mic_enc_open()函数,参数mic_output为编码后数据输出的函数,code_type为要进行编码的类型,可选AUDIO_CODING_OPUS和AUDIO_CODING_SPEEX,使用示例如下图:
/*encode test*/ extern int audio_mic_enc_open(int (*mic_output)(void *priv, void *buf, int len), u32 e_type); audio_mic_enc_open(mic_enc_output_data, AUDIO_CODING_OPUS);//opus encode test /* audio_mic_enc_open(mic_enc_output_data, AUDIO_CODING_SPEEX);//speex encode test *
6.5. 通用编码接口的使用
配置说明:通用编码接口在audio_codec_demo.c 文件里面,使用该接口需要在板级配置文件里面使能ENC_DEMO_EN这个宏,配置如下图所示:
#define ENC_DEMO_EN ENABLE;
要创建一个编码只需要调用如下的audio_demo_enc_open函数
int audio_demo_enc_open(\ **int** (*demo_output)(**void** \*priv, **void** \*buf, int len), u32 code_type, u8 ai_type)
第一个参数为外部注册的编码输出回调,注册此回调,在此回调中即可得到编码的后数据,第二个参数为编码类型,根据传入参数选择对应编码,可选的编码有OPUS 编码, SPEEX 编码, ADPCM编码,LC3编码,SBC编码和MSBC编码,创建对应编码器需分别在板级文件中使能TCFG_ENC_OPUS_ENABLE,TCFG_ENC_SPEEX_ENABLE,TCFG_ENC_ADPCM_ENABLE TCFG_ENC_SBC_ENABLE,TCFG_ENC_SBC_ENABLE,MSBC编码默认打开,没有宏控制
#define TCFG_ENC_OPUS_ENABLE ENABLE #define TCFG_ENC_SPEEX_ENABLE ENABLE #define TCFG_ENC_LC3_ENABLE ENABLE #define TCFG_ENC_ADPCM_ENABLE ENABLE #define TCFG_ENC_SBC_ENABLE ENABLE
第三个参数是speex 编码的参数,根据需要传0或者传1即可,不同的编码参数 修改均在audio_demo_enc_open函数内部修改 fmt 结构体的值即可,以adpcm 参数为例,如下
case AUDIO_CODING_WAV: fmt.sample_rate = 16000; fmt.bit_rate = 1024; //blockSize,可配成 256/512/1024/2048 fmt.channel = 2; fmt.coding_type = AUDIO_CODING_WAV; break;
根据实际编码参数修改fmt 结构体 成员的值即可,audio_demo_enc_open函数里默认打开了个定时器,定时器向解码器中写入需要编码的源数据,定时器执行如下函数:
static **void** demo_frame_test_time_fundc(\ **void** \*parm)
在此函数中写入源数据即可,代码默认写入正弦波数据去编码
关闭编码只需要调用如下的audio_demo_enc_close函数
**int** audio_demo_enc_close()
6.6. Audio_MIDI的使用
文件下载配置:在SDK/cpu/br23/tools下添加对应midi.bin文件,在同级目录的download.bat下添加下载项:
isd_download.exe -tonorflash -dev br23 -boot 0x12000 -div8 -wait 300 -uboot uboot.boot -app app.bin cfg_tool.bin -res midi.bin %1
在download.bat同级目录的isd_config.ini文件添加:
INTERNAL_DIR_ALIGN=0X2; //flash内目录里的文件起始地址4对齐
在对应的SDK/apps/spp_and_le/board/br23/board_ac635n_demo_cfg.h文件中,使能AUDIO 功能:
#define TCFG_AUDIO_ENABLE 1//DISABLE #define AUDIO_MIDI_CTRL_CONFIG 1 //midi电子琴接口使能 ,开这个宏要关掉低功耗使能
关闭低功耗模式:
#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown#if TCFG_USER_BLE_ENABLE
在SDK/cpu/br23/audio_dec/audio_dec_midi_ctrl.c中做如下设置:具体函数内容以SDK为准。
void midi_paly_test(u32 key) { static u8 open_close = 0; static u8 change_prog = 0; static u8 note_on_off = 0; switch (key) { case KEY_IR_NUM_0: if (!open_close) { /* midi_ctrl_dec_open(16000);//启动midi key */ //midi_ctrl_dec_open(16000, "storage/sd0/C/MIDI.bin\0");//启动midi key SD卡 midi_ctrl_dec_open(16000,SDFILE_RES_ROOT_PATH"MIDI.bin\0");//启动midi key 系统 } else { midi_ctrl_dec_close();//关闭midi key } open_close = !open_close; break; case KEY_IR_NUM_1: if (!change_prog) { midi_ctrl_set_porg(0, 0);//设置0号乐器,音轨0 } else { midi_ctrl_set_porg(22, 0);//设置22号乐器,音轨0 } change_prog = !change_prog; break; case KEY_IR_NUM_2: if (!note_on_off) { //模拟按键57、58、59、60、61、62,以力度127,通道0,按下测试 ... } else //模拟按键57、58、59、60、61、62松开测试 ... } note_on_off = !note_on_off; break; default: break; } }
在app_spp_and_le.c种调用midi_play_test()函数播放对应文件:
static void app_key_event_handler(struct sys_event *event) { ...... #if TCFG_AUDIO_ENABLE if (event_type == KEY_EVENT_CLICK && key_value == TCFG_ADKEY_VALUE0) { /*midi test*/ printf(">>>key0:open midi\n"); midi_paly_test(KEY_IR_NUM_0); } if (event_type == KEY_EVENT_CLICK && key_value == TCFG_ADKEY_VALUE1) { printf(">>>key0:set midi\n"); midi_paly_test(KEY_IR_NUM_1); } if (event_type == KEY_EVENT_CLICK && key_value == TCFG_ADKEY_VALUE2) printf(">>>key2:play midi\n"); midi_paly_test(KEY_IR_NUM_2); }