實習公司讓我用C++ vs編輯工具做一個獲取電腦麥克風分貝值的工具。我在網上查了一下相關的源碼很少,幾乎不能用。我就試着寫了一個。其實沒有什么技術含量,只不過就是調用一下windowAPI。重要的還是計算分貝的算法。
我先展現一下計算分貝的代碼:

1 int CMicDlg:: getPcmDB(const unsigned char* pcmdata, size_t size) 2 { 3 4 int db = 0; 5 short int value = 0; 6 double sum = 0; 7 for (int i = 0; i < size; i += 2) 8 { 9 memcpy(&value, pcmdata + i, 2); //獲取2個字節的大小(值) 10 sum += abs(value); //絕對值求和 11 } 12 sum = sum / (size / 2); //求平均值(2個字節表示一個振幅,所以振幅個數為:size/2個) 13 if (sum > 0) 14 { 15 db = (int)(20.0 * log10(sum)); 16 } 17 return db; 18 }
這是計算聲音分貝值的函數
用到的公式
公式說明
參數:Pref:就是聲音總的振幅最大值;Prms:就是當前聲音的振幅值;Lp:就是我們需要的聲音分貝值了。
計算分貝值我有一個很好的鏈接他寫比較好https://www.cnblogs.com/waimen/p/9062814.html
其實分貝值的計算本就沒有什么物理意義。它只不過就是把很大數簡短的表示出來。
這是錄音的代碼:
變量定義:

HWAVEIN hWaveIn; //輸入設備 WAVEFORMATEX waveform; //采集音頻的格式,結構體 BYTE* pBuffer1;//采集音頻時的數據緩存 WAVEHDR wHdr1; //采集音頻時包含數據緩存的結構體 HANDLE wait;
初始化變量:

1 waveform.wFormatTag = WAVE_FORMAT_PCM;//聲音格式為PCM 2 waveform.nSamplesPerSec = 8000;//采樣率,16000次/秒 3 waveform.wBitsPerSample = 16;//采樣比特,16bits/次 4 waveform.nChannels = 1;//采樣聲道數,2聲道 5 waveform.nAvgBytesPerSec = 16384;//每秒的數據率,就是每秒能采集多少字節的數據 6 waveform.nBlockAlign = 2;//一個塊的大小,采樣bit的字節數乘以聲道數 7 waveform.cbSize = 0;//一般為0
開始錄音

1 int CMicDlg::GetAudio() 2 { 3 4 wait = CreateEvent(NULL, 0, 0, NULL); 5 //使用waveInOpen函數開啟音頻采集 6 waveInOpen(&hWaveIn, WAVE_MAPPER, &waveform, (DWORD_PTR)wait, 0L, CALLBACK_EVENT); 7 //建立兩個數組(這里可以建立多個數組)用來緩沖音頻數據 8 DWORD bufsize = 1024;//每次開辟1k的緩存存儲錄音數據 9 10 //結合音頻解碼和網絡傳輸可以修改為實時錄音播放的機制以實現對講功能 11 pBuffer1 = new BYTE[bufsize]; 12 wHdr1.lpData = (LPSTR)pBuffer1; 13 wHdr1.dwBufferLength = bufsize; 14 wHdr1.dwBytesRecorded = 0; 15 wHdr1.dwUser = 0; 16 wHdr1.dwFlags = 0; 17 wHdr1.dwLoops = 1; 18 waveInPrepareHeader(hWaveIn, &wHdr1, sizeof(WAVEHDR));//准備一個波形數據塊頭用於錄音 19 waveInAddBuffer(hWaveIn, &wHdr1, sizeof(WAVEHDR));//指定波形數據塊為錄音輸入緩存 20 waveInStart(hWaveIn);//開始錄音 21 Sleep(1000); 22 23 CString mic; 24 int sum = getPcmDB(pBuffer1, 1024); 25 mic.Format(_T("%d"), sum ); 26 edit.SetWindowTextW(mic); 27 waveInReset(hWaveIn);//重置輸入 28 delete[]pBuffer1; 29 // waveInClose(hWaveIn); 30 return 0; 31 }
代碼邏輯:
我用公式計算出聲波一段的分貝值,每一秒計算一次。
我用的是mfc里的onTimer()函數來實現的。