WINDOWS下對音頻的處理過程(轉)

WINDOWS下對音頻的處理過程
WINDOWS下對音頻的處理,大致可分爲兩部分,即音頻的輸入、輸出,和ACM壓縮處理。

  一般情況下在WINDOWS下可以調用諸如sndPlaySound等API(MCI)來播放一個WAV文件,但那顯然不是我們需要做的。必須能夠直接對音頻數據流進行處理。在WINDOWS下,也爲之提供了一系列的API,以waveIn和waveOut開頭的一組API就是幹這個的。

  先說輸入吧。常用的相關API爲waveInOpen(打開一個音頻輸入設備)、waveInPrepareHeader(爲一個即將在waveInAddBuffer中調用的輸入緩衝區準備頭部)、waveInAddBuffer(添加一個輸入用的數據緩衝區)、 waveInStart(開始錄音)、waveInClose(關閉音頻輸入設備)等幾個,以及需要在waveInOpen中指定的一個回調函數或者線程,其作用是在一個數據緩衝區被錄滿後被調用,以對這些數據進行處理,和其他一些相關的操作。

  首先你得確定一下需要用什麼回調方式,即在某個時間片的音頻數據被錄完後,Windows將通過這個回調來激活對這些數據的處理過程,一般用到的無非是FUNCTION、THREAD和EVENT這幾類,而比較方便簡單的就是FUNCTION和THREAD了。FUNCTION方式是指Windows會調用你這個函數,而THREAD則是由 Windows來激活你所指定的線程。這些都在waveInOpen中指定。其函數原型爲:

MMRESULT waveInOpen( LPHWAVEIN phwi,
UINT uDeviceID,
LPWAVEFORMATEX pwfx,
DWORD dwCallback,
DWORD dwCallbackInstance,
DWORD fdwOpen
);

  其中:phwi是返回的句柄存放地址,uDeviceID是要打開的音頻設備ID號,一般都指定爲WAVE_MAPPER。 dwCallback則爲指定的回調函數或線程等的地址,fdwOpen指定回調方式,dwCallbackInstance爲需要向回調 函數或線程送入的用戶參數。至於那個pwfx,則比較關鍵,它指定了要以什麼音頻格式打開音頻輸入設備, 它是一個結構WAVEFORMATEX:
typedef struct { WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD wBitsPerSample;
WORD cbSize;
} WAVEFORMATEX;
  機器上的WIN9X安裝時選擇了音頻壓縮,可以在wFormatTag中指定一些壓縮的音頻格式,如G723.1,TURE DSP,等之類。不過一般都是選用WAVEFORMAT_PCM格式,即未壓縮的音頻格式,至於壓縮,可以在錄完後調用下面將要談到的ACM單獨進行。
  nChannels爲聲道數,1或者2。nSamplesPerSec爲每秒採樣數,8000、11025、22050、44100爲幾個標準值,其他的非標準值我倒沒試過行不行。nAvgBytesPerSec爲每秒平均的字節數,在PCM方式中就等於nChannels*nSamplesPerSec*wBitsPerSample/8,但對於其它的壓縮的音頻格式,由於很多壓縮方式是按時間片進行的,如G723.1,就是以30ms爲一個壓縮單位,這樣,nAvgBytesPerSec只是一個大概的數字,並不準確,程序中的計算是不應該以這個量爲準的。這一點在下面的壓縮音頻輸出和ACM音頻壓縮中非常重要。nBlockAlign是一個比較特殊的值,表示對音頻處理時的最小處理單位,對於PCM非壓縮,它就是wBitsPerSample*nChannels/8,而對於非壓縮格式,則表示壓縮/解壓處理的最小單位了,如G723.1,就是30ms的數據大小(20bytes或者24bytes)。wBitsPerSample就是每採樣值的位數,8或者16。 cbSize則是表示該WAVEFORMATEX的結構在標準的頭部之後還有多少字節數,對於很多非PCM的音頻格式,有一些自己的定義格式參數,這些就緊跟在標準的WAVEFORMATEX後面,其大小就由cbSize指定。對於PCM格式而言,爲0,或者忽略不檢查。

  這樣,指定了這些參數後,你應該就能夠打開音頻輸入設備了。下面要做的事情就是準備幾個用做錄音的緩衝區。常準備多個緩衝區,並在回調中循環使用。另外,還得考慮好錄得的音頻數據放哪兒,比如一個臨時文件,就得準備好文件的句柄。對於緩衝區,得使用waveInPerpareHeader準備一下頭部,這個API比較簡單,如果你是循環使用緩衝區,對每個緩衝區也只需要調用一次waveInPrepareHeader。

  一切準備好之後,就可以調用waveInAddBuffer和waveInStart開始錄音了,只要你一調用這個waveInStart,錄音就開始了,即使這個緩衝區錄滿之後你沒有加入新的緩衝區進去,錄音也不會停,只是這中間的語音數據全都丟了。當通過 waveInAddBuffer送入的緩衝區被錄滿後,Windows就會通過你在waveInOpen中指定的方式進行回調,在回調中把錄好的語音數據取出來,並且,如果還想繼續錄音的話,得將下一個緩衝區添加進去。考慮到這個處理是有時間延遲的,而且音頻對時間很敏感,一般都要先預加入若干個緩衝區,比如,一共定義了8個緩衝區,而爲了保險起見,最好保證任一時刻至少有3個緩衝區可被錄音使用,那麼在開始錄音時,則先加入4個緩衝區,然後在回調中,如果當前錄好的緩衝區第n個,則對第(n+4)%8調用waveInAddBuffer,這時,還有第(n+1)%8,(n+2)%8, (n+3)%8這三個緩衝區可用,即基本上就可以保證所錄得音頻中不會有斷開的間隔。

  想結束錄音時,最好在waveInClose之前調用一下waveInReset,這樣可以清掉尚在等待錄音的緩衝區,同時在回調中還必須注意一下送入參數中的消息種類。

  音頻輸出部分相對簡單一點。對應的API有waveOutOpen、waveOutPrepareHeader、waveOutWrite以及waveOutClose。如果希望直接輸出壓縮格式的音頻的話,必須注意waveOutOpen中指定的音頻格式參數。你必須很清楚這類格式的具體參數及其含義。不過,你可以通過下面說到的ACM(Audio Compress Manager)得到你需要的音頻格式的具體參數,這個格式參數可以直接用於waveOutOpen。如同音頻的輸入,waveOutPrepareHeader也是必需的。waveOutWrite 則是填入輸出緩衝區,爲了避免間斷,也應該保證某一時刻緩衝區隊列中數目足夠。

 

  如果安裝WIN98時在附件中選擇了音頻壓縮,那麼機器上的ACM就可用了。ACM爲Audio Compress Manager。 WIN98提供了一些常用的音頻壓縮算法程序包,供用戶調用。可以通過ACM獲得本機上所有的音頻壓縮驅動及其所支持的音頻格式。不過,似乎不是每種ACM格式都能被調用來進行壓縮,不過ACM中的壓縮驅動大多都是針對語音頻段,如果用來壓縮頻帶較寬的音頻,如音樂,則效果很差.

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/WhiteCloud/archive/2001/08/17/12641.aspx

發佈了39 篇原創文章 · 獲贊 11 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章