Apr*_*rel 6 audio operating-systems audio-recording
如果我将线路或 USB 麦克风插入我的 PC,我可以录制 44.1kHz 的音频。这是大约每 23 微秒一个音频样本。音频波必须经过精确采样和回放,否则听起来会失真。非实时操作系统如何以如此高的采样率管理对时间非常敏感的音频录制和播放过程?无论是在主板音频上播放/录制音频还是在 USB 扬声器/麦克风上播放音频,这个过程有什么不同吗?
all*_*tic 10
如果我将线路或 USB 麦克风插入我的 PC,我可以录制 44.1kHz 的音频。这是大约每 23 微秒一个音频样本。音频波必须经过精确采样和回放,否则听起来会失真。非实时操作系统如何以如此高的采样率管理对时间非常敏感的音频录制和播放过程?无论是在主板音频上播放/录制音频还是在 USB 扬声器/麦克风上播放音频,这个过程有什么不同吗?
这归结为缓冲。
44.1 kHz 并不意味着模拟信号从声卡(USB、PCIe、板载,无所谓)发送到 CPU 时必须完美计时。事实上,信号是数字的。以 44100 赫兹发送数字脉冲编码调制比特流仅意味着,对于每一秒的音频,信号中将有 44,100 个“数据点”。信号被量化,这意味着它基本上是一个数字序列。这些数字的大小(8 位、16 位等)由样本格式决定。
现在,考虑一下,一旦音频被量化,它被捕获的多快或多慢都无关紧要:因为它只是音频的一堆数据点(“样本”),它可以被系统同样好地捕获,如果你每微秒传输 1 个样本,每秒传输 1 个样本,每年传输 1 个样本,等等——只要你的计算机知道预期的采样率是多少,它就可以以它喜欢的任何速度收集所有数据点,然后存储它们在磁盘(或 RAM 或其他任何地方)上,以便稍后以 100% 的保真度复制。这就是数字信号处理的美妙之处。唯一的最低要求是,如果您从麦克风“实时”捕获音频数据,您必须能够将样本流写入 CPU 并至少处理它们与样品进入一样快。但您不必将每个单独的样品作为单独的传输进行处理。
虽然音频工作确实需要相当精确的定时,以使声音人耳无法感知可闻“滞后”,这是从来没有一个数字音频源,如声卡或USB麦克风,将永远传递的情况下每个个体样本的和当它们被接收时,直接发送到 CPU,一次一个。问题是从音频源到 CPU 的每次传输都有很大的开销。
PCI Express 上的开销比 USB 低得多(实际上,USB 2.0 只能大约每 1 毫秒发送和接收一次数据包——对于单独发送 44,100 个样本来说太粗粒度了),但在任何一种情况下,您都不是将能够在一秒钟内发送 44100 个单独的样本,每个样本都是独立的。
为了解决这个问题,我们使用buffering。虽然缓冲确实会引入延迟,但目标是有一个足够小的缓冲区,用户可以在任何用例中容忍它,同时足够高,以便非 RTOS 的抢占式多任务内核调度程序将“切断”任何其他占用 CPU 的任务,并让您的音频堆栈有机会处理堆积的样本。
缓冲的基本思想是你有一个内存位置序列,其中代表一定数量样本的位(通常是这 44,100 个中的几千个)排队。一旦缓冲区已满或接近满,声源就会向内核发送一个中断,告诉 CPU 缓冲区已准备好读取。然后,当内核有时间时,它会安排一项任务,将这些样本执行直接内存访问 (DMA) 传输到系统内存。从那里,进行声音捕获的程序可以处理样本。对于音频播放,该过程类似,但有些颠倒。
因此,如果您有一个 50 毫秒(1/20 秒)的缓冲区,这种情况并不少见,那么每个缓冲区中将有 44100 / 20 = 2205 个样本。因此,与每秒接收 44100 个中断不同(这肯定会使 CPU 在接收和处理这些中断的开销中过载!),CPU 每秒仅接收 20 个中断。好多了。
这是示例的“动手”演练:
由于我们假设操作系统不是实时的,CPU 总是有可能有太多的任务来竞争 CPU 时间,以至于它根本没有时间及时读取或写入音频数据,在声卡继续移动到下一组样本之前。通过在操作系统内核中实现可预测的调度程序,例如将任务划分为时间片,有可能最小化(虽然,永远不会 100% 消除)辍学的可能性。例如,如果 HypotheticalOS 有一个内核调度程序,它是抢占式的,并为任何请求 CPU 时间的任务分配 1 毫秒的时间片,并在竞争任务之间公平地分配这些时间片,那么正在处理您的音频 I/O 的任务将是可能得到:
(以上假设一个单处理器和一个完全饱和的 CPU;SMP 会使事情变得复杂。)
因此,您可以看到 100 毫秒的缓冲区意味着内核调度程序必须为您的音频 I/O 堆栈(通常包括内核和用户空间组件)提供至少10 个时间片来处理每一秒的音频。如果音频管道需要多个时间片来完成它的工作,那么它每秒需要更多的时间片。
希望这些时间片是均匀分布的:如果在给定秒的前 50 毫秒内有 50 个时间片,然后在剩余的 950 毫秒内有0 个时间片,并且有 100 毫秒的缓冲区,那么用户将体验几乎整整一秒的辍学!哎呀。
稍微有点分歧,我应该注意到还有其他方法可以进行音频 I/O,但这是在典型台式机上完成的最传统的方法。在 GNU/Linux 上,有一个名为 PulseAudio 的声音服务器,它告诉您的声卡停止发送中断,并根据它正在使用的缓冲区的大小(可以随时间变化)在需要时从声音缓冲区中获取数据以适应应用程序要求的更高 CPU 需求或更低延迟!)这种技术称为基于时间的调度,它依赖于 Linux 内核中非常好的调度程序实现。
归档时间: |
|
查看次数: |
526 次 |
最近记录: |