Platform SDK: DirectX

Filling and Playing Static Buffers

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.

Note  A static buffer is not necessarily created by setting the DSBCAPS_STATIC flag in the buffer description. This flag requests allocation of memory on the sound card, which is often not available. A static buffer can exist in system memory and can be created with either the DSBCAPS_LOCHARDWARE or DSBCAPS_LOCSOFTWARE flag.

[C++]

Loading data into a static buffer is a three-step process.

  1. Lock the entire buffer by using IDirectSoundBuffer::Lock. You specify the offset within the buffer where you intend to begin writing (normally 0), and get back the memory address of that point.
  2. Write the audio data to the returned address by using a standard memory-copy routine.
  3. Unlock the buffer using IDirectSoundBuffer::Unlock.

These steps are shown in the following example, where lpdsbStatic is an IDirectSoundBuffer 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.
    }

To play the buffer, call IDirectSoundBuffer::Play, as in the following example.

lpdsbStatic->SetCurrentPosition(0);
HRESULT hr = lpdsbStatic->Play(
        0,    // Unused.
        0,    // Priority for voice management.
        0);   // Flags.

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 IDirectSoundBuffer::Stop. When you stop a buffer prematurely, the current read position remains where it is. Hence the call to IDirectSoundBuffer::SetCurrentPosition in the example, which ensures that the buffer starts from the beginning.

[Visual Basic]

A static buffer can be created and filled with data by using a single method call, either DirectSound.CreateSoundBufferFromFile or DirectSound.CreateSoundBufferFromResource.

The following sample code creates a static buffer from the wave identified as "bounce" in the resource file. Assume that m_ds is a DirectSound object.

Dim dsbd As DSBUFFERDESC
Dim dsbResource As DirectSoundBuffer
Dim waveFormat As WAVEFORMATEX
 
dsbd.lFlags = DSBCAPS_CTRLVOLUME
Set dsbResource = m_ds.CreateSoundBufferFromResource( _
        "", "bounce", dsbd, waveFormat)

The resource file has been compiled into the executable file, so no module name needs to be provided. Nor does the value of the lBufferBytes member of the DSBUFFERDESC type need to be set, because the method determines the size of the buffer from the size of the data. The WAVEFORMATEX type receives information about the wave format from the header stored in the file or resource.

To play the buffer, call DirectSoundBuffer.Play, as in the following example.

dsbResource.SetCurrentPosition 0
dsbResource.Play 0

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 DirectSoundBuffer.Stop. When you stop a buffer prematurely, the current read position remains where it is. Hence the call to DirectSoundBuffer.SetCurrentPosition in the example, which ensures that the buffer starts from the beginning.

You can also create a static buffer by using DirectSound.CreateSoundBuffer and then fill it with data from another location in memory by using the DirectSoundBuffer.WriteBuffer method.

For more information on writing to secondary buffers, see Using Streaming Buffers.