目录
音频处理代码逻辑分析
如何配置i2s输出
音频处理代码逻辑分析
音频模块的初始化
app_audio_open/* 首先是注册了app线程的APP_MODUAL_AUDIO模块的回调函数*/app_set_threadhandle(APP_MODUAL_AUDIO, app_audio_handle_process);
然后我们在来看看当有音频要处理时,流程是怎样的
/* 当有音频处理的消息时,比如通话,音乐,提示音等等 */
app_audio_handle_processapp_bt_stream_open/* 这里根据是音乐、通话、还是提示音启用不同的音频处理接口*/case APP_BT_SETTING_OPEN:/*配置通话的音频,这里我简单的说一下一些主要的参数以及接口,详细请参考sdk*/bt_sco_player/* 主麦配置,其中.handler是数据的处理回调函数*/stream_cfg.io_path = AUD_INPUT_PATH_MAINMIC;stream_cfg.device = AUD_STREAM_USE_INT_CODEC;stream_cfg.handler = bt_sco_codec_playback_data;af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE, &stream_cfg);/* 硬件speaker配置,bt_sco_codec_playback_data中能看到解码之后的pcm数据*/stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;stream_cfg.device = AUD_STREAM_USE_INT_CODEC;stream_cfg.handler = bt_sco_codec_playback_data;af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg);/* 降噪mic配置,如果使能了anc */stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;stream_cfg.device = AUD_STREAM_USE_MC;stream_cfg.handler = audio_mc_data_playback_sco;af_stream_open(AUD_STREAM_ID_1, AUD_STREAM_CAPTURE, &stream_cfg);/* 不确定具体的作用,猜测是远端过来的数据先在这里接收,然后在转到第二个实体speaker*/stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;stream_cfg.device = AUD_STREAM_USE_BT_PCM;stream_cfg.handler = bt_sco_btpcm_capture_data;af_stream_open(AUD_STREAM_ID_1, AUD_STREAM_CAPTURE, &stream_cfg);/*配置音乐的音频处理*/bt_sbc_player/* 音频解码配置,bt_sbc_player_more_data 可以看到解码之后的原始音频数据*/stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;stream_cfg.device = AUD_STREAM_USE_INT_CODEC;stream_cfg.handler = bt_sbc_player_more_data;af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg);a2dp_audio_init/* 这里根据编辑格式,将不同的解码驱动赋值给a2dp_audio_context.audio_decoder *//*a2dp_audio_sbc_decoder_config -- sbc解码器驱动*//*a2dp_audio_aac_lc_decoder_config -- aac解码器驱动*//*a2dp_audio_ldac_decoder_config -- ldac解码器驱动*//*a2dp_audio_scalable_decoder_config -- scalable解码器驱动*/switch (codec_type)case A2DP_AUDIO_CODEC_TYPE_SBC:memcpy(&(a2dp_audio_context.audio_decoder), &a2dp_audio_sbc_decoder_configcase A2DP_AUDIO_CODEC_TYPE_MPEG2_4_AAC:memcpy(&(a2dp_audio_context.audio_decoder), &a2dp_audio_aac_lc_decoder_config....../*配置提示音的音频处理*/app_play_audio_onoffstream_cfg.device = AUD_STREAM_USE_INT_CODEC;stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;stream_cfg.handler = app_play_sbc_more_data;af_stream_open(AUD_STREAM_ID_2, AUD_STREAM_PLAYBACK, &stream_cfg);
上面已经主要是对音频的相关参数进行配置,下面我们在来看看,当数据到来,比如播放音乐时,收到了远端的数据是如何解码输出的
/*上面在配置bt_sbc_player的时候,我们有说过这个接口,当接收到远端的数据之后, 这里会从buff区去读取数据,并进行解码操作,最终由codec输出到硬件*/
bt_sbc_player_more_dataa2dp_audio_playback_handler/* 上面a2dp_audio_init中,我们已经把相应的解码驱动赋值给a2dp_audio_context,以指针的方式找到对应的接口*/a2dp_audio_context.audio_decoder.audio_decoder_decode_frame->a2dp_audio_sbc_decode_framea2dp_audio_sbc_mcu_decode_frame/* 这里出来的就是解码之后的音频数据了 */btif_sbc_decode_frames
到这里,流程就基本比较清晰了,我这里也只是将我觉得比较重要的接口摘出来说明一下,详细的逻辑还是要自己去看sdk
如何配置i2s输出
- 打开这个宏AF_DEVICE_I2S
- 在bt_sco_player/bt_sbc_player/app_play_audio_onoff函数中,把参数进行如下设置即可
stream_cfg.device = AUD_STREAM_USE_I2S_MASTER(i2s主) / AUD_STREAM_USE_I2S_SLAVE(i2s从)
最后会通过af_stream_open(..., AUD_STREAM_PLAYBACK, &stream_cfg)将参数设置下去
- 在bt_sco_player中有要注意的地方,会调用三次af_stream_open,只改下面这个地方的参数,其他的不要动
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg)这个的stream_cfg.device,同时stream_cfg.channel_num = 2,不然可能会死机
上面的方法我只在在立体声的工程试过,ibrt工程我没试过!并且i2s参数(采样率,采样位数,通道数)随蓝牙的传过来的音频的参数,固定采样率的接口用不了,很麻烦,不知道ibrt的版本是否有改善
相关资料请到<bes2300开发调试笔记>文章底部的网盘链接中下载!