Capture Buffer Notification

[The feature associated with this page, DirectSound, is a legacy feature. It has been superseded by WASAPI and Audio Graphs. Media Casting have been optimized for Windows 10 and Windows 11. Microsoft strongly recommends that new code use Media Casting instead of DirectSound, when possible. Microsoft suggests that existing code that uses the legacy APIs be rewritten to use the new APIs if possible.]

To copy data out of the capture buffer at regular intervals, your application has to know when the read cursor, which is the point up to which it is safe to read data, reaches certain points in the buffer. One way to get this information is to poll the position of the read cursor using IDirectSoundCaptureBuffer8::GetCurrentPosition. A more efficient way is to use notifications. Using the IDirectSoundNotify8::SetNotificationPositions method, you can set any number of points within the buffer where events are to be signaled. You cannot do this while the buffer is running.

First you must obtain the IDirectSoundNotify8 interface. You can do this by using the buffer object's QueryInterface method.

For each notification position, create an event object with the Win32 CreateEvent function. Put the handle to this event in the hEventNotify member of a DSBPOSITIONNOTIFY structure. In the dwOffset member of that structure, specify the offset within the buffer where you want the event to be signaled. Then pass the address of the structure-or of an array of structures, if you want to set more than one notification position-to SetNotificationPositions.

The following example sets up three notification positions in a one-second buffer. One event will be signaled when the read position nears the halfway point in the buffer, another will be signaled when it nears the end of the buffer, and the third will be signaled when capture stops.

HRESULT SetCaptureNotifications(LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB)
{
  #define cEvents  3

  LPDIRECTSOUNDNOTIFY8 pDSNotify;
  WAVEFORMATEX         wfx;  
  HANDLE     rghEvent[cEvents] = {0};
  DSBPOSITIONNOTIFY  rgdsbpn[cEvents];
  HRESULT    hr;

  if (NULL == pDSCB) return E_INVALIDARG;
  if (FAILED(hr = pDSCB->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&pDSNotify)))
  {
    return hr;
  }
  if (FAILED(hr = pDSCB->GetFormat(&wfx, sizeof(WAVEFORMATEX), NULL)))
  {
    return hr;
  }

  // Create events.
  for (int i = 0; i < cEvents; ++i)
  {
    rghEvent[i] = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (NULL == rghEvent[i])
    {
      hr = GetLastError();
      return hr;
    }
  }
 
  // Describe notifications. 
 
  rgdsbpn[0].dwOffset = (wfx.nAvgBytesPerSec/2) -1;
  rgdsbpn[0].hEventNotify = rghEvent[0];
 
  rgdsbpn[1].dwOffset = wfx.nAvgBytesPerSec - 1;
  rgdsbpn[1].hEventNotify = rghEvent[1];
 
  rgdsbpn[2].dwOffset = DSBPN_OFFSETSTOP;
  rgdsbpn[2].hEventNotify = rghEvent[2];
 
  // Create notifications.
 
  hr = pDSNotify->SetNotificationPositions(cEvents, rgdsbpn);
  pDSNotify->Release();
  return hr;
}