A2DP Sink 音乐播放前几秒有明显的毛刺

luxianquan
Posts: 21
Joined: Tue Jul 13, 2021 12:23 pm

A2DP Sink 音乐播放前几秒有明显的毛刺

Postby luxianquan » Mon Nov 18, 2024 12:34 pm

我在使用ESP32 的A2DP Sink 功能进行开发的时候遇到客户反馈,A2DP 播放的前几秒都会有噪音,后面就会逐渐改善噪音消失。后来我使用官方开发板ESP32-LyraT 运行A2DP_Sink 官方例程 进行验证,结果发现蓝牙连接后首次播放或者停止播放后等待几秒钟再重新播放都会有这个噪音,于是我使用示波器+逻辑分析仪扫描波形发现是I2S 向Codec 写数据的时候出现了空包于是乎Codec 解码就出现了毛刺。如下图所示。
logic analyzer.png
logic analyzer.png (21.14 KiB) Viewed 3566 times
osc.png
osc.png (622.84 KiB) Viewed 3566 times
我在github 上搜索解决方案的时候发现同样的问题在2019年就有人提出了Issues 并且通过bugfix 解决了,以下是Issues的链接。
https://github.com/espressif/esp-idf/issues/3407
我的疑问是,这个问题是否已经有解决方案,是否已经更新到最新的idf或者ADF 中。
我现在遇到同样的问题需要怎么确认和修改。

luxianquan
Posts: 21
Joined: Tue Jul 13, 2021 12:23 pm

Re: A2DP Sink 音乐播放前几秒有明显的毛刺

Postby luxianquan » Fri Dec 06, 2024 7:32 am

经过长时间的在网上查找解决方案,我粗浅的理解是:异步传输播放的音频方案包括蓝牙都有类似问题,如果蓝牙传输慢于音频处理速度则会出现空数据,这样就可能产生这样的毛刺;如果音频处理速度低于蓝牙传输数据就会产生缓冲区溢出,这样的结果就是音频跳变。
因此解决这个问题就需要处理蓝牙传输和音频处理的同步问题。
我不知道怎么实现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;
以上修改后蓝牙播放的前几秒中之前必然发生的毛刺,破音问题得到了很好的改善。算是做到能接受的水平。虽然长时间播放也偶尔有卡顿一下的感觉。
希望以上经历能帮助到各位。

Who is online

Users browsing this forum: No registered users and 9 guests