来源 http://www.qttaudio.com/android-aec.html

回声消除介绍

http://www.baike.com/wiki/%E5%9B%9E%E9%9F%B3%E6%B6%88%E9%99%A4%E6%8A%80%E6%9C%AF

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

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

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

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

Android平台回声消除方法

系统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)

QttAudio

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

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;
}

论android等平台回音消除解决方案相关推荐

  1. android speex AEC 回音消除

    android speex AEC 回音消除. 有时候喇叭声音会被mic录制进去,就会产生回音数据,这是非常让人头疼的,所以去回音在音视频应用中非常重要. 现在主流的回音消除手段有android自带a ...

  2. Android app 录音回音消除两种方法

    在app开发录音功能的时候 会遇到回音的问题,今天就来借助android 自带的api 来解决回音的问题 1.通过设置AudioManager.MODE_IN_COMMUNICATION模式进行录音, ...

  3. Android 平台语音通话及回音消除、噪音消除研究

    一 Android平台语音通讯 正因为Android平台优越的性能.美观的界面,越来越多人使用Android手机,从而在Android平台上的 语音通话越来越多.语音通话大概流程如下:我认为一个语音通 ...

  4. Android 平台语音通话及回音消除、噪音消除研究(转)

    一 Android操作系统由来 Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平 板电脑,由Google公司和开放手机联盟领导及开发.尚未有统一中文名 ...

  5. 【转】Android 平台语音通话及回音消除、噪音消除研究

    本文转自博客:https://www.cnblogs.com/jianglijs/p/8583603.html -------------------------------------------- ...

  6. 开源 基于Android的SIP电话-----Speex 回音消除 在android 平台

    我的毕业论文题目是: 基于Android的移动VoIP高清视频通话系统的设计与实现 可以去CNKI下载察看,希望对大家有帮助 搞了将近一个月的时间,将Speex的编码和解码做好了,发现还不错. 参考A ...

  7. android 电话回音消除,智能门铃中可视对讲的回音消除

    原标题:智能门铃中可视对讲的回音消除 智能家居市场火爆已久,无论是大厂家.还是小品牌都在其中奋战,比较常见的智能家居有插座.门锁.音箱等,这些产品的竞争早已白热化,而在硝烟四起的智能家居领域,智能门铃 ...

  8. webrtc回声消除线程android,android WebRTC 示例demo源码(回音消除)

    [实例简介] 有相关文档和测试demo,回音消除等处理,学习WebRTC.回音消除的同学可以好好参考 [实例截图] [核心代码] /* * Copyright (c) 2013 The WebRTC ...

  9. android音频杂音问题_Android 音视频去回声、降噪(Android音频采集及回音消除)(转)...

    好久没写文章了,其实是想记录一下自己在Android开发的成长历程.谈到音视频这块,对于新手来说刚接触到这一块,那是非常非常的恶心~我自己弄这一块也是从头开始,在 网上也翻阅了无数的资料.浏览了无数的 ...

最新文章

  1. 最后一片蓝海的终极狂欢-写在Win10发布前夕
  2. 【透明版九宫格背景图片】仅依靠background的几个属性组合搭配出酷炫的透明背景卡片效果→适用于大数据可视化、数据大屏展示页面
  3. php 提交的数据覆盖,如何高效的做数据覆盖操作
  4. 人工智能行业:人脸识别报告,“刷脸”时代到来
  5. Spring-AOP @AspectJ进阶之命名切点
  6. 密码学研究-密钥长度限制
  7. 菜鸟成长日记(四)之WMIC简单命令应用
  8. 计算机文化基础性考二,电大计算机文化基础形考二答案
  9. Oracle入门(十二)之SQL的DDL
  10. pthread_cond_wait的spurious wakeup问题
  11. 管理动物园动物c++_中国动物园行业供需预测及投资潜力分析
  12. 车间调度建模系列1|复杂车间调度问题特点
  13. Matlab中进行高斯滤波-学习笔记
  14. (附源码)springboot校园疫情智慧防控微信小程序 毕业设计 011133
  15. 在edge浏览器找不到internet选项?
  16. python 串口助手 简书_【Python】PyQt5之串口助手【2】
  17. tp5的时间查询,查询时间戳是否在某一天中
  18. 英文歌曲:Action Songs for kids
  19. 让AI简单且强大:深度学习引擎OneFlow技术实践
  20. 的路由放在本地_大佬私藏玩法,NAS还能当路由

热门文章

  1. python应用——习题练习
  2. 【Unity项目】仿《空洞骑士》项目
  3. 安卓游戏--浅塘之辅助开发(C/S模式)
  4. 聊聊引擎底层如何实现Bloom渲染算法
  5. 明光市机器人_明光市情侣酒店客房语音智能控制系统厂家
  6. Spring(ioc和di)简介
  7. python第二周基本图形绘制
  8. 基于Ubuntu 18.04机器人操作系统环境和深度学习环境配置
  9. 2020年王鼎杯反序列化题目复现
  10. 泰捷we30c系统语言,泰捷方盒WE30C测评:看电视久违的清爽