首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

DirectSound 波形捕捉系列(九):寫入 WAV 檔案

     編輯:關於C++

使用 CWaveFile 類將捕捉緩衝區資料寫入 WAV 檔案

DirectSound API 本身不提供 WAV 檔案寫入功能,但 DXUT 提供的 CWaveFile 類封裝了 RIFF/WAV 格式操作,支援標準 PCM 音訊檔案建立。

WAV 檔案結構基礎

  • RIFF 容器格式,包含多個命名區塊
  • 必要區塊:fmt (格式資訊)、data(音訊樣本)
  • Win32 提供 mmio* 系列函式操作 RIFF 檔案

CWaveFile 核心方法

方法功能
Open(filename, &wfx, WAVEFILE_WRITE)建立檔案並寫入 fmt 區塊
Write(byte_count, buffer, &written)將緩衝區資料寫入 data 區塊
Close()更新 data 區塊大小至檔頭並關閉檔案

開啟 WAV 檔案範例

CWaveFile* g_pWaveFile = new CWaveFile();
WAVEFORMATEX wfx = {};
wfx.wFormatTag      = WAVE_FORMAT_PCM;
wfx.nSamplesPerSec  = 22050;
wfx.wBitsPerSample  = 8;
wfx.nChannels       = 1;
wfx.nBlockAlign     = wfx.nChannels * (wfx.wBitsPerSample / 8);
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;

if (FAILED(g_pWaveFile->Open(L"capture.wav", &wfx, WAVEFILE_WRITE))) {
    g_pWaveFile->Close();
    delete g_pWaveFile;
    return E_FAIL;
}

從捕捉緩衝區寫入資料

HRESULT RecordCapturedData() {
    HRESULT hr;
    BYTE* pbData1 = nullptr; DWORD dwLen1;
    BYTE* pbData2 = nullptr; DWORD dwLen2;
    DWORD dwReadPos;
    LONG  lLockSize;

    // 1. 取得目前讀取位置
    if (FAILED(hr = g_pDSBCapture->GetCurrentPosition(nullptr, &dwReadPos)))
        return hr;

    // 2. 計算可安全讀取的資料長度(避開寫入游標)
    lLockSize = dwReadPos - g_dwNextCaptureOffset;
    if (lLockSize < 0) lLockSize += g_dwCaptureBufferSize;
    if (lLockSize == 0) return S_FALSE;

    // 3. 鎖定捕捉緩衝區(可能跨越緩衝區邊界產生兩段)
    if (FAILED(hr = g_pDSBCapture->Lock(g_dwNextCaptureOffset, lLockSize,
        &pbData1, &dwLen1, &pbData2, &dwLen2, 0)))
        return hr;

    // 4. 寫入 WAV 檔案(分兩段處理環繞)
    DWORD dwWritten;
    if (FAILED(hr = g_pWaveFile->Write(dwLen1, pbData1, &dwWritten))) return hr;
    if (pbData2 && FAILED(hr = g_pWaveFile->Write(dwLen2, pbData2, &dwWritten))) return hr;

    // 5. 解鎖並更新下次讀取位移
    g_pDSBCapture->Unlock(pbData1, dwLen1, pbData2, dwLen2);
    g_dwNextCaptureOffset = (g_dwNextCaptureOffset + dwLen1 + dwLen2) % g_dwCaptureBufferSize;

    return S_OK;
}

關鍵技術點

  • 環繞處理:環狀緩衝區讀取可能跨越邊界,Lock 返回兩段指標
  • 讀寫分離:讀取游標 (dwReadPos) 標示安全讀取上限,避免覆蓋未讀資料
  • 位移追蹤:g_dwNextCaptureOffset 記錄下次讀取起始位置

結束捕捉

g_pWaveFile->Close();  // 寫入 data chunk 大小、更新 RIFF header、關閉檔案
delete g_pWaveFile;

完整系列導覽

  1. 枚舉捕捉裝置
  2. 建立捕捉裝置物件
  3. 查詢裝置能力
  4. 建立捕捉緩衝區
  5. 取得緩衝區資訊
  6. 設定通知位置
  7. 啟用特效 (AEC/NS)
  8. 使用捕捉緩衝區
  9. 寫入 WAV 檔案 (本文)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved