WavePci 端口驱动程序处理与 WaveCyclic 驱动程序不同的音频流的缓冲。
如果 WavePci miniport 驱动程序提供硬件混合,DirectSound 会将一个包含整个 DirectSound 波形流的 IRP 提交到 WavePci 端口驱动程序,该流位于单个循环缓冲区中。 DirectSound 将缓冲区分配为连续的虚拟内存块。 为了避免复制 DirectSound 缓冲区,内核流层将缓冲区映射到内核模式虚拟内存,并生成一个 MDL(内存描述符列表),该列表指定循环缓冲区中内存页的虚拟地址和物理地址。 WavePci 端口驱动程序将循环缓冲区分区为一系列分配器帧(请参阅 KS 分配器)。 微型端口驱动程序在流初始化期间由端口驱动程序调用 其 IMiniportWavePciStream::GetAllocatorFraming 方法时指定其首选分配器帧大小。 但是,系统图形生成器 SysAudio 可以替代微型端口驱动程序的首选项,以满足音频筛选器图中其他组件的要求。
WavePci 端口驱动程序将循环缓冲区作为映射序列公开给微型端口驱动程序。 映射可以是一个完整的分配帧,也可以是帧的一部分。 如果特定分配帧完全位于页面中,端口驱动程序会将该帧呈现为微型端口驱动程序作为单个映射。 如果分配帧跨越一个或多个页面边界,则端口驱动程序会拆分每个页面边界的帧,并将其呈现为两个或多个映射。 每次调用 IPortWavePciStream::GetMapping 都会生成序列中的下一个连续映射。
与 WaveCyclic 情况相比,微型端口驱动程序几乎无法控制缓存在硬件中的数据时长,而 WavePci 微型端口驱动程序则拥有相当大的控制权,可以控制其任一时刻打开的映射数。 每次调用 GetMapping 时,打开的映射数增加一;每次调用 ReleaseMapping 时,打开的映射数减少一。 (当然,GetMapping 调用可能会失败,因此驱动程序对映射数量的不完全控制。通过控制打开的映射数量并跟踪映射的累积大小,微型端口驱动程序可以确定,在取决于映射大小的容差范围内,硬件可用的缓冲毫秒数。 WavePci 微型端口驱动程序应请求足够的页面映射,以降低资源匮乏到可接受水平的可能性。
如果微型端口驱动程序的策略是缓冲多达 50 毫秒的数据,例如,在读取和写入指针之间,请记住,此限制表示驱动程序将累积的最大数据量,但它不代表驱动程序对流延迟的贡献。 驱动程序应设计为尽可能小地保持其延迟。 当微型端口驱动程序在开始播放新流之前获取其初始映射集时,微型端口驱动程序可以继续请求映射,直到它达到其缓冲区限制(在此示例中为 50 毫秒),或者不再提供任何映射。 但是,在后一种情况下,小型端口驱动程序在开始播放流之前,不能等待直到有更多的映射可用。 相反,驱动程序应立即开始播放它已获取的映射。 稍后,随着更多的映射可用,驱动程序可以继续获取其他映射,直到它达到其缓冲区大小限制或没有立即可用的映射为止。
通常,WavePci 设备的 DMA 硬件应该设计为能够直接访问存储在任意字节对齐的音频帧,这些帧可以跨越物理内存中非连续页之间的边界。 如果你有一个设备要求映射必须是完整的音频帧数,那么该设备会在支持的音频格式类型上受到限制。 当然,具有此限制的设备仍应能够处理大小为 2 的幂的音频帧。
例如,具有四个通道和 16 位样本大小的设备需要 8 个字节的音频帧大小。 音频帧的整数个数可以完美地匹配在一个页面内(或任何其他分配帧大小为8个字节的倍数)。 但是,对于具有 16 位样本的 5.1 通道流,音频帧大小为 12 字节,并且超过单个页面大小的流必然包含跨页边界的音频帧。 ( 波形筛选器 中的数字说明了此问题。无法处理任意字节对齐和任意字节长度映射的硬件必须依赖于驱动程序来执行中间副本,这会降低性能。
Microsoft Windows 驱动程序工具包 (WDK) 中的 Ac97 示例适配器驱动程序实现 GetAllocatorFraming 方法。 微型端口驱动程序使用此方法传达其首选帧分配大小。 在 Windows 2000 和 Windows Me 中,仅当 拆分器系统驱动程序 (Splitter.sys)在输出引脚上方实例化时,端口驱动程序才会调用此方法。 在 Windows XP 及更高版本中,端口驱动程序也会为输入流调用此方法。 请记住,在决定帧分配大小时,SysAudio 可能会选择忽略微型端口驱动程序的首选项。