音頻的編解碼(codec)根據應用場景的不一樣主要由幾大技術組織制定,分別是ITU-T、3GPP、MPEG。固然也有一些公司或者公司的聯合體等制定,如微軟的WMA。他們不只制定了codec的規範,同時還提供軟件實現的reference code,這樣便於普及制定的codec的使用。本文先談談這些codec,而後講怎麼樣根據reference code去優化codec(主要是減小CPU load)。web
1,codec 規範算法
1)ITU-T編程
ITU-T制定的是有線語音的codec標準,即G系列,主要有G.7十一、G.72二、G.72六、G.72八、G.729等。採樣率窄帶是8KHz,寬帶是16KHz。碼率從64kbps到8kbps不等。下表列出了具體的採樣率和碼率。數組
2)3GPP網絡
3GPP制定的是移動語音的codec標準,主要是AMR(adaptive multi-rate,自適應多碼率)系列等,能根據網絡情況自適應的調整碼率。採樣率窄帶是8KHz,寬帶是16KHz。近年來爲了應對互聯網的競爭(互聯網公司提出了涵蓋語音和音樂的OPUS codec),3GPP出臺了EVS(enhanced voice service)音頻編解碼規範。EVS也涵蓋了語音和音樂,能在二者之間靈活切換,支持多種採樣率和碼率。具體以下表。函數
3)MPEG工具
MPEG制定的主要是音樂的編解碼規範,主要有MP三、AAC等。MP3你們都很熟悉,是近二十年來聽音樂的最主要的格式,AAC是MP3的繼承者,下一代的最主要的音樂編解碼規範。音樂中採樣率通常是44100HZ,也有的用48000HZ。碼率在一個範圍內,碼率越大,音質越好。測試
4)公司或公司聯合體優化
一些公司或者公司聯合體根據須要制定音頻的編解碼規範,好比微軟的WMA,Skype的SILK,GIPS(GIPS在2011年被谷歌收購,谷歌基於GIPS的音視頻解決方案推出了webRTC並開源出來,影響巨大)的ILBC等。還有一個不得不提的就是OPUS,它是由非盈利的Xiph.org 基金會、Skype 和Mozilla 等共同主導開發的,全頻段(8kHZ到48kHZ),支持語音和音樂(語音用SILK, 音樂用CELT),已被IETF接納成爲網絡上的聲音編解碼標準(RFC6716)。指針
我用過的codec從語音到音樂分別有G.711/G.722/G.726/G.728/G.729/AMR-NB/AMR-WB/ILBC/OPUS/MP3/AAC/WMA/APE/Vorbis/ALAC/FLAC等。
2,codec的優化
這裏講的優化主要是指CPU load的優化,即優化後運行codec佔用更少的CPU,在具體的硬件平臺上運行的更流暢。優化到什麼程度算結束這依賴需求而定。若是優化後給所在項目用,就要看項目給你多長時間優化以及項目能接受的優化後的CPU load,通常狀況下項目用上優化後的codec後在最複雜的場景下能流暢運行又不影響其餘功能就能夠了,由於項目上要騰出人手作其餘事情,畢竟項目進度和質量是最重要的。若是優化後做爲庫賣給客戶用,就要儘可能優化到極致,由於這是用戶選擇用哪家公司庫的重要指標,是賣點,這種狀況下就會有更多的優化方法和技巧。我作過的優化都是給項目用,沒有做爲庫給客戶用,於是技巧不是特別多。
1)優化前的準備工做
a) 通讀一下要優化的codec的代碼,儘可能讀懂,即便沒懂也要搞清楚函數是幹什麼的,這有利於後面優化。
b) 準備好profiling工具,profiling工具就是測量運行某個函數花了多少clock。有現成的profiling工具最好,若是沒有就根據具體OS和硬件平臺(ARM/MIPS等)本身作工具。
c) 準備好test vector,即測試的音源,通常codec制定的官方會提供,一般是多個vector, 對應於不一樣的場景。優化的原則是在減小CPU load的同時算法運算結果不被改變,因此在作優化時每優化一些就要用test vector跑一下,看結果有沒有改變,若是改變了,就要退回到上一個版本。我作優化時天天至少保留一個版本,有時兩個或者三個,就是爲了出問題時好回溯,儘快查出哪一個地方的優化出了問題。
2)優化步驟與方法
a) 將編譯器的優化選項從-o0改成-o3
b) 給代碼中那些常常被調用的又短小的函數加上inline
一般狀況下作完a,b後load會下來一大截,如同擠泡沫同樣,會擠掉很大一部分。
c) ITU-T或者3GPP的codec reference code中有好多基本運算(加減乘除)的函數,這些函數都寫的特別嚴謹,同時調用的頻次又很是高,於是加大了運算複雜度。這些函數中有些在保證正確的前提下能夠簡化(如一些防飽和就能夠不要),這樣處理後load會降下來一些。
d) 用profiling工具一步步排查看到底哪一個函數花的load多,明白這個函數是幹什麼的,而後具體問題具體分析,看怎麼樣來優化。
e) 有些函數就是一個小算法,reference code中寫的比較複雜,調用頻次又比較高。要去找有沒有簡單的實現能夠替代,有的話替代了load就會降下來一些。好比codec中常常有求平方根的計算,reference code中一般寫的比較複雜。咱們知道用牛頓迭代法也能夠求平方根,就能夠用牛頓迭代法去替換將load降下來。
f) 用匯編優化。若是在C級別能解決問題就不要用匯編了。各個處理器都有本身的彙編指令集,須要去學而且掌握其中的思想和技巧。一般是用的頻次較高的又比較佔load的函數用匯編去寫,即用C和彙編混合編程。彙編優化花的時間會相對長一些。
固然還有一些小的技巧好比展開for循環、用指針替代數組等,這裏就不一一說了。