Microsoft DirectX 9.0 |
A streaming buffer plays a long sound that cannot all fit into the buffer at once. As the buffer plays, old data is periodically replaced with new data.
To play a streaming buffer, call the IDirectSoundBuffer8::Play method, specifying DSBPLAY_LOOPING in the dwFlags parameter.
To halt playback, call the IDirectSoundBuffer8::Stop method. This method stops the buffer immediately, so you need to be sure that all data has been played. This can be done by polling the play position or by setting a notification position.
Streaming into a buffer requires the following steps:
The reason IDirectSoundBuffer8::Lock might return two addresses is that you can lock any number of bytes, up to the size of the buffer, regardless of the start point. If necessary, the locked portion wraps around to the beginning of the buffer. If it does, you have to perform two separate memory copies.
For example, say you lock 30,000 bytes beginning at offset 20,000 in a 40,000-byte buffer. When you call Lock in this case, it returns four values:
If no wraparound is necessary, the last two values are NULL and 0 respectively.
Although it's possible to lock the entire buffer, you must not do so while it is playing. Normally you refresh only a fraction of the buffer each time. For example, you might lock and write to the first quarter of the buffer as soon as the play cursor reaches the second quarter, and so on. You must never write to the part of the buffer that lies between the play cursor and the write cursor.
The following function writes data to a sound buffer, starting at the position passed in dwOffset:
BOOL AppWriteDataToBuffer(
LPDIRECTSOUNDBUFFER8 lpDsb, // The buffer.
DWORD dwOffset, // Our own write cursor.
LPBYTE lpbSoundData, // Start of our data.
DWORD dwSoundBytes) // Size of block to copy.
{
LPVOID lpvPtr1;
DWORD dwBytes1;
LPVOID lpvPtr2;
DWORD dwBytes2;
HRESULT hr;
// Obtain memory address of write block. This will be in two parts
// if the block wraps around.
hr = lpDsb->Lock(dwOffset, dwSoundBytes, &lpvPtr1,
&dwBytes1, &lpvPtr2, &dwBytes2, 0);
// If the buffer was lost, restore and retry lock.
if (DSERR_BUFFERLOST == hr)
{
lpDsb->Restore();
hr = lpDsb->Lock(dwOffset, dwSoundBytes,
&lpvPtr1, &dwBytes1,
&lpvPtr2, &dwBytes2, 0);
}
if (SUCCEEDED(hr))
{
// Write to pointers.
CopyMemory(lpvPtr1, lpbSoundData, dwBytes1);
if (NULL != lpvPtr2)
{
CopyMemory(lpvPtr2, lpbSoundData+dwBytes1, dwBytes2);
}
// Release the data back to DirectSound.
hr = lpDsb->Unlock(lpvPtr1, dwBytes1, lpvPtr2,
dwBytes2);
if (SUCCEEDED(hr))
{
// Success.
return TRUE;
}
}
// Lock, Unlock, or Restore failed.
return FALSE;
}
See Also