次の方法で共有


再生バッファーの通知

DirectSound では、バッファーの特定の位置に再生カーソルが到達すると、またはバッファーが停止すると、アプリケーションにこれを通知できます。これは以下の 2 つの一般的な状況で役立つ場合があります。

  • サウンドの再生が終了したときに、別のバッファーの再生など、アプリケーションが何らかのアクションを行う必要がある。
  • アプリケーションはデータをバッファーにストリーミングしていて、再生されたデータを新しいデータと置き換えることができるように、定義済みの位置に生成カーソルが到達したことを知る必要がある。

音声管理を利用している場合は、通知位置に到達する前にバッファーを終了することは可能です。DSBPOSITIONNOTIFY の「解説」を参照してください。

IDirectSoundNotify8::SetNotificationPositions メソッドを使用すると、イベント通知を行うポイントをバッファー内に必要なだけ設定できます。バッファーの再生中はこの設定はできません。

最初に、IDirectSoundNotify8 インターフェイスへのポインターを取得する必要があります。これには、バッファー オブジェクトの QueryInterface メソッドを使用します。通知を設定したい各バッファーから別々のインターフェイスを取得する必要があります。

それぞれの通知位置に、Win32 の CreateEvent 関数を使用してイベント オブジェクトを作成します。このイベントへのハンドルを、DSBPOSITIONNOTIFY 構造体の hEventNotify メンバーに配置します。この構造体の dwOffset メンバーで、イベント通知を行う位置のバッファー内におけるオフセットを指定します。次に、この構造体のアドレスを SetNotificationPositions に渡します。通知位置を複数設定する場合は、構造体の配列のアドレスを渡します。

以下は、1 つの通知位置を設定する関数の例です。このイベントは、再生の停止時にシグナル ステートになります。これは、非ループ バッファーの最後に到達したか、アプリケーションが IDirectSoundBuffer8::Stop メソッドを読み出したためです。hMyEvent が CreateEvent から返されたハンドルで、lpDsbSecondary が DSBCAPS_CTRLPOSITIONNOTIFY フラグによって作成されたセカンダリ バッファーであるとします。

HRESULT SetStopNotification(HANDLE hMyEvent, 
        LPDIRECTSOUNDBUFFER8 lpDsbSecondary)
{
  LPDIRECTSOUNDNOTIFY8 lpDsNotify; 
  DSBPOSITIONNOTIFY PositionNotify;
  HRESULT hr;

  if (SUCCEEDED(
      hr = lpDsbSecondary->QueryInterface(IID_IDirectSoundNotify8,
             (LPVOID*)&lpDsNotify))) 
  { 
    PositionNotify.dwOffset = DSBPN_OFFSETSTOP;
    PositionNotify.hEventNotify = hMyEvent;
    hr = lpDsNotify->SetNotificationPositions(1, &PositionNotify);
    lpDsNotify->Release();
  }
  return hr;
}

ハードウェアによって制御されるバッファーの通知を、すべてのドライバーが正確に提供するとは限りません。ドライバーによっては誤った通知を生成することもあります。この問題を回避するには、アプリケーションが通知を受け取るたびに IDirectSoundBuffer8::GetCurrentPosition を呼び出すことで、通知位置が実際に到達した場所になるようにします。もう 1 つの解決策は、ソフトウェア内にバッファーを作成することです。