原文地址:http://billhoo.blog.51cto.com/2337751/1213801html
【2015年2月15日】java
Bill 這段時間沒有再關注 WebRTC 以及音頻處理的相關信息,且我我的早已再也不推薦單獨編譯 WebRTC 中的各個模塊出來使用。實際上本文的參考價值已經很小了,甚至可能會產生誤導。不刪這篇文章的緣由在於文後有不少讀者的討論,其中的一些仍具有必定的價值,請你們務必以批判和審慎的態度閱讀文章。android
【2014年5月14日】git
昨天有幸在 Google 論壇裏詢問到 AECM 模塊的延遲計算一事,Project member 說搗騰這個延遲實際上對 AECM的效果沒有幫助,這個延遲值僅在 AECM 啓動時加快內置延遲估算器的收斂,若是更新的延遲有誤,甚至會使AECM 內置的延遲估算器出現錯誤的偏移,他建議我使用一個理論上的定值,Chrome 中他們用了 100ms。我以前也在 AECM 裏看到了它對內置的 delay_estimator 二進制延遲估算器有很大的依賴,近端與遠端數據匹配與否,幾乎所有仰仗這個延遲估算器的結果。所以,對於 AECM 的使用,是否還須要花時間去計算這個系統延遲,bill 再也不置評,箇中效果你們本身實踐和把握。web
其次,AECM 產生的唧唧聲 Project member 澄清這不是 bug,而是 AECM 算法原本就有此表現,屬正常現象。算法
在這裏僅但願你們知道此事,以避免被我一家之言誤導。windows
【2014年5月8日】app
本文已有一年之久,隨着本身在學習過程當中認識的加深,以及期間和各位在文後的討論,擔憂後來者照着這一年前的文章走彎路,bill 以爲有必要對文章作一個更新,點出本身走的彎路,以避免誤導後來者。dom
1. 本身最開始是把 AECM、NS、VAD、AGC 各個模塊單獨提取出來使用,如今看來實屬麻煩,且效果也不甚理想。若是你們的項目沒有特殊的要求,大可將整個語音引擎 VoiceEngine 編譯出來使用。就我我的而言,目前的解決方案是獨立編譯使用音頻處理單元 AudioProcessingModule,由於 APM 是一個純淨的音頻處理單元,其接口僅與音頻處理有關,APM編譯請見此文。APM的使用加上上層代碼的優化,能夠保證基本的通話效果(離完美還很遠),回聲基本是沒有的。主要會存在兩個問題,一是AECM出來的效果會有唧唧聲,這個聲音能夠經過對延遲計算的不斷優化而獲得改善,最終能夠作到說幾句話以後有1~2次唧唧聲。二是通話過程當中聲音會忽大忽小,目前我是懷疑由AECM的double talk處理引發的,具體的還要本身去倒騰。eclipse
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