單獨編譯和使用webrtc音頻降噪模塊(附完整源碼+測試音頻文件)
單獨編譯和使用webrtc音頻增益模塊(附完整源碼+測試音頻文件)
說實話很不想寫這篇文章,因為這和我一貫推崇的最好全部編譯並使用webrtc音頻處理模塊相悖。可是不知不覺已經把降噪和增益寫出來,回聲消除如果用戶可以得到完美利用也不失為一個很好的方法。但是還是那句話,最好還是全部編譯和使用webrtc的整個音頻處理模塊。另外這篇文章已經不單單的回聲消除模塊了,其中包括了降噪,增益,靜音檢測,如果有需要可以選擇其中的一部分單獨提取調試。
相對而言回聲消除比起其他模塊要復雜很多,不光光是計算量大(之前在一部380MHz的攝像頭中測試過,其消耗的時間為降噪的三倍以上,如果音頻延遲更大甚至根本跑不起來),而且其中也涉及到一個delay的計算,delay計算是否精確完全影響回聲消除的效果。
至於delay的計算,網上有很多說明,有復雜也有簡單的。在這里我還是簡單的提一下:
這張圖很多東西可以無視,我們重點看T0,T1,T2三項。
T0代表着聲音從揚聲器傳到麥克風的時間,這個時間可以忽略,因為一般來說話筒和揚聲器之間距離不會太遠,考慮到聲音340米每秒的速度,這個時間都不會超過1毫秒。
T1代表遠處傳到你這來的聲音,這個聲音被傳遞到回聲消除遠端接口(WebRtcAec_BufferFarend)的到播放出來的時間。一般來說接收到的音頻數據傳入這個接口的時候也就是上層傳入揚聲器的時刻,所以可以理解成該聲音防到播放隊列中開始計時,到播放出來的時間。
T2代表一段聲音被揚聲器采集到,然后到被送到近端處理函數(WebRtcAec_Process)的時刻,由於聲音被采集到馬上會做回聲消除處理,所以這個時間可以理解成麥克風采集到聲音開始計時,然后到你的代碼拿到音頻PCM數據所用的時間。
好了,delay=T0+T1+T2,其實也就是T1+T2。
一般來說,一個設備如果能找到合適的delay,那么這個設備再做回聲消除處理就和降噪增益一樣幾乎沒什么難度了。從網上看iPhone的固定delay是60ms,不過不確定,MacBook掛了,在等四季度新MacBook上市,所以暫時沒辦法做驗證。
因為回聲消除過程,可以理解成已經把藍黑兩種顏色的墨水完全混合,然后分離出來所需要的藍色或者黑色顏色。事實上完全混在一起的音頻數據是無法徹底分開的,但是我們可以把混在一起的聲音理解成兩段聲音,其中有一段聲音可以找到一段幾乎相近的對比原聲,然后在混音中找到和原聲近似的數據,這樣就可以分離了。delay的意義顯而易見就是要把原聲和混在一起的聲音數據作對比時,校正時刻所用,這個時刻越是精確,那么回聲消除的效果越好。不過從實際效果來看這個delay也並不需要特別精確,在這段測試音頻數據里面范圍可以接近100毫秒。
從兩段音頻波形起始位置看delay的時間應該超過100毫秒,那么可以用一段代碼做測試,測試代碼和音頻文件來自於網上:
1 int WebRtcAecTest() 2 { 3 #define NN 160 4 short far_frame[NN]; 5 short near_frame[NN]; 6 short out_frame[NN]; 7 8 void *aecmInst = NULL; 9 FILE *fp_far = fopen("speaker.pcm", "rb"); 10 FILE *fp_near = fopen("micin.pcm", "rb"); 11 FILE *fp_out = fopen("out.pcm", "wb"); 12 13 do 14 { 15 if(!fp_far || !fp_near || !fp_out) 16 { 17 printf("WebRtcAecTest open file err \n"); 18 break; 19 } 20 21 WebRtcAec_Create(&aecmInst); 22 WebRtcAec_Init(aecmInst, 8000, 8000); 23 24 AecConfig config; 25 config.nlpMode = kAecNlpConservative; 26 WebRtcAec_set_config(aecmInst, config); 27 28 while(1) 29 { 30 if (NN == fread(far_frame, sizeof(short), NN, fp_far)) 31 { 32 fread(near_frame, sizeof(short), NN, fp_near); 33 WebRtcAec_BufferFarend(aecmInst, far_frame, NN);//對參考聲音(回聲)的處理 34 35 WebRtcAec_Process(aecmInst, near_frame, NULL, out_frame, NULL, NN,109,0);//回聲消除 36 fwrite(out_frame, sizeof(short), NN, fp_out); 37 } 38 else 39 { 40 break; 41 } 42 } 43 } while (0); 44 45 fclose(fp_far); 46 fclose(fp_near); 47 fclose(fp_out); 48 WebRtcAec_Free(aecmInst); 49 return 0; 50 }
源碼下載(VS2010編譯版本,也可以移植到其他平台無縫編譯):WebRtcAudioAllTest.rar