波形筛选器表示呈现和/或捕获波形格式的数字音频数据的设备。 应用程序通常通过 DirectSound API 或 Microsoft Windows 多媒体 waveOutXxx 和 waveInXxx 函数访问这些设备的功能。 有关 WDM 音频驱动程序可以支持的波形格式的信息,请参阅 WAVEATEX 和 WAVEATEXTENSIBLE。
波形渲染滤波器接收波形数字音频流作为输入,并输出模拟音频信号(可连接到一组扬声器或外部混音器)或数字音频流(例如,用于 S/PDIF 连接器)。
波形捕获筛选器接收模拟音频信号(来自麦克风或输入插孔)或数字流(例如,来自 S/PDIF 连接器)的输入。 同一筛选器输出包含数字音频数据的波形流。
单个波形筛选器可以同时执行渲染和捕获。 例如,这种类型的筛选器可能表示音频设备,该设备可以通过一组扬声器播放音频,同时通过麦克风录制音频。 或者,波形呈现和波形捕获硬件可能表示为单独的波滤器,如动态音频子设备中所述。
音频适配器驱动程序通过绑定波形微型端口驱动程序(硬件供应商作为适配器驱动程序的一部分实现)和系统实现的波形端口驱动程序来形成波形筛选器。 微型端口驱动程序处理波筛选器所有特定于硬件的操作,而端口驱动程序管理所有通用波筛选器功能。
PortCls 系统驱动程序(Portcls.sys)实现三个波形端口驱动程序:WaveRT、WavePci 和 WaveCyclic。
三种类型的波形筛选器按如下方式运行:
WaveRT 筛选器为波形数据分配缓冲区,并使该缓冲区直接可供用户模式客户端访问。 缓冲区可以包含连续或非连续内存块,具体取决于波形设备的硬件功能。 客户端以连续的虚拟内存块的形式访问缓冲区。 缓冲区是循环缓冲区,这意味着当设备的读取(用于呈现)或写入(用于捕获)指针到达缓冲区的末尾时,它会自动环绕到缓冲区的开头。
WavePci 筛选器直接访问客户端的缓冲区。 尽管客户端以单个连续的虚拟内存块的形式访问缓冲区,但 WavePci 筛选器必须以一系列可能不连续的内存块的形式访问缓冲区。 包含渲染或捕获流连续段的块在设备上进行排队。 当设备的读取或写入指针到达一个块的末尾时,它会移动到队列中下一个块的开头。
WaveCyclic 筛选器分配一个由单个连续内存块组成的缓冲区,用作其输出(用于呈现)或输入(用于捕获)缓冲区。 此缓冲区是循环的。 由于无法直接访问该缓冲区,因此驱动程序必须在驱动程序的循环缓冲区和客户端的用户模式缓冲区之间复制数据。
WaveRT 优先于 WavePci 和 WaveCyclic。 WavePci 和 WaveCyclic 与早期版本的 Windows 一起使用。
WaveRT 筛选器可以表示驻留在系统总线上的音频设备,例如 PCI 或 PCI Express。 WaveRT 筛选器在 WaveCyclic 或 WavePci 筛选器上的主要优点是,WaveRT 筛选器允许用户模式客户端直接与音频硬件交换音频数据。 相比之下,WaveCyclic 和 WavePci 筛选器都需要驱动程序定期进行软件干预,这会增加音频流的延迟。 此外,具有和不使用散点/收集 DMA 功能的音频设备可以表示为 WaveRT 筛选器。 有关详细信息,请参阅 用于 Real-Time 音频流式处理白皮书的波形端口驱动程序 。
WaveRT 筛选器
WaveRT 筛选器实现为端口/微型端口驱动程序对。 在 Windows Vista 及更高版本中,WaveRT 筛选器工厂创建 WaveRT 筛选器,如下所示:
它实例化 WaveRT 微型端口驱动程序对象。
它通过调用具有 GUID 值的 PcNewPort 来实例化 WaveRT 端口驱动程序对象 CLSID_PortWaveRT。
它调用端口驱动程序的 IPort::Init 方法,将微型端口驱动程序绑定到端口驱动程序。
Subdevice Creation 中的代码示例演示了此过程。 端口和微型端口驱动程序通过其 IPortWaveRT 和 IMiniportWaveRT 接口相互通信。
有关详细信息,请参阅 用于 Real-Time 音频流式处理白皮书的波形端口驱动程序 。
早期版本的 Windows 的信息
WaveCyclic 信息(适用于旧版本的 Windows)
WaveCyclic 筛选器可以表示连接到系统总线的音频设备,例如 ISA、PCI、PCI Express 或 PCMCIA。 顾名思义,WavePci 筛选器通常表示连接到 PCI 总线的设备,但原则上,WavePci 设备也可能连接到 ISA 总线。 与 WaveCyclic 支持的更简单设备不同,WavePci 支持的设备必须具有散点/收集 DMA 功能。 驻留在 PCI 总线但缺少散布/集结 DMA 的音频设备可以表示为 WaveCyclic 过滤器,但不能表示为 WavePci 过滤器。
适用于早期版本 Windows 的 WavePci 信息
WavePci 设备能够执行分散/聚集 DMA 传输,这些缓冲区可以位于任何内存地址,并且可以以任意字节对齐开始和结束。 相较而言,WaveCyclic 设备的 DMA 硬件只需具备将数据移入或移出由设备的微型端口驱动程序分配的单个缓冲区的能力。 WaveCyclic 微型端口驱动程序可以自由分配满足其 DMA 通道有限功能的循环缓冲区。 例如,典型 WaveCyclic 设备的 DMA 通道可能需要满足以下限制的缓冲区:
缓冲区位于物理地址空间的某个区域。
缓冲区在物理地址空间和虚拟地址空间中是连续的。
缓冲区以四到八字节边界开始和结束。
但是,为了换取这种简单性,WaveCyclic 设备必须依赖于向/从循环缓冲区复制数据的软件,而 WavePci 设备依赖于其 DMA 硬件的散点/收集功能以避免此类复制。 将波形音频数据传送到呈现设备或从捕获设备检索数据的 IRP 附带数据缓冲区,其中每个缓冲区都包含正在呈现或捕获的音频流的一部分。 WavePci 设备可以通过散点/收集 DMA 引擎直接访问这些缓冲区,而 WaveCyclic 设备需要将数据从 IRP 复制到其循环缓冲区,反之亦然。
WavePci 筛选器
注意:早期版本的 Windows 的 WavePci 信息
WavePci 筛选器作为端口/微型端口驱动程序对实现。 WavePci 筛选器工厂创建 WavePci 筛选器,如下所示:
它实例化 WavePci 微型端口驱动程序对象。
它通过调用 PcNewPort 并使用 GUID 值 CLSID_PortWavePci 来实例化 WavePci 端口驱动程序对象。
它调用端口驱动程序的 IPort::Init 方法,将微型端口驱动程序绑定到端口驱动程序。
Subdevice Creation 中的代码示例演示了此过程。 端口和微型端口驱动程序通过其 IPortWavePci 和 IMiniportWavePci 接口相互通信。
有关详细信息,请参阅 WavePci 设备的实现问题。
WaveCyclic 筛选器
注释
Microsoft支持多样化的包容性环境。 本文包含有关无偏见通信 Microsoft风格指南 识别为排除项的术语的参考。 本文中的单词或短语用于一致性,因为它当前显示在软件中。 当软件更新以删除某种语言时,本文将随之更新以保持一致。
注意:早期版本的 Windows 的 WaveCyclic 信息
WaveCyclic 筛选器作为端口/微型端口驱动程序对实现。 WaveCyclic 筛选器工厂创建 WaveCyclic 筛选器,如下所示:
它实例化 WaveCyclic 微型端口驱动程序对象。
它通过调用 PcNewPort 并使用 GUID 值 CLSID_PortWaveCyclic 来实例化 WaveCyclic 端口驱动程序对象。
它调用端口驱动程序的 IPort::Init 方法,将微型端口驱动程序绑定到端口驱动程序。
Subdevice Creation 中的代码示例演示了此过程。 端口和微型端口驱动程序通过其 IPortWaveCyclic 和 IMiniportWaveCyclic 接口相互通信。
WaveCyclic 筛选器的循环缓冲区始终包含一个连续的虚拟内存块。 IDmaChannel::AllocateBuffer 方法的端口驱动程序实现始终分配物理和虚拟内存地址空间中连续的缓冲区。 如前所述,WaveCyclic 设备的 DMA 引擎对缓冲区内存施加其他约束时,微型端口驱动程序可以自由实现自己的缓冲区分配方法来满足这些约束。
如果操作系统拒绝原始请求,那么请求大型缓冲区(例如,8 个物理连续内存页)的 WaveCyclic 微型端口驱动程序应准备好接受较小的缓冲区。 音频设备有时可能会卸载并重新加载以重新平衡系统资源(请参阅 “停止设备重新平衡资源”。
具有内置总线主控 DMA 硬件的 WaveCyclic 设备称为 主设备。 或者,WaveCyclic 设备可以是没有内置 DMA 硬件功能的 从属设备 。 从属设备必须依赖系统 DMA 控制器来执行它所需的任何数据传输。 有关主设备和从属设备的详细信息,请参阅 IDmaChannel 和 IDmaChannelSlave。
WaveCyclic 微型端口驱动程序可以实现自己的 DMA 通道对象,而不是使用默认的 DMA 通道对象,该对象由端口驱动程序的新XxxDmaChannel 方法之一创建:
IPortWaveCyclic::NewMasterDmaChannel
IPortWaveCyclic::NewSlaveDmaChannel
适配器驱动程序的自定义 IDmaChannel 实现可以执行数据的自定义处理以满足特殊硬件约束。 例如,Windows 多媒体函数使用波形格式,其中 16 位样本始终是有符号值,但音频呈现硬件可能设计为改用无符号 16 位值。 在这种情况下,可以编写驱动程序的自定义 IDmaChannel::CopyTo 方法,将签名的源值转换为硬件所需的未签名目标值。 尽管此方法可用于处理硬件设计缺陷,但它在软件开销方面也会产生重大成本。
有关实现其自己的 DMA 通道对象的驱动程序示例,请参阅早期版本的 WDK 中的 Sb16 示例音频适配器。 如果常量OVERRIDE_DMA_CHANNEL定义为 TRUE,源代码中的条件编译语句将启用专有 IDmaChannel 对象的实现,驱动程序使用该对象代替 IPortWaveCyclic::NewXxxDmaChannel 调用中的默认 IDmaChannel 对象。