Microsoft DirectX 8.0 (C++)

ストリーム バッファの使い方

ストリーム バッファは、一度にバッファに収まらない長いサウンドを再生する。バッファが再生されるにつれ、古いデータは定期的に新しいデータに置き換わる。

ストリーム バッファを再生するには、dwFlags パラメータに DSBPLAY_LOOPING を指定して IDirectSoundBuffer8::Play メソッドを呼び出す。

再生を停止するには、IDirectSoundBuffer8::Stop メソッドを呼び出す。このメソッドはバッファを即時に停止するので、すべてのデータが再生されたことを確認する必要がある。これを行うには、再生位置をポーリングするか、通知位置を設定する。

バッファにストリーミングするには、次のステップが必要である。

  1. IDirectSoundBuffer8::Lock を使って、バッファの一部をロックする。このメソッドは、データを記述できる 1 つ、または 2 つのアドレスを返す。
  2. この 1 つまたは 2 つのアドレスに対して、標準のメモリコピー ルーチンを使ってオーディオ データを書き込む。
  3. IDirectSoundBuffer8::Unlock を使って、バッファをアンロックする。

IDirectSoundBuffer8::Lock が 2 つのアドレスを返すことがあるのは、開始位置にかかわらず、バッファのサイズまでのバイト数をロックできるからである。必要に応じて、ロックされる部分はバッファの先頭にラップされる。ラップされる場合は、2 つの個別のメモリ コピーを実行しなければならない。

たとえば 40,000 バイトのバッファで、オフセット 20,000 で始まる 30,000 バイトをロックする場合、Lock を呼び出すと 4 つの値が返される。

ラップ アラウンドが必要ない場合は、最後の 2 つの値がそれぞれ NULL と 0 になる。

バッファ全体をロックすることもできるが、再生中に行うべきではない。毎回バッファの一部だけをリフレッシュすること。たとえば、再生カーソルが 2/4 に達したらすぐに、バッファの最初の 1/4 をロックして書き込むようにする。バッファの再生カーソルと書き込みカーソルの間にある部分には書き込んではならない。詳細については、「再生カーソルと書き込みカーソル」を参照すること。

次の関数は、dwOffset に渡された位置から、データをサウンド バッファに書き込む。

BOOL AppWriteDataToBuffer( 
    LPDIRECTSOUNDBUFFER8 lpDsb,  // バッファ。
    DWORD dwOffset,              // 独自の書き込みカーソル。
    LPBYTE lpbSoundData,         // データの開始。
    DWORD dwSoundBytes)          // コピーするブロックのサイズ。
{ 
    LPVOID  lpvPtr1; 
    DWORD   dwBytes1; 
    LPVOID  lpvPtr2; 
    DWORD   dwBytes2; 
    HRESULT hr; 
 
    // 書き込みブロックのメモリ アドレスを取得する。ブロックがラップアラウンドされる場合、
    // これは 2 つの部分になる。
 
    hr = lpDsb->Lock(dwOffset, dwSoundBytes, &lpvPtr1, 
        &dwBytes1, &lpvPtr2, &dwBytes2, 0); 
 
    // バッファが失われた場合、復元してロックを再試行する。 
 
    if (DSERR_BUFFERLOST == hr) 
 
    { 
        lpDsb->Restore(); 
        hr = lpDsb->Lock(dwOffset, dwSoundBytes, 
            &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0); 
    } 
    if SUCCEEDED(hr) 
    { 
        // ポインタに書き込む。 
 
        CopyMemory(lpvPtr1, lpbSoundData, dwBytes1); 
        if (NULL != lpvPtr2) 
        { 
            CopyMemory(lpvPtr2, lpbSoundData+dwBytes1, dwBytes2); 
        } 
 
        // データを解放して DirectSound に戻す。 
 
        hr = lpDsb->Unlock(lpvPtr1, dwBytes1, lpvPtr2, 
            dwBytes2); 
        if SUCCEEDED(hr) 
        { 
            // 成功。 
            return TRUE; 
        } 
    } 
 
    // ロック、アンロック、または復元が失敗した。 
 
    return FALSE; 
} 
 

詳細については、次のトピックを参照すること。