Writing to Sound Buffers

Your application can obtain write access to a sound buffer by using the IDirectSoundBuffer::Lock method. Once the sound buffer (memory) is locked, you can write or copy data to the buffer. The buffer memory must then be unlocked by calling the IDirectSoundBuffer::Unlock method.

Since streaming sound buffers usually wrap around and continue playing from the beginning of the buffer, DirectSound returns two write pointers when locking a sound buffer. For example, if you try to lock 300 bytes beginning at the midpoint of a 400 byte buffer, IDirectSoundBuffer::Lock would return a pointer to the last 200 bytes of the buffer, and a second pointer to the first 100 bytes. Depending on the offset and the length of the buffer, the second pointer may be NULL.

You should be aware that memory for a sound buffer can be lost in certain situations. In particular, this might occur when buffers are located in the hardware sound memory. In the most dramatic case, the sound card itself might be removed from the system while being used; this situation can occur with PCMCIA sound cards. It can also occur when an application with the write-primary cooperative level (DSSCL_WRITEPRIMARY flag) gains the input focus. If this flag is set, DirectSound makes all other sound buffers become lost so that the application with the focus can write directly to the primary buffer. If this happens, DirectSound returns the DSERR_BUFFERLOST error code in response to the IDirectSoundBuffer::Lock and IDirectSoundBuffer::Play methods. When the application lowers its cooperative level from write-primary, or loses the input focus, other applications can attempt to reallocate the buffer memory by calling the IDirectSoundBuffer::Restore method. If successful, this method restores the buffer memory and all other settings for the buffer, such as volume and pan settings. However, a restored buffer does not contain valid sound data. The owning application must rewrite the data to the restored buffer.

The following function writes data to a sound buffer using the IDirectSoundBuffer::Lock and IDirectSoundBuffer::Unlock methods:

BOOL AppWriteDataToBuffer(

LPDIRECTSOUNDBUFFER lpDsb,

DWORD dwOffset,

LPBYTE lpbSoundData,

DWORD dwSoundBytes)

{

LPVOID lpvPtr1;

DWORD dwBytes1;

LPVOID lpvPtr2;

DWORD dwBytes2;

HRESULT hr;

// Obtain write pointer.

hr = lpDsb->lpVtbl->Lock(lpDsb, dwOffset, dwSoundBytes, &lpvPtr1,

&dwBytes1, &lpvPtr2, &dwBytes2, 0);

// If we got DSERR_BUFFERLOST, restore and retry lock.

if(DSERR_BUFFERLOST == hr) {

lpDsb->lpVtbl->Restore(lpDsb);

hr = lpDsb->lpVtbl->Lock(lpDsb, dwOffset, dwSoundBytes,

&lpvPtr1, &dwAudio1, &lpvPtr2, &dwAudio2, 0);

}

if(DS_OK == hr) {

// Write to pointers.

CopyMemory(lpvPtr1, lpbSoundData, dwBytes1);

if(NULL != lpvPtr2) {

CopyMemory(lpvPtr2, lpbSoundData+dwBytes1, dwBytes2);

}

// Release the data back to DirectSound.

hr = lpDsb->lpVtbl->Unlock(lpDsb, lpvPtr1, dwBytes1, lpvPtr2,

dwBytes2);

if(DS_OK == hr) {

// Success!

return TRUE;

}

}

// If we got here, then we failed Lock, Unlock, or Restore.

return FALSE;

}