Your application can obtain write access to a sound buffer by using the IDirectSoundBuffer::Lock method. After the sound buffer (memory) is locked, the application can write or copy data to the buffer. The buffer memory must then be unlocked by calling the IDirectSoundBuffer::Unlock method.
Because streaming sound buffers usually play continually, DirectSound returns two write pointers when locking a sound buffer. For example, if you tried to lock 300 bytes beginning at the midpoint of a 400-byte buffer, IDirectSoundBuffer::Lock would return one 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 can be NULL.
Memory for a sound buffer can be lost in certain situations. In particular, this can occur when buffers are located in the hardware sound memory. In the worst case, the sound card itself might be removed from the system while in use; this situation can occur with PCMCIA sound cards. It can also occur when an application with the write-primary cooperative level gains the input focus. If this flag is set, DirectSound makes all other sound buffers 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 example writes data to a sound buffer by 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 DSERR_BUFFERLOST is returned, 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;
}
}
// Lock, Unlock, or Restore failed.
return FALSE;
}