Microsoft DirectX 8.0 (Visual Basic)

ウェーブ ファイルへの書き込み

短いサウンドは、DirectSoundSecondaryBuffer8.SaveToFile を使って、セカンダリ バッファからウェーブ ファイルに保存できる。このメソッドは、バッファの内容全体をファイルにコピーする。

多くの場合、サウンドの保存はキャプチャ バッファから始める。次のコードは、キャプチャ バッファ dscb からセカンダリ バッファに、次にファイルにデータを移動する方法を示している。

Dim ds As DirectSound8
Dim dscb As DirectSoundCaptureBuffer8 
Dim dscd As DSCBUFFERDESC
Dim dsd As DSBUFFERDESC
Dim capCurs As DSCURSORS
Dim numBytes As Long
Dim ByteBuffer() As Integer 
.
.
.
' ds が作成され、dscb が作成されてデータを格納し、
' dscd がキャプチャ バッファのフォーマットを保持しているとする。
 
' 同じフォーマットで、キャプチャ バッファに書き込まれた
' すべてのデータを格納するのに十分な大きさのセカンダリ バッファを作成する。
 
dscb.GetCurrentPosition capCurs
numBytes = capCurs.lWrite + 1
dsd.lBufferBytes = numBytes
dsd.fxFormat = dscd.fxFormat
Set dsb = ds.CreateSoundBuffer(dsd)
 
' 同じデータを保持するのに十分な大きさのプライベート バッファを作成する。
 
ReDim ByteBuffer(numBytes)
 
' キャプチャ バッファの内容をプライベート バッファに読み込む。
 
dscb.ReadBuffer 0, numBytes, ByteBuffer(0), DSCBLOCK_DEFAULT
 
' プライベート バッファをセカンダリ バッファに書き込む。
 
dsb.WriteBuffer 0, numBytes, ByteBuffer(0), DSBLOCK_DEFAULT
 
' ウェーブを保存する。
 
dsb.SaveToFile "captured.wav"

キャプチャ バッファの長さを超えてしまうサウンドに対しては、開発者自身がウェーブ ファイルを作成し、そのファイルにデータをストリーミングしなければならない。キャプチャされたデータをウェーブ ファイルにストリーミングするのは、次のステップで行う。

  1. ファイルを作成し、ファイル ヘッダー、フォーマット チャンク、およびデータ チャンクのヘッダーを書き込む。フォーマット チャンクは、キャプチャ バッファのフォーマットを記述しなければならない。ただし、フォーマットの要素は WAVEFORMATEX 型と同じ順番ではないことに注意すること。ヘッダーとチャンクの編成の情報については、「ウェーブ ファイルの読み込み」を参照すること。
  2. キャプチャ バッファからプライベート バッファまで、またそのバッファからファイルまでのデータのストリーミングを行う。このとき、書き込まれたバイトの数を追跡する。詳細については、「キャプチャ バッファの使い方」を参照すること。
  3. キャプチャが停止し、すべてのデータが書き込まれたら、データ チャンクの長さとファイルの合計サイズを計算し、これらの値をデータ チャンク ヘッダーとファイル ヘッダーのそれぞれの適切な位置に書き込む。

次のコードは、ファイルを作成して RIFF ヘッダー情報を書き込む。

Private Type FileHeader
    lRiff As Long
    lFileSize As Long
    lWave As Long
    lFormat As Long
    lFormatLength As Long
End Type
 
Private Type WaveFormat
    wFormatTag As Integer
    nChannels As Integer
    nSamplesPerSec As Long
    nAvgBytesPerSec As Long
    nBlockAlign As Integer
    wBitsPerSample As Integer
' Integer 型の cbSize
End Type
 
Private Type ChunkHeader
    lType As Long
    lLen As Long
End Type
 
Dim fh As FileHeader
Dim wf As WaveFormat
Dim ch As ChunkHeader

Private Sub OpenFile(WaveFileName As String)

  Open WaveFileName For Binary Access Write As #1
  
  With fh
    .lRiff = &H46464952    ' <RIFF> チャンク タグ
    .lFileSize = 0         ' 後で取得
    .lWave = &H45564157    ' <WAVE> チャンク タグ
    .lFormat = &H20746D66  ' <fmt > チャンク タグ
    .lFormatLength = Len(wf)
  End With
  
  Put #1, , fh
  
  With wf
    .wFormatTag = dscbDesc.fxFormat.nFormatTag
    .nChannels = dscbDesc.fxFormat.nChannels
    .nSamplesPerSec = dscbDesc.fxFormat.lSamplesPerSec
    .wBitsPerSample = dscbDesc.fxFormat.nBitsPerSample
    .nBlockAlign = dscbDesc.fxFormat.nBlockAlign
    .nAvgBytesPerSec = dscbDesc.fxFormat.lAvgBytesPerSec
  End With
  
  Put #1, , wf
  
    ch.lType = &H61746164  ' <data> チャンク タグ
  
  Put #1, , ch
  
End Sub

これで、キャプチャしたデータをファイルに追加できるようになった。ファイルに書き込まれたデータのバイト数が BytesWritten と呼ばれる Long に格納されているとすると、ファイルは次のプロシージャを使って閉じられる。

Private Sub CloseFile()
 
  Dim fsize As Long
  
  ' ファイルのサイズを書き込む。
 
  fsize = Len(fh) + Len(wf) + Len(ch) + BytesWritten
  Put #1, 5, fsize
  
  ' データのチャンク ヘッダーをサイズに書き換える。
  
  ch.lLen = BytesWritten
  Put #1, Len(fh) + Len(wf) + 1, ch
  
  Close #1
 
End Sub