Search code examples
winapidirectsound

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


I want to detect buffer underrun situation in direct sound environment.

I use two sound buffers (primary and secondary). Sometimes (when server gives data) I call lock method of IDirectSoundBuffer interface for posting data to secondary sound buffer. If data from server do not have time to come, the sound buffer starts play again from start of the buffer (and repeat it until I send new data to buffer). Maybe it's flag DSBPLAY_LOOPING, but as I read (and test it), primary buffer cannot be created without this flag (there was error at Play method).

I try to get status of playing, but GetStatus method always returns the same status, even there is no new data and player repeat old data.

So, how can I detect buffer underrun situation (when there is no new data for playing and all old data is played)?

Thanks in advance.


Solution

  • 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.

    A few things to note:

    • DirectSound is 'legacy', meaning it hasn't been actively worked on, promoted, or tested directly in ages. The last samples were shipped in the also now end-of-life DirectX SDK in November 2007. Versions of DirectSound prior to 8 are not supported for x64 native applications, and the DirectSound 8 headers/libs are in the Windows SDK as of the Windows SDK 7. It's not supported for Windows on ARM, or Windows Store apps, or Universal Windows apps. The documentation for DirectSound can only be found offline in the legacy DirectX SDK and is not on Microsoft Docs--the only DirectSound content still online is for driver writers.

    • DirectSound is also 'emulated' on modern versions of Windows so there's nothing actually 'direct' about it. The primary buffer is not actually connected directly to the audio hardware or used for mixing at all, so it's just another software buffer like a secondary buffer. It does emulate the legacy restrictions of primary buffers that applied back in Windows 9x/ME, but it doesn't' do much at all otherwise.

    • Starting with Windows Vista, LOC_HARDWARE buffers are no longer supported at all. Windows Vista did add support for multi-channel LOC_SOFTWARE buffers, which on Windows XP were only available as LOC_HARDWARE buffers.

    • Starting with Windows Vista, Effects (ID3L, EAX, etc.) are not supported through DirectSound.

    TL;DR: Don't use DirectSound in new applications. It is only still supported at all for old software & games.

    So, what is a developer supposed to use if not DirectSound?

    (1) Windows Core Audio (WASAPI) is a good option if you can provide the sound data at a known data rate and format. If you need any real-time mixing or source-rate conversion, you have to do it yourself -or- you can use one of the many existing 3rd party audio libraries to do it that also send the final result to WASAPI. See Microsoft docs.

    (2) XAudio version 2 is a good choice if you want to do real-time mixing, source-rate conversion, and software-based DSP effects. It is included in the operating system as of Windows 8, but to support Windows 7 you have to use some legacy distribution and SDKs. See Microoft docs and this blog.

    Both WASPI and XAudio use a 'audio packet' model instead of a looping buffer for data submission. As long as a packet is pending processing, you won't have under-run.