本人從事音頻軟件開發10+年,既開發過voice相關的,又開發過music相關的,但大多數仍是開發voice相關的。掐指一算到如今在通訊終端上開發過的語音解決方案共有五套,它們既有有線通訊的,又有無線通訊的;既有在上層開發的,又有在底層開發的;既有在ARM上開發的,又有在DSP上開發的,總之各有特點。但由於都是語音通訊解決方案,又有共同的地方,都要有語音的採集播放、編解碼、先後處理和傳輸等。今天我就選取有表明性的三套方案,講講它們的實現。html
1,在嵌入式Linux上開發的有線通訊語音解決方案web
這方案是在嵌入式Linux上開發的,音頻方案基於ALSA,語音通訊相關的都是在user space 作,算是一個上層的解決方案。因爲是有線通訊,網絡環境相對無線通訊而言不是特別惡劣,用的丟包補償措施也不是不少,主要有PLC、RFC2198等。我在前面的文章(如何在嵌入式Linux上開發一個語音通訊解決方案)詳細描述過方案是怎麼作的,有興趣的能夠去看看。算法
2,在Android手機上開發的傳統無線通訊語音解決方案微信
這方案是在Android手機上開發的,是手機上的傳統語音通訊方案(相對於APP語音通訊而言)。Android是基於Linux的,因此也會用到ALSA,可是主要是作控制用,如對codec芯片的配置等。跟音頻數據相關的驅動、編解碼、先後處理等在Audio DSP上開發,網絡側相關的在CP(通訊處理器)上開發,算是一個底層解決方案。該方案的軟件框圖以下:網絡
從上圖看出,AP在方案中起控制做用,一是控制codec芯片上音頻路徑的選擇(經過配置寄存器完成),二是控制Audio DSP上音頻流的start/stop等。真正的音頻數據處理是在Audio DSP和CP上實現的(Audio DSP和CP上的實如今兩個不一樣的部門作,我是在Audio DSP上作音頻開發,對CP上的實現只是瞭解,不能詳細敘述CP上的Audio實現)。語音通訊分上行和下行,先看上行。經過codec芯片採集到的語音數據由I2S送給Audio DSP。Audio DSP中有DMA IN中斷,5ms發生一次,獲取語音數據,而後作重採樣(方案中codec芯片的採樣率是48k Hz,而編解碼codec的採樣率是8k/16k等,須要作重採樣)變成8k/16k等的語音數據並保存在buffer中。發生四次就得到了20ms的語音數據(基於20ms是由於AMR/EVS的一幀都是20ms),把這20ms數據先作前處理(AEC/ANS/AGC等),再作編碼得到碼流,並把碼流經過IPC送給CP。CP中作些網絡側相關的處理最後經過空口發送給對方。再看下行。CP從空口收到語音數據後作網絡側處理(jitter buffer等)後將碼流發給Audio DSP。Audio DSP收到碼流後先解碼成PCM數據並作後處理(ANS/AGC等),而後作重採樣變成48k Hz的語音數據,還要作混音處理(主要是系統音,要一塊兒播放出來),處理完後放在buffer裏。下行也有一個DMA OUT中斷,也是5ms一次,把一幀20ms的數據分四次送給codec芯片,也就是每次從上述buffer裏取5ms數據,取四次buffer就取空了,而後再取下一幀的數據播放。送給codec芯片的數據就會經過外設播放出來。socket
因爲在DSP上開發,硬件資源(DSP 頻率/memory)成了瓶頸,好多時間花在load/memory的優化上。DSP頻率只有300多MHZ,上下行的先後處理、編解碼、重採樣又是比較耗load的,不優化根本不能流暢運行,在C級別優化後一些場景仍是不能流暢運行,最後好多地方用了終極大法彙編優化,才使各類場景下都能流暢運行。Memory份內部memory (DTCM(Data Tightly Coupled Memory, 數據緊密耦合存儲器,用於存data)和PTCM(Program Tightly Coupled Memory, 程序緊密耦合存儲器,用於存code))和外部memory(DDR)。要想快速運行,data和code最好都放在內部memory,可是內部memory的空間又特別小,DTCM和PTCM都只有幾十K Word(DSP上的基本單位是Word,一個Word是兩個字節),memory不只不能隨意用,在寫代碼時時時刻刻都要注意省內存,還要優化(常常遇到的是開發新feature,memory不夠了,先優化memory,而後再開發,memory都是一點一點摳出來的),最後優化也摳不出memory了,怎麼辦呢?用了overlay機制,說白了就是在不一樣場景下的memory複用。好比播放音樂和打電話不可能同時出現,使用的部分memory就能夠複用。再好比打電話時只有一種codec在工做,而系統會同時支持多種codec,這幾種codec的使用的部分memory就能夠複用。函數
3,在Android手機上開發的APP上的語音解決方案oop
這方案也是在Android手機上開發的,可是是APP語音通訊,相似於微信語音,在Native層作,調用Android JNI提供的API,算是一個上層解決方案。該方案的軟件框圖以下:性能
本方案是在AP(應用處理器)上實現,語音採集和播放並無直接調用系統提供的API(AudioTrack/AudioRecorder), 而是用了開源庫openSL ES,讓openSL ES去調用系統的API。咱們會向openSL ES註冊兩個callback函數(一個用於採集語音,一個用於播放語音),這兩個callback每隔20Ms被調用一次,分別得到採集到的語音以及把收到的語音送給底層播放,從底層拿到的以及送給底層的語音數據都是PCM格式,都配置成16k採樣率單聲道的模式。在上行方向,codec芯片採集到的語音PCM數據經過I2S送給audio DSP,audio DSP處理後把PCM數據送給AP,最終經過註冊的採集callback函數把PCM數據送給上層。在上層先作前處理,包括AEC/AGC/ANS等,用的是webRTC的實現(如今APP語音內的先後處理基本上用的都是webRTC的實現),作完前處理後還要根據codec看是否須要作重採樣,如codec是8k採樣率的,就須要作重採樣(16k轉到8k), 如codec是16k採樣率的,就不須要作重採樣了。再以後是編碼獲得碼流,同時用RTP打包,並用UDP socket把RTP包發給對方。在下行方向,先用UDP socket收語音RTP包,去包頭獲得碼流放進jitter buffer中。每隔20Ms會從jitter buffer中拿一幀數據解碼獲得PCM,有可能還要作PLC和重採樣,而後再作後處理(ANS/AGC),最終經過播放callback函數把PCM數據一層層往下送給Audio DSP,audio DSP處理後把PCM數據送給codec芯片播放出來。APP上的語音通訊屬於OTT (On The Top)語音,不像傳統語音通訊那樣有QoS保障,要保證語音質量,必需要採起更多的補償措施(因爲無線網絡環境是變化無窮的,常常會比較惡劣,會致使亂序丟包等),常見的方法有FEC(前向糾錯)、重傳、PLC(丟包補償)等。補償措施是該方案的難點,經過補償把語音質量提升了,可是增大了時延和增長了流量。優化
方案的實現是上圖中灰色虛線上面的部分,我之因此畫出灰色虛線下面部分,是想給你們看看整個完整的語音數據流向的實現,下面的部分對APP開發人員來講是黑盒子,他們可見的就是系統提供的API。我先是作APP上的語音通訊,後來才作手機上的傳統語音通訊。作APP上的語音通訊時不清楚底層是怎麼實現的,很想知道,可是沒有資料可供瞭解。我想不少作APP語音的人跟我有同樣的困惑,底層實現究竟是什麼樣的。後來作了手機上傳統語音通訊的實現,清楚了底層是怎麼作的,算是把APP語音的整個數據流向搞清楚了。本文把底層實現框圖也畫出來,就是想讓作APP語音通訊的人也瞭解底層的實現。不一樣手機平臺上的針對APP語音的底層實現是不同的(主要是指DSP上的實現,Android Audio Framework上的實現基本是同樣的),好比有的有先後處理(一般是中高端機),有的沒有先後處理(一般是低端機)。中高端機在上層不作回聲消除也沒有回聲,那是由於在底層作掉了。一樣的回聲消除算法在越接近硬件處作效果越好,主要是由於近遠端之間的latency越靠近硬件算的越準確不變,latency準確不變回聲消除纔會有更好的性能。在上層算latency就會引入軟件帶來的時延,並且軟件引入的時延有多是變化的,這就致使在上層算latency不如底層精確。在APP上層作回聲消除時,機型不同,latency也就不一樣(硬件不一樣以及底層軟件實現不一樣),當時是一個機型一個機型測出來的,有一百多毫秒的,也有兩百多毫秒的,差別很大。至於怎麼測的,有興趣能夠看我前面寫的一篇文章(音頻處理之回聲消除及調試經驗)。在底層DSP上作回聲消除時,算是最靠近硬件了,我當時算DMA OUT和DMA IN之間的delay,只有五點幾毫秒,並且屢次測latency都是很穩定,偏差不超過幾個採樣點,這樣就保證了回聲消除的高性能。當時測時在硬件上把speaker和MIC的線連起來,造成一個loopback,DMA OUT的數據就徹底進入DMA IN,用特殊波形(好比正弦波)穿越,同時把DMA OUT和DMA IN的音頻數據dump出來用CoolEdit看,從而獲得latency的準確值。低端機在上層是必定要作回聲消除的,那是由於底層沒作。APP語音通訊解決方案要兼顧全部機型,因此在APP語音解決方案內回聲消除是必定要有的,固然還包括其餘的先後處理模塊,好比ANS、AGC。
以上方案就是我作過的三種典型的語音通訊方案,有有線通訊,有無線通訊,也有APP語音通訊,在我看來應該是把目前通訊終端上的主要語音解決方案都囊括了。因爲在不一樣的平臺上開發,在不一樣的層次開發,從而表現出巨大的差別性,可是語音通訊的核心模塊都是同樣的。