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

前言

在写【单独编译使用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 文件,编辑如下:


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等模块了。如何使用他们,如何融进自己的项目,到时候就知道了。

时间: 2024-10-13 02:01:09

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

WebRTC 音频模块单独编译 --【转载】

原文地址:http://billhoo.blog.51cto.com/2337751/1213801 [2015年2月15日] Bill 这段时间没有再关注 WebRTC 以及音频处理的相关信息,且我个人早已不再推荐单独编译 WebRTC 中的各个模块出来使用.实际上本文的参考价值已经很小了,甚至可能会产生误导.不删这篇文章的原因在于文后有很多读者的讨论,其中的一些仍具备一定的价值,请大家务必以批判和审慎的态度阅读文章. [2014年5月14日] 昨天有幸在 Google 论坛里询问到 AECM

单独编译和使用webrtc音频降噪模块(附源码+测试demo)

webrtc的音频处理模块分为降噪ns,回音消除aec,回声控制acem,音频增益agc,静音检测部分.另外webrtc已经封装好了一套音频处理模块APM,如果不是有特殊必要,使用者如果要用到回声消除,音频增益等较为复杂的模块时,最好使用全部的音频处理模块二不要单独编译其中一部分以免浪费宝贵的时间. 但是音频降噪部分较为简单,用起来也就几个函数,除了需要传入的音频数据以外,需要调整的参数也就是音频采样率和降噪等级.另外这部分代码采用纯C语言语法编写,可以跨平台编译.整个算法也不算特别复杂,运行起

C预编译, 预处理, C/C++头文件, 编译控制,

在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征.依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的. 其格式一般为: #Pragma Para 其中Para 为参数,下面来看一些常用的参数. (1)message 参数. Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输

WebRTC音视频引擎研究(1)--整体架构分析

WebRTC技术交流群:234795279 原文地址:http://blog.csdn.net/temotemo/article/details/7530504 1.WebRTC目的 WebRTC(Web Real-Time Communication)项目的最终目的主要是让Web开发者能够基于浏览器(Chrome\FireFox\...)轻易快捷开发出丰富的实时多媒体应用,而无需下载安装任何插件,Web开发者也无需关注多媒体的数字信号处理过程,只需编写简单的Javascript程序即可实现,W

跨平台:GN实践详解(ninja, 编译, windows/mac/android实战)

跨平台:GN实践详解(ninja, 编译, windows/mac/android实战)展开目录一.概览二.跨平台代码编辑器三.GN入门四.示范工程五.关键细节六.结语 [编译器选项] 其中前两部分是前缀部分,原本没有跨平台构建经验和知识的同学可以借助来帮助理解,后四部分则是讲述GN工程的基本结构.如何搭建一个GN构建的工程.以及关键的一些GN知识 一.概览如何开始这个话题是我比较在意的,因为对于部分人而言,真正从思维和理解上切入这篇文章真正要阐述的点是有困难的.这在于跨平台编译和开发这块,如果

Cocos2d-x 3.0 编译 eclipse+Win7+Android 篇

文档 Eclipse --> Windows--> Preferences ... 3. Set up Variables: 1. Path Variable `COCOS2DX`: * Eclipse->Preferences->General->Workspace->**Linked Resources** * Click **New** button to add a Path Variable `COCOS2DX` pointing to the root co

Linux下编译VLC for Android源代码总结

转:http://blog.chinaunix.net/uid-26611383-id-3678766.html 由于项目需要,需要一个在android平台能够支持RTSP协议的播放器,由于之前没有android平台的经验,所以找了著名的video LAN的VLC播放器,更令人惊奇的是这款播放器居然还是完全开源的.在此向那些开源软件的作者和组织致以崇高的敬意,是你们的存在使得计算机软件产业蓬勃发展,你们帮助了很多囊中羞涩的个人和企业,让他们也有机会用上高质量的软件,同时不可避免的吸引了一批有志之

在Ubuntu上下载、编译和安装Android最新源代码

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6559955 看完了前面说的几本书之后,对Linux Kernel和Android有一定的认识了,是不是心里蠢蠢欲动,想小试牛刀自己编译一把Android源代码了呢?一直习惯使用Windows系统,而Android源代码是不支持在Windows上编译上,于是决定使用虚拟机安装Ubuntu,然后下载.编译和安装Android源代码. 一. 环境准备

在Ubuntu上下载、编译和安装Android最新内核源代码(Linux Kernel)

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6564592 在前一篇文章提到,从源代码树下载下来的最新Android源代码,是不包括内核代码的,也就是Android源代码工程默认不包含Linux Kernel代码,而是使用预先编译好的内核,也就是prebuilt/android-arm/kernel/kernel-qemu文件.那么,如何才能DIY自己的内核呢?这篇文章一一道来. 一. 首选