常见问题
播放时应用层可设置的 buffer 大小范围是多少
在 RT-Thread 的 Audio 框架中,应用层设置的 buffer 大小范围受到内存池配置的限制。具体来说,应用层一次读取音频文件的最大 buffer
大小是 RT_AU×DIO_REPLAY_MP_BLOCK_SIZE ×
RT_AUDIO_REPLAY_MP_BLOCK_COUNT。
Driver
层的默认配置如下:
RT-Thread options --->
RT-Thread Components --->
Device Drivers --->
[*] Using Audio device drivers
(2048) Replay memory pool block size //RT_AUDIO_REPLAY_MP_BLOCK_SIZE
(2) Replay memory pool block //RT_AUDIO_REPLAY_MP_BLOCK_COUNT
(2048) Record pipe size因此,可设置的最大 buffer 大小为 RT_AUDIO_REPLAY_MP_BLOCK_SIZE ×
RT_AUDIO_REPLAY_MP_BLOCK_COUNT = 2048 * 2 = 4096。
播放音频文件时会先播放一段 0 数据
在 RT-Thread 的 Audio 框架中,播放音频时出现起始部分为 0 数据的问题确实比较常见。这主要是由于内存池管理机制导致的。当读取的音频数据长度小于内存池一个 block 的大小时,即使已经将音频数据写入内存池,也不会立即将该 block 加入到数据队列中,而是等到一个 block 写满才加入数据队列。尽管未加入数据队列,但 audio 框架也会立即开始传输。此时数据队列中没有任何数据,会先填充一个 period_len 长度的 0 数据,所以播放会有 0 数据出现,示意图如下:

为了避免播放起始部分出现 0 数据,可以采取以下几种方法:
- 在应用层保证读取音频文件的 buffer 长度 64 字节对齐,同时不大于 buffer 的最大长度(4096),推荐使用 1024。
参考 bsp/examples/test-audio/aplay.c
#define BUFSZ 1024 int to_read = (size > BUFSZ) ? BUFSZ : size; length = read(fd, buffer, to_read); rt_device_write(snd_dev, 0, buffer, length);这样在第一次写内存池时,就可以将 block 加入到数据队列。如下图所示:

- 预填充音频数据,即在开始播放之前,先向内存池中预填充一段音频数据。这样在播放开始时,内存池中已经有数据可供传输,避免了播放起始部分出现 0
数据。
rt_device_write(snd_dev, 0, buffer, length); //预填充数据 rt_device_control(snd_dev, AUDIO_CTL_START, (void *)&stream); //开始播放
