次の方法で共有


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();