Platform SDK: DirectX

ステップ 7 : ウェーブ ファイルへのデータのストリーミング

[Visual Basic]

ここでは、C および C++ でのアプリケーション開発について説明する。Visual Basic については、「DirectSound Visual Basic チュートリアル」を参照すること。

[C++]

最初のチュートリアルでは、通知位置のオフセットをチェックすることにより、安全に書き込みが行えるバッファ セグメントを識別する方法を学んだ。この手法は、このチュートリアルのキャプチャ バッファにも同様に適用できるが、ここでは多少異なった作業を行う必要がある。

前のステップでは、通知イベントに応答して StreamToFile 関数を呼び出す方法を学んだ。最初のチュートリアルの StreamToBuffer 関数とは異なり、この関数はパラメータとしてイベント インデックスをとらない。

BOOL StreamToFile(void)
{
    DWORD               dwReadPos;
    DWORD               dwNumBytes;
    LPBYTE              pbInput1, pbInput2;
    DWORD               cbInput1, cbInput2;
    static DWORD        dwMyReadCursor = 0;  
    UINT                dwBytesWritten;
 

dwMyReadCursor がスタティックとして宣言されている点に注意すること。これは、読み込みたい次のデータ バイトのオフセットである。言い換えると、直前に読み込んでこの関数を通して渡したバイトのすぐ後のバイトである。

この関数は最初に、現在の読み込み位置を検索する。この位置が、読み込んでも安全なデータの最初の位置を示している点に注意すること。これは通知位置に一致するとは限らない。イベントがシグナル送信された後、おそらく現在の読み込み位置は先へ進んでいるからである。

    IDirectSoundCaptureBuffer_GetCurrentPosition(lpdscb, 
            NULL, &dwReadPos);
 

次にこの関数は、(ラップ アラウンドに対処した後) 現在の読み込み位置からアプリケーション内部の読み込みカーソルを引き、新しいデータが何バイト利用できるかを決定する。

    if (dwReadPos < dwMyReadCursor)
            dwReadPos += dscbDesc.dwBufferBytes;
    dwNumBytes = dwReadPos - dwMyReadCursor;
 

次にバッファをロックして、コピーを行う。利用可能なものとして識別したデータ セグメントは、バッファの先頭と中間にある通知位置と必ずしも一致しているわけではないので、バッファのロック位置はラップ アラウンドしている (ロックされた部分がバッファの先頭へ戻り、バッファの最後と先頭の 2 つにまたがる) 可能性がある。この場合、コピー作業を 2 回行う必要がある。

    if FAILED(IDirectSoundCaptureBuffer_Lock(lpdscb, 
            dwMyReadCursor, dwNumBytes,
            (LPVOID *)&pbInput1, &cbInput1, 
            (LPVOID *)&pbInput2, &cbInput2, 0))
        OutputDebugString("Capture lock failure");
 
    else   
        {
        if (WaveWriteFile(hmmio, cbInput1, pbInput1, &mmckinfoData,
                        &dwBytesWritten, &mmioinfo))
          OutputDebugString("ファイルへのデータの書き込みに失敗しました。\n");
        dwTotalBytesWritten += dwBytesWritten; 
 
        // ラップ アラウンド。
        if (pbInput2 != NULL) 
        {
            if (WaveWriteFile(hmmio, cbInput2, pbInput2,
                    &mmckinfoData, &dwBytesWritten, &mmioinfo))
              OutputDebugString("ファイルへのデータの書き込みに失敗しました。\n");
            dwTotalBytesWritten += dwBytesWritten; 
        } 
 
        IDirectSoundCaptureBuffer_Unlock(lpdscb, 
                pbInput1, cbInput1, 
                pbInput2, cbInput2);
    }
 

WaveWriteFile 関数は、成功した場合は 0 を返し、実際にファイルにコピーしたバイト数を dwBytesWritten に書き込む。この値を累積合計に追加する。累積合計は、ファイルを閉じるときに必要になる。

最後に、内部の読み込みカーソルを更新して、ラップ アラウンドを補正し、メッセージ ループへ戻る。

    dwMyReadCursor += dwNumBytes;
    if (dwMyReadCursor >= dscbDesc.dwBufferBytes)
                dwMyReadCursor -= dscbDesc.dwBufferBytes;
 
    return TRUE;       
} // StreamToFile() の終わり。
 

次項 : ステップ 8 : キャプチャの停止