滤波器
波次筛选器表示呈现和/或捕获波次格式的数字音频数据的设备。 应用程序通常通过 DirectSound API 或通过 Microsoft Windows 多媒体 waveOutXxx 和waveInXxx 函数访问这些设备的功能。 有关 WDM 音频驱动程序可以支持的波次格式的信息,请参阅 WAVEFORMATEX 和 WAVEFORMATEXTENSIBLE。
波次呈现筛选器接收波次数字音频流作为输入,并输出模拟音频信号(输出到一组扬声器或外部混音器)或数字音频流(例如,输出到 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 筛选器。 有关详细信息,请参阅用于实时音频流式处理的波次端口驱动程序白皮书。
WaveRT 筛选器
WaveRT 筛选器以端口/微型端口驱动程序对的形式实现。 在 Windows Vista 及更高版本中,WaveRT 筛选器工厂会创建 WaveRT 筛选器,具体如下:
它会实例化 WaveRT 微型端口驱动程序对象。
它通过调用 GUID 值为 CLSID_PortWaveRT 的 PcNewPort 来实例化 WaveRT 端口驱动程序对象。
它调用端口驱动程序的 IPort::Init 方法,将微型端口驱动程序绑定到端口驱动程序。
Subdevice Creation 中的代码示例演示了此过程。 端口和微型端口驱动程序通过其 IPortWaveRT 和 IMiniportWaveRT 接口相互通信。
有关详细信息,请参阅用于实时音频流式处理的波次端口驱动程序白皮书。
针对以前版本的 Windows 的信息
针对以前版本的 Windows 的 WaveCyclic 信息
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 微型端口驱动程序对象。
它通过调用 GUID 值为 CLSID_PortWavePci 的 PcNewPort 来实例化 WavePci 端口驱动程序对象。
它调用端口驱动程序的 IPort::Init 方法,将微型端口驱动程序绑定到端口驱动程序。
Subdevice Creation 中的代码示例演示了此过程。 端口和微型端口驱动程序通过其 IPortWavePci 和 IMiniportWavePci 接口相互通信。
有关详细信息,请参阅 WavePci 设备的实现问题。
WaveCyclic 筛选器
注意
Microsoft 支持多样化、包容性环境。 本文包含 Microsoft 无偏见通信风格指南视为排除项的术语参考。 本文中的单词或短语当前显示在软件中,用于实现一致性。 当软件更新为删除语言时,本文将更新以保持一致。
注意:针对以前版本的 Windows 的 WaveCyclic 信息
WaveCyclic 筛选器以端口/微型端口驱动程序对的形式实现。 WaveCyclic 筛选器工厂会创建 WaveCyclic 筛选器,具体如下:
它会实例化 WaveCyclic 微型端口驱动程序对象。
它通过调用 GUID 值为 CLSID_PortWaveCyclic 的 PcNewPort 来实例化 WaveCyclic 端口驱动程序对象。
它调用端口驱动程序的 IPort::Init 方法,将微型端口驱动程序绑定到端口驱动程序。
Subdevice Creation 中的代码示例演示了此过程。 端口和微型端口驱动程序通过其 IPortWaveCyclic 和 IMiniportWaveCyclic 接口相互通信。
WaveCyclic 筛选器的循环缓冲区始终包含一个连续虚拟内存块。 IDmaChannel::AllocateBuffer 方法的端口驱动程序实现始终分配在物理和虚拟内存地址空间中连续的缓冲区。 如果如之前所述,WaveCyclic 设备的 DMA 引擎对缓冲区内存施加额外的约束,微型端口驱动程序可以自由地实现自己的缓冲区分配方法,以满足这些约束。
如果操作系统拒绝原始请求,则请求大型缓冲区(例如,八个物理连续内存页)的 WaveCyclic 微型端口驱动程序应准备好满足较小的缓冲区大小。 有时可能会卸载再重新加载音频设备,以重新平衡系统资源(请参阅停止设备以重新平衡资源。
具有内置总线主控 DMA 硬件的 WaveCyclic 设备称为主设备。 或者,WaveCyclic 设备也可以是没有内置 DMA 硬件功能的从属设备。 从属设备必须依赖系统 DMA 控制器,才能执行所需的任何数据传输。 有关主设备和从属设备的详细信息,请参阅 IDmaChannel 和 IDmaChannelSlave。
WaveCyclic 微型端口驱动程序可以实现自己的 DMA 声道对象,而不是使用默认的 DMA 声道对象,该对象由端口驱动程序的其中一个 NewXxxDmaChannel 方法创建:
IPortWaveCyclic::NewMasterDmaChannel
IPortWaveCyclic::NewSlaveDmaChannel
适配器驱动程序的自定义 IDmaChannel 实现可以执行数据的自定义处理,以满足特殊硬件约束。 例如,Windows 多媒体函数使用波次格式,其中 16 位样本始终是有符号值,但音频呈现硬件可能设计为改用无符号 16 位值。 在这种情况下,可以编写驱动程序的自定义 IDmaChannel::CopyTo 方法,以将已签名源值转换为硬件所需的未签名目标值。 尽管此方法可用于处理硬件设计缺陷,但它在软件开销方面也会产生重大成本。
有关实现其自己的 DMA 声道对象的驱动程序示例,请参阅以前版本的 WDK 中的 Sb16 示例音频适配器。 如果将常量 OVERRIDE_DMA_CHANNEL 定义为 TRUE,源代码中的条件编译语句将启用专有 IDmaChannel 对象的实现,驱动程序将使用该对象来代替 IPortWaveCyclic::NewXxxDmaChannel 调用中的默认 IDmaChannel 对象。