It is easy to mix multiple streams with DirectSound. Your application can simply create secondary buffers, receiving an IDirectSoundBuffer interface for each sound. You can then use these interfaces to write data into the buffers using the IDirectSoundBuffer::Lock and IDirectSoundBuffer::Unlock methods and play the buffers using the IDirectSoundBuffer::Play method. The buffers can be stopped at any time by calling the IDirectSoundBuffer::Stop method.
The IDirectSoundBuffer::Play method will always start 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 will stop playing when it reaches the end of the buffer. This is the correct behavior for non-looping 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 continuously repeat, your application should call IDirectSoundBuffer::Play and specify the DSBPLAY_LOOPING flag in the dwFlags parameter. This will cause the buffer to loop back to the beginning once it reaches the end.
For streaming buffers, your application is responsible for ensuring that the next block of data is written into the buffer before the play cursor loops back to the beginning. This can be done by using the Win32 functions SetTimer or SetEvent 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 which needs to 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 one 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 out of 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 will download these buffers to the sound hardware memory, where available, and will thereby not incur any processing overhead in mixing these buffers. The most important static buffers should be created first, in order to give them first priority for hardware acceleration.
The DirectSound mixer will produce the best sound quality if all of 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.
The hardware output format can be changed by creating a primary 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 each time the application gains the input focus.