Platform SDK: DirectX |
DirectSoundBuffer.SaveToFile を使うと、短いサウンドをセカンダリ バッファからウェーブ ファイルに保存できる。このメソッドはバッファの内容全体をファイルにコピーする。
多くの場合、サウンドの保存はキャプチャ バッファから始める。次のコードは、キャプチャ バッファ dscb から、ファイルに保存できるセカンダリ バッファにデータを移動する方法を示す。
Dim ByteBuffer() As Integer Dim dsc As DirectSoundCapture Dim dscd As DSCBUFFERDESC Dim dsd As DSBUFFERDESC Dim capCURS As DSCURSORS . . . ' dscd はキャプチャ バッファのフォーマットで初期化され、 ' dsb が同じサイズのセカンダリ バッファを ' 表すと仮定する。 ' キャプチャ バッファと同じフォーマットで ' セカンダリ バッファを作成する。 Set dsb = ds.CreateSoundBuffer(dsd, dscd.fxFormat) ' キャプチャ バッファの書き込みカーソルまでの内容を保持できる ' 大きさでプライベート バッファを作成する。 dscb.GetCurrentPosition capCURS ReDim ByteBuffer(capCURS.lWrite + 1) ' キャプチャ バッファの内容をプライベート バッファに読み込む。 dscb.ReadBuffer 0, capCURS.lWrite * dscd.fxFormat.nBlockAlign, _ ByteBuffer(0), DSCBLOCK_DEFAULT ' プライベート バッファをセカンダリ バッファに書き込む。 dsb.WriteBuffer 0, capCURS.lWrite, ByteBuffer(0), DSBLOCK_DEFAULT
キャプチャ バッファの長さを超えてしまうサウンドに対しては、開発者自身がウェーブ ファイルを作成し、そのファイルにデータをストリーミングしなければならない。キャプチャされたデータをウェーブ ファイルにストリーミングするのは、次のステップで行う。
ウェーブ ファイルへの書き込みを準備するには、アプリケーションは最初に、Wavwrite.cpp 内の関数に渡される 4 つの変数を宣言しなければならない。
WAVEFORMATEX wfx; // ウェーブ フォーマット情報。 HMMIO hmmio; // ファイル ハンドル。 MMCKINFO mmckinfoData; // チャンク情報。 MMCKINFO mmckinfoParent; // 親チャンク (ファイル) 情報。
キャプチャ バッファの情報を使って WAVEFORMATEX 構造体の初期化も行わなければならない。
次に WaveOpenFile 関数を呼び出し、希望のファイル名とグローバル変数のアドレスを渡す。この関数は指定されたファイルを作成し、何らかのヘッダー情報を書き込む。Wavwrite.cpp 内の他の関数と同様、WaveOpenFile は成功した場合に 0 を返す。
if (WaveOpenFile(pszFileName, &hmmio, &wfx, &mmckinfoData, &mmckinfoParent)) { // 失敗。 }
次に WaveStartDataWrite 関数を呼び出す。この関数は、データ チャンクを初期化する。
if (WaveStartDataWrite(&hmmio, &mmckinfoData, &mmioinfo)) { // 失敗。 }
これでファイルはデータを受け取る準備ができた。次の部分的なコードは、キャプチャ バッファからファイルへデータをコピーする方法を示す。
/* 次の変数に有効な値が割り当てられていることを 想定する。 LPDIRECTSOUNDCAPTUREBUFFER lpdscb; // キャプチャ バッファ。 DSCBUFFERDESC dscbDesc; // キャプチャ バッファの記述。 DWORD dwReadCursor; // バッファ内の内部カーソル。 DWORD dwNumBytes; // 利用可能なバイト数。 DWORD dwTotalBytesWritten; // 現時点までにファイル内に書き込まれた合計バイト数。 */ LPBYTE pbInput1, pbInput2; // バッファ内のデータへのポインタ。 DWORD cbInput1, cbInput2; // ロックされた部分のバイト カウント。 UINT BytesWritten; // ファイルに書き込まれたバイト カウント。 if FAILED(hr = lpdscb->Lock(dwReadCursor, dwNumBytes, (LPVOID *)&pbInput1, &cbInput1, (LPVOID *)&pbInput2, &cbInput2, 0)) { // 失敗。 } else { if (WaveWriteFile(hmmio, cbInput1, pbInput1, &mmckinfoData, &dwBytesWritten, &mmioinfo)) { // 失敗。 } else dwTotalBytesWritten += BytesWritten; if (pbInput2 != NULL) { if (WaveWriteFile(hmmio, cbInput2, pbInput2, &mmckinfoData, &BytesWritten, &mmioinfo)) { // 失敗。 } else dwTotalBytesWritten += BytesWritten; } lpdscb->Unlock(pbInput1, cbInput1, pbInput2, cbInput2); // 内部カーソルをインクリメントし、ラップ アラウンド (先頭へ戻る) を補正する。 dwReadCursor += dwNumBytes; while (dwReadCursor >= dscbDesc.dwBufferBytes) dwMyReadCursor -= dscbDesc.dwBufferBytes; }
データのキャプチャリングが終わった後で、ファイルを閉じる。
WaveCloseWriteFile(&hmmio, &mmckinfoData, &mmckinfoParent, &mmioinfo, dwTotalBytesWritten / (wfx.wBitsPerSample / 8));
WaveCloseWriteFile 関数は、ファイル内のサンプルの合計数を計算し、その値をデータ チャンクのヘッダーに書き込む。