1、C#使用Windows API時必須先使用DllImport來Include Library,主要使用下列九個Windows API:
1-1、waveOutGetNumDevs(waveInGetNumDevs) 一 查詢系統上有多少輸出(輸入)設備
1-2、waveOutGetDevGaps (waveInGetGaps) 一 查詢特定輸出(輸入)波形設備的能力
1-3、waveOutOpen(waveInOpen) 一 開啟特定的波輸出(輸入)設備
1-4、waveOutPrepareHeader(waveInPrepareHeader) 一 設定波形輸出(輸入)的緩衝區
1-5、waveOutWrite(waveInWrite) 一 傳送(接收)資料區塊
1-6、waveOutRest(waveInRest) 一 停止重播及重設播放位置為零
1-7、waveOutClose(waveInClose) 一 關閉特定的波形輸出(輸入)設備
1-8、waveOutUnprepareHeader(waveInUnprepareHeader) 一 移除波形輸出(輸入)的緩衝區
1-9、waveInStart 一 開始接收輸入音訊資料
2、 使用waveOutOpen(waveInOpen)函式時,必須先做下列三件事情:
2-1、宣告和設定WAVEFORMATEXTENSIBLE(WAVEFORMATEX) Structure - 設定波形資料的格式
2-1-1 wFormatTag:波形的格式類型
2-1-2 nChannels:設定聲道的數量
2-1-3 nSamplesPreSec:設定取樣頻率
2-1-4 nAvgBytesPreSec:計算每秒有多少位元組 (nSamplePreSec * nBlockAlign )
2-1-5 nBlockAlign:資料的區塊,表示一筆聲音資料的長度 (nChannel*wBitsPerSample/8)
2-1-6 wBitsPerSample:設定每個取樣資料的位元數 (16 or 24)
2-1-7 cbSize:WAVEFORMATEX額外的資料長度
(sizeof(WAVEFORMATEXTENSIBLE) -sizeof(WAVEFORMATEX) )
2-1-8 wValidBitsPerSample:實際使用的位元數,通常和wBitsPersample相同
2-1-9 dwChannelMask:當設備支援多聲道時用來設定波形傳送(接收)的聲道
2-1-10 SubFormat: 設定資料的格式 (設定為KSDATAFORMAT_SUBTYPE_PCM)
2-2、宣告和設定WAVEHDR Structure - 設設波形資料的緩衝區
2-2-1 lpData:存放波形資料的緩衝區位置
2-2-2 dwBufferLength:波形緩衝區的長度
2-2-3 dwBytesRecorded:當開啟為輸入設備時,設定有多少資料在緩衝區 (設定為0)
2-2-3 dwUser:使用者資料 (設定為0)
2-2-4 dwFlags:設定/取得緩衝區支援的訊息 (設定為0)
2-2-5 dwLoops:提供同筆資料播放的次數,只有設定輸出設備時才有用 (設定為1)
2-2-6 lpNext: 保留 (設定為0)
2-2-7 reserved:保留 (設定為0)
2-3、由於C#中並沒有Callback Function,因此必須使用Delegate代替。
Ex: //定義Delegate
delegate void WaveDelegate (
ushort hwi,
ushort uMsg,
uint dwInstance,
uint dwParam1,
uint dwParam2
);
// 宣告Delegate
WaveDelegate outWaveProc = new WaveDelegate(WaveProc);
WaveDelegate inWaveProc = new WaveDelegate(WaveProc);
// 宣告並建立Delegate回傳的函數
private void WaveProc (
ushort hwi,
ushort uMsg,
uint dwInstance,
uint dwParam1,
uint dwParam2
);
3、將上述的所建立的WAVEHDR Structure使用waveOutPrepareHeader (waveInPrepareHeader)
函式,設定給已經開啟的輸出(輸入)設備;當輸入設備設定後必須再執行waveInStart函式才會開始接收
音訊資料。
4、以脈衝編碼(PCM)而言產生波形(waveform)的方法有下列四個步驟:
4-1、計算波形的取樣數量: 取樣數 = 取樣頻率 / 波形頻率
4-2、計算取樣弧度:取樣累積弧度 = 取樣的累積弧度 + ( 2 * 3.1416(pi) / 取樣數 )
4-3、計算波形的取樣值:波形的取樣值 = 最大音量值 (直徑) * 取樣累積弧度的正弦值
16 bits 最大音量值為 32768
24 bits 最大音量值為 388607
4-4、當累積弧度大於2pi時則將累積弧度減去2pi,以此類推直到將緩衝區填滿為止
5、我自已計算波形(waveform)的方法是主要將完整的波形分成四個階段如下圖:
5-1、讀取緩衝區前二筆資料作為起始的座標和計算起始的階段
5-2、利用緩衝區內(N-1)和N筆資料來計算是否符合階段移動的順序(1->2->3->4->1……etc.)
5-3、當上次的階段和本次的階段相同時則依照不同的階段使用下列規則進行判斷:
1、4 Phase : 第(N-1)筆資料 <= 第N筆資料
2、3 Phase: 第(N-1)筆資料 >= 第N筆資料
5-4、完成階段循環 (1->2->3->4->1or->2)後根據最後階段來使用下列的規則判斷是否為一個完整的波形
1、4 Phase:起始座標 <= 第N筆資料
2、3 Phase:起始座標 >= 第N筆資料
5-5、最後計算頻率的方法: 波形頻率 = 取樣頻率 / 完整波形的資料個數
6、當關閉輸出(輸入)設備時有必須執行三個函式:
6-1、執行waveOutReset(waveInReset)
6-2、執行waveOutClose(waveInClose)
6-3、執行waveOutUnprepareHeader(waveInUnprepareHeader)
Download : WaveGenerator.zip WaveGenerator.exe
Result :