Using the DirectSound Mixer

It is easy to mix multiple streams with DirectSound. Your application can simply create secondary sound buffers, receiving an IDirectSoundBuffer interface for each sound. You can then use these interfaces to write data to the buffers by using the IDirectSoundBuffer::Lock and IDirectSoundBuffer::Unlock methods, and you can play the buffers by using the IDirectSoundBuffer::Play method. You can stop playing the buffers at any time by using the IDirectSoundBuffer::Stop method.

The IDirectSoundBuffer::Play method always starts playing at the buffer's current position. The current position is specified by an offset, in bytes, into the buffer. The current position of a newly created buffer is 0. When a buffer is stopped, the current position immediately follows the next sample played. The current position can be set explicitly by calling the IDirectSoundBuffer::SetCurrentPosition method, and can be queried by calling the IDirectSoundBuffer::GetCurrentPosition method.

By default, IDirectSoundBuffer::Play stops playing when the end of the buffer is reached. This is the correct behavior for nonlooping static buffers. (The current position will be reset to the beginning of the buffer at this point.) For streaming buffers or for static buffers that continually repeat, your application should call IDirectSoundBuffer::Play and specify the DSBPLAY_LOOPING flag in the dwFlags parameter. This causes the buffer to loop back to the beginning once it reaches the end.

For streaming sound buffers, your application is responsible for ensuring that the next block of data is written to the buffer before the play cursor loops back to the beginning. Your application can do this by using the SetTimer or SetEvent Win32 functions to cause a message or callback function to occur at regular intervals. In addition, many DirectSound applications will already have a real-time DirectDraw component that must service the display at regular intervals; this component should be able to service DirectSound buffers as well. For optimal efficiency, all applications should write at least 1 second ahead of the current play cursor to minimize the possibility of gaps in the audio output during playback.

The DirectSound mixer can obtain the best usage from hardware acceleration if your application correctly specifies the DSBCAPS_STATIC flag for static buffers. This flag should be specified for any static buffers that will be reused. DirectSound downloads these buffers to the sound hardware memory, where available, and thereby does not incur any processing overhead in mixing these buffers. The most important static sound buffers should be created first to give them first priority for hardware acceleration.

The DirectSound mixer produces the best sound quality if all your application's sounds use the same wave format and the hardware output format is matched to the format of the sounds. If this is done, the mixer need not perform any format conversion.

Your application can change the hardware output format by creating a primary sound buffer and calling the IDirectSoundBuffer::SetFormat method. Note that this primary buffer is for control purposes only; only applications with a cooperative level of DSSCL_PRIORITY or higher can call this function. DirectSound will then restore the hardware format to the format specified in the last IDirectSoundBuffer::SetFormat method call every time the application gains the input focus.