如何检查 IDirectSoundBuffer 是否真的在播放? (缓冲区欠载检测)

How to check if IDirectSoundBuffer is really playing? (buffer underrun detection)

我想在直达声环境中检测缓冲区欠载情况。

我使用两个声音缓冲器(主要和次要)。有时(当服务器提供数据时)我调用 IDirectSoundBuffer 接口的 lock 方法将数据发布到辅助声音缓冲区。如果来自服务器的数据没有时间到来,声音缓冲区会从缓冲区的开头再次开始播放(并重复它直到我将新数据发送到缓冲区)。也许它是标志 DSBPLAY_LOOPING,但正如我阅读(并测试它),如果没有这个标志就无法创建主缓冲区(Play 方法有错误)。

我尝试获取播放状态,但是GetStatus方法总是returns相同的状态,即使没有新数据和播放器重复旧数据。

那么,如何检测buffer underrun情况(没有新数据播放,所有旧数据都在播放)?

提前致谢。

IDirectSoundBuffer8::GetCurrentPosition is really the only way you can determine where it is playing from, but it's also only reliable on Windows Vista or later systems that report DSBCAPS_TRUEPLAYPOSITION.

注意几点:

  • DirectSound 是 'legacy',这意味着它已经很久没有被积极地开发、推广或直接测试了。最后一个样本于 2007 年 11 月在现已停产的 DirectX SDK 中发布。x64 本机应用程序不支持 DirectSound 8 之前的版本,并且 DirectSound 8 headers/libs 在 Windows 从 Windows SDK 7 开始的 SDK。它不支持 Windows on ARM、Windows Store 应用程序或通用 Windows 应用程序。 DirectSound 的文档只能在旧版 DirectX SDK 中离线找到,而不能在 Microsoft Docs 上找到——唯一仍然在线的 DirectSound 内容是为驱动程序编写者提供的。

  • DirectSound 在 Windows 的现代版本上也是 'emulated',因此实际上 'direct' 没有任何关于它的内容。主缓冲区实际上并不直接连接到音频硬件或根本用于混合,因此它只是另一个软件缓冲区,如辅助缓冲区。它确实模拟了在 Windows 9x/ME 中应用的主缓冲区的遗留限制,但它并没有做太多其他事情。

  • 从 Windows Vista 开始,根本不再支持 LOC_HARDWARE 缓冲区。 Windows Vista 确实添加了对多通道 LOC_SOFTWARE 缓冲区的支持,这在 Windows XP 上仅可用作 LOC_HARDWARE 缓冲区。

  • 从 Windows Vista 开始,DirectSound 不支持效果器(ID3L、EAX 等)。

TL;DR: 不要在新的应用程序中使用 DirectSound。只有旧软件和游戏才完全支持它。

那么,如果不是 DirectSound,开发人员应该使用什么?

(1) Windows 如果您可以以已知的数据速率和格式提供声音数据,Core Audio (WASAPI) 是一个不错的选择。如果您需要任何实时混合或源速率转换,您必须自己完成 - 或者 - 您可以使用许多现有的第 3 方音频库之一来完成,同时将最终结果发送到 WASAPI。参见 Microsoft docs

(2) 如果您想进行实时混音、源速率转换和基于软件的 DSP 效果,XAudio 版本 2 是一个不错的选择。从 Windows 8 开始,它已包含在操作系统中,但要支持 Windows 7,您必须使用一些旧版发行版和 SDK。参见 Microoft docs and this blog

WASPI 和 XAudio 都使用 'audio packet' 模型而不是循环缓冲区来提交数据。只要数据包处于待处理状态,您就不会有 under-运行.