播放期间的流延迟

当音频播放流处于“运行”状态时,WaveRT 端口驱动程序的角色最小。 如下图所示,在播放期间,WaveRT 端口驱动程序的客户端将其数据写入循环缓冲区,然后音频设备从缓冲区读取此数据。 此活动不需要端口驱动程序的干预。 换句话说,音频数据直接在用户模式应用程序与音频硬件之间流动,而无需由任何内核模式软件组件触摸。

在关系图中,当音频数据流通过循环缓冲区时,写入和播放位置会从左向右不断进行。 缓冲区被描述为循环缓冲区,因为当播放位置或写入位置到达缓冲区的末尾时,它会自动环绕到缓冲区的开头。

播放期间的流延迟有两个主要源,在下图中指定为 A 和 B。

Diagram showing the latency of a playback stream with write and play positions in a cyclic buffer.

在上图中, 写入位置 是客户端写入缓冲区的最后一个示例刚过的位置。 “播放位置是音频设备当前正在通过扬声器播放的示例。

从客户端将音频示例写入缓冲区到音频设备播放为止的延迟只是写入和播放位置之间的分离。 这种分离是以下两个延迟源的总和(在关系图中标记为 A 和 B):

延迟 A:音频设备从缓冲区读取数据后,数据驻留在硬件“先出先出”(FIFO)缓冲区中,直到音频设备通过数字到模拟转换器(DAC)时钟数据。

延迟 B:客户端将数据写入循环缓冲区后,数据将驻留在缓冲区中,直到音频设备读取数据。

客户端无法控制完全依赖于硬件的延迟 A。 典型的 FIFO 可能会存储足够的样本,以便为 DAC 提供大约 64 个样本时钟周期。 但是,客户端确实控制了延迟 B。使延迟 B 过大会给系统带来不必要的延迟;但是,使其太小的风险消耗音频设备。

尽管客户端可以设置计时器来定期激活其缓冲区写入线程,但此方法不会达到最小的延迟。 为了进一步降低延迟,客户端可以将设备配置为在设备每次从缓冲区读取新的播放数据块时生成硬件通知。 在这种情况下,客户端线程由硬件通知而不是计时器激活。

通过让音频设备在每次从缓冲区读取数据块后通知客户端,客户端可以降低延迟,否则会降低延迟。

客户端可以通过向 WaveRT 端口驱动程序发送 KSPROPERTY_RTAUDIO_HWLATENCY 请求来获取导致流延迟的延迟摘要。

在客户端确定在写入和播放位置之间保持的分离量后,客户端会监视播放位置的变化,以确定写入位置的前进距离。 在 Windows Server 2008 及更高版本的操作系统中,客户端发出 KSPROPERTY_RTAUDIO_POSITIONREGISTER 属性请求来确定播放位置。 PortCls 系统驱动程序中的改进提供了对此功能的支持。

如果音频设备的位置寄存器如上图所示,则属性请求会将寄存器映射到可供用户模式客户端访问的虚拟内存地址。 映射位置寄存器后,客户端可以读取内存地址的内容以确定当前播放位置。