【WebRTC音频预处理单元APM的整体编译及使用 - android】

本文涉及的产品
云拨测,每月3000次拨测额度
简介: 前言 在写【单独编译使用WebRTC的音频处理模块 - android】一文之前,就一直想直接把WebRTC的音频处理引擎VoE整个儿编译出来供自己的项目使用,但限于技术拙劣、时间紧迫,所以没能成功。

前言

在写【单独编译使用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组织结构如下:

102738855.png

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 := liblu_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 了,不过在编译过程中肯定还会有很多小问题出现(比如相对路径不正确、找不到某某函数的符号等等),这些问题就留给读者自行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,那么在加载这两个库时应该参照如下顺序:

 

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接下来该花时间去看看NetEq、Jitter Buffer等模块了。如何使用他们,如何融进自己的项目,到时候就知道了。

目录
相关文章
|
17天前
|
消息中间件 网络协议 Java
Android 开发中实现数据传递:广播和Handler
Android 开发中实现数据传递:广播和Handler
16 1
|
19天前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
20天前
|
Unix Linux Shell
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
在Linux环境下交叉编译Android所需的FFmpeg so库,首先下载`android-ndk-r21e`,然后解压。接着,上传FFmpeg及相关库(如x264、freetype、lame)源码,修改相关sh文件,将`SYSTEM=windows-x86_64`改为`SYSTEM=linux-x86_64`并删除回车符。对x264的configure文件进行修改,然后编译x264。同样编译其他第三方库。设置环境变量`PKG_CONFIG_PATH`,最后在FFmpeg源码目录执行配置、编译和安装命令,生成的so文件复制到App工程指定目录。
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
|
7天前
|
存储 安全 Android开发
安卓应用开发:构建一个高效的用户登录系统
【5月更文挑战第3天】在移动应用开发中,用户登录系统的设计与实现是至关重要的一环。对于安卓平台而言,一个高效、安全且用户体验友好的登录系统能够显著提升应用的用户留存率和市场竞争力。本文将探讨在安卓平台上实现用户登录系统的最佳实践,包括对最新身份验证技术的应用、安全性考量以及性能优化策略。
|
10天前
|
前端开发 Android开发 iOS开发
【Flutter前端技术开发专栏】Flutter在Android与iOS上的性能对比
【4月更文挑战第30天】Flutter 框架实现跨平台移动应用,通过一致的 UI 渲染(Skia 引擎)、热重载功能和响应式框架提高开发效率和用户体验。然而,Android 和 iOS 的系统差异、渲染机制及编译过程影响性能。性能对比显示,iOS 可能因硬件优化提供更流畅体验,而 Android 更具灵活性和广泛硬件支持。开发者可采用代码、资源优化和特定平台优化策略,利用性能分析工具提升应用性能。
【Flutter前端技术开发专栏】Flutter在Android与iOS上的性能对比
|
11天前
|
监控 Java Android开发
安卓应用开发:打造高效用户界面的五大策略
【4月更文挑战第29天】 在安卓应用开发的世界中,构建一个既美观又高效的用户界面(UI)对于吸引和保留用户至关重要。本文将深入探讨五种策略,这些策略可以帮助开发者优化安卓应用的UI性能。我们将从布局优化讲起,逐步过渡到绘制优化、内存管理、异步处理以及最终的用户交互细节调整。通过这些实践技巧,你将能够为用户提供流畅而直观的体验,确保你的应用在竞争激烈的市场中脱颖而出。
|
2天前
|
Java API 开发工具
java与Android开发入门指南
java与Android开发入门指南
8 0
|
3天前
|
Android开发 Kotlin
Kotlin开发Android之基础问题记录
Kotlin开发Android之基础问题记录
15 1
|
3天前
|
Java Android开发
Android开发@IntDef完美替代Enum
Android开发@IntDef完美替代Enum
12 0
|
4天前
|
Android开发
Android 盒子开发过程中遇到的问题及解决方法
Android 盒子开发过程中遇到的问题及解决方法
8 2