[轉(zhuǎn)貼]音頻錄入
一、數(shù)字音頻基礎(chǔ)知識
Fourier級數(shù):
任何周期的波形可以分解成多個正弦波,這些正弦波的頻率都是整數(shù)倍。級數(shù)中其他正線波的頻率是基礎(chǔ)頻率的整數(shù)倍。基礎(chǔ)頻率稱為一級諧波。
PCM:
pulse code modulation,脈沖編碼調(diào)制,即對波形按照固定周期頻率采樣。為了保證采樣后數(shù)據(jù)質(zhì)量,采樣頻率必須是樣本聲音最高頻率的兩倍,這就是Nyquist頻率。
樣本大小:采樣后用于存儲振幅級的位數(shù),實(shí)際就是脈沖編碼的階梯數(shù),位數(shù)越大表明精度越高,這一點(diǎn)學(xué)過數(shù)字邏輯電路的應(yīng)該清楚。
聲音強(qiáng)度:
波形振幅的平方。兩個聲音強(qiáng)度上的差常以分貝(db)為單位來度量,
計(jì)算公式如下:
20*log(A1/A2)分貝。A1,A2為兩個聲音的振幅。如果采樣大小為8位,則采樣的動態(tài)范圍為20*log(256)分貝=48db。如果樣本大小為16位,則采樣動態(tài)范圍為20*log(65536)大約是96分貝,接近了人聽覺極限和痛苦極限,是再線音樂的理想范圍。windows同時支持8位和16位的采樣大小。
二、相關(guān)API函數(shù),結(jié)構(gòu),消息
對于錄音設(shè)備來說,windows 提供了一組wave***的函數(shù),比較重要的有以下幾個:
打開錄音設(shè)備函數(shù)
MMRESULT waveInOpen(
LPHWAVEIN phwi, //輸入設(shè)備句柄
UINT uDeviceID, //輸入設(shè)備ID
LPWAVEFORMATEX pwfx, //錄音格式指針
DWORD dwCallback, //處理MM_WIM_***消息的回調(diào)函數(shù)或窗口句柄,線程ID
DWORD dwCallbackInstance,
DWORD fdwOpen //處理消息方式的符號位
);
為錄音設(shè)備準(zhǔn)備緩存函數(shù)
MMRESULT waveInPrepareHeader( HWAVEIN hwi, LPWAVEHDR pwh, UINT bwh );
給輸入設(shè)備增加一個緩存
MMRESULT waveInAddBuffer( HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh );
開始錄音
MMRESULT waveInStart( HWAVEIN hwi );
清除緩存
MMRESULT waveInUnprepareHeader( HWAVEIN hwi,LPWAVEHDR pwh, UINT cbwh);
停止錄音
MMRESULT waveInReset( HWAVEIN hwi );
關(guān)閉錄音設(shè)備
MMRESULT waveInClose( HWAVEIN hwi );
Wave_audio數(shù)據(jù)格式
typedef struct {
WORD wFormatTag; //數(shù)據(jù)格式,一般為WAVE_FORMAT_PCM即脈沖編碼
WORD nChannels; //聲道
DWORD nSamplesPerSec; //采樣頻率
DWORD nAvgBytesPerSec; //每秒數(shù)據(jù)量
WORD nBlockAlign;
WORD wBitsPerSample;//樣本大小
WORD cbSize;
} WAVEFORMATEX;
waveform-audio 緩存格式
typedef struct {
LPSTR lpData; //內(nèi)存指針
DWORD dwBufferLength;//長度
DWORD dwBytesRecorded; //已錄音的字節(jié)長度
DWORD dwUser;
DWORD dwFlags;
DWORD dwLoops; //循環(huán)次數(shù)
struct wavehdr_tag * lpNext;
DWORD reserved;
} WAVEHDR;
相關(guān)消息
MM_WIM_OPEN:打開設(shè)備時消息,在此期間我們可以進(jìn)行一些初始化工作
MM_WIM_DATA:當(dāng)緩存已滿或者停止錄音時的消息,處理這個消息可以對緩存進(jìn)行重新分配,實(shí)現(xiàn)不限長度錄音
MM_WIM_CLOSE:關(guān)閉錄音設(shè)備時的消息。
相對于錄音來說,回放就簡單的多了,用到的函數(shù)主要有以下幾個:
打開回放設(shè)備
MMRESULT waveOutOpen(LPHWAVEOUT phwo, UINT uDeviceID, LPWAVEFORMATEX pwfx, DWORD dwCallback, DWORD dwCallbackInstance, DWORD fdwOpen );
為回放設(shè)備準(zhǔn)備內(nèi)存塊
MMRESULT waveOutPrepareHeader(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh );
寫數(shù)據(jù)(放音)
MMRESULT waveOutWrite(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh );
相應(yīng)的也有三個消息,用法跟錄音的類似:
三、程序設(shè)計(jì)
一個錄音程序的簡單流程: 打開錄音設(shè)備waveInOpen===>準(zhǔn)備wave數(shù)據(jù)頭waveInPrepareHeader===>
準(zhǔn)備數(shù)據(jù)塊waveInAddBuffer===>開始錄音waveInStart===>停止錄音(waveInReset) ===>
關(guān)閉錄音設(shè)備(waveInClose)
當(dāng)開始錄音后當(dāng)buffer已滿時,將收到MM_WIM_DATA消息,處理該消息可以保存已錄好數(shù)據(jù)。
回放程序比這個要簡單的多: 打開回放設(shè)備waveOutOpen===>準(zhǔn)備wave數(shù)據(jù)頭waveOutPrepareHeader===>寫wave數(shù)據(jù)waveOutWrite===>
停止放音(waveOutRest) ===>關(guān)閉回放設(shè)備(waveOutClose)
如何處理MM消息: MSDN告訴我們主要有 CALLBACK_FUNCTION、CALL_BACKTHREAD、CALLBACK_WINDOW 三種方式,常用的是
Thread,window方式。
線程模式
waveInOpen(&hWaveIn,WAVE_MAPPER,&waveform,m_ThreadID,NULL,CALLBACK_THREAD),我們可以繼承MFC的CwinThread類,只要相應(yīng)的處理線程消息即可。
MFC線程消息的宏為:
ON_THREAD_MESSAGE,
可以這樣添加消息映射: ON_THREAD_MESSAGE(MM_WIM_CLOSE, OnMM_WIM_CLOSE)
窗口模式
類似于線程模式,參見源程序即可
posted on 2006-06-15 06:57
Jerry Cat 閱讀(1138)
評論(0) 編輯 收藏 引用