Microsoft Windows CE 3.0  

Playing Sounds

This is retired content. This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

Playing a sound consists of the following steps:

  1. Lock a portion of the secondary buffer using IDirectSoundBuffer::Lock. This method returns a pointer to the address where writing will begin, based on the offset from the beginning of the buffer that you pass in to the method.
  2. Write the audio data to the buffer.
  3. Unlock the buffer using IDirectSoundBuffer::Unlock.
  4. Send the sound to the primary buffer and from there to the output device using IDirectSoundBuffer::Play. If the buffer is a streaming buffer, it will continue playing in a loop as steps 1 to 3 are repeated.

    Because streaming sound buffers usually play continually and are conceptually circular, DirectSound returns two write pointers when locking a sound buffer. For example, if you tried to lock 3,000 bytes beginning at the midpoint of a 4,000-byte buffer, the Lockmethod would return one pointer to the last 2,000 bytes of the buffer, and a second pointer to the first 1,000 bytes. The second pointer is NULL if the locked portion of the buffer does not wrap around.

    Normally the buffer stops playing automatically when the end is reached. However, if the DSBPLAY_LOOPING flag was set in the dwFlagsparameter to the Playmethod, the buffer plays repeatedly until the application calls the IDirectSoundBuffer::Stopmethod.

    Note   When using a waveout driver, DirectSound will use waveOutGetPosition which returns a 32 bit value. This value will wrap in just under 7 hours, making the DirectSound subsystem unstable. If your application requires prolonged continous playback of audio with DirectSound, a DirectSound driver should be developed to avoid this problem.

    For streaming sound buffers, your application is responsible for ensuring that each block of data is written to the buffer ahead of the current play position. (For more on the play position, see Current Play and Write Positions.) Applications should write at least 1 second ahead of the current play position to minimize the possibility of gaps in the audio output during playback.

    The following C example writes data to a sound buffer, starting at the offset into the buffer passed in dwOffset:

    lpDsb, // the DirectSound 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->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
    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->lpVtbl->Unlock(lpDsb, lpvPtr1,
    dwBytes1, lpvPtr2, dwBytes2); if SUCCEEDED(hr) { // Success. return
    TRUE; } } // Lock, Unlock, or Restore failed. return FALSE; }

     Last updated on Tuesday, May 18, 2004

    © 2004 Microsoft Corporation. All rights reserved.