何时更新 ALSA 音频驱动程序缓冲区指针

Posted

技术标签:

【中文标题】何时更新 ALSA 音频驱动程序缓冲区指针【英文标题】:When to Update ALSA Audio Driver Buffer Pointer 【发布时间】:2015-08-31 09:00:43 【问题描述】:

我正在使用ALSA APIs 编写USB Audio Playback 驱动程序。为此,我试图了解Linux 内核中现有的音频驱动程序。但是我对何时更新内核音频缓冲区指针感到困惑。我们知道内核将新的音频数据放入环形缓冲区,我们的驱动程序任务是从环形缓冲区中获取新数据,通过 USB 传递并更新内核缓冲区指针。

我正在查看的驱动程序在 URB 完成函数中处理了这个问题。假设他们有一个预定义的 USB 传输大小宏,几乎在所有情况下都在 4096 字节左右。所以当URB传输完成并且代码执行路径进入URB完成时,他们将另一个4096字节从内核缓冲区复制到URB缓冲区,再次提交URBUSB控制器并将内核缓冲区指针转发4096字节。

但我不明白的是,他们为什么如此确定在URB 传输完成时,内核缓冲区中有4096 字节的新数据?内核缓冲区中的新数据量可能小于4096 字节?那为什么它总是以4096 字节更新缓冲区指针。我认为应该知道内核缓冲区中有多少新字节,并且驱动程序应该只更新那个数量,或者我可能误解了什么?任何建议或指南都是值得赞赏的。

【问题讨论】:

【参考方案1】:

这些 USB 音频驱动程序的行为与 PCI 声卡完全一样,即,当设备需要一些样本时,这些样本只是从环形缓冲区中读取。

PCI 芯片无法知道缓冲区的哪一部分实际包含有效样本。 稍后软件会检测到缓冲区欠载(设备通过中断通知驱动程序当前位置;如果位置超前,中断处理程序会引发欠载错误)。

USB 音频驱动程序使用完全相同的机制来检测欠载,即snd_pcm_period_elapsed() 函数检查当前位置(由您的.pointer 回调返回)是否超前。

【讨论】:

谢谢 CL。这回答了我的问题。只需要弄清楚一些事情。您说 USB 驱动程序使用 snd_pcm_period_elapsed() 函数来检查当前位置是否超前。那么如果它太超前了,它如何解决这个问题呢?我们是否必须让我们的驱动程序来解决这个问题,或者 ALSA 会处理这个问题? ALSA 负责停止流,或执行配置的任何操作。

以上是关于何时更新 ALSA 音频驱动程序缓冲区指针的主要内容,如果未能解决你的问题,请参考以下文章

linux下ALSA音频驱动软件开发

Linux音频驱动学习之:ASOC分析

arm linux利用alsa驱动并使用usb音频设备

linux音频alsa-uda134x驱动分析之二(时钟)

Linux ALSA驱动之五:Linux ALSA驱动之Platform源码分析(基于Linux 5.18)

播放音频时 Alsa 缓冲区溢出