WAV ファイルへの書き込み
WAV ファイルは RIFF (Resource Interchange File Format) 形式です。これは、ヘッダー情報 (サウンド サンプルのフォーマットなど) とデータ (サンプルそのものの) のいずれかを含む可変の名前付きチャンクで構成されています。Win32 API は、RIFF ファイルを開いて閉じるための関数や、チャンクをシークするための関数を提供します。これらの関数の名前はすべて "mmio" から始まります。
DirectSound API には、WAV ファイルへの書き込みに使用するメソッドがありません。ただし、DXUTsound.cpp ファイルは、キャプチャー ファイルを管理するための以下のメソッドを備えた CWaveFile クラスを実装しています。
- Open。ファイルを開いてヘッダー チャンクを書き込む。
- Write。バッファーからデータ チャンクへの書き込みを行い、書き込みカーソルを前進させる。
- Close。データ チャンクのサイズをヘッダーに書き込み、ファイルを閉じる。
WAV ファイルを書き込むための最初の手順は、CWaveFile::Open メソッドの呼び出しです。このメソッドはファイルを作成し、WAV フォーマット チャンクを書き込みます。パラメーターは、ファイル名、初期化された WAVEFORMATEX 構造体へのポインター、および WAVEFILE_WRITE フラグです。このメソッドは、HRESULT を返します。
次のコードは、書き込み用の WAV ファイルを開きます。
CWaveFile g_pWaveFile;
WAVEFORMATEX wfxInput;
ZeroMemory( &wfxInput, sizeof(wfxInput));
wfxInput.wFormatTag = WAVE_FORMAT_PCM;
wfxInput.nSamplesPerSec = 22050
wfxInput.wBitsPerSample = 8;
wfxInput.nChannels = 1;
wfxInput.nBlockAlign =
wfxInput.nChannels * (wfxInput.wBitsPerSample / 8);
wfxInput.nAvgBytesPerSec =
wfxInput.nBlockAlign * wfxInput.nSamplesPerSec;
g_pWaveFile = new CWaveFile;
if (FAILED(g_pWaveFile->Open("mywave.wav", &wfxInput,
WAVEFILE_WRITE)))
{
g_pWaveFile->Close();
}
以上で、アプリケーションはキャプチャー バッファーからファイルへのデータ コピーを開始できるようになります。
次の例に示す関数は、読み取りカーソルが通知位置に到達するたびに呼び出されます。この関数では、次のグローバル変数が使用されています。
- g_pDSBCapture は、キャプチャー バッファーの IDirectSoundCaptureBuffer8 インターフェイスへのポインターです。
- g_dwNextCaptureOffset は、ファイルにコピーする次のデータ ブロックのバッファー オフセットを追跡します。
- g_dwCaptureBufferSize は、キャプチャー バッファーのサイズで、ラップ アラウンドの計算に使用されます。
HRESULT RecordCapturedData()
{
HRESULT hr;
VOID* pbCaptureData = NULL;
DWORD dwCaptureLength;
VOID* pbCaptureData2 = NULL;
DWORD dwCaptureLength2;
VOID* pbPlayData = NULL;
UINT dwDataWrote;
DWORD dwReadPos;
LONG lLockSize;
if (NULL == g_pDSBCapture)
return S_FALSE;
if (NULL == g_pWaveFile)
return S_FALSE;
if (FAILED (hr = g_pDSBCapture->GetCurrentPosition(
NULL, &dwReadPos)))
return hr;
// Lock everything between the private cursor
// and the read cursor, allowing for wraparound.
lLockSize = dwReadPos - g_dwNextCaptureOffset;
if( lLockSize < 0 ) lLockSize += g_dwCaptureBufferSize;
if( lLockSize == 0 ) return S_FALSE;
if (FAILED(hr = g_pDSBCapture->Lock(
g_dwNextCaptureOffset, lLockSize,
&pbCaptureData, &dwCaptureLength,
&pbCaptureData2, &dwCaptureLength2, 0L)))
return hr;
// Write the data. This is done in two steps
// to account for wraparound.
if (FAILED( hr = g_pWaveFile->Write( dwCaptureLength,
(BYTE*)pbCaptureData, &dwDataWrote)))
return hr;
if (pbCaptureData2 != NULL)
{
if (FAILED(hr = g_pWaveFile->Write(
dwCaptureLength2, (BYTE*)pbCaptureData2,
&dwDataWrote)))
return hr;
}
// Unlock the capture buffer.
g_pDSBCapture->Unlock( pbCaptureData, dwCaptureLength,
pbCaptureData2, dwCaptureLength2 );
// Move the capture offset forward.
g_dwNextCaptureOffset += dwCaptureLength;
g_dwNextCaptureOffset %= g_dwCaptureBufferSize;
g_dwNextCaptureOffset += dwCaptureLength2;
g_dwNextCaptureOffset %= g_dwCaptureBufferSize;
return S_OK;
}
キャプチャーが終了すると、アプリケーションは WAV ファイルを閉じます。
g_pWaveFile->Close();