WebRTC提供一套音頻處理引擎,
包含以下算法:
AGC自動增益控制(Automatic Gain Control)
ANS噪音抑制(Automatic Noise Suppression)
AEC是聲學回聲消除(Acoustic Echo Canceller for Mobile)
VAD是靜音檢測(Voice Activity Detection)
這是一套非常經典,以及值得細細品閱學習的音頻算法資源。
在前面分享的博文,也有提及音頻相關知識點。
一些算法優化的知識點,由於歷史的原因,
WebRTC的實現已經不是當下最優的思路。
但也是非常經典的。
例如:
AGE算法中的WebRtcSpl_Sqrt 快速開平方的實現。
可以采用如下匯編函數替換之:
static float fast_sqrt(float x) { float s; #if defined(__x86_64__) __asm__ __volatile__ ("sqrtss %1, %0" : "=x"(s) : "x"(x)); #elif defined(__i386__) s = x; __asm__ __volatile__ ("fsqrt" : "+t"(s)); #elif defined(__arm__) && defined(__VFP_FP__) __asm__ __volatile__ ("vsqrt.f32 %0, %1" : "=w"(s) : "w"(x)); #else s = sqrtf(x); #endif return s; }
現代很多cpu 匯編指令已經支持開平方的快速實現,
經過測試比對確實會比WebRtcSpl_Sqrt 快不少的。
關於開平方的快速實現,詳情可以看下:
https://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi
做算法優化的同學,就放過開平方吧。
每個算法有兩個基本指標,
性能,效果。
WebRTC 着力於音頻通信,所以它對性能的要求是極高的。
而算法的性能的優化,絕大多數情況的思路,都是特例化。
以前在公司開技術分享會的時候,也分享過。
也就一句話,越靠近CPU,性能越快。
也就是除非要不得以,請不要寫到硬盤上,然后再讀上來。
因為硬盤離CPU太遠了。
所以優化的思路也就非常明顯了。
從快到慢的介質分別是
CPU的寄存器 -> CPU的緩存 -> 內存空間 -> 硬盤空間(磁盤)
所以 盡可能地要使用上層的資源,能用寄存器就用寄存器,
能往CPU的資源上靠,就要把算法數據結構和資源做得更加緊湊。
關於CPU的相關資源:
https://www.cpuid.com/softwares/cpu-z.html
可以下一個CPU-Z 查看一下。
抽絲剝繭,一定要了解CPU的結構性能信息。
然后對症下葯,盡可能符合CPU的口味。
科普下算法優化的思路:
1.盡可能多用局部變量,編寫最短,最有效的閉合函數。
為了編譯處理的時候,能最終用上寄存器,去緩存。
2.盡可能少調用函數,參數最好是指針或引用傳遞,這樣能減少拷貝,
當然,可以的話參數要盡可能地少。
3.處理的數據盡可能緊湊且少,數據對齊很大程度上,
就是為了符合CPU的喜好,用上它的緩存。
4.盡可能順序讀寫,也是為了用上緩存資源
5.計算降級,一般情況下乘法比加法耗時,除法比乘法耗時。
浮點比整形耗時。
所以將乘法降為加法,將除法降為乘法,浮點降為整形(定點化)。
這一條大多數朋友若是不清楚為什么,可以移步資源:
https://github.com/ARM-software/CMSIS_5
閱讀其中的一些實現,你會找到具體原因的。
這里就不展開了。
6.能用內存的,就不要用磁盤,我想這個沒必要多解釋了。
7.當然如果能用特定算法思路數據接口進行優化也是可以的,例如查表之類的。
好像有點跑題了,回到主題上。
抽空把以上提及的幾個算法整理成
單文件實現的方式,並附加示例代碼。
便於學習或者工程化之用。
相關項目地址:
https://github.com/cpuimage/WebRTC_AECM
https://github.com/cpuimage/WebRTC_NS
https://github.com/cpuimage/WebRTC_VAD
https://github.com/cpuimage/WebRTC_AGC
路漫漫其修遠兮,一條道走到黑。
用cmake即可進行編譯示例代碼,詳情見CMakeLists.txt。
若有其他相關問題或者需求也可以郵件聯系俺探討。
郵箱地址是:
gaozhihan@vip.qq.com