单独编译使用WebRTC的音频处理模块 - android

简介: VAD的使用和NS区别不大,唯一需要注意的是VAD仅仅只是检测,返回结果1表示VAD检测此帧为活动帧,0表示此帧为静音帧,至于判断为静音后该进行何种处理,就和你自己的项目相关了。

前言

   最近一直在捣腾如何在androidiOS上使用GoogleWebRTC——一个无疑大力推动了互联网即时通信以及VoIP发展的开源项目。

   虽然WebRTC主要目标是为互联网提供高质量的富媒体即时通信,但其源码为C/C++所写,且其开发版中也包含对android  iOS 等移动设备的支持,因此对于如今飞速发展的移动互联网,WebRTC也能推波助澜大显神通。

   WebRTC提供一套音频处理引擎VOE(本文不涉及视频处理引擎VIE),但VOE android  iOS 上的整体编译一直是一个比较繁琐且恼火的问题,于是单独提取了VOE中的NS(Noise Suppression 噪声抑制)、VADVoice Activity Detection 静音检测)、AECMAcoustic Echo Canceller for Mobile 声学回声消除)以及 AGCAuto 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源码外,如果要在androidJava代码中使用,还需自行编写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 循环对10ms8000Hz、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


目录
相关文章
|
2月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
272 4
|
5月前
|
Java Android开发 C++
Android Studio JNI 使用模板:c/cpp源文件的集成编译,快速上手
本文提供了一个Android Studio中JNI使用的模板,包括创建C/C++源文件、编辑CMakeLists.txt、编写JNI接口代码、配置build.gradle以及编译生成.so库的详细步骤,以帮助开发者快速上手Android平台的JNI开发和编译过程。
423 1
|
3月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
132 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
3月前
|
编译器 Android开发
配置环境变量,使CMakeLists.txt可直接使用Android NDK工具链编译项目
配置环境变量,使CMakeLists.txt可直接使用Android NDK工具链编译项目
|
3月前
|
Ubuntu Shell API
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
|
4月前
|
Web App开发 网络协议 Android开发
Android平台一对一音视频通话方案大比拼:WebRTC VS RTMP VS RTSP,谁才是王者?
【9月更文挑战第4天】本文详细对比了在Android平台上实现一对一音视频通话时常用的WebRTC、RTMP及RTSP三种技术方案。从技术原理、性能表现与开发难度等方面进行了深入分析,并提供了示例代码。WebRTC适合追求低延迟和高质量的场景,但开发成本较高;RTMP和RTSP则在简化开发流程的同时仍能保持较好的传输效果,适用于不同需求的应用场景。
250 1
|
5月前
|
监控 Java 开发工具
如何快速对接Android平台GB28181接入模块(SmartGBD)
大牛直播SDK推出的Android平台GB28181接入SDK(SmartGBD),可实现不具备国标音视频能力的 Android终端,通过平台注册接入到现有的GB/T28181—2016服务,可用于如执法记录仪、智能安全帽、智能监控、智慧零售、智慧教育、远程办公、明厨亮灶、智慧交通、智慧工地、雪亮工程、平安乡村、生产运输、车载终端等场景,可能是业内为数不多功能齐全性能优异的商业级水准GB28181接入SDK。
|
5天前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
9天前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
1月前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
71 19

热门文章

最新文章