標籤:預先處理 win7 als 無法 根據 code 前言 tin 3.0
前言
在寫【單獨編譯使用WebRTC的音頻處理模組 - android】一文之前,就一直想直接把WebRTC的音頻處理引擎VoE整個兒編譯出來供自己的項目使用,但限於技術拙劣、時間緊迫,所以沒能成功。只得挨個挨個把引擎中的Aecm、Agc、Ns以及Vad模組單獨編譯出來湊合著用。雖能達到一定效果,但始終不甚理想。5個月後,bill需要最佳化之前的項目,於是就下了狠心,定要將整個音頻處理模組用上 ...
本文
然而本次最佳化仍然沒能用上整套VoE,因為VoE不僅僅包含音頻預先處理,它將音頻編碼模組、傳輸模組一併融入了引擎,而bill的項目需要使用既有的編碼、傳輸層,因此使用整個VoE對我來說顯得冗餘且不可操作。天無絕人之路,拋開VoE不談,bill找到了僅次於VoE層級的模組 —— APM(Audio Preprocessing Module) —— 一個整合了前文所有模組且純粹的音頻預先處理單元。
Step 1 - 下載Google WebRTC源碼
Google WebRTC的開發進度還是可觀的,本文將以WebRTC的最新trunk revision 5125為例進行講解。請自行使用SVN同步以下目錄(至於同步的方法,請自行google):
http://webrtc.googlecode.com/svn/trunk/
Step 2 - 提取編譯APM所需資源
APM的整體編譯需要WebRTC源碼目錄下的如下資源:
1)common_audio 整個目錄
2)modules 目錄(不包含 video 部分)
3)system_wrappers 整個目錄
4)位於 WebRTC 源碼根目錄下的 common_types.h | common.h | typedefs.h 三個標頭檔。
5)位於 WebRTC 主目錄下的 android-webrtc.mk 檔案。
Step 3 - 在Eclipse中編譯APM基礎步驟及部分要點
對於Eclipse中jni的編譯及使用請參見上篇文章所述,在此不再贅述。
此節僅按照自己的jni目錄組織圖進行講解,讀者可根據自己需要進行調整。
在Eclipse中的jni組織圖如下:
Step-2中的所有檔案夾及標頭檔均位於 webrtc 子目錄下。android-webrtc.mk 位於 jni 根目錄下。
下面我們逐步進行分解:
step 3.1
首先我們需要對整個 android 工程進行描述和設定,開啟 jni 根目錄下的 Application.mk 檔案,編輯如下:
| 123456789101112 |
# 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_staticAPP_CPPFLAGS := -frtti -fexceptionsAPP_ABI := armeabi armeabi-v7aAPP_PLATFORM := android-9 |
其中 APP_STL 的官方說明如下:
| 1234567891011 |
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 檔案即可:
| 123456789 |
# 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 檔案如下:
| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
# 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)## voiceinclude $(MY_WEBRTC_ROOT_PATH)/common_audio/signal_processing/Android.mkinclude $(MY_WEBRTC_ROOT_PATH)/common_audio/vad/Android.mkinclude $(MY_WEBRTC_ROOT_PATH)/modules/audio_processing/aec/Android.mkinclude $(MY_WEBRTC_ROOT_PATH)/modules/audio_processing/aecm/Android.mkinclude $(MY_WEBRTC_ROOT_PATH)/modules/audio_processing/agc/Android.mkinclude $(MY_WEBRTC_ROOT_PATH)/modules/audio_processing/Android.mkinclude $(MY_WEBRTC_ROOT_PATH)/modules/audio_processing/ns/Android.mkinclude $(MY_WEBRTC_ROOT_PATH)/modules/audio_processing/utility/Android.mkinclude $(MY_WEBRTC_ROOT_PATH)/modules/utility/source/Android.mkinclude $(MY_WEBRTC_ROOT_PATH)/modules/audio_device/Android.mkinclude $(MY_WEBRTC_ROOT_PATH)/system_wrappers/source/Android.mk## build .soLOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_ARM_MODE := armLOCAL_MODULE := liblu_audio_preprocessingLOCAL_MODULE_TAGS := optionalLOCAL_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_neonendifLOCAL_STATIC_LIBRARIES := \ libprotobuf-cpp-2.3.0-liteLOCAL_SHARED_LIBRARIES := \ libcutils \ libdl \ libstlportLOCAL_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.aLOCAL_LDLIBS += -lOpenSLESifndef NDK_ROOTinclude external/stlport/libstlport.mkendifinclude $(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 了,不過在編譯過程中肯定還會有很多小問題出現(比如相對路徑不正確、找不到某某函數的符號等等),這些問題就留給讀者自行google、SO解決了,bill就不再贅述。
Step 4 - 在android應用中使用APM的注意事項
經過上述步驟,讀者便能夠得到 libwebrtc_audio_preprocessing.so 這個動態連結程式庫。我們需要做的僅僅是編寫自己的 jni 封裝函數向 android 應用程式層提供 APM 的介面。具體做法bill之前的文章已經詳細介紹過。這裡需要注意的是,如果讀者打算在自己的動態庫中引用已經編譯好的 APM 庫,那麼在 android 類載入這兩個庫時的順序是敏感的。
假設讀者將自己的 JNI 介面封裝成單獨的庫 libmy_jni_wrapper.so,而該庫引用了 libwebrtc_audio_preprocessing.so,那麼在載入這兩個庫時應該參照如下順序:
| 12345 |
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接下來該花時間去看看NetEq、Jitter Buffer等模組了。如何使用他們,如何融進自己的項目,到時候就知道了。
【WebRTC音頻預先處理單元APM的整體編譯及使用 - android】