原文链接:http://www.jianshu.com/p/4bcf6ae4c478
<div class="show-content-free"><p>目前比较好的开源音频降噪方法,一是speex,另外一个就是webrtc中的NoiseSuppression模块。speex是一个强大点音频处理工具,除了包含speex编解码外还有对于音频效果处理回声消除、自动增益与噪声抑制。WebRTC的强大自不必提,自从Google开源gips的音频处理技术后,很多做实时通讯的公司都在使用WebRTC的VoiceEngine做音频处理。VoiceEngine本是对于实时音视频通讯而设计的,但也可以摘取其中near end的一些处理应用到直播的推流端来优化音频效果,增加音频的体验,比如降噪,解决环境音较重问题;比如自动增益,解决主播离手机或其他直播设备较远(还处于近场)时采集到声音较小的问题。</p>

APM(Audio Preprocessing Module)为VoiceEngine层级的音频处理模块,本文介绍了在直播推流中如何使用APM进行音频降噪,并对降噪效果进行了简单分析

一. 介绍

进入正题前先简单了解下WebRTC的结构,WebRTC由语音引擎,视频引擎和网络传输三大模块组成,其中语音引擎是WebRTC中最具价值的技术之一。

WebRTC总体架构图

语音引擎的一般工作流程如下:

  1. 发起端进行音频采集;
  2. 采集到的音频数据进行回声消除,噪音抑制,自动增益控制处理;
  3. 音频编码;
  4. 通过网路传输到接收端;
  5. 到达接收端,先进入NetEQ模块进行抖动消除,丢包隐藏解码等操作;
  6. 将处理过后的音频数据送入声卡设备进行播放。
语音引擎的工作流程

降噪NS模块(NoiseSuppression),是VoiceEngine中一个关键的语音信号处理组件。在 VOIP 语音通信过程中,来自周围环境和传输媒介引入的噪声、通信设备内部电噪声乃至其它讲话者的干扰不可避免地会对正常语音通信产生影响。这些干扰使接收端接收到的语音成为受噪声污染的带噪语音信号。从带噪语音信号中最大限度提取纯净的原始语音是噪声抑制的主要目标。

二. APM集成说明

2.1 提取编译APM

WebRTC源码链接https://chromium.googlesource.com/external/webrtc/

APM模块的提取与编译可以参考这篇文章,不过版本略旧,模块与新版本略有区别。大家可以同步最新版本进行测试,以下为使用较新版本提取出的apm文件结构

APM文件结构

提取编译完成后,我们看一下APM的主要接口文件/webrtc/modules/audio_processing/include/audio_processing.h,APM提供了简单易用的接口,将AEC、AGC、VAD、NS等模块都包含在一个处理接口中,audio_processing.h中包含所有需要的接口,调用一个process接口即可实现所有音频处理功能,但同样因为如此,想将某一块功能剥离出来也比较麻烦。audio_processing.h注释写的也很详细,不过在代码更新的时候注释没有相应的更新,有些接口已经废弃,网上大多数的对调用流程的说明还是停留在旧版本的注释上。下面通过噪音抑制模块的使用,来说明APM对音频的处理流程以及可能会遇到的一些坑。

2.2 APM关键数据结构说明

2.2.1 整型格式pcm与浮点格式pcm

APM中的接口根据输入数据格式不同分为两类,int16 interfacesfloat interfaces

  • 整型格式PCM,现在终端用户用的最多的,是16位的整数,音乐制作方用的最多的,是24位的整数。人听力的动态范围大约有85dB,16位整数有65536个不同的取值,动态区间是96dB。 如果能够完全利用起来,其实已经足以满足人类对动态范围的需求。但整数格式的数字信号处理,不可避免的会产生误差,在只利用8,9位整数的情况下,产生1位的误差就会产生-50dB左右的噪音,如果误差更大,噪音就更明显。
  • 使用浮点格式来保存音频数据,对于正确还原声音动态以及减小音效处理时产生的误差是十分有利的。但浮点运算的复杂度,要远远大于整数运算的复杂度,而且浮点格式在播放的时候还是需要把浮点数转化为整数,才能进行数模转换,而得到扬声器能够播放的模拟信号。

考虑到终端采集到的pcm为整型格式,如果使用浮点格式处理,还需要经过两次转换,而且浮点处理会增加cpu消耗(这点没有测试...),所以最后使用了int16的接口进行降噪。

2.2.2 AudioFrame类

在VoiceEngine擎中,进行音频数据操作的基本单位为 AudioFrame。主要成员变量如下:

  1. int id_;
  2. // RTP timestamp of the first sample in the AudioFrame.
  3. uint32_ttimestamp_;
  4. // Time since the first frame in milliseconds.
  5. // -1 represents an uninitialized value.
  6. int64_telapsed_time_ms_;
  7. // NTP time of the estimated capture time in local timebase in milliseconds.
  8. // -1 represents an uninitialized value.
  9. int64_tntp_time_ms_;
  10. int16_tdata_[kMaxDataSizeSamples];
  11. size_tsamples_per_channel_;
  12. intsample_rate_hz_;
  13. size_tnum_channels_;
  14. SpeechTypespeech_type_;
  15. VADActivityvad_activity_;
  16. boolinterleaved_;

其中:

  • id_ :记录的是这个 AudioFrame 对应的 channelId,即属于哪个与会者终端。
  • timestamp_ :用于编解码。
  • data_ :存放待处理的音频帧
  • samples_per_channel_ :每个声道包含的采样数
  • sample_rate_hz_ :采样频率。每一种编解码方式都有对应的采样频率。另外目前降噪支持8K、16K、32K、48K
  • num_channels_ :音频采样声道数。
  • speech_type_ :音频数据类型。此处是一个枚举变量,类型有 kNormalSpeech,kPLC,kCNG,kPLCCNG,kUndefined。
  • vad_activity_:同样是一个枚举变量,表示的是经过静音检测后该 AudioFrame 对应的类型。

2.3 调用流程

APM操作两个一帧接一帧的音频流。一个主流,一个逆向流。所有的处理都将被应用到主流的帧,这些帧通过ProcessStream函数传递过去。逆向流的帧被一些组件拿去分析,逆向流的帧通过AnalyzeReverseStream函数传递过去。这里作为推流端没有逆向流,只有主流,将采集到的音频数据输入就可以了。

组件接口遵循类似的模式设计,通过APM中相应的getter函数访问。 所有的组件在创建时默认都是不可用的。启用一个组件,新的设置将会被应用到APM。启用组件会触发内存分配和初始化,以允许这个组件开始处理音频流。 基于下面的假设,提供了线程安全,用以减少锁的开销:

  • 在ProcessStream的时候,流的getter和setters方法应该在同一个线程被调用。更确切的说,流的方法绝对不能在ProcessStream的同时被调用。
  • 参数的getter和setter绝不能同时调用。

2.3.1 使用示例

APM描述降噪相关接口如下:

1. 创建APM实例,AudioProcessing::Create()
为需要处理的每个主流使用一个实例。 在客户端,这通常是near-end流的一个实例,以及需要处理的每个远端流的附加实例。 在服务器端,这通常是每个传入流的一个实例。也可以调用带参构造函数,传递一些配置项。

2. 创建AudioFrame实例
设置 sample_rate_hz_、num_channels_、samples_per_channel_

3. 启用噪音抑制组件,设置降噪等级
apm->noise_suppression()->set_level(kVeryHigh);
apm->noise_suppression()->Enable(true);

4. 处理音频数据
apm->ProcessStream(capture_frame);

5. 结束app,删除amp
// Close the application... delete apm;

2.4 多采样率适配

  1. // APM accepts only linear PCM audio data in chunks of 10 ms. The int16
  2. // interfaces use interleaved data, while the float interfaces use deinterleaved data.
  3. // The int16 interfaces require: only |NativeRate|s be used.
  4. // The float interfaces accept arbitrary rates.

APM仅能接受以10ms长度的线性pcm音频数据,对于16bit pcm,降噪只能支持NativeRate中测采样率,即8k、16k、32、48k,回声消除、自动增益也同样如此。对于32位或64位浮点数pcm可以支持输入任意采样率且去交错的多声道pcm。

  1. enum NativeRate {
  2. kSampleRate8kHz = 8000,
  3. kSampleRate16kHz = 16000,
  4. kSampleRate32kHz = 32000,
  5. kSampleRate48kHz = 48000
  6. };

从int16的接口ProcessStream的实现看,也对于其他的采样率也是不支持的

  1. // Must be a native rate.
  2. if (frame->sample_rate_hz_ != kSampleRate8kHz &&
  3. frame->sample_rate_hz_ != kSampleRate16kHz &&
  4. frame->sample_rate_hz_ != kSampleRate32kHz &&
  5. frame->sample_rate_hz_ != kSampleRate48kHz) {
  6. return kBadSampleRateError;
  7. }

如果在这两处加上其他的采样率,处理结果也是有问题的,噪音降低但是会引入其它杂音。所以在需要处理其它采样率时有两种选择,一种是先进行重采样,转为支持的采样格式后再进行降噪;另一种是转换为浮点数格式,进行降噪处理,处理完成后再转换为16bit格式,因为目前浮点数格式只能转换成整数,才能进行数模转换,而得到扬声器能够播放的模拟信号。浮点数pcm能减小处理过程中的精度损失,但运算的复杂度,要远远大于整数运算的复杂度,处理过程cpu的消耗也会更大。

三. 降噪效果分析

APM集成好了,现在来测试下效果。我们使用audition进行分析。

3.1 直观感受

输入16000HZ 16bit mono 音频数据观察降噪效果:

降噪前音频
降噪后音频

上图为降噪前,下图为降噪后,可以看出降噪前后对比比较明显,降噪后整体整体能量有所下降,音频较低处下降更为明显;实际感受降噪后环境噪音大幅度降低,但人声也会略有降低。

3.2 不同level降噪效果

采集48000HZ 16bit stereo音频数据,降噪有4个level(kLow、kModerate、kHigh、kVeryHigh)为方便对比,将采集到的音频数据存储到本地文件,从文件中读取数据依次使用没有level进行处理。

降噪前音频
Low Level降噪后音频
Moderate Level降噪后音频
High Level降噪后音频
VeryHigh Level降噪后音频

继续对比其他level的处理结果,发现随着level的提高,频域上较低的声音逐渐被消掉,噪音消的越来越干净,但level越高声音的细节也损失也越大,整体音量也有减小的趋势,实际用歌曲来测试发现立体声效果随level提高也越来越弱。

四. 总结

WebRTC的降噪效果不错,但降噪的同时对人声也会略有影响,所以还是要根据需要选择适合的降噪等级。

转载请注明:
作者金山视频云,首发简书 Jianshu.com


也欢迎大家使用我们的直播/短视频SDK,SDK已经支持APM的降噪功能。

  • Android直播SDK(推流 + 播放):https://github.com/ksvc/KSYLive_Android
  • iOS直播SDK(推流 + 播放):https://github.com/ksvc/KSYLive_iOS

有关音视频的更多精彩内容,请参考https://github.com/ksvc
视频云技术交流群(QQ):574179720。

金山云SDK
      </div></div></div>

WebRTC APM相关推荐

  1. 安卓webrtc在ubuntu 2004下编译使用

    文章目录 安卓webrtc在ubuntu 2004下编译使用 相关网址链接 Http 全局代理配置 android webrtc 编译 boto 代理配置 Unable to reach the sn ...

  2. 单独编译使用WebRTC的音频处理模块

    不推荐单独编译 WebRTC 中的各个模块出来使用. 昨天有幸在 Google 论坛里询问到 AECM 模块的延迟计算一事,Project member 说捣腾这个延迟实际上对 AECM 的效果没有帮 ...

  3. WebRTC音频预处理单元APM的整体编译及使用

    正文 然而本次优化仍然没能用上整套VoE,因为VoE不仅仅包含音频预处理,它将音频编码模块.传输模块一并融入了引擎,而bill的项目需要使用既有的编码.传输层,因此使用整个VoE对我来说显得冗余且不可 ...

  4. 技术宝典 | WebRTC ADM 源码流程分析

    导读: 本文主要基于 WebRTC release-72 源码及云信音视频团队积累的相关经验而成,主要分析以下问题: ADM(Audio Device Manager)的架构如何?ADM(Audio ...

  5. WebRTC系列之音频的那些事

    年初因为工作需要,开始学习WebRTC,就被其复杂的编译环境和巨大的代码量所折服,注定是一块难啃的骨头.俗话说万事开头难,坚持一个恒心,终究能学习到WebRTC的设计精髓.今天和大家聊聊WebRTC中 ...

  6. WebRTC 的 AudioSource/AudioTrack

    按照 WebRTC 的设计,AudioSource 是一个音频源,它可以向外提供 PCM 音频帧数据,比如麦克风录制可以提供 PCM 音频帧数据,它应该是一个 AudioSource.然而在 WebR ...

  7. WebRTC 的音频处理流水线

    基于 RTC 场景下要解决的声音的问题,WebRTC 有一个大体如下图所示的音频处理流水线: WebRTC 的音频处理流水线,不是一次性建立起来的,而是分阶段分步骤建立的.整体而言,可以认为这个流水线 ...

  8. WebRTC 中的基本音频处理操作

    在 RTC,即实时音视频通信中,要解决的音频相关的问题,主要包括如下这些: 音频数据的采集及播放. 音频数据的处理.主要是对采集录制的音频数据的处理,即所谓的 3A 处理,AEC (Acoustic ...

  9. java webrtc ns降噪_单独编译和使用webrtc音频降噪模块(附完整源码+测试音频文件)...

    webrtc的音频处理模块分为降噪ns,回音消除aec,回声控制acem,音频增益agc,静音检测部分.另外webrtc已经封装好了一套音频处理模块APM,如果不是有特殊必要,使用者如果要用到回声消除 ...

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

    原文地址:http://billhoo.blog.51cto.com/2337751/1213801 [2015年2月15日] Bill 这段时间没有再关注 WebRTC 以及音频处理的相关信息,且我 ...

最新文章

  1. 如何导出android studio程序,Android Studio 如何导出 Jar 给 Unity 使用
  2. android -------- Lint优化工具
  3. 如何在面试中有条理的回答用户体验方面的问题
  4. python与机器视觉(X)打包为exe可执行文件
  5. SQL Server 2005 Service Pack 2 – CTP December 2006发布
  6. Java_基础—用LinkedList模拟栈数据结构的集合并测试
  7. 用matlab抽样定理验证,用MATLAB验证时域抽样定理
  8. Pytorch/Caffe可以先转换为ONNX,再转换为TensorRT
  9. Win10 新机,这些必装软件你拥有了吗?
  10. 主动轮廓模型——Snake分割算法(MATLAB)
  11. 飞凌单片机解密_[资料] 常见的IC芯片解密方法与原理解析!
  12. Java-综合项目-房屋出租系统(总结与反思)
  13. PHP短视频无水印解析源码
  14. FydeOS | ChromeOS配置Flutter开发环境
  15. webp是什么文件格式?
  16. rm 好凶残,太 TM 吓人了!
  17. mysql横竖表转换
  18. ctab法提取dna流程图_(完整版)CTAB法提取DNA原理及步骤、制胶、电泳
  19. access tempvars 宏_Access数据库教程之使用常用对象来加快Access 2007数据库三
  20. 接线 科思模块怎么和plc_PLC输入输出电路接线方法图解

热门文章

  1. 信息可视化图表设计指南
  2. 数据库考研信息管理系统
  3. 如何突破村镇银行业务发展的瓶颈
  4. java助理工程师主要做什么工作,Java助理工程师面试的惨痛教训
  5. C语言实现推箱子游戏
  6. /etc.login.defs 权限权限解析
  7. 由磁场和光驱动的软体机器人来了,旋转跳跃不停歇~
  8. python炫酷gui界面_如何炫酷的使用Python
  9. mysql 3个表左连接查询_MySQL数据库三个表的左连接查询(LEFT JOIN)
  10. eleme后台的el-form表单分为左右两边放数据 :inline=true