Microsoft DirectX 8.0 (C++) |
ここでは、DirectMusic ローダーおよびパフォーマンスを使用せずに、ウェーブ ファイルのデータを DirectSound バッファにロードする方法について説明する。ほとんどのアプリケーションでは、ウェーブ データやバッファを直接処理する必要はない。ウェーブのロードや再生の優先される方法については、「オーディオ データのロード」および「サウンドの再生」を参照すること。
ウェーブ ファイルは RIFF (Resource Interchange File Format、リソース交換ファイル フォーマット) を採用しており、ヘッダー情報 (たとえばサウンド サンプルのウェーブ フォーマット) とデータ (サンプル自体) を保持する、任意の数のチャンクによって構成されている。Win32 API は、RIFF ファイルを開いたり閉じたりするための関数や、チャンクの検索関数などを提供する。これらの関数の名前はすべて "mmio" で始まる。
DirectSound API は、ウェーブ ファイルを処理するためのメソッドを備えていない。ただし、多くの SDK サンプル アプリケーションで使用される Dsutil.cpp ファイルは、次のパブリック メソッドを持つ CWaveFile クラスを実装する。
ウェーブ ファイルを読み込む最初のステップは、CWaveFile::Open メソッドを呼び出すことである。このメソッドは、ファイルが RIFF フォーマットであることを確認し、ウェーブ フォーマットに関する情報を取得する。パラメータはファイル名、フォーマットの NULL、および WAVEFILE_READ フラグである。このメソッドは HRESULT を返す。
次のコードは、ウェーブ ファイルを開く。
CWaveFile waveFile; if (FAILED(waveFile.Open("mywave.wav", NULL, WAVEFILE_READ))) { waveFile.Close(); }
これで、アプリケーションはファイルからセカンダリ バッファへのコピーを開始できる。通常は、ウェーブのフォーマットを取得するまではサウンド バッファを作成しない。次のコードは、ファイル内の全データを保持するのにちょうどよいサイズのスタティック バッファを作成する。
LPDIRECTSOUNDBUFFER lpdsbStatic; DSBUFFERDESC dsbdesc; memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = 0; /* ウェーブ フォーマットとデータ チャンクのサイズは、 // CWaveFile::Open が呼び出された後、CWaveFile に格納される。 dsbdesc.dwBufferBytes = waveFile.GetSize(); dsbdesc.lpwfxFormat = waveFile.m_pwfx; // lpds は有効な IDirectSound8 ポインタである。 if FAILED(lpds->CreateSoundBuffer(&dsbdesc, &lpdsbStatic, NULL)) { // エラー処理。 . . . }
これで、バッファにデータを書き込むことができる。この場合、アプリケーションはデータのストリーミングを行わないので、バッファ全体が先頭からロックされる。ラップアラウンド (先頭へ戻る) も発生しないので、必要なのは 1 つのポインタとバイト カウントである。
LPVOID lpvAudio1; DWORD dwBytes1; if FAILED(lpdsbStatic->Lock( 0, // ロック開始のオフセット。 0, // ロックのサイズ。この場合は無視される。 &lpvAudio1, // ロック開始のアドレス。 &dwBytes1, // ロックされるバイト数。 NULL, // ラップアラウンドの開始。使用されない。 NULL, // ラップアラウンドのサイズ。使用されない。 DSBLOCK_ENTIREBUFFER)) { // エラー処理。 . . . }
CWaveFile::Read メソッドを使って、次のようにバッファに書き込むことができる。
DWORD dwBytesRead; waveFile.Read((BYTE*)lpvAudio1, dwBytes1, &dwBytesRead);
最後にアプリケーションはバッファをアンロックし、ウェーブ ファイルを閉じる。
lpdsbStatic->Unlock(lpvAudio1, dwBytes1, NULL, 0); waveFile.Close();
ストリーム バッファの場合は、通常、再生カーソルの動きによって決定される一定の間隔で CWaveFile::Read を呼び出す。バッファのロックされた部分がラップ アラウンドしている場合は、ロックの各セグメントごとにこのメソッドを呼び出す。
ストリーミングの詳細については、「ストリーム バッファの使い方」および「再生バッファの通知」を参照すること。
CWaveFile クラスの使い方のその他の例については、DirectX SDK インストールに含まれるサンプル アプリケーションを参照すること。