c - USB 音频缓冲区溢出

标签 c audio usb microcontroller race-condition

我正在微 Controller 上进行 USB 音频异步实现,我似乎在 48kHz 采样率/24 比特率(尽管它在 44.1kHz 下工作)的输入端遇到缓冲区欠载问题。

我在我的实现中使用了双缓冲:

(1) 编解码器 -> DMA 有几个缓冲区。当一个缓冲区完全填满时,我将其加载到我的 USB 缓冲区中。

(2) USB端有40个缓冲区(基本上是40ms的数据)。当缓冲区的状态为“FILLED”时,可以发送。 USB 回调在成功的 USB 传输后完成并发送下一个填充的缓冲区。

在我的实现中,我在 USB 开始传输实际数据之前填充了至少 3/4 的缓冲区(30 个缓冲区)(因此在前 30 毫秒内,它只是“静默”数据)。基本上,缓冲区欠载发生是因为我的编解码器/dma 缓冲区尚未完全填满,下一个要读取的缓冲区是“空”。我觉得最简单的解决方案是拥有更多缓冲区(显然 40 个缓冲区不够;大约 11kb 的数据,因为 40 * 294 字节 = 11760 字节),但是我无法增加它,因为我的微 Controller 已经用完了可用的内存。

此时我有哪些解决方案?是否有解决方法来限制我拥有的可用缓冲区/可用剩余内存?或者是添加 SRAM 以获得足够可用缓冲区的唯一方法。

谢谢!

编辑:看起来这有点令人困惑。基本上编解码器的填充速度不够快;因此,USB 缓冲区中存在数据间隙并造成数据“欠载”。

EDIT2:我正在运行一个带有隐式同步端点的异步;主机每帧被读取一次。抱歉,这也不清楚。

最佳答案

您的端点应由主机每帧读取一次(我假设您正在构建等时 IN 端点,异步与隐式同步)。如果您的情况并非如此,请在您的问题中明确说明,因为这将是一个非常奇怪的问题。

无论如何,正因为如此,三个以上的缓冲区并没有多大用处(两个也需要仔细考虑)。您不需要更多缓冲区。但是您的缓冲区应该比计算出的标称每帧样本长一些,并且您的端点的描述符应该包含这个扩展长度。

然后,您始终切换缓冲区被填充,并且仅在 USB 帧的开始(或与 USB SOF 同步的任何其他事件)。 无论当前缓冲区中的数据量如何!当 USB 主机想要从您的端点读取数据时,您的设备必须返回与当前读取缓冲区中实际存在的样本一样多的样本。不多也不少。

所以不会有欠载的机会。当正在读取的缓冲区之前未完全填满时,您只需向主机发送较少数量的样本,主机的任务就是以任何合适的方式处理时钟漂移和重采样。另一方面,您可能担心超限。如果 SOF 频率与 ADC 的采样率相比太低,您可能会在 SOF 到来之前填满整个缓冲区,并最终无处可用于下一个采样。简单的解决方法是使您的缓冲区至少比计算的标称速率长几个样本。那你应该是安全的,否则其他地方可能已经坏了很多。

您可能担心的最后一个问题是当 SOF 正常运行时主机没有为您的端点发送读取请求。好吧,在这种情况下,覆盖旧缓冲区不会造成太大伤害,因为此时主机显然对数据不感兴趣,并且缓冲事物——从而增加延迟——可能弊大于利。

关于c - USB 音频缓冲区溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46432862/

相关文章:

c - C中的预编译消息

c - C 中的嵌套结构和指针

我可以在同一个文件中使用来自 time.h 的两个 tm 结构吗?

android - 播放 mp3 Android 异步。播放但随后崩溃线程

matlab - 将两个 wav 文件的左右声道合并为一个单独的立体声文件

docker - 使用 docker run --privileged 托管单个 USB 设备

winapi - 在 Windows 上的 Qt 中检测 USB 通知

c - C 中的 SSL 包装器流

python - 如何实时改变音量

android - 使用 libusb 在 UCG102 上设置采样率