程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> DirectSound學習指南之使用WAV數據

DirectSound學習指南之使用WAV數據

編輯:關於VC++

使用WAV數據

在Windows 驅動模型(WDM)中,DirectSound硬件緩沖區能夠播放任何未壓縮或壓縮的聲音格式,這些格式能夠被一個WAVEFORMATEX或WAVEFORMATEXTENSIBLE結構描述,並由硬件支持。軟件緩沖區和非WDM硬件緩沖區只支持8位和16位未壓縮格式。

波形(WAV)數據通常儲存在資源交換文件格式(RIFF)的文件或資源中。數據包括一個WAV格式描述,包含如采樣率和輸出通道數等參數。

多波段WAV格式

在WDM驅動器中,DirectSound緩沖區支持擁有兩個以上輸出通道的WAV格式。對於如5.1的揚聲器配置,它在前台左,中,右,後台左,右,以及低頻增強器處均有揚聲器。

WAVEFORMATEXTENSIBLE結構描述了一個多通道波形格式。這個結構是對WAVEFORMATEX的擴展,配置了已經由WAVEFORMATEX中cbSize成員支持的額外字節。當需要WAVEFORMATEX的地方,WAVEFORMATEXTENSIBLE結構能夠被轉化為WAVEFORMATEX。

如果系統配置的物理揚聲器比多波段WAV文件中指定的通道數少,音頻數據將被適當混合並輸出到現有的揚聲器。DirectSound不支持多波段格式的緩沖區的3D處理和效果。企圖創建帶有DSBCAPS_CTRL3D或DSBCAPS_CTRLFX標識的緩沖區和一個多波段WAV格式將會失敗。

讀取WAV數據

WAV文件是資源交換文件格式(RIFF),它由若干數量的包含頭信息(如聲音采樣格式)或數據(采樣本身)的命名塊組成。Win32 API提供了打開和關閉RIFF文件,探索塊等函數。這些函數名都以“mmio”開頭。

為了以可執行方式存儲WAV聲音,將WAV文件作為資源進行導入,並為它們命名。注意CWaveFile類期望這些資源是WAVE或WAV類型,並且是可執行模塊而不是一個DLL。

DirectSound API 不包含載入聲音數據的方法。然而,Dsutil.cpp文件被許多SDK例子程序用來實現若干類,這些類能夠被用來從文件,資源或一個內存地址創建聲音緩沖區。

使用例子類初始化DirectSound和創建載入緩沖區的步驟包括:

1.創建一個CSoundManager例子類的對象。

2.調用CSoundManager::Initialize創建設備對象。

3.將一個文件或資源名傳給CSoundManager::Create或將一個內存地址傳給CSoundManager::CreateFromMemory。這些方法返回一個CSound例子類的對象,該類表示一個或多個大小恰能容納數據的靜態緩沖區。(你能夠創建多個緩沖區來同時播放多個聲音實例)或者,向CStreamingSound例子類傳遞一個文件或資源名。這個方法返回一個CStreamingSound例子類的對象,它表示了一個單獨的流緩沖區。

4.調用先前步驟中獲取的對象中的FillBufferWithSound方法。它將文件,資源或者內存地址中的數據讀入緩沖區。對於流緩沖區,它以所能容納的最大數據為限填充緩沖區,並使用CStreamingSound::HandleWaveStreamNotification在播放緩沖區的同時更新數據。

注意實際的數據讀取是由一個CWaveFile對象完成,它是CSound或CStreamingSound對象中的一個受保護成員。你通常不必直接使用CWaveFile類;然而,你能夠參考這個類的實現來獲取分析WAV數據的信息。

計算一個WAV聲音的持續時間

一個波形將要播放的時間長度取決於數據大小和格式。數據大小和格式能夠通過調用DirectSound例子框架中的CWaveFile::GetSize和CWaveFile::GetFormat方法獲取。

以下例子函數,並沒有使用例子類,返回了一個WAV文件的持續時間,以毫秒為單位:

DWORD GetSoundLength(LPSTR strFileName)
...{
 CWaveFile* pWav;
 DWORD dwLen = 0;
 DWORD dwSize;
 WAVEFORMATEX* wfx;
 pWav = new CWaveFile();
 if (SUCCEEDED(pWav->Open(strFileName, NULL, WAVEFILE_READ)))
 ...{
  wfx = pWav->GetFormat();
  dwSize = pWav->GetSize();
  dwLen = (DWORD) (1000 * dwSize / wfx->nAvgBytesPerSec);
  pWav->Close();
 }
 if (pWav) delete pWav;
 return dwLen;
}

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