基於API的錄音機程式

來源:互聯網
上載者:User


基於API的錄音機程式

作者/欒義明

 一、數字音頻基礎知識

  • Fourier級數:

任何周期的波形可以分解成多個正弦波,這些正弦波的頻率都是整數倍。級數中其他正線波的頻率是基礎頻率的整數倍。基礎頻率稱為一級諧波。

  • PCM:

pulse code modulation,脈衝編碼調製,即對波形按照固定周期頻率採樣。為了保證採樣後資料品質,採樣頻率必須是樣本聲音最高頻率的兩倍,這就是Nyquist頻率。
樣本大小:採樣後用於儲存振幅級的位元,實際就是脈衝編碼的階梯數,位元越大表明精度越高,這一點學過數字邏輯電路的應該清楚。

  • 聲音強度:

波形振幅的平方。兩個聲音強度上的差常以分貝(db)為單位來度量,

  • 計算公式如下:

20*log(A1/A2)分貝。A1,A2為兩個聲音的振幅。如果採樣大小為8位,則採樣的動態範圍為20*log(256)分貝=48db。如果樣本大小為16位,則採樣動態範圍為20*log(65536)大約是96分貝,接近了人聽覺極限和痛苦極限,是再線音樂的理想範圍。windows同時支援8位和16位的採樣大小。

 二、相關API函數,結構,訊息
對於錄音裝置來說,windows 提供了一組wave***的函數,比較重要的有以下幾個:

  • 開啟錄音裝置函數
MMRESULT waveInOpen(  LPHWAVEIN phwi,            //輸入裝置控制代碼  UINT uDeviceID,            //輸入裝置ID  LPWAVEFORMATEX pwfx,       //錄音格式指標  DWORD dwCallback,          //處理MM_WIM_***訊息的回呼函數或視窗控制代碼,線程ID  DWORD dwCallbackInstance,    DWORD fdwOpen              //處理訊息方式的符號位);
  • 為錄音裝置準備緩衝函數
MMRESULT waveInPrepareHeader(  HWAVEIN hwi,  LPWAVEHDR pwh, UINT bwh );  
  • 給輸入裝置增加一個緩衝
MMRESULT waveInAddBuffer(  HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh );  
  • 開始錄音
MMRESULT waveInStart(  HWAVEIN hwi  );  
  • 清除緩衝
MMRESULT waveInUnprepareHeader( HWAVEIN hwi,LPWAVEHDR pwh, UINT cbwh);  
  • 停止錄音
MMRESULT waveInReset( HWAVEIN hwi );  
  • 關閉錄音裝置
MMRESULT waveInClose( HWAVEIN hwi );  
  • Wave_audio資料格式
typedef struct {     WORD  wFormatTag; //資料格式,一般為WAVE_FORMAT_PCM即脈衝編碼    WORD  nChannels; //聲道    DWORD nSamplesPerSec; //採樣頻率    DWORD nAvgBytesPerSec; //每秒資料量    WORD  nBlockAlign;     WORD  wBitsPerSample;//樣本大小     WORD  cbSize; } WAVEFORMATEX;  
  • waveform-audio 緩衝格式  
typedef struct {     LPSTR  lpData; //記憶體指標    DWORD  dwBufferLength;//長度     DWORD  dwBytesRecorded; //已錄音的位元組長度    DWORD  dwUser;     DWORD  dwFlags;     DWORD  dwLoops; //迴圈次數    struct wavehdr_tag * lpNext;     DWORD  reserved; } WAVEHDR;  
  • 相關訊息  
MM_WIM_OPEN:開啟裝置時訊息,在此期間我們可以進行一些初始化工作MM_WIM_DATA:當緩衝已滿或者停止錄音時的訊息,處理這個訊息可以對緩衝進行重新分配,實現不限長度錄音MM_WIM_CLOSE:關閉錄音裝置時的訊息。

相對於錄音來說,回放就簡單的多了,用到的函數主要有以下幾個:

  • 開啟回放裝置  
MMRESULT waveOutOpen(  LPHWAVEOUT phwo,             UINT uDeviceID,              LPWAVEFORMATEX pwfx,         DWORD dwCallback,            DWORD dwCallbackInstance,    DWORD fdwOpen              );  
  • 為回放裝置準備記憶體塊  
MMRESULT waveOutPrepareHeader(  HWAVEOUT hwo,    LPWAVEHDR pwh,   UINT cbwh      );
  • 寫資料(放音)  
MMRESULT waveOutWrite(  HWAVEOUT hwo,    LPWAVEHDR pwh,   UINT cbwh      );

相應的也有三個訊息,用法跟錄音的類似: 

 三、程式設計 

一個錄音程式的簡單流程:

開啟錄音裝置waveInOpen===>準備wave資料頭waveInPrepareHeader===>準備資料區塊waveInAddBuffer===>開始錄音waveInStart===>停止錄音(waveInReset) ===>關閉錄音裝置(waveInClose)

當開始錄音後當buffer已滿時,將收到MM_WIM_DATA訊息,處理該訊息可以儲存已錄好資料。

回放程式比這個要簡單的多:  

開啟回放裝置waveOutOpen===>準備wave資料頭waveOutPrepareHeader===>寫wave資料waveOutWrite===>停止放音(waveOutRest) ===>關閉回放裝置(waveOutClose)

如何處理MM訊息:

MSDN告訴我們主要有 CALLBACK_FUNCTION、CALL_BACKTHREAD、CALLBACK_WINDOW 三種方式,常用的是Thread,window方式。

 線程模式
waveInOpen(&hWaveIn,WAVE_MAPPER,&waveform,m_ThreadID,NULL,CALLBACK_THREAD),我們可以繼承MFC的CwinThread類,只要相應的處理線程訊息即可。
MFC線程訊息的宏為:

    ON_THREAD_MESSAGE,

可以這樣添加訊息映射:

    ON_THREAD_MESSAGE(MM_WIM_CLOSE, OnMM_WIM_CLOSE)  

 視窗模式
類似於線程模式,參見來源程式即可。 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.