程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 波形捕捉:(9)寫入到WAV文件

波形捕捉:(9)寫入到WAV文件

編輯:關於C++

WAV文件為資源交換文件格式(RIFF),包括若干數量的命名塊,其中包含頭 信息(如聲音采樣格式)或數據(如樣本本身)。Win 32 API提供了打開關閉 FIFF文件、查找塊等函數。這些函數的名字都以“mmio”開頭。

DirectSound API 不包括寫入WAV文件的方法。但是 DXUTsound.cpp 文 件實現了一個 CWaveFile 類,這個類具有以下管理捕捉文件的方 法:

·Open 方法。打開一個文件並且寫入頭部塊。

·Write 方法。將數據從緩沖區寫入到數據塊中並且提高寫指針 。

·Close 方法。將數據塊的大小寫入到頭部並且關閉文件。

寫入到一個WAV文件的第一步是調用 CWaveFile::Open 方法。這樣會創 建一個文件並且寫WAV格式塊。參數為文件名,一個指向初始化後的 WAVEFORMATEX 結構體的指針和 WAVEFILE_WRITE 標志。這個方法返回一個 HRESULT。

下面的代碼為寫入打開了一個WAV文件:

Code

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 表示緩沖區大 小,被用在計算"環繞"。

Code

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;
  }

When capturing is finished, the application closes the WAV file.

  g_pWaveFile->Close ();

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved