來源 http://www.qttaudio.com/webrtc-android-lydj.html
在一般的數字樓宇對講系統應用中,對講雙方需要進行實時的語音交流,而在室内或是樓道門E1都采用外置音箱放音的形式,這勢必會産生回聲H。21,即通話的一方說話後通過網絡傳到通話另一方的音箱進行播放,然後播放出來的聲音又被另一方的傳聲器采集到并且通過網絡傳回自己。這時,回聲的産生将會影響對講的通話品質和使用者對于樓宇對講産品體驗,而對于現在新興的Android數字樓宇對講系統。更是如此。目前Android數字樓宇對講系統中的回聲消除技術實作有以下3方面的難點和問題:
1)Android本地實時回聲消除技術問題Android系統是便攜式嵌入式系統,軟硬體的計算資源相對有限,很多在Windows系統等PC機平台上應用很成熟的回聲消除算法和技術到Android平台上可能都會出現一些适應性問題。
2)回聲消除中音頻采集、播放的延時問題因為Android不是實時作業系統,造成傳聲器的錄音、音響的放音之間都有一定時延,而且這個時延每個Android裝置可能都不一樣,這樣即便有很好的回聲消除方法,由于不能将錄音、放音對齊将會使得回聲消除沒有效果或是消去正常通話聲音,這會進一步增加Android回聲消除難度。
3)Android回聲消除的平台移植性
目前,Android版本很多,如何使Android回聲消除技術能應用于多樣的終端上是一個現實問題。
為了解決以上問題,采用WebRTC的回聲消除子產品實作Android本地實時回聲消除,并設計了多線程程式設計技術實作音頻采集、播放的同步,解決了Android樓宇對講系統的回聲問題,最後利用JNI(Java Native Interface——JAVA本地調用)技術将Android樓宇對講系統回聲消除程式進行封裝,便于不同Android平台的移植。
1 技術基礎
目前,主流的實時通信軟體中應對回聲消除問題基本都采用了這兩種回聲消除子產品:Speex[41和Global IPSound(GIPS)”1。Speex是很多開源即時通信軟體都會使用的方案,其最大亮點也是完全開源的,而GlobalIP Sound(GIPS)則是瑞典Global IP Solutions公司所研制的回聲消除技術,廣泛應用與商業軟體中。針對Speex和GIPS這兩個回聲消除子產品,筆者采用了兩種通信軟體進行了實際網絡語音測試:Skype(采用GIPS)、Speex(采用Speex),以證明哪種回聲消除的效果更好。結果Skype的通話很好,基本沒有回音,雙方交流很順暢,而相對Skype,使用Speex通話一直有殘餘回音,雙方交流困難。由此可見,GIPS回聲消除子產品有更好的回聲消除效果,但是一般GIPS回聲消除子產品都是商用,且費用不菲。
2010年Google高價收購了Global IP Solutions公司,并将其擁有的WebRTC(Web Real Time Communiea—tion)技術項目開源。WebRTC是于Web浏覽器應用的實時音視訊的通信技術,其功能非常強大,内容主要包含語音引擎子產品(voice engine)、視訊引擎子產品(videoengine)、傳輸層子產品(Transport)、使用管理模組(sessionmanagement),而在其語音引擎子產品(voice engine)中就公開了GIPS回聲處理技術(AEC),這為Android數字樓宇對講系統的回聲消除實作提供了很好的基礎,并對研究Android數字樓宇對講系統的回聲消除處理問題具有重要意義。
2 Android數字樓宇系統回聲消除技術設計
在引言中提到,Android數字樓宇對講系統中回聲消除技術的實作具有3個問題或者說是難點:一是An·droid本地實時回聲消除技術問題,二是回聲消除中音頻采集、播放的延時問題,三是Android回聲消除的平台移植性。
針對這三個問題,解決方案如下:
1)使用WebRTC中的GIPS回聲處理技術實作Android數字樓宇對講系統的本地實時回聲消除;
2)采用多線程緩存技術,将音頻采集、播放進行同步處理,以使GIPS回聲處理技術能夠應用并取得很好的回聲消除效果。
3)利用JNI技術,将WebRTC中的GIPS核心C代碼都編譯成動态連結庫以應用,可保證Android回聲消除應用于不同版本的Android平台上。
3 Android數字樓宇系統回聲消除技術實作
本部分内容主要針對上文的設計思路進行具體的實作。首先利用WebRTC中的GIPS回聲處理技術實作本地回聲消除,然後采用多線程态連結庫便于使用。
3.1 WebRTC中的GILES本地回聲消除
前文中介紹過WebRTC中語音引擎子產品(voice en—gine)公開了GIPS回聲處理技術(AEC),而另一方面WebRTC功能很強大,包括很多的子產品,這意味着代碼量也很大,這裡能否将GIPS回聲處理技術(AEC)提取出來單獨使用呢?答案是肯定的。
WebRTC的代碼結構布局清晰,在“webrtc\modules\audio_processing\aee”目錄下可以找到幾個用于回聲處理GIPS的AEC源檔案。然後主要查找每個AEC源檔案所關聯的WebRTC代碼,就可找出回聲處理子產品所需要WebRTC相關的源代碼檔案和頭檔案,這樣就可以将AEC從WebRTC中提取出來單獨使用。為友善使用,将需要這些代碼分成2個子產品,通用音頻處理子產品webRTC_AUDIO和GIPS-AEC子產品。WebRTC—AUDIO子產品中包含AEC源檔案運作所依賴的WebRTC音頻處理相關源檔案及頭檔案,而GIPS—AEC子產品則是WebRTC中專門用于回聲處理GIPS的AEC源檔案。GIPS-AEC子產品以WebRTC_AUDIO子產品為基礎,對回聲進行處理。
在GIPS-AEC子產品主要使用了5個函數完成回聲消除:
1)建立回聲消除函數
WebRtc—Word32 WebRtcAec—Create(void * aecInst);
函數會建立一個AEC資料結構,用于存放AEC過程中的變量和狀态,并将這個結構的位址存在形參aecInst指向的void指針中。
2)初始化回聲消除函數
WebRte_Word32 WebRtcAec_Init(void * aecInst,WebRtc_Word32 sampFreq,WebRtc_Word32 scSampFreq);
該函數可指定采樣率來初始化aecInst所指向的AEC資料結構(如采樣率sampFreq、scSampFreq可設定為8000)。
3)設定需要消去的參考音頻資料函數
WebRtc_Word32 WebRtcAec_BufferFarend(void * aeclnst, const WebRtc_Wordl6 * farend,WebRtc—Wordl6 nrOfSamples);
其中,形參farend指向需要消去的參考音頻資料塊,形參nrOfSamples是需要消去煩人音頻資料的采樣點數量(一般取值為160或80)。
4)回聲消除函數
WebRte_Word32 WebRtcAec—Process(void * aecInst,
const WebRtc_Wordl6 * nearend,
eonst WebRtc_Word 16 * nearendH,
WebRtc_Wordl6 * out,
WebRte Wordl6 * outH,
WebRtc_Wordl6 nrOiSamples,
WebRtc_Wordl6 mslnSndCardBuf,
WebRtc—Word32 skew):
該函數完成具體的回聲消除操作。AEC程式回聲消除的基本原理就是以音頻播放的資料為參照,消除傳聲器風采集到音頻中的已經播放内容。形參nearend就是指向本地所采樣的音頻資料指針,out是回聲消除後輸出資料指針;nrOfSamples是輸入的nearend音頻資料的采樣點數量(一般取值為160或80);形參mslnSnd.CardBuf就是聲霸卡實際輸入和輸出之間的時間差,即本地音頻和消去參考音頻之間的錯位時間。
5)釋放AEC回聲消除函數
WebRtc_Word32 WebRtcAec_Free(void * aecInst);
該函數釋放AEC資料結構。
完成這兩個子產品後,筆者于單機進行了本地回聲消除的驗證,具體過程如圖1所示,首先準備2個音頻檔案,一個為帶有原聲和回聲的音頻檔案,另一個為隻有回聲參考源的音頻檔案,然後将2個檔案的音頻資料分别導入筆者實作的回聲消除子產品,帶有原聲和回聲的音頻資料帶入到nearend,隻有回聲參考源的音頻資料帶人到farend,通過回聲消除處理後,生成的out資料并儲存為檔案,即為隻有原聲資料的音頻檔案。通過該實驗驗證,得到了非常滿意的回聲消除效果,原聲清晰且無回聲。
基于WebRTC的Android數字樓宇對講系統回聲消除
3.2音頻采集、播放的同步
因為Android不是實時作業系統,造成傳聲器的錄音、音響的放音之間都有一定時延,而且這個時延每個Android裝置可能都不一樣,這樣即便有很好的回聲消除方法,但有很多人卻得不到理想的回聲消除效果。
回聲消除AEC的基本原理就是以音頻播放的資料為參照,消除傳聲器風采集到音頻中的已經播放内容。如果音頻播放和音頻采集之間的時間差過大,即做回聲消除時參照的音頻播放資料和音頻采集資料之間有過大的錯位,那麼必然無法正确地消除回聲。
如果想要在網絡音頻通信中成功消除回聲,必須實作音頻采集、播放的同步。為此采用4個程式線程和3個隊列進行具體的實作(如圖2所示)。4個線程分别是ReadThread、WriteThread、InThread和AecOutThread。線程之間的資料交換則是使用了3個隊列來完成,這3個隊列分别是接收隊列、采集隊列和播放隊列。
基于WebRTC的Android數字樓宇對講系統回聲消除
在Android應用程式中,使用AudioRecord類進行音頻采集,使用AudiorTraek進行遠端音頻播放。為了保證時間上的連續性和時間差,使用了兩個單獨線程ReadThread和WriteThread來分别進行音頻采集和音頻播放,且這2個線程同時進行的。
InThread完成網絡音頻資料的接收。而AecOut-Thread則完成回聲消除操作,并将處理後的資料發送給通話另一方。
線程之間的資料交換使用隊列來完成,接收隊列存儲InThread通過網絡接收到對方發來的音頻資料,WriteThread從接收隊列中讀出對方發來音頻資料并播放。WriteThread播放過的音頻資料會放入播放隊列存儲,等待AecOutThread線程使用。采集隊列用于存儲ReadThread通過傳聲器風采集到的音頻資料,供AecOutThread使用。AecOutThread同時提取采集隊列和播放隊列中音頻資料進行回聲消除處理,并把處理後結果通過發送出去。這樣就可以保證音頻采集、播放的同步性,并達到滿意的回聲消除效果。
3.3 WebRTC中的GIPS回聲消除代碼封裝
為了友善使用,通過JNI技術。将GIPS核心C代碼封裝成動态連結庫。本部分的主要工作就是将使用的通用音頻處理子產品WebRTC_AUDIO和GIPS—AEC子產品進行封裝,得到Android下的動态連結庫檔案。具體就是需要編寫WebRTC_AUDIO和GIPS-AEC的Android.mk檔案以控制.SO檔案的編譯過程。
通用音頻處理子產品WebRTC—AUDIO和GIPS—AEC子產品在Android下編譯基本的步驟是:
1)編寫WebRTC_AUDIO的Android.mk檔案,将Osip中的所有源代碼和頭檔案按照要求加進去,然後利用NDK(Native Development Kit——本地開發工具包)在Cygwin(linux平台)下直接編譯WebRTC_AUDIO源代碼和Android.mk生成libWebRTC_AUDIO.SO動态連結庫檔案。
2)然後完成GIPS-AEC的Android.mk檔案,基本過程與上面類似,但是GIPS-AEC是基于WebRTC_AUDIO的,是以必須将生成的WebRTC_AUDIO.SO導入到自己的Android.mk的檔案中,最後編譯生成libGIPS_AEC.SO檔案。
下面以webRTC_AUDIO的Android.mk簡單介紹一下.mk的編寫,其基本内容如下:
LOCAL_PATH:=$(call my-dir) 指定本地LOCAL_PATH變量位置
include $(CLEAR_VARS) 編譯子產品開始
LOCAL_SRC_FILES:=...此處加入需要編譯的C源檔案名稱
LOCAL_CFLAGS+= -DWEBRTC_ANDROID\-DWEBRTC_ARCH_ARM\
..... 定義宏
LOCAL—C—INCLUDES:= .... 加入所需要包含的頭檔案路徑
LOCAL_LDLIBS+= -ldl 調用第三方庫
LOCAL_MODULE:=WebRTC_audio 指定生成.SO檔案名稱
include $(BUILD_SHARED—LIBRARY) 指定生成.SO檔案,編譯子產品結束
通過JNI技術将獨立出來的通用音頻處理子產品WebRTC_AUDIO和GIPS—AEC子產品核心C代碼封裝成libWebRTC_AUDIO.SO和libGIPS-AEC.SO動态連結庫檔案,便于應用于不同的Android版本平台上。
4 總結
Android回聲消除技術直接影響着Android數字樓宇對講系統對講的通話品質及使用者産品體驗。本文的目的是實作一種便于使用的Android樓宇對講的Android回聲消除技術。采用WebRTC的回聲消除子產品實作Android本地實時回聲消除,并設計了多線程程式設計技術實作音頻采集、播放的同步,解決了Android樓宇對講系統的回聲問題,最後利用JNI技術将我們的Android樓宇對講系統回聲消除程式進行封裝,便于不同Android平台的移植應用。本文中所研究的Android回聲消除技術不僅可應用于Android數字樓宇對講系統,對于其他Android數字通信系統也同樣适用。