A secondary buffer that contains an entire self-contained sound is called a static buffer. Although it is possible to reuse the same buffer for different sounds, typically data is written to a static buffer only once.
Static buffers are created and managed just like streaming buffers. The only difference is in the way they are used: static buffers are filled once and then played, but streaming buffers are constantly refreshed with data as they are playing.
Note A static buffer is not necessarily one created by setting the DSBCAPS_STATIC flag in the buffer description. This flag requests allocation of memory on the sound card, which is not available on most modern hardware. A static buffer can exist in system memory and can be created with either the DSBCAPS_LOCHARDWARE or DSBCAPS_LOCSOFTWARE flag.
Loading data into a static buffer is a three-step process:
These steps are shown in the following example, where lpdsbStatic is an IDirectSoundBuffer8 interface pointer and pbData is the address of the data source:
LPVOID lpvWrite; DWORD dwLength; if (DS_OK == lpdsbStatic->Lock( 0, // Offset at which to start lock. 0, // Size of lock; ignored because of flag. &lpvWrite, // Gets address of first part of lock. &dwLength, // Gets size of first part of lock. NULL, // Address of wraparound not needed. NULL, // Size of wraparound not needed. DSBLOCK_ENTIREBUFFER)) // Flag. { memcpy(lpvWrite, pbData, dwLength); lpdsbStatic->Unlock( lpvWrite, // Address of lock start. dwLength, // Size of lock. NULL, // No wraparound portion. 0); // No wraparound size. } else ( ErrorHandler(); // Add error-handling here. }
To play the buffer, call IDirectSoundBuffer8::Play, as in the following example:
lpdsbStatic->SetCurrentPosition(0); HRESULT hr = lpdsbStatic->Play( 0, // Unused. 0, // Priority for voice management. 0); // Flags. if (FAILED(hr)) ( ErrorHandler(); // Add error-handling here. }
Because the DSBPLAY_LOOPING flag is not set in the example, the buffer automatically stops when it reaches the end. You can also stop it prematurely by using IDirectSoundBuffer8::Stop. When you stop a buffer prematurely, the play cursor position remains where it is. Hence the call to IDirectSoundBuffer8::SetCurrentPosition in the example, which ensures that the buffer starts from the beginning.