非 PCM 支持的背景
几个问题导致早期版本的 Microsoft Windows 无法通过 waveOut 和 DirectSound API 支持非 PCM 格式。 下面讨论了这些问题及其解决方法。
waveOut API
将 waveOut 应用程序与 VxD 波形驱动程序分开的软件层相当精简。 支持自定义波形格式的驱动程序和应用程序可以以该格式流式传输数据,而不管操作系统是否了解该格式。
但是,在 Windows 2000 和 Windows 98 中,WDM 音频框架回强制由 waveOut API(和 DirectShow 的 waveOut 呈现器)处理的所有音频数据通过 KMixer 系统驱动程序 (Kmixer.sys),这是内核音频混音器。 仅当 KMixer 支持格式时,waveOutOpen 调用才会成功,而不管驱动程序是否支持该格式。
KMixer 会处理所有 WDM 操作系统上的 WAVE_FORMAT_PCM。 Windows 2000 和更高版本以及 Windows 98 SE 扩展了 KMixer,不仅支持 PCM 和 IEEE 浮点格式的 WAVE_FORMAT_IEEE_FLOAT,而且还支持 WAVEFORMATEXTENSIBLE 变体。 由于 KMixer 不支持非 PCM 格式,因此尝试通过 KMixer 传递非 PCM 数据会失败。
Windows 通过允许非 PCM 音频数据绕过 KMixer 来支持非 PCM 格式。 具体而言,waveOut 非 PCM 数据流直接流向 PortCls(或 USBAudio),而不是首先通过 KMixer。 非 PCM 数据的任何混合都必须在硬件中完成,但采用 AC-3 或 WMA Pro 等格式使用非 PCM 数据的应用程序通常不需要混合,驱动程序通常不支持采用该格式的硬件混合。
DirectSound API
在旧版 waveOut 驱动程序和 VxD 驱动程序上,DirectSound 支持主缓冲区和辅助缓冲区的 WAVEFORMATEX(但不支持 WAVEFORMATEXTENSIBLE)PCM 格式,每个样本 8 位或 16 位,一个或两个声道,采样率介于 100 Hz 和 100 kHz 之间。 当协作级别设置为 DSSCL_WRITEPRIMARY 时,VxD 驱动程序可以进一步限制主缓冲区允许的格式(请参阅 DirectX SDK 中 IDirectSoundBuffer::SetFormat 方法的说明)。 Windows Me 或 Windows XP 中没有更改这些限制。
WDM 驱动程序可以同时支持采用 WAVEFORMATEX 和 WAVEFORMATEXTENSIBLE 形式的 PCM 格式。 对于 Windows 2000 及更高版本、Windows Me 和 Windows 98 SE,驱动程序还可以同时支持主和辅助 DSBCAPS_LOCSOFTWARE 缓冲区(由 KMixer 混合)的 WAVE_FORMAT_IEEE_FLOAT 格式,该格式同时采用 WAVEFORMATEX 和 WAVEFORMATEXTENSIBLE 形式。
调用 SetFormat 会指定主缓冲区的数据格式只会对声卡选择的最终混合格式产生间接影响。 主缓冲区对象用于获取 IDirectSound3DListener 接口并设置设备的全局音量和平移,但不表示声卡中的单个输出流。 相反,KMixer 会混合主缓冲区数据,以便允许多个 DSSCL_WRITEPRIMARY DirectSound 客户端同时运行。
在 Windows 2000 和 Windows 98 上,DirectSound 仅支持 PCM 数据。 (DirectShow 也是如此,它使用 DirectSound 的呈现器。)对具有非 PCM 格式的 CreateSoundBuffer 的调用始终失败,即使驱动程序支持该格式也是如此。 失败的原因有两个。 首先,每当 DirectSound 创建 KS 引脚时,它都会自动指定 KSDATAFORMAT_SUBTYPE_PCM,而不是从用于创建 IDirectSoundBuffer 对象的 WAVEFORMATEX 结构的 wFormatTag 成员派生子类型。 其次,DirectSound 要求每个数据路径都具有音量和 SRC(采样率转换)节点(KSNODETYPE_VOLUME 和 KSNODETYPE_SRC),无论客户端请求 DirectSound 缓冲区上的平移、音量还是频率控制。 如果数据通过 KMixer 或设备执行硬件混合,则满足此要求。 但是,对于非 PCM 格式,KMixer 在数据路径中不存在,当被要求执行硬件混合时,驱动程序本身通常会失败。
Windows XP 和更高版本以及 Windows Me 消除了导致 DirectSound 应用程序使用非 PCM 格式的限制。 DirectSound 8(及更高版本)使用正确的格式子类型,并且不再自动需要每个数据路径中的音量和 SRC 节点。