WebRTC 音频模块单独编译 --【转载】
原文地址:http://billhoo.blog.51cto.com/2337751/1213801
【2015年2月15日】
????Bill?這段時間沒有再關注?WebRTC?以及音頻處理的相關信息,且我個人早已不再推薦單獨編譯?WebRTC?中的各個模塊出來使用。實際上本文的參考價值已經很小了,甚至可能會產生誤導。不刪這篇文章的原因在于文后有很多讀者的討論,其中的一些仍具備一定的價值,請大家務必以批判和審慎的態度閱讀文章。
?
【2014年5月14日】
? ?昨天有幸在?Google?論壇里詢問到?AECM?模塊的延遲計算一事,Project member?說搗騰這個延遲實際上對?AECM的效果沒有幫助,這個延遲值僅在?AECM?啟動時加快內置延遲估算器的收斂,如果更新的延遲有誤,甚至會使AECM?內置的延遲估算器出現錯誤的偏移,他建議我使用一個理論上的定值,Chrome?中他們用了?100ms。我之前也在?AECM?里看到了它對內置的?delay_estimator?二進制延遲估算器有很大的依賴,近端與遠端數據匹配與否,幾乎全部仰仗這個延遲估算器的結果。因此,對于?AECM?的使用,是否還需要花時間去計算這個系統延遲,bill?不再置評,個中效果大家自己實踐和把握。
? ?其次,AECM?產生的唧唧聲?Project member?澄清這不是?bug,而是?AECM?算法本來就有此表現,屬正常現象。
? ?在這里僅希望大家知道此事,以免被我一家之言誤導。
?
? ?【2014年5月8日】
? ?本文已有一年之久,隨著自己在學習過程中認識的加深,以及期間和各位在文后的討論,擔心后來者照著這一年前的文章走彎路,bill?覺得有必要對文章做一個更新,點出自己走的彎路,以免誤導后來者。
? ?1. 自己最開始是把?AECM、NS、VAD、AGC?各個模塊單獨提取出來使用,現在看來實屬麻煩,且效果也不甚理想。如果大家的項目沒有特殊的要求,大可將整個語音引擎?VoiceEngine?編譯出來使用。就我個人而言,目前的解決方案是獨立編譯使用音頻處理單元?AudioProcessingModule,因為?APM?是一個純凈的音頻處理單元,其接口僅與音頻處理有關,APM編譯請見此文。APM的使用加上上層代碼的優化,可以保證基本的通話效果(離完美還很遠),回聲基本是沒有的。主要會存在兩個問題,一是AECM出來的效果會有唧唧聲,這個聲音可以通過對延遲計算的不斷優化而得到改善,最終可以做到說幾句話之后有1~2次唧唧聲。二是通話過程中聲音會忽大忽小,目前我是懷疑由AECM的double talk處理引起的,具體的還要自己去倒騰。
? ?2. 關于回聲消除濾波器延遲的計算,之前自己一直認為只要這個延遲計算準確,就能得到理想的回聲消除效果,現在發現這個想法太幼稚,一是AECM算法本身有一定局限性,二是Android上的采集延遲沒有系統API支持,很難計算準確,而播放端的API又不能保證其準確性。目前我的能力只能做到盡量優化上層的延遲計算,盡量減少由Android音頻API對延遲造成的影響。
? ?3. 在?Android?上層優化計算系統音頻延遲的代碼達到一定瓶頸后,可以將優化目標轉向?1)AECM?算法。?2)優化AEC(PC)(使其能在手機上正常運行,目前AECPC默認濾波器長度為12塊,每塊64個點,即AECPC僅能處理48ms的單聲道16kHz延遲的數據,而Android的音頻系統延遲大多在100ms以上,因此既要增加AECPC濾波器長度又要保證其運行效率是優化的重點)?3)其他模塊的優化(比如抖動緩沖區等)。
? ?4. 文后的源碼列表已經過時,由于我目前不再支持單獨編譯這些模塊,恕我不再更新該列表,如確有獨立編譯需求的,可自行在WebRTC項目對應目錄中找到需要的文件。
?
附言
? ?WebRTC是時下比較熱門的新技術,由于bill接觸時間尚短,對該項目的理解和認知定存在不足甚或偏差,文中有描述不當之處還望各位悉心指出,感激不盡。
?
前言
? ?最近一直在搗騰如何在android和iOS上使用Google的WebRTC——一個無疑大力推動了互聯網即時通信以及VoIP發展的開源項目。
? ?雖然WebRTC主要目標是為互聯網提供高質量的富媒體即時通信,但其源碼為C/C++所寫,且其開發版中也包含對android?和?iOS?等移動設備的支持,因此對于如今飛速發展的移動互聯網,WebRTC也能推波助瀾大顯神通。
? ?WebRTC提供一套音頻處理引擎VOE(本文不涉及視頻處理引擎VIE),但VOE在?android?和?iOS?上的整體編譯一直是一個比較繁瑣且惱火的問題,于是單獨提取了VOE中的NS(Noise Suppression?噪聲抑制)、VAD(Voice Activity Detection?靜音檢測)、AECM(Acoustic Echo Canceller for Mobile?聲學回聲消除)以及?AGC(Auto Gain Control?自動增益控制)等模塊進行編譯并搗鼓其使用方法。
? ?經過自己兩月有余的搗騰和測試,終于在?android?和?iOS?上成功編譯出各模塊并在項目中使用了NS/VAD/AECM三大模塊,效果比較不錯。
? ?回過頭來看看,這幾大模塊的編譯其實非常簡單,不過兩月前的自己也著實為這個花了一番力氣。
?
正文
? ?由于幾大模塊的編譯方式相同,故本文僅以?NS?模塊為例,其余模塊請讀者自行摸索和實驗。
?
Step 1 - 下載?google WebRTC?源碼
? ?WebRTC目前的開發版主線版本已經到了?r4152 - 3.32,但這幾大模塊并未有大的修改,故本文依舊按bill當時的版本?3.31?進行講解,請自行使用SVN同步以下目錄(至于同步的方法,請自行google):
http://webrtc.googlecode.com/svn/branches/3.31/
?
?
Step 2?- 提取WebRTC - NS模塊代碼
? ?同步源碼后,進入目錄?\webrtc\modules\audio_processing\ns?,將NS模塊的源碼拷貝出來,下面是單獨編譯NS時的參考源碼列表(部分頭文件在WebRTC項目其他目錄下,請自行搜索提取):
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?defines.h
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?signal_procession_library.h
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?spl_inl.h
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?typdefs.h
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?windows_private.h
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?fft4g.h / fft4g.c
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?noise_suppression.h / noise_suppression/c
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ns_core.h / ns_core.c
? ?除了上述WebRTC源碼外,如果要在android的Java代碼中使用,還需自行編寫JNI包裝文件:
ns_jni_wrapper.c(此為自定義的?jni?包裝文件,詳情請見?此文)
?
ADDED(billhoo - 2013-6-14)?鑒于有朋友詢問JNI Wrapper的編寫,下面提供NS模塊create以及initialize函數(這兩個函數足以說明問題)的wrapper源碼及注釋,希望對大家有所幫助。更詳細的編寫步驟請參考 Oracle官方文檔 或?此文?或?此文。
?
WebRtcNs_Create?包裝函數及注釋
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /*** ?*?Summary ?*?types: ?*???NSinst_t?:?the?type?of?noise?suppression?instance?structure. ?*???NsHandle?:?actually?the?same?type?of?NSinst_t,?defined?in ?*??????????????"noise_suppression.h"?as?a?empty?struct?type?named ?*??????????????"NsHandleT". ?* ?*???Note: ?*????1.You?have?no?need?to?pass?env?and?jclazz?to?these?functions, ?*??????cus'?JVM?will?does?it?for?you. ?*????2.We?only?support?10ms?frames,?that?means?you?can?only?input?320 ?*??????Bytes?a?time. ?**/ /** ?*?This?function?wraps?the?"WebRtcNs_Create"?function?in?"noise_suppression.c". ?*?Input: ?*????????none. ?*?Output: ?*????????the?handler?of?created?noise?suppression?instance. ?*?Return?value: ?*????????-1?:?error?occurs. ?*????????other?value?:?available?handler?of?created?NS?instance. ?* ?*?@author?billhoo ?*?@version?1.0?2013-1-29 ?*/ JNIEXPORT?jint?JNICALL Java_你的類限定名_createNSInstance(JNIEnv?*env, ????????jclass?jclazz)?{ ????NsHandle?*hNS?=?NULL;?//create?a?pointer?to?NsHandle?on?native?stack. ????if?(WebRtcNs_Create(&hNS)?==?-1)?{?//allocate?dynamic?memory?on?native?heap?for?NS?instance?pointed?by?hNS. ????????return?-1;??//error?occurs ????}?else?{ ????????return?((int)?(NSinst_t?*)?hNS);?//returns?the?address?of?NS?instance?on?native?heap. ????} } |
?
WebRtcNs_Initiate?包裝函數及注釋
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | /** ?*?This?function?wraps?the?"WebRtcNs_Init"?function?in ?*?"noise_suppression.c". ?*?Initializes?a?NS?instance?and?has?to?be?called?before?any?other ?*?processing?is?made. ?* ?*?Input: ?*????????-?nsHandler???-?Handler?of?NS?instance?that?should?be ?*????????????????????????initialized. ?*????????-?sf??????????-?sampling?frequency,?only?8000,?16000,?32000 ?*????????????????????????are?available. ?*?Output: ?*?????????nsHandler??-?the?handler?of?initialized?instance. ?*?Return?value: ?*?????????0????????????????-?OK ?*?????????-1???????????????-?Error ?* ?*?@author?billhoo ?*?@version?1.0?2013-1-29 ?*/ JNIEXPORT?jint?JNICALL Java_你的類限定名_initiateNSInstance(JNIEnv?*env, ????????jclass?jclazz,?jint?nsHandler,?jlong?sf)?{ ????NsHandle?*hNS?=?(NsHandle*)?nsHandler; ????return?WebRtcNs_Init(hNS,?sf); } |
?
[END OF ADDED]
?
?
Step 3?- 編譯WebRTC - NS模塊
? ?此步請參照?bill之前的文章將剛才提取的NS代碼添加進eclipse工程進行編譯即可。以下為NS模塊的Android.mk文件:
?
?
| 1 2 3 4 5 6 7 8 9 | LOCAL_PATH?:=?$(call?my-dir) include?$(CLEAR_VARS) LOCAL_MODULE????:=?webrtc_ns LOCAL_SRC_FILES?:=?\ ????????noise_suppression.c?\ ????????ns_core.c?\ ????????fft4g.c?\ ????????ns_jni_wrapper.c include?$(BUILD_SHARED_LIBRARY) |
?
? ?編譯完成后,將項目中的?webrtc_ns.so?動態庫拷貝出來以備后續使用。
?
Step?4?- 加載編譯好的NS模塊動態庫
? ?接下來只需要按照?此文?的描述在?android?的JAVA代碼中使用剛才編譯好的?webrtc_ns.so?動態庫便大功告成。
?
Step 5?- 幾大模塊的使用及注意事項
? ?前四步已經完成了幾大音頻處理模塊在android上的單獨編譯過程,并分別生成了?webrtc_ns.so、webrtc_vad.so、webrtc_aecm.so?以及?webrtc_agc.so?四個動態庫,下面bill簡要介紹對NS、VAD以及AECM三個庫的函數使用方法及注意事項:
?
5.1 -?NS庫函數的使用及注意事項
? ?這個很簡單,參照?noise_suppression.h?頭文件中對各API的描述即可,首先使用?WebRtcNs_Create?創建NS實體,然后?WebRtcNs_Init?初始化該實體,WebRtcNs_set_policy?設置噪聲抑制的級別(bill使用的是最高級別 2,效果比較理想),設置完成后便可調用?WebRtcNs_Process?循環對10ms(8000Hz、16000Hz)音頻幀進行NS處理,注意最后別忘了調用?WebRtcNs_Free?將NS實體銷毀。
?
?
5.2 -?VAD庫函數的使用及注意事項
VAD的使用和NS區別不大,唯一需要注意的是VAD僅僅只是檢測,返回結果1表示VAD檢測此幀為活動幀,0表示此幀為靜音幀,至于判斷為靜音后該進行何種處理,就和你自己的項目相關了。
?
?
5.3 -?AECM庫函數的使用及注意事項
AECM實體的創建、初始化和銷毀工作與上述相同,之后需要在遠端和近端分別調用?WebRtcAecm_BufferFarend以及?WebRtcAecm_Process,對于AECM的使用,需要注意的重點在于Process函數的參數msInSndCardBuf,該參數在audio_procession.h頭文件中以名為delay的變量呈現,該延遲的計算確為一難點(對于單獨使用AECM模塊來說),不過只要嚴格按照delay的描述進行操作即可。
?
附:
? ?其他幾大模塊單獨編譯時需要的源文件列表(所有依賴頭文件略,請自行根據報錯添加):
WebRTC - VAD?模塊源文件列表
? ? ? ?注意:VAD的編譯需要宏?WEBRTC_POSIX?的支持,而該宏是否有實現,由?WEBRTC_ANDROID?等宏是否被定義決定,若你在編譯時提示?once?函數未定義等錯誤, 請自行添加對?WEBRTC_ANDROID宏的定義。
? ? ? ?webrtc_vad.c
? ? ? ?vad_core.c
? ? ? ?vad_filterbank.c
? ? ? ?vad_gmm.c
? ? ? ?vad_sp.c
? ? ? ?real_fft.c
? ? ? ?division_operations.c
? ? ? ?complex_bit_reverse.c
? ? ? ?cross_correlation.c
? ? ? ?complex_fft.c
? ? ? ?downsample_fast.c
? ? ? ?vector_scaling_operations.c
? ? ? ?get_scaling_square.c
? ? ? ?energy.c
? ? ? ?min_max_operations.c
? ? ? ?spl_init.c
?
WebRTC - AECM?模塊源文件列表
? ? ? ?randomization_functions.c
? ? ? ?spl_sqrt_floor.c
? ? ? ?division_operations.c
? ? ? ?min_max_operations.c
? ? ? ?ring_buffer.c
? ? ? ?delay_estimator.c
? ? ? ?delay_estimator_wrapper.c
? ? ? ?complex_bit_reverse.c
? ? ? ?complex_fft.c
? ? ? ?aecm_core.c
? ? ? ?echo_control_mobile.c
?
WebRTC - AGC?模塊源文件列表
?
?
?
? ? ? ?spl_sqrt.c
? ? ? ?copy_set_operations.c
? ? ? ?division_operations.c
? ? ? ?dot_product_with_scale.c
? ? ? ?resample_by_2.c
? ? ? ?analog_agc.c
? ? ? ?digital_agc.c
轉載于:https://www.cnblogs.com/Martin-Ma/p/5379346.html
總結
以上是生活随笔為你收集整理的WebRTC 音频模块单独编译 --【转载】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jquery send(data) 对d
- 下一篇: REDIS 字典数据结构