WebRTC音頻預處理單元APM的總體編譯及使用




正文php

然而本次優化仍然沒能用上整套VoE,由於VoE不只僅包含音頻預處理,它將音頻編碼模塊、傳輸模塊一併融入了引擎,而bill的項目須要使用既有的編碼、傳輸層,所以使用整個VoE對我來講顯得冗餘且不可操做。天無絕人之路,拋開VoE不談,bill找到了僅次於VoE層級的模塊 —— APM(Audio Preprocessing Module)—— 一個整合了前文全部模塊且純粹的音頻預處理單元。html



Step 1 - 下載Google WebRTC源碼linux

Google WebRTC的開發進度仍是可觀的,本文將以WebRTC的最新trunk revision 5125爲例進行講解。請自行使用SVN同步如下目錄(至於同步的方法,請自行google):android

http://webrtc.googlecode.com/svn/trunk/ios



Step 2 - 提取編譯APM所需資源c++

APM的總體編譯須要WebRTC源碼目錄下的以下資源:git

1)common_audio 整個目錄github

2)modules 目錄(不包含 video 部分)web

3)system_wrappers 整個目錄網絡

4)位於 WebRTC 源碼根目錄下的 common_types.h | common.h | typedefs.h 三個頭文件。

5)位於 WebRTC 主目錄下的 android-webrtc.mk 文件。



Step 3 - 在Eclipse中編譯APM基礎步驟及部分要點

對於Eclipsejni的編譯及使用請參見上篇文章所述,在此再也不贅述。

此節僅按照本身的jni目錄組織結構進行講解,讀者可根據本身須要進行調整。

Eclipse中的jni組織結構以下:

Step-2中的全部文件夾及頭文件均位於 webrtc 子目錄下。android-webrtc.mk 位於 jni 根目錄下。

下面咱們逐步進行分解:



step 3.1

首先咱們須要對整個 android 工程進行描述和設定,打開 jni 根目錄下的 Application.mk 文件,編輯以下:



1
2
3
4
5
6
7
8
9
10
11
12
# Copyright (c) 2013 BillHoo. All Rights Reserved.
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS.  All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
APP_STL :=  gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi armeabi-v7a
APP_PLATFORM := android-9

其中 APP_STL 的官方說明以下:

1
2
3
4
5
6
7
8
9
10
11
APP_STL
     By default, the NDK build system provides C++ headers for the minimal
     C++ runtime library (/system/lib/libstdc++.so) provided by the Android
     system.
     However, the NDK comes with alternative C++ implementations that you can
     use or link to in your own applications. Define APP_STL to select one of
     them. Examples are:
        APP_STL := stlport_static    --> static STLport library
        APP_STL := stlport_shared    --> shared STLport library
        APP_STL := system            --> default C++ runtime library
     For more information on the subject, please read docs/CPLUSPLUS-SUPPORT.html

因爲 NDK默認使用最小 C++ 運行時庫進行項目的編譯,致使沒法編譯 WebRTC 中使用諸如 std::map 等 STL 容器的源碼。所以咱們須要自行設定適合本項目的 C++ 運行時庫gnustl_static



step 3.2

打開並編輯 jni 根目錄下的 Android.mk 文件以下,本文件只需告訴 NDK 去調用全部子目錄下的 Android.mk 文件便可:

1
2
3
4
5
6
7
8
9
# Copyright (c) 2013 BillHoo. All Rights Reserved.
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS.  All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
include $(call all-subdir-makefiles)



step 3.3

準備工做就緒,下面就能夠開始着手編譯整個 APM 單元了,首先打開 jni/webrtc 目錄,新建 Android.mk 文件以下:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# Copyright (c) 2013 BillHoo. All Rights Reserved.
# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS.  All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
#
MY_WEBRTC_ROOT_PATH := $(call my- dir )
#
# voice
include $(MY_WEBRTC_ROOT_PATH) /common_audio/signal_processing/Android .mk
include $(MY_WEBRTC_ROOT_PATH) /common_audio/vad/Android .mk
include $(MY_WEBRTC_ROOT_PATH) /modules/audio_processing/aec/Android .mk
include $(MY_WEBRTC_ROOT_PATH) /modules/audio_processing/aecm/Android .mk
include $(MY_WEBRTC_ROOT_PATH) /modules/audio_processing/agc/Android .mk
include $(MY_WEBRTC_ROOT_PATH) /modules/audio_processing/Android .mk
include $(MY_WEBRTC_ROOT_PATH) /modules/audio_processing/ns/Android .mk
include $(MY_WEBRTC_ROOT_PATH) /modules/audio_processing/utility/Android .mk
include $(MY_WEBRTC_ROOT_PATH) /modules/utility/source/Android .mk
include $(MY_WEBRTC_ROOT_PATH) /modules/audio_device/Android .mk
include $(MY_WEBRTC_ROOT_PATH) /system_wrappers/source/Android .mk
#
# build .so
LOCAL_PATH := $(call my- dir )
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_MODULE := lib lu _audio_preprocessing
LOCAL_MODULE_TAGS := optional
LOCAL_WHOLE_STATIC_LIBRARIES := \
     libwebrtc_spl \
     libwebrtc_apm \
     libwebrtc_apm_utility \
     libwebrtc_vad \
     libwebrtc_ns \
     libwebrtc_agc \
     libwebrtc_aec \
     libwebrtc_aecm \
     libwebrtc_system_wrappers \
     libwebrtc_audio_device \
     libwebrtc_utility
#
# Add Neon libraries.
ifeq ($(WEBRTC_BUILD_NEON_LIBS), true )
LOCAL_WHOLE_STATIC_LIBRARIES += \
     libwebrtc_aecm_neon \
     libwebrtc_ns_neon \
     libwebrtc_spl_neon
endif
LOCAL_STATIC_LIBRARIES := \
     libprotobuf-cpp-2.3.0-lite
LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libdl \
     libstlport
LOCAL_PRELINK_MODULE :=  false
#
#TODO(billhoo) find a properway to do this.
LOCAL_LDLIBS += $(NDK_ROOT) /sources/cxx-stl/gnu-libstdc ++ /4 .6 /libs/armeabi/libgnustl_static .a
LOCAL_LDLIBS += -lOpenSLES
ifndef NDK_ROOT
include external /stlport/libstlport .mk
endif
include $(BUILD_SHARED_LIBRARY)

須要注意的幾點:

1)在編譯時如提示找不到 ../../../Android.mk 文件等錯誤,請檢查並修正你的相對路徑。

2)位於第60行的gnu靜態庫連接路徑是針對NDK版本 r8d 的,如讀者版本不匹配,請自行找到 libgnustl_static.a 靜態庫的路徑進行替換。

3)本示例並不打算編譯 WebRTC 的測試工程,請使用 Eclipse 搜索文件功能,找到 Android.mk 文件中的 -DWEBRTC_AUDIOPROC_DEBUG_DUMP 並註釋掉。



step 3.4

萬事俱備,咱們能夠開始編譯 APM 了,不過在編譯過程當中確定還會有不少小問題出現(好比相對路徑不正確、找不到某某函數的符號等等),這些問題就留給讀者自行googleSO解決了,bill就再也不贅述。



Step 4 - 在android應用中使用APM的注意事項

通過上述步驟,讀者便可以獲得 libwebrtc_audio_preprocessing.so這個動態連接庫。咱們須要作的僅僅是編寫本身的 jni 包裝函數向 android 應用層提供 APM 的接口。具體作法bill以前的文章已經詳細介紹過。這裏須要注意的是,若是讀者打算在本身的動態庫中引用已經編譯好的 APM 庫,那麼在 android 類加載這兩個庫時的順序是敏感的。

假設讀者將本身的 JNI 接口封裝成單獨的庫 libmy_jni_wrapper.so,而該庫引用了 libwebrtc_audio_preprocessing.so,那麼在加載這兩個庫時應該參照以下順序:

1
2
3
4
5
static {
     // Ordering of loading these shared libraries is significant.
     System.loadLibrary( "webrtc_audio_preprocessing" );
     System.loadLibrary( "my_jni_wrapper" );
}

若順序寫反,在運行時將獲得找不到 webrtc_audio_preprocessing 庫中符號的異常。



總結

整個編譯工做在如今看來很是簡單,但須要不少的耐心和搜索,不過結果仍是使人比較滿意的,APM出來的效果比以前本身單獨使用各個音頻模塊要好不少。不過對於抖動等因素的影響,APM就力不從心了。也許bill接下來該花時間去看看NetEqJitter Buffer等模塊了。如何使用他們,如何融進本身的項目,到時候就知道了。



出處http://billhoo.blog.51cto.com/2337751/1325273




[3樓]      huangqizhen  回覆
2013-12-09 17:59:42
博主您好,看您的文章頗有啓發。

參看了您的博文以後,關於迴音處理部分個人項目也基本完成了,正像您所說的,在網絡比較差的時候,因爲延時與抖動,和丟包所引發的質量降低。而個人下一步也是想把NetEQ使用本身的項目中。若是您有什麼進展的話,指望能和您一塊兒討論討論。


[5樓]      liusimon  回覆
2014-02-13 15:20:53
編譯鏈接出錯求指點E:/cygwin/android-ndk-r8d/toolchains/arm-linux-androideabi-4.6

bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux

d.exe: E:/cygwin/home/simon/WebRTC/obj/local/armeabi/libwebrtc

dio_device_opensles_android.o): in function webrtc::AudioDevic

MicrophoneIsAvailable(bool&):E:/cygwin/home/simon/WebRTC/jni/w

o_device/android/audio_device_opensles_android.cc:167: error:

e to 'webrtc::OpenSlesInput::MicrophoneIsAvailable(bool&)'




[7樓]樓主      Bill_Hoo  回覆
2014-02-14 20:37:45
回覆 it206: [4樓]



您好it206,

最近沒有倒騰android上的回聲消除了,效果和以前是同樣的,好的時候很好,差的時候總能聽到唧唧聲,很不爽。如今效果很不完美。關於apk,那是團隊的成果了,我沒有權力拿出來分享,博客裏我已經把本身能分享的都分享給你們了,忘海涵。


[8樓]      it206  回覆
2014-02-17 16:01:38
碰到的狀況和博主同樣,偶爾會出現唧唧聲,感受在一些麥克和話筒距離比較遠的手機上效果好,有些手機麥克和話筒緊靠着,一直有比較大唧唧聲,效果不好


[9樓]      liusimon  回覆
2014-02-26 16:20:21
你好,請教一下,APM具體怎麼使用,能夠分享一下嗎,處理第三方的音頻數據


[10樓]樓主      Bill_Hoo  回覆
2014-03-20 16:18:53
回覆 liusimon: [9樓]



您好,APM各個接口的使用方法在其頭文件 audio_processing.h 中描述的很清楚。android上因爲沒有控制MIC音量的接口,故APM中的AGC不要使用 kAdaptiveAnalog 模式。


[11樓]      菜鳥阿陳  回覆
2014-05-19 10:17:59
您好!Bill_Hoo.很是感謝您分享的這片博客。我也正在編譯中,但是遇到一個錯誤提示:webrtc/system_wrappers/source/cpu_features_android.c:11:26: error: cpu-features.h: No such file or directory;我想問下您編譯的時候有遇到?我在網上沒找到相關錯誤解答,因此想在這裏,向Bill_Hoo,提起,這問題應該如何解決呢。


[12樓]      菜鳥阿陳  回覆
2014-05-19 11:47:27
您好!Bill_Hoo.關於上面編譯遇到錯誤提示:一個錯誤提示:webrtc/system_wrappers/source/cpu_features_android.c:11:26: error: cpu-features.h: No such file or directory

,我查找了,在webrtc/system_wrappers/source/Android.mk 文件中添加了$(call import-module,android/cpufeatures)

,能夠編譯經過這個錯誤了,這是正確解決方法?另外編譯system_wrappers/source/Android.mk,又遇到提示一個錯誤:system_wrappers/source/spreadsortlib/spreadsort.hpp:1034:139: error: macro "getchar" passed 2 arguments, but takes just 0;這個真心不知道什麼錯誤,很想問,Bill_Hoo,你在編譯過程,又遇到這些錯誤?這我應該如何解決呢,有點困惑。


[13樓]      techLong  回覆
2014-05-20 15:09:22
請教下啊!爲何我這裏經過ctrl點擊可以找到相應的頭文件,但是編譯的時候就顯示fatal error,no such file呢!!!


[14樓]      liuliu886  回覆
2014-12-16 22:11:08
感謝分享 請問有在iso用過此模塊嗎 ?


[15樓]      liuliu886  回覆
2014-12-16 22:11:49
打錯了 應該是 iOS
2014-12-17 09:11:05
回覆 liuliu886: [14樓]

你好,IOS 上僅使用了 NS降噪 和 NetEQ 抖動緩衝,回聲消除交由其自身的 API 實現更加合適。

2014-12-17 15:32:09
感謝回覆 我發現博主之前在Stack Overflow上曾分享過一個示例代碼
https://github.com/billhoo/webrtc-based-android-aecm
可是如今已經沒法下載了 能否給我一份做爲研究 不勝感激 71892967@qq.com

2014-12-17 15:45:15
另外關於安卓下錄放音,除了兩個Java的類之外,還能夠用ndk層c++的OpenSL,目前個人程序是用它(SLRecordItf)錄音的。
它不是用AudioRecord.read這種阻塞式函數讀取錄到的數據,
而是和ios中AudioQueue相似的填滿一個緩衝區即回調的方式,我想這樣是否是更容易計算延遲一些呢?

2014-12-27 14:22:37
樓主好,我編譯的時候提示不少這一類的錯誤,找不到頭文件的狀況,可是在mk文件中路徑是已經添加進去了的
[armeabi] Compile arm   : webrtc_spl <= auto_corr_to_refl_coef.c
jni/webrtc/common_audio/signal_processing/auto_corr_to_refl_coef.c:17:85: fatal error: webrtc/common_audio/signal_processing/include/signal_processing_library.h: No such file or directory

2014-12-30 09:04:18
回覆 tanningzhong: [19樓]

您好,根據你的錯誤路徑提示,編譯 auto_corr_to_refl_coef.c 的 Android.mk 至少應該包含路徑:
「$(LOCAL_PATH)/../../../..」,即目錄「jni」。
也就是說,你須要讓編譯器可以找到根目錄 「webrtc」

2014-12-30 09:06:15
回覆 liuliu886: [17樓]

您好,GitHub上的示例我已經刪除了,那是當時本身最開始自覺得是的認爲手機上的回聲消除很簡單,因此有了一個直接使用AECM對靜態音頻文件進行消除的例子。但實際上VoIP和靜態文件是兩碼事。爲避免誤導他人,故已刪除。

2014-12-30 09:09:55
回覆 liuliu886: [18樓]

就我的經驗而言,Java層的 AudioTrack 以及 AudioRecord 實在不適合(未考慮最新版本的Android)作所謂的「延遲估算」。OpenSLES 我沒有實際測試過,不敢妄言。

2015-01-09 16:09:17
bill,你好,經過你這篇文章的幫助,我成功編譯出了libwebrtc_audio_preprocessing.so,可是接下來不知道如何總體地區使用他,請問有相關的資料能夠借鑑嗎?

2015-05-27 14:25:19
回覆 Bill_Hoo: [16樓]

回覆 liuliu886:
[14樓]

你好,IOS 上僅使用了 NS降噪 和 NetEQ 抖動緩衝,回聲消除交由其自身的 API 實現更加合適。
你好,bill。請問IOS具體哪一個API能夠用來消除回聲呢?

2015-06-19 09:52:37
樓主 ,咱們也在研究 webrtc, 可否求指教

2015-08-28 18:20:58
我以最少改動,編譯出來了so文件,歡迎你們參考,如今就差apm總體模塊的使用了,哪一個有apm的使用方法的,歡迎通知我哈。目前只發如今modules\audio_processing\test目錄下有unit_test.cc,等我研究好其使用了再詳細記錄下。 http://wiki.elesos.com/index.php?title=WebRTC%E7%B3%BB%E5%88%974:%E9%9F%B3%E9%A2%91%E5%A4%84%E7%90%86%E6%A8%A1%E5%9D%97apm%E4%B8%8B%E8%BD%BD%E4%B8%8E%E6%95%B4%E4%BD%93%E7%BC%96%E8%AF%91
相關文章
相關標籤/搜索