回声消除介绍

http://www.qttaudio.com/aecjsgs.html

在即时通讯应用中,需要进行双方,或是多方的实时语音交流,在要求较高的场合,通常都是采用外置音箱放音,这样必然会产生回音,即一方说话后,通过对方的音箱放音,然后又被对方的Mic采集到回传给自己。如果不对回音进行处理,将会影响通话质量和用户体验,更严重的还会形成震荡,产生啸叫。

​回声消除就是在Mic采集到声音之后,将本地音箱播放出来的声音从Mic采集的声音数据中消除掉,使得Mic录制的声音只有本地用户说话的声音。

传统的回声消除都是采用硬件方式,在硬件电路上集成DSP处理芯片,如我们常用的固定电话、手机等都有专门的回音消除处理电路,而采用软件方式实现回声消除一直存在技术难点。

回声消除已经成为即时通讯中提供全双工语音的标准方法。声学回声消除是通过消除或者移除本地话筒中拾取到的远端的音频信号来阻止远端的声音返回去的一种处理方法。这种音频的移除都是通过数字信号处理来完成的。回声消除技术是数字信号处理的典型应用之一。

Android平台回声消除方法

QttAudio

  1. QttAudio解决了什么问题?
  • Android、iOS、Windows、(嵌入式)Linux系统的回音消除问题:通话再无回声啸叫,高清音质
  • 多语音流混音问题:多人会议模式很简单
  • 内置多种语音编解码格式:摆脱烦人的编解码开发工作量
  • 跨平台,接口一致性,集成简单:合四为一,加速应用开发,助您抢占先机
  • 与服务器无关:摆脱云服务绑架,私有云部署,更安全,更划算
  1. 一个代码小例子

Java(Android )

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);try {//初始化QttAudioEngineQttAudioEngine.me().init(this, "your appkey");//创建QttAudioStreamQttAudioStream stream = QttAudioEngine.me().createStream();//设置mic的编码参数,pcm,单声道,48000hz采样率QttAudioEngine.me().setMicCodecParams("pcm", 1, 48000, 0);//设置mic采集回调函数QttAudioEngine.me().setMicCaptureCb(new QttCaptureCallbak() {@Overridepublic void onCapture(byte[] buf, int bufLength, Object userdata) {QttAudioStream tmpStream = (QttAudioStream) userdata;//将mic采集到的播放出来,实现音频回放功能tmpStream.writePayload(buf, 0, bufLength);}}, stream);//启动stream,开始工作stream.start();} catch (QttException e) {e.printStackTrace();}}
}

C (iOS、Linux、Windows)

static void onCapture(char *buf, size_t len, void *userdata) {QttAudioStream *stream = (QttAudioStream *)userdata;//将mic采集到的播放出来,实现音频回放功能qtt_stream_write_payload(stream, buf, len);
}int main() {//创建QttAudioEngineQttAudioEngine *engine = qtt_engine_init("your appkey");if (engine == NULL) {fprintf(stderr, "qtt_engine_init fail\n");return -1;}//创建QttAudioStreamQttAudioStream *stream = qtt_engine_create_stream(engine);if (stream == NULL) {fprintf(stderr, "qtt_engine_create_stream fail\n");return -1;}//设置mic的编码参数,pcm,单声道,48000hz采样率qtt_engine_set_mic_codec_params(engine, "pcm", 1, 48000, 0);//设置mic采集回调函数qtt_engine_set_mic_capture_callback(engine, onCapture, stream);//启动stream,开始工作qtt_stream_start(stream);char c = getchar();qtt_stream_stop(stream);qtt_stream_free(stream);qtt_engine_free(engine);return 0;
}

系统API

Android在4.1(API level 16)的时候增加了一个API:AcousticEchoCanceler。

下面简单的介绍下AcousticEchoCanceler的使用方法:

private AcousticEchoCanceler canceler;
//判断当前机型是否支持AEC
public boolean isDeviceSupportAEC()
{return AcousticEchoCanceler.isAvailable();
}
//初始化AEC
public boolean initAEC(int audioSession)
{if (canceler != null){return false;}canceler = AcousticEchoCanceler.create(audioSession);canceler.setEnabled(true);return canceler.getEnabled();
}public boolean setAECEnabled(boolean enable)
{if (null == canceler){return false;}canceler.setEnabled(enable);return canceler.getEnabled();
}public boolean release()
{if (null == canceler){return false;}canceler.setEnabled(false);canceler.release();return true;
}

从以上代码可知,AcousticEchoCanceler的初始化需要一个sessionid,这个sessionid由初始化好的AudioRecord对象获得:

sessionid = audioRecord.getAudioSessionId();

初始化AudioTrack时,也需要额外的处理sessionid:

audioTrack = new AudioTrack(AudioManager.STREAM_VOICE_CALL, frequency, channelOUT, audioEncoding, tmpSize, AudioTrack.MODE_STREAM, sessionid);

为什么AcousticEchoCanceler和AudioTrack初始化都需要AudioRecord对象的sessionid呢?这牵涉到理解回声消除的原理,请见这篇文章。

Speex

Speex提供开源的的回音消除算法,从提供的文档(https://speex.org/docs/manual/speex-manual/node7.html#SECTION00740000000000000000)和测试用例看,效果还是非常棒的。下面简单介绍speex echo cancellation api的使用方法,官方示例文件testecho.c:

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "speex/speex_echo.h"
#include "speex/speex_preprocess.h"#define NN 128
#define TAIL 1024int main(int argc, char **argv)
{FILE *echo_fd, *ref_fd, *e_fd;short echo_buf[NN], ref_buf[NN], e_buf[NN];SpeexEchoState *st;SpeexPreprocessState *den;int sampleRate = 8000;if (argc != 4){//mic_signal是mic实时采集到的音频数据(包含speaker_signal),speaker_signal是由喇叭放出去的音频数据(也可称为远端数据),output是将mic_signal中去掉speaker_signal的数据,就得到了干净无回声的数据fprintf(stderr, "testecho mic_signal.sw speaker_signal.sw output.sw\n");exit(1);}echo_fd = fopen(argv[2], "rb");ref_fd  = fopen(argv[1],  "rb");e_fd    = fopen(argv[3], "wb");st = speex_echo_state_init(NN, TAIL);den = speex_preprocess_state_init(NN, sampleRate);speex_echo_ctl(st, SPEEX_ECHO_SET_SAMPLING_RATE, &sampleRate);speex_preprocess_ctl(den, SPEEX_PREPROCESS_SET_ECHO_STATE, st);while (!feof(ref_fd) && !feof(echo_fd)){fread(ref_buf, sizeof(short), NN, ref_fd);fread(echo_buf, sizeof(short), NN, echo_fd);//ref_buf是采集到的声音,至少包含两部分:我们的说话声和喇叭放出来的声音(echo_buf)//echo_buf是喇叭放出来的声音//e_buf是干净的声音speex_echo_cancellation(st, ref_buf, echo_buf, e_buf);speex_preprocess_run(den, e_buf);fwrite(e_buf, sizeof(short), NN, e_fd);}speex_echo_state_destroy(st);speex_preprocess_state_destroy(den);fclose(e_fd);fclose(echo_fd);fclose(ref_fd);return 0;
}

以上代码是处理文件,而在实际的VOIP通话中,难点在于NN和TAIL的指定,也就是frame_size和tail_length,因为像android\ios、windows或linux等非实时系统,用户调用采集或者播放的接口,到实际硬件真正采集和播放声音,根据各硬件平台以及系统的不一样,这中间是有几十至几百毫秒的延迟,这对于回声处理增加了非常大的难度。

WebRTC

WebRTC,名称源自网页实时通信(Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的技术。

WebRTC源代码中设计了两个回声消除模块,AEC(Acoustic Echo Canceller)和AECM(Acoustic Echo Canceller Mobile),AEC是在电脑端使用的回声消除器,而AECM是在移动端使用。由于电脑与移动设备的差别比较明显,在处理速度上,编解码器的性能上和内存方面都有着较大的差异。

在VoIP实时语音通话中,之所以会产生声学回声的原因是,近端通话者的声音被自己的麦克风拾取后通过网络传到远端,远端扬声器播放出来的声音被麦克风拾取后通过网络又重新发回近端。加上网络和数据处理等各种延迟的影响,使得近端通话者能够从扬声器中听到自己的刚才所说的话,就产生了回声。

下面主要来简单介绍一下AECM模块 中echo_control_mobile.c的两个函数:

//farend 是远端传过来的音频数据,也就是将要从喇叭放出来的声音,类似于speex的echo_buf
WebRtcAecm_BufferFarend(void *aecmInst, const int16_t *farend, int16_t nrOfSamples)
//nearendNoisy 是从mic采集到的声音,类似于speex的ref_buf
//nearendClean 可以放入经过Noise Reduction的音频数据
//msInSndCarBuf 该值需要特别计算才能够取得良好的去回音效果,也即将听筒播放出来的声音被mic采集到时的一个精确的值,才能使AECM达到良好的回音消除效果
WebRtcAecm_Process(void *aecmInst, const int16_t *nearendNoisy, const int16_t *nearendClean, int16_t *out, int16_t nrOfSamples, int16_t msInSndCardBuf)
转自:http://www.qttaudio.com/android-aec.html

android、ios、windows等平台回声消除的解决方案相关推荐

  1. android ios wp三大平台神器软件分享

    喜欢折腾手机,android,ios,wp.这三大主流平台出来许多神器的软件,今天分享一下. IOS篇: 苹果什么都好,就是安装软件特别麻烦,iTunes前期配置太麻烦了,许多小白用户没人教根本就搞不 ...

  2. ios emjoi java_前端App开发,实际工作中三端(android,ios,前端H5)emoji表情显示解决方案...

    想起最近开发APP的时候,产品提的一个需求,用户的帖子正文还有评论内容里,要能够显示emoji表情,因为我们这款app是混合开发的,APP里的发贴,发评论是原生做的(android和ios),但帖子详 ...

  3. 论android等平台回音消除解决方案

    来源 http://www.qttaudio.com/android-aec.html 回声消除介绍 http://www.baike.com/wiki/%E5%9B%9E%E9%9F%B3%E6%B ...

  4. 【Flutter】手机应用类型 ( Android | iOS | Native 应用 | Web 应用 | Hybrid 应用 | ReactNative 应用 | Flutter 应用 )

    文章目录 一.Native 应用 二.Web 应用 三.Hybrid 应用 四.ReactNative 应用 五.Flutter 应用 一.Native 应用 原生应用开发 : Android / i ...

  5. 用HTML5/CSS3/JS开发Android/IOS应用

    现在人人都想成为安卓/IOS应用开发工程师.其实,安卓/IOS应用可以用很多种语言来实现.由于我们前端开发工程师,对HTML5/CSS/JavaScript的网络编程已经相当熟悉了.所以,今天大家将会 ...

  6. 使用Mac开发Android/iOS/OS X图标生成工具推荐

    今天我为大家大家推荐一款在Mac下开发所使用到的图标生成工具,非常方便.可以根据一幅图片快速生成Android/iOS/OS X平台下所需要的图标icon. 该款应用的名字就叫"图标生成&q ...

  7. Windows/Android/iOS平台H265编码视频播放器EasyPlayerPro支持高码率视频播放和D3D画面旋转代码参考

    EasyPlayerPro是一款全功能的流媒体播放器,支持RTSP.RTMP.HTTP.HLS.UDP.RTP.File等多种流媒体协议播放.支持本地文件播放,支持本地抓拍.本地录像.播放旋转.多屏播 ...

  8. 幸福生活事务管理 app -Dislike 支持全平台(iOS、Android、Windows、macOS)

    Dislike 是优秀的个人事务管理工具,支持全平台(iOS.Android.Windows.macOS),这对我们使用多设备的用户来说简直就是福音!不用不同平台寻找同类产品来代替! 先说 iOS 端 ...

  9. Unity3d(U3D) Windows/Android/IOS 播放rtmp/rtsp方案

    如果基于Unity3d完全重新开发一个播放器,代价大,周期长,不适合快速出产品,最好的方式就是集成现有Native平台上成熟稳定播放器. 集成Navtive播放器可行性分析: 安卓: Unity3d可 ...

  10. android 开源计算器,开源Windows 10计算器应用迎来Web/Android/iOS移植版

    开源的跨平台特性,使得基于 UWP 代码的 Windows 10 计算器应用可以在非 Windows 平台上运行. Uno 在一篇博客文章中表示:Windows Calculator 完全使用标准的 ...

最新文章

  1. 本科-人工智能模拟卷
  2. windows系统下的python环境的搭建
  3. 和nptf螺纹一样吗_摩托车火花塞长短不同,对发动机有影响吗?
  4. 数据仓库—数据仓库—Sybase IQ 介绍
  5. 记一次偶遇Adminer
  6. Tomcat如何配置X-Frame-Options头
  7. OC中字符串的提取与替换-四种不同方法实现
  8. 【UIKit】键盘设计2
  9. ajax实现form表单提交
  10. php hprose扩展1.5.5,基于Hprose for PHP 1.5.6、Yii2.0.7的RPC的基本实现流程
  11. Monte Carlo算法
  12. linux查找外接摄像头端口
  13. 一名2012计算机应届毕业生的求职之路
  14. mailgun php版本,使用 PHP mailgun 发送邮件
  15. 深度学习笔记——情感分析
  16. Excel如何根据分组插入空行
  17. 09-Scrum过程-评审会(Review Meeting) 反思会(Retrospective Meeting)
  18. vs进行cuda编程失败,报错“the provided PTX was compiled with an unsupported toolchain.”
  19. python案例教程钱毅湘_Python案例教程 清华大学出版社 钱毅湘等 高等学校通识教育系列教材 软件工具 程序设计Python...
  20. pat乙级练习记录-1017

热门文章

  1. 费马大定理与费马小定理
  2. 商标注册成功后的中肯建议
  3. Vue Router4路由
  4. ArcGIS学习总结(二)——空间数据处理
  5. 数学不好可以学计算机科学吗,数学不好可以学习计算机专业吗?
  6. 解决笔记本HDMI外接显示器没声音的问题
  7. 街篮中服务器维修什么时候能结束,街头篮球手游1月6日微信iOS维护公告 服务器扩容...
  8. cad2006激活未找到html文件,[转载]AutoCAD2006启动时提示“许可证系统出现问题”解决方法...
  9. 使用AppleScript批量删除Mac中的信息
  10. 陶哲轩实分析 习题5.5.2