キャプチャー バッファーの通知
定期的にキャプチャー バッファーからデータをコピーするには、読み取りカーソルがバッファー内の指定のポイントに到達したことをアプリケーションで認識する必要があります。読み取りカーソルとは、安全に読み取ることのできるデータの末尾を示すポイントです。この情報を取得する方法の 1 つは、IDirectSoundCaptureBuffer8::GetCurrentPosition を使用して、読み取りカーソルの位置をポーリングすることです。さらに効果的な方法として、通知を使用する方法があります。IDirectSoundNotify8::SetNotificationPositions メソッドを使用すると、イベント通知を行うポイントをバッファー内に必要なだけ設定できます。バッファーの実行中はこの設定はできません。
最初に、IDirectSoundNotify8 インターフェイスを取得する必要があります。これには、バッファー オブジェクトの QueryInterface メソッドを使用します。
それぞれの通知位置に、Win32 の CreateEvent 関数を使用してイベント オブジェクトを作成します。イベントへのハンドルを、DSBPOSITIONNOTIFY 構造体の hEventNotify メンバーに配置します。この構造体の dwOffset メンバーで、イベント通知を行う位置のバッファー内におけるオフセットを指定します。次に、この構造体のアドレスを SetNotificationPositions に渡します。通知位置を複数設定する場合は、構造体の配列のアドレスを渡します。
次の例では、1 秒分のバッファーに 3 つの通知位置を設定しています。1 つ目のイベントは、読み取り位置がバッファーの中間ポイントに近づいたときに通知されます。2 つ目は、読み取り位置がバッファーの最後に近づいたときに、3 つ目は、キャプチャーが停止したときにそれぞれ通知されます。
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;
}