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