Android实现声音采集回声与回声消除
作者:大飞飞鱼 发布时间:2022-09-28 12:13:17
本文实例为大家分享了Android实现声音采集回声与回声消除的具体代码,供大家参考,具体内容如下
一、回声产生的原因
回声(或称回音)是指障碍物对声音的反射。声波在遇到障碍物时,一部分声波会穿过障碍物,而另一部分声波会反射回来形成回声。若障碍物具有坚硬光滑的表面易产生回声;反之,具有柔软的表面则易吸收声音;另外,粗糙的表面易散射声音。回声相比那些直接传播的声音所经过的路程更长,所以会比直接传播的声音晚被听到。如果两列声波的时间间隔小于0.1秒,人耳边无法分辨,只能听到被延长的声音。因为室温(20℃)时空气中的声速是343米每秒,所以站在声源处的人要听到回声需要障碍物到声源的距离至少17米。
二、消除回声的原理
很多时候直播有连麦的需求,这时候就需要对采集的声音进行回声消除。当处在连麦的情况下,手机一边播放对方的声音,一边用麦克风进行采集,然后又将采集的声音传送给对方,这样的话对方就会听到自己的回声,由于这个循环回路一直进行,从而就会使得回声越来越多,最后出现嗡鸣声。
回声消除就是在麦克风录制外音的时候去除掉手机自身播放出来的声音,这样就将对方的声音从采集的声音中过滤出去,从而就避免了回声的产生。下面一张图片很好展示了回声消除的机制。
在近端,麦克风会采集到扬声器播放出来的远端声音,假设这路声音为y(n),当然由于需要将远端传来播放出来,我们当然能得到远端传来的声音信号,假设这路声音为x(n)。不难发现x(n)经过扬声器的播放,然后经过空气的传播,最后被麦克风采集,然后变为y(n),x(n)和y(n)具有明显的相关性。假设麦克风采集到的总声音信号为z(n),这时候需要通过自适应滤波器根据x(n)找出z(n)中的y(n),然后从z(n)中过滤掉y(n)。
三、Android 中的声音采集与回声消除
在Android中回声消除可以通过三种方式进行处理:
1、通过VOICE_COMMUNICATION模式进行录音,自动实现回声消除;
2、利用Android自身带的AcousticEchoCanceler进行回声消除处理;
3、使用第三方库(Speex、Webrtc)进行回声消除处理。
使用AudioRecord模式进行录音的时候,需要将AudioManager设置模式为MODE_IN_COMMUNICATION,还需要将麦克风打开。
有一点需要特别注意,音频采样率必须设置8000或者16000,通道数必须设为1个。
AudioManager audioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioManager.setSpeakerphoneOn(true);
使用AcousticEchoCanceler过程比较简单,录制声音的时候可以通过AudioRecord得到AudioSessionId,在创建AudioTrack的时候也可以传入一个AudioSessionId,这时候将这个统一的AudioSessionId传入AcousticEchoCanceler,那么AcousticEchoCanceler将根据之前讲过的回声消除的原理进行回声消除。
private void initAec(int audioSessionId) {
if(!AudioAecUtils.isAcousticEchoCancelerApproved()) {
aecSwitch.setEnabled(false);
return;
}
aec = AcousticEchoCanceler.create(audioSessionId);
if (aec == null) {
Log.e(TAG, "AcousticEchoCanceler.create failed");
aecSwitch.setEnabled(false);
return;
}
}
private boolean setEnableAec(boolean enable) {
if (aec == null) {
return false;
}
int ret = aec.setEnabled(enable);
if (ret != AudioEffect.SUCCESS) {
Log.e(TAG, "AcousticEchoCanceler.setEnabled failed");
return false;
}
if(enable) {
Log.d(TAG, "Aec On");
} else {
Log.d(TAG, "Aec Off");
}
return true;
}
当使用Speex或者Webrtc第三方库进行回声消除的时候,需要将采集到的音频数据传入作为源数据,需要将此刻播放的音频数据传入作为参考数据,然后还需要传入一个延时间隔,这样第三方库就能工作,从而得到回声消除后的声音。因为播放的声音需要传播,而且麦克风采集声音还有相应的缓冲区,因此需要传入一个延时间隔。关于Speex和Webrtc在github上能找到相应的Android ndk库。
本人对三种方式都进行了尝试,发现第一种效果最好,兼容性也较好,因为手机免提通话的时候就进行了回声消除处理,所以基本上所有的手机是支持的。第二种方式支持的很少,Nexus 5支持第二种方式。理论上第三种方式兼容性最好,但是本人多次实验发现要设置合适的延时间隔很难,有些时候设置好了,但是通话一段时间效果又变差。
四、Android中的声音模式设置与回声消除
在Android系统中有着多种的声音模式,通过AudioManager.setMode()可以设置声音的模式。就像上面回声消除所描述的,通过设置声音模式为MODE_IN_COMMUNICATION,加上一些声音参数的设置可以启动Android自身的硬件回声消除(通话时候的回声消除)。
设置声音模式的时候需要权限“android.permission.MODIFY_AUDIO_SETTINGS”。不同的声音模式声音的输出行为不一样。
当设置为MODE_IN_COMMUNICATION模式时,声音默认是听筒出声,这时候如果是在连麦模式而且主播没有戴耳机的情况下显然这样不符合,这时候需要调用audioManager.setSpeakerphoneOn(true)切换成外放出声。当插上耳机后,声音不需要外放,需要从耳机出声,这样可以设置audioManager.setSpeakerphoneOn(false)。
当声音模式为MODE_NORMAL,没有插耳机的时候声音自动外放,插上耳机声音从耳机出声,不需要进行相应的设置。
来源:https://blog.csdn.net/ababab12345/article/details/119860746
猜你喜欢
- package dao;import java.sql.*;public class BaseDao { //oracle//&n
- 1. 前言无论是自我学习中,还是在工作中,固然会遇到与前端搭配实现分页的功能,发现有几种方式,特此记录一下。2. 先说结论分页功能直接交给前
- 1.SpringBoot整合JDBCTemplate1.1.导入jdbc相关依赖包主要的依赖包:<dependency> &nb
- 之前的一篇文章中的代码中有一个using的用法,刚开始查看了一些资料说是强制关闭对象的一个命令。今天又查了一些资料,才明白,原来using指
- mybatis-plus-generator + clickhouse 自动生成代码依赖<!--> mybatis-plus &
- 数据适配DataAdapter 对象是DataSet 和数据源之间的桥梁,可以建立并初始化数据表(即DataTable),对数据源执行SQL
- 本文实例分析了C#动态生成DropDownList执行失败原因。分享给大家供大家参考。具体如下:今天研究DDL控件的动态生成的时候遇到了点问
- 本文实例讲述了java之swing表格实现方法。分享给大家供大家参考。具体如下:import java.awt.*;import java.
- Java中List.of()和Arrays.asList()的区别及原因动手写一下,让自己更有印象1.Arrays.asList()可以插入
- 一、Code First 代码优先DbContext可以用于数据库优先,代码优先和模型优先的开发。DbContext主要包含一组非常易于使用
- 什么是事务处理事务是计算机应用中不可或缺的组件模型,它保证了用户操作的原子性 ( Atomicity )、一致性 ( Consistency
- 在Spring4之后,要使用注解开发,必须要保证aop的包导入了使用注解需要导入context约束,增加注解的支持!<?xml ver
- 一、基本特点1. 开始时是乐观锁, 如果锁冲突频繁, 就转换为悲观锁.2. 开始是轻量级锁实现, 如果锁被持有的时间较长, 就转换成重量级锁
- 背景在最近的项目中,有一个需求是对一个很大的数据库进行查询,数据量大概在几千万条。但同时对查询速度的要求也比较高。这个数据库之前在没有使用P
- Java里一个对象obj被创建时,被放在堆里。当GC运行的时候,发现没有任何引用指向obj,那么就会回收obj对象的堆内存空间。换句话说,一
- JavaFX主要致力于富客户端开发,以弥补swing的缺陷,主要提供图形库与media库,支持audio,video,graphic,ani
- 文档中可通过应用不同的字体来呈现不一样的视觉效果,通过字体来实现文档布局、排版等设计需要。应用字体时,可在创建文档时指定字体,也可以用新字体
- 从何说起前些天和朋友讨论一个问题,他们的应用有几十万会员然后对应有积分,现在想做积分排名的需求,问有没有什么好方案。这个问题也算常见,很多地
- java通过IP解析地理位置在项目开发中,需要在登录日志或者操作日志中记录客户端ip所在的地理位置。目前根据ip定位地理位置的第三方api有
- 上一篇介绍了elasticsearch的client结构,client只是一个门面,在每个方法后面都有一个action来承接相应的功能。但是