经过长时间的在网上查找解决方案,我粗浅的理解是:异步传输播放的音频方案包括蓝牙都有类似问题,如果蓝牙传输慢于音频处理速度则会出现空数据,这样就可能产生这样的毛刺;如果音频处理速度低于蓝牙传输数据就会产生缓冲区溢出,这样的结果就是音频跳变。
因此解决这个问题就需要处理蓝牙传输和音频处理的同步问题。
我不知道怎么实现A2DP 和esp32 怎么实现同步的功能。
我能做的是:
1.加大环形缓冲区大小。
2.确保音频处理速度的准确性。网上的说法是esp32-adf 默认的I2S 不稳定,我自己也通过示波器,逻辑分析仪检查MCLK,SCLK 不稳定,偏差很大。
<1>通过以下代码实现环形缓冲区加大:
a2dp_stream.c, 308~322
Code: Select all
if (config->type == AUDIO_STREAM_READER) {
// A2DP sink
s_aadp_handler.stream_type = AUDIO_STREAM_READER;
cfg.destroy = a2dp_sink_destory;
cfg.out_rb_size = 16384;
el = s_aadp_handler.sink_stream = audio_element_init(&cfg);
esp_a2d_sink_register_data_callback(bt_a2d_sink_data_cb);
esp_a2d_register_callback(bt_a2d_sink_cb);
esp_a2d_sink_init();
} else {
// A2DP source
s_aadp_handler.stream_type = AUDIO_STREAM_WRITER;
cfg.destroy = a2dp_source_destory;
el = s_aadp_handler.source_stream = audio_element_init(&cfg);
<2>通过修改i2s clk source ,从SOC_MOD_CLK_PLL_F160M 该成 SOC_MOD_CLK_APLL 稳定I2S MCLK SCLK的问题。代码如下:
clk_tree_defs.h 265~269
Code: Select all
typedef enum {
I2S_CLK_SRC_DEFAULT = SOC_MOD_CLK_APLL, /*!< Select PLL_F160M as the default source clock */
I2S_CLK_SRC_PLL_160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */
I2S_CLK_SRC_APLL = SOC_MOD_CLK_APLL, /*!< Select APLL as the source clock */
} soc_periph_i2s_clk_src_t;
以上修改后蓝牙播放的前几秒中之前必然发生的毛刺,破音问题得到了很好的改善。算是做到能接受的水平。虽然长时间播放也偶尔有卡顿一下的感觉。
希望以上经历能帮助到各位。