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 を使ってセカンダリ バッファにコピーする。

ストリーミングの詳細については、「ストリーム バッファの使い方」および「再生バッファの通知」を参照すること。