Microsoft DirectX 8.0 (Visual Basic) |
ここでは、DirectMusic ローダーおよびパフォーマンスを使用せずに、ウェーブ ファイルのデータを DirectSound バッファにロードする方法について説明する。ほとんどのアプリケーションでは、ウェーブ データやバッファを直接処理する必要はない。ウェーブのロードや再生の優先される方法については、「オーディオ データのロード」および「サウンドの再生」を参照すること。
短いサウンドの場合、DirectSound だけを使ってウェーブ ファイルを再生する最も簡単な方法は、DirectSound8.CreateSoundBufferFromFile メソッドを呼び出してスタティック バッファにロードする方法である。「セカンダリ バッファの作成」を参照すること。
メモリに収まらない大きいファイルの場合は、ストリーム バッファを作成して、ファイルを分割して読み込む必要がある。
ウェーブ ファイルは RIFF (Resource Interchange File Format、リソース交換ファイル フォーマット) を採用しており、ファイル ヘッダーと、それぞれヘッダーとデータから成る任意の数の "チャンク" によって構成されている。チャンク ヘッダーは、データの型を識別する 4 文字のタグとデータの長さを与える Long で構成される。
ウェーブ ファイル ヘッダーは次のようになる。
最初のチャンクは常にフォーマット チャンクであり、次のようになる。
ウェーブ ファイルの PCM サンプル データは、文字列 "data" で始まるチャンクに保持される。これは、Long &H61746164 としても読み取られる。ほとんどの場合このチャンクはフォーマット チャンクに直接続くが、RIFF が拡張可能なフォーマットなので、ほかのタイプのチャンクが先行しないという保証はない。ファイル パーサーには、処理できないチャンクを無視できる能力が必要である。
ウェーブ ファイルを解析するには、3 つのユーザー定義型を準備するとよい。最初のタイプは、ファイル ヘッダーとフォーマット チャンクのヘッダー内の情報をすべて受け取る。
Private Type FileHeader lRiff As Long lFileSize As Long lWave As Long lFormat As Long lFormatLength As Long End Type
2 番目のタイプは、フォーマット データを受け取る。これには、メンバが異なる順序である WAVEFORMATEX 型は使用できない。このユーザー定義型は、16 バイトのチャンクのうち 14 バイトだけを取得しなければならない。なぜなら、チャンク内の最後の Integer 値は WAVEFORMATEX.lExtra と同等で、標準的な PCM ファイルでは常に 0 だからである。
Private Type WaveFormat wFormatTag As Integer nChannels As Integer nSamplesPerSec As Long nAvgBytesPerSec As Long nBlockAlign As Integer wBitsPerSample As Integer End Type
3 番目のタイプは、データ チャンクも含め任意のチャンクのヘッダーを取得するために使われる。
Private Type ChunkHeader lType As Long lLen As Long End Type
次のサンプル関数は、ファイルが RIFF ウェーブ ファイルであることを確認し、サンプル データの始まりを検索し、ウェーブ フォーマットについての情報を保持する WAVEFORMATEX 型を返す。
Dim FileFree As Long ' グローバル ファイルのハンドル。 Dim lDataLength As Long ' グローバル データの長さ。 Private Function FillFormat(FileName As String) As WAVEFORMATEX Dim Header As FileHeader Dim HdrFormat As WaveFormat Dim chunk As ChunkHeader Dim by As Byte Dim i As Long ' ファイルを開き、ヘッダーを読み込む。 Close #FileFree FileFree = FreeFile Open FileName For Binary Access Read As #FileFree Get #FileFree, , Header ' "RIFF" タグをチェックし、見つからない場合は終了する。 If Header.lRiff <> &H46464952 Then Exit Function End If ' "wAVE" タグをチェックし、見つからない場合は終了する。 If Header.lWave <> &H45564157 Then Exit Function End If ' フォーマット チャンクの長さをチェックし、16 未満の場合は、 ' PCM データではないので、使用できない。 If Header.lFormatLength < 16 Then Exit Function End If ' フォーマットを取得する。 Get #FileFree, , HdrFormat ' フォーマット バイトを破棄して次のチャンクを検索する。 For i = 1 To Header.lFormatLength - 16 Get #FileFree, , by Next ' "data" チャンクに到達するまでチャンクを無視する。 Get #FileFree, , chunk Do While chunk.lType <> &H61746164 For i = 1 To chunk.lLen Get #FileFree, , by Next Get #FileFree, , chunk Loop ' データのサイズを取得する。 lDataLength = chunk.lLen ' 返された型にフォーマット情報を書き込む。 With FillFormat .lAvgBytesPerSec = HdrFormat.nAvgBytesPerSec .lExtra = 0 .lSamplesPerSec = HdrFormat.nSamplesPerSec .nBitsPerSample = HdrFormat.wBitsPerSample .nBlockAlign = HdrFormat.nBlockAlign .nChannels = HdrFormat.nChannels .nFormatTag = HdrFormat.wFormatTag End With End Function
これでアプリケーションは、ファイルからのデータを読み込み、セカンダリ サウンド バッファにそのデータをストリーミングできるようになる。ファイルから直接データをセカンダリ バッファに読み込むことはできない。まず、データをプライベート バッファに読み込んだ後、DirectSoundSecondaryBuffer8.WriteBuffer を使ってセカンダリ バッファにコピーする。
ストリーミングの詳細については、「ストリーム バッファの使い方」および「再生バッファの通知」を参照すること。