談談我開發過的幾套語音通信解決方案


本人從事音頻軟件開發10+年,既開發過voice相關的,又開發過music相關的,但大多數還是開發voice相關的。掐指一算到現在在通信終端上開發過的語音解決方案共有五套,它們既有有線通信的,又有無線通信的;既有在上層開發的,又有在底層開發的;既有在ARM上開發的,又有在DSP上開發的,總之各有特色。但因為都是語音通信解決方案,又有共同的地方,都要有語音的采集播放、編解碼、前后處理和傳輸等。今天我就選取有代表性的三套方案,講講它們的實現。

 

1,在嵌入式Linux上開發的有線通信語音解決方案

這方案是在嵌入式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芯片的數據就會通過外設播放出來。

 

由於在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上的語音解決方案

這方案也是在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語音通信,在我看來應該是把目前通信終端上的主要語音解決方案都囊括了。由於在不同的平台上開發,在不同的層次開發,從而表現出巨大的差異性,但是語音通信的核心模塊都是一樣的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM