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

基於API的錄音機程序

編輯:關於VC++

一、數字音頻基礎知識

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)

窗口模式

類似於線程模式,參見源程序即可。

本文配套源碼

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