我有一个树莓派 0 w,它通过 i2s(使用通用 dmic 驱动程序)进行声音输入,并使用 bluez5 连接到蓝牙扬声器。
我设置了 bluez-alsa,以便连接的蓝牙设备可用作 alsa PCM。这有效,我可以使用 aplay 播放文件。
我还可以使用 arecord 记录输入。
我现在的要求是:
- 记录连续的 i2s 输入并将其通过管道传输到蓝牙 alsa 输出。
- 延迟应尽可能低
- 音质应该不错。
i2s输入的采样率为96khz和32位,而大多数蓝牙扬声器最多可以处理48khz和16位的采样率。
我尝试了 alsaloop 和组合的 arecord/aplay 方法。
对于 alsaloop 我使用了这个命令:alsaloop -C i2s-input -P "bluealsa:DEV=XX" -c 2 -r96000 -fS32_LE -t 20000
在使用时间/缓冲区/周期参数时,我可以将延迟设置为相当低的值,但它非常不稳定。一段时间后,我同时遇到缓冲区溢出和不足,声音开始变得奇怪,或者完全失败。
对于 arecord 和 aplay 我尝试了类似的东西arecord -D i2s-device -c2 -r96000 -fS32_LE -traw | aplay -D "bluealsa:DEV=XX" -c2 -r96000 -fS32_LE -traw
工作正常,但延迟相当高,CPU 负载比 alsaloop 高得多。但我也经常遇到 xruns,声音断断续续。
你有什么建议我可以改进这个设置吗?缓冲区/周期值到底应该如何优化设置?
答案1
经过一番测试后我找到了解决方案:sox
我没有使用 alsaloop 或 arecord/aplay,而是使用 sox 设置了一个简单的管道:
mkfifo /tmp/pipe
rec -b 32 -r 96000 --endian little -t raw -e signed-integer /tmp/pipe &
sox -b 32 -r 96000 --endian little -t raw -e signed-integer /tmp/pipe -t raw -e signed-integer -p rate 48000 | AUDIODEV="bluealsa:DEV=XX:XX:XX:XX:XX:XX" play -b 32 -r 96000 --endian little -t raw -e signed-integer -p &
这将创建一个命名管道/tmp/pipe
并rec
用输入填充它对
sox
音频数据重新采样,然后play
播放它