ストリーミング バッファーの使用
ストリーミング バッファーは、バッファーにすべてを一度に納めることができない長いサウンドを再生します。バッファーが再生されると、古いデータは周期的に新しいデータと置き換えられます。
ストリーミング バッファーを再生するには、IDirectSoundBuffer8::Play メソッドを呼び出して、dwFlags パラメーターに DSBPLAY_LOOPING を指定します。
再生を中断するには、IDirectSoundBuffer8::Stop メソッドを呼び出します。このメソッドによってバッファーは突然停止されるため、すべてのデータが再生されていることを確認する必要があります。これは、再生位置をポーリングするか、通知位置を設定することで行うことができます。
バッファーへのストリーミングでは、以下の手順を実行する必要があります。
- バッファーが新しいデータを受け取る準備ができているかどうかを確認します。これは、再生カーソルをポーリングするか、通知を待機することで行うことができます。
- IDirectSoundBuffer8::Lock を使用することでバッファーの一部をロックします。このメソッドは、データを書き込むことができるようになったアドレスを 1 つまたは 2 つ返します。
- 標準のメモリーコピー ルーチンを使用して返されたアドレスにオーディオ データを書き込みます。
- IDirectSoundBuffer8::Unlock を使用してバッファーのロックを解除します。
開始位置に関係なく、バッファーのサイズまでは、任意のバイト数をロックできるため、IDirectSoundBuffer8::Lock は 2 つのアドレスを返すことがあります。必要があれば、ロック部分はバッファーの先頭へラップ アラウンドします。その場合は、2 つのメモリー コピーを別々に実行する必要があります。
たとえば、40,000 バイトのバッファーにおいて、オフセット 20,000 から始まる 30,000 バイトをロックするとします。この場合、ロックを呼び出すと、次の 4 つの値が返されます。
- オフセット 20,000 のメモリー アドレス。
- ロックされるバイト数。この位置からバッファーの終端までがロックされます。つまり 20,000 バイトです。このバイト数は最初のアドレスに書き込んでください。
- オフセット 0 のメモリー アドレス。
- ロックを開始するバイト数。つまり 10,000 バイトです。このバイト数は 2 つめのアドレスに書き込んでください。
ラップアラウンドが不要な場合は、最後の 2 つの値はそれぞれ NULL と 0 になります。
バッファー全体をロックすることはできますが、再生中には行わないでください。通常、毎回バッファーの一部のみを更新してください。たとえば、再生カーソルが 4 分の 2 番目に到達したらすぐに、バッファーの 4 分の 1 番目をロックして書き込むというようにします。再生カーソルと書き込みカーソルとの間のバッファー部分には決して書き込まないでください。
以下の関数は、サウンド バッファーにデータを書き込み、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;
}
関連項目