播放音频时 Alsa 缓冲区溢出
Posted
技术标签:
【中文标题】播放音频时 Alsa 缓冲区溢出【英文标题】:Alsa Buffer overrun while playback of audio 【发布时间】:2014-07-09 18:06:29 【问题描述】:我已将IMX
板背靠背连接到电脑。
我在板上运行一个二进制文件,它每 5.7 毫秒发送 1024 个字节的音频帧。
pc接收帧并使用
printf("snd_pcm_avail %d \n",snd_pcm_avail (FMWK.FMWK_Handler.playback_handle));
err = snd_pcm_writei(FMWK.FMWK_Handler.playback_handle, OutputPointer, PERIOD_BYTES);
播放时,每 6 秒我就会损坏管道
播放成功时的日志
snd_pcm_avail 32
snd_pcm_avail 17
snd_pcm_avail 81
snd_pcm_avail 25
snd_pcm_avail 89
snd_pcm_avail 32
snd_pcm_avail 17
snd_pcm_avail 81
snd_pcm_avail 32
snd_pcm_avail 17
snd_pcm_avail 81
snd_pcm_avail 25
snd_pcm_avail 89
snd_pcm_avail 32
snd_pcm_avail 17
snd_pcm_avail 81
大约减少了 56 当 5 秒后使用率增加并且缓冲区溢出 buffer_size=256 的配置限制
日志:
snd_pcm_avail 89
snd_pcm_avail 112
snd_pcm_avail 96
snd_pcm_avail 120
snd_pcm_avail 104
snd_pcm_avail 129
snd_pcm_avail 153
snd_pcm_avail 137
snd_pcm_avail 160
snd_pcm_avail 184
snd_pcm_avail 168
snd_pcm_avail 193
snd_pcm_avail 176
snd_pcm_avail 201
snd_pcm_avail 224
snd_pcm_avail 209
snd_pcm_avail 232
snd_pcm_avail 217
snd_pcm_avail 240
snd_pcm_avail -32
(AVB Info) 12:26:11 PM.606306 (Slave) ==> Broken pipe
snd_pcm_avail 256
snd_pcm_avail 48
我将 period_size 设置为 128
我不确定我是否在 snd_pcm 的初始配置中遗漏了什么?是44.1khz
音频。
【问题讨论】:
这些音频帧从何而来?您如何测量 5.7 毫秒? 我们在发送端实现了一个定时器,它每 5.7ms 发送 1024 个字节。 @user3659653:您不得使用系统计时器(使用 ALSA)来确定何时发送下一帧。是的,理智的事情是期待,这是可行的。但不幸的是,进程调度程序的粒度本身是毫秒级的,因此您无法将时间精确到 +/-0.1 毫秒。它更像是您可以有效获得的 +/-2ms 精度。此外,DAC 时钟和您的系统定时器时钟不会同步运行(这是 PC 架构的一个巨大设计愚蠢,可以通过外围互连标准的下一个修订版轻松消除),因此您必须只依赖在 DAC 采样时钟上。 Datenwolf 感谢您的回复。我如何从 DAC 导出时序,因为在用户空间中没有要读取的抽象或接口。如何获得用户空间的编解码器时钟,是否有任何提供此 ADC/DAC 时钟的 alsa 接口? 如何回复发送方和接收方的 DAC 时钟?..有什么方法可以获取 DAC/ADC 的时序? 【参考方案1】:发生的情况是,您的程序无法跟上设备对 PCM 数据的播放。当“Broken pipe”发生时,音频设备会等待新的样本,但您的程序没有及时交付它们。
您遇到的情况是在线音频系统的祸根;不幸的是,现有的 Linux 音频架构 (ALSA) 并不能很好地发挥作用; PulseAudio + RealtimeKit 尝试(恕我直言,不是很成功)通过做奇怪而疯狂的巫术来避免让 ALSA 司机挨饿;由于某些驱动程序被破坏并且没有正确报告播放头的位置,事情并没有变得更好。
在你的情况下,你可以做两件事:
使用更大的帧(缓冲区中的更多样本) 对更多帧进行排队(将多个缓冲区排队)并在队列中保持最少数量的帧【讨论】:
Datenwolf 感谢您的回复。但是根据avail值,不是pcm有大量数据用于播放,但不是以相同的速率播放吗?我会尝试第二个选项。【参考方案2】:音频设备通常有自己的采样时钟,它与系统时钟不同步。
因此您不能使用系统时钟来控制将样本发送到设备的速度;它会在几乎所有系统上运行太快或太慢。
要以正确的速度发送样本,只需尝试尽可能快地编写样本;如果缓冲区已满,snd_pcm_write
* 会自动等待。
如果您无法从接收方控制发送方的速度(因为它们不在同一台机器上,并且您没有提供反馈的协议),则必须测量发送方和接收方的相对速度,并重新采样适当的数据。
【讨论】:
是的,时钟同步是计算机音频的主要祸根。正如您可能知道或可能不知道的那样,我目前正在为 Linux 开发一个新的音频子系统,并且代码的主要部分处理使时钟不匹配的麻烦消失。我永远无法理解为什么 PC 平台不简单地添加一个系统范围的分布式 10MHz 时钟,所有定时器都来自该时钟。这会让事情变得简单得多:如果 GPU 的垂直回扫基于与音频 DAC 采样时钟完全相同的时钟,那么您将在视频帧和音频帧之间建立完美的关系。 当然,所有专业设备都使用外部字时钟工作,一切都会同步到。音频接口、摄像头、显卡等一切都连接到一个通用时钟,突然间所有问题都消失了。 CL -> 如果它们在两个独立的系统中运行,我们如何获得相对的 ADC 和 DAC 速度。是否有任何 ioctl 或 alsa 接口为用户空间应用程序提供 ADC/DAC 的时钟。 您必须对样本进行计数。以上是关于播放音频时 Alsa 缓冲区溢出的主要内容,如果未能解决你的问题,请参考以下文章