第9课 回声抑制(AEC+AGC+ANS)的实现
在第8课中,我们将推流端与播放端合并实现了一对一音视频聊天功能,一切看起来还不错。但在实际使用时,会遇到一个烦心的问题:说话时会听到比较大的回声,影响正常使用。所以,这节课我们来重点解决这个问题。
解决回声的方案可以利用操作系统本身提供的AEC功能,也可以引入第三方SDK实现。业界比较好用的AEC方案是webRTC开源的回声抑制方案,除了AEC,还可以同时实现AGC和ANS。
1.配置开发环境
与使用FFmpeg和openCV的SDK类似,我们在使用前需要先包括webRTC的头文件和库文件:
E:\SDK\webrtc-sdk\x86\include;
E:\SDK\webrtc-sdk\x86\lib;
2.初始化webRTC
在fmle.cpp中加入初始化代码:
//AEC初始化
void *aecInst = NULL;
int sampleNum = 160;
char far_frame[320];
char near_frame[320];
char out_frame[320];
WebRtcAec_Create(&aecInst);
ret = WebRtcAec_Init(aecInst, 8000, 8000);
printf("ret WebRtcAec_Init: %d\n", ret);
AecConfig aecConfig;
//aecConfig.skewMode = kAecFalse;
//aecConfig.metricsMode = kAecFalse;
//aecConfig.delay_logging = kAecFalse;
aecConfig.nlpMode = kAecNlpConservative;
ret = WebRtcAec_set_config(aecInst, aecConfig);//AGC初始化
void *agcInst = NULL;
int minLevel = 0;
int maxLevel = 255;
int agcMode = kAgcModeFixedDigital;
int fs = 16000;
int status = 0;
WebRtcAgc_Create(&agcInst);
ret = WebRtcAgc_Init(agcInst, minLevel, maxLevel, agcMode, fs);WebRtcAgc_config_t agcConfig;
agcConfig.compressionGaindB = 20;
agcConfig.limiterEnable = 1;
agcConfig.targetLevelDbfs = 3;
ret = WebRtcAgc_set_config(agcInst, agcConfig);NsHandle *nsInst = NULL;
WebRtcNs_Create(&nsInst);
WebRtcNs_Init(nsInst, 8000);
WebRtcNs_set_policy(nsInst, 1);
3.处理回声
在FFmpeg处理音频部分进行回声处理,注意需要先获取播放流音频也就是代码中的mainDlg->myFmlp->outAudioQue.front().audioDataArr作为参考:
//是否处理回声
BOOL ifAEC = mainDlg->ifAEC;;
if (!mainDlg->myFmlp->outAudioQue.empty() && ifAEC){memcpy(farAudioBuffer, mainDlg->myFmlp->outAudioQue.front().audioDataArr, 2048);for (int num = 0; num <7; num++){if (sampleNum*num * 2 < 1920){memcpy(far_frame, farAudioBuffer + sampleNum*num * 2, sampleNum * 2);memcpy(near_frame, nearAudioBuffer + sampleNum*num * 2, sampleNum * 2);}else{memcpy(far_frame, farAudioBuffer + 1920, 128);memcpy(near_frame, nearAudioBuffer + 1920, 128);}ret = WebRtcAec_BufferFarend(aecInst, (int16_t *)far_frame, sampleNum);backTime = mainDlg->backTime;WebRtcAec_Process(aecInst, (int16_t *)near_frame, (int16_t *)1, (int16_t *)out_frame, (int16_t *)1, sampleNum, backTime, 0);memcpy(aecAudioBuffer + sampleNum*num * 2, out_frame, sampleNum * 2);} memcpy(audioBuffer, (uint8_t*)aecAudioBuffer, 2048); }
else{memcpy(audioBuffer, (uint8_t*)inAudioQue.front().audioDataArr, 2048);
}
4.测试效果
调试运行,如何能听到明显的回声消除效果则表示成功,否则需要进一步微调backTime。
相关文章:
第9课 回声抑制(AEC+AGC+ANS)的实现
在第8课中,我们将推流端与播放端合并实现了一对一音视频聊天功能,一切看起来还不错。但在实际使用时,会遇到一个烦心的问题:说话时会听到比较大的回声,影响正常使用。所以,这节课我们来重点解决这个问题。 …...
软件测试|Python中的变量与关键字详解
简介 在Python编程中,变量和关键字是非常重要的概念。它们是构建和控制程序的基本要素。本文将深入介绍Python中的变量和关键字,包括它们的定义、使用方法以及一些常见注意事项。 变量 变量的定义 变量是用于存储数据值的名称。在Python中࿰…...
修改安卓apk设置为安卓主屏幕(launcher)
修改安卓apk 将apk可以设置安卓主屏幕 原理: 将打包好的apk文件进行拆包增加配置文件在重新编译回apk包 需要得相关文件下载 解包 apktool :https://pan.baidu.com/s/1oyCIYak_MHDJCvDbHj_qEA?pwd5j2xdex2jar:https://pan.baidu.com/s/1Nc-0vppVd0G…...
unity中 canvas下物体的朝向跟随
public Transform target; private Vector3 direction; void Update() { //第一种 //direction target.position - transform.position; //transform.up -direction.normalized; //第二种 if (target ! null ) { …...
HarmonOS 日期选择组件(DatePicker)
本文 我们一起来看基础组件中的 DatePicker 这就是 日程开发中的日期组件 他可以创建一个日期的范围 并创建一个日期的滑动选择器 这里 我们先写一个组件的骨架 Entry Component struct Index {build() {Row() {Column() {}.width(100%)}.height(100%)} }然后 我们先在Column组…...
linux中的系统安全
一.账号安全 将非登录用户的shell设为/sbin/nologin 系统中用户有三种:超级管理员 普通用户 程序用户 前两种用户可以登录系统,程序用户不给登录 所以称为非登录用户 命令格式: usermod -s /sbin/nologin(改已有用户&#…...
LeetCode(209)长度最小的子数组⭐⭐
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。 示例: 输入:s 7, nums [2,3,1,2,4,3]输出:2…...
【JAVA】MySQL中datetime类型23:59:59自动变为下一天的00:00:00
如:2024-08-11 23:59:59 变成了 2024-08-12 00:00:00。 解析:数据库入库的时候会有500毫秒的进位,然而程序在赋值时间给变量的时候很大概率会超过500ms,有时是999ms。 解决方案 // DateUtil Hutool官网 将生成的时间往前偏移99…...
Unity游戏内相机(主角头部视角)的旋转问题:“万向节锁定”(Gimbal Lock)
前言: 在Unity中,相机的正前方是Z正半轴,相机的正右方是X正半轴,相机的正上方是Y正半轴。这个很好理解。 现在,我想要相机看向左前上方45,你会觉得要怎么做呢? 如果是我的话,我的第一…...
Keras实现seq2seq
概述 Seq2Seq是一种深度学习模型,主要用于处理序列到序列的转换问题,如机器翻译、对话生成等。该模型主要由两个循环神经网络(RNN)组成,一个是编码器(Encoder),另一个是解码器…...
1080p 1k 2k 4k 8k 分辨率,2K就不应该存在。
众所周知 1K(1080P):分辨率为19201080像素,2K:分辨率为25601440像素4K:分辨率为38402160像素8K:分辨率为76804320像素 边长比例,和像素比例如下: 2K宽高都是1k的1.333…...
接口芯片选型分析 四通道差分驱动可满足ANSI TIA/EIA-422-B 和ITU V.11 的要求 低功耗,高速率,高ESD
四通道差分驱动可满足ANSI TIA/EIA-422-B 和ITU V.11 的要求 低功耗,高速率,高ESD。 其中GC26L31S可替代AM26LS31/TI,GC26L32S替代AM26LS32/TI,GC26E31S替代TI的AM26LV31E...
使用.Net nanoFramework获取ESP32板载按键的点击事件
本文以 ESP32-S3-Zero 板载的按键为例,介绍了GPIO的使用方法,以及如何获取按键的点击事件。板载按钮作为自带的天然用户按钮,除了其本身的功能外,也可以作为某些应用场景下的简单的交互方式。 1. 引言 对于一般的产品来说&#x…...
安全远控如何设置?揭秘ToDesk、TeamViewer 、向日葵安全远程防御大招
写在前面一、远程控制:安全性不可忽略二、远控软件安全设置实测 ◉ ToDesk◉ TeamViewer◉ 向日葵 三、远控安全的亮点功能四、个人总结与建议 写在前面 说到远程办公,相信大家都不陌生。远程工作是员工在家中或者其他非办公场所上班的一种工作模式&am…...
Spring AOP(详解)
目录 1.AOP概述 2.AOP相关术语 3.Spring AOP的原理机制 3.1JDK动态代理 3.2 CGLIB动态代理 3.3简单代码展示 3.3.1JDK动态代理 3.3.2CGLIB动态代理 4.Spring的AOP配置 4.1pom.xml 4.2增强方法 4.3切点 4.4切面 5.基于注解的AOP配置 5.1.创建工程 5.2.增强 5.3AOP…...
Linux系统编程之进程
目录 1、进程关键概念 1.什么是程序,什么是进程,有什么区别 2.如何查看系统中有那些进程 3.什么是进程标识符 4.什么叫父进程,什么叫子进程 5.C语言的存储空间是如何分配的 2、进程创建 1.fork函数创建进程 2.vfork函数创建进程 3、…...
Vue中使用require.context自动引入组件的方法介绍
我们项目开发中,经常需要import或者export各种模块,那么有没有什么办法可以简化这种引入或者导出操作呢?答案是肯定的,下面就为大家介绍一下require.context require.context 是 webpack 提供的一个 API,用于创建 con…...
Java 监控诊断利器 Arthas monitor/watch/trace 命令使用详解
目录 一、命令介绍二、测试Demo三、命令使用示例3.1、monitor 命令3.1.1、监控primeFactors方法调用情况(5秒一个周期,每过5秒将这5秒统计的信息输出)3.1.2、监控primeFactors方法调用情况(5秒一个周期,每过5秒将这5秒…...
论文阅读:基于MCMC的能量模型最大似然学习剖析
On the Anatomy of MCMC-Based Maximum Likelihood Learning of Energy-Based Models 相关代码:点击 本文只介绍关于MCMC训练的部分,由此可知,MCMC常常被用于训练EBM。最后一张图源于Implicit Generation and Modeling with Energy-Based Mod…...
【Verilog】期末复习——设计一个带异步复位端且高电平有效的32分频电路
系列文章 数值(整数,实数,字符串)与数据类型(wire、reg、mem、parameter) 运算符 数据流建模 行为级建模 结构化建模 组合电路的设计和时序电路的设计 有限状态机的定义和分类 期末复习——数字逻辑电路分…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
高考志愿填报管理系统---开发介绍
高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发,采用现代化的Web技术,为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## 📋 系统概述 ### 🎯 系统定…...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...
Xcode 16.2 版本 pod init 报错
Xcode 版本升级到 16.2 后,项目执行 pod init 报错; ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchron…...
深度学习学习率优化方法——pytorch中各类warm up策略
warm-up具体原理以及为什么这么做在之前的博客有介绍,这里直接介绍如何直接使用pytorch中的warm-up策略,在pytorch中对于warm-up所有支持的方法都有描述,可以直接阅读1。 深度学习中各类学习率优化方法(AdaGrad/RMSprop/Adam/Warm-UP)原理及其…...
IDEA中微服务指定端口启动
在使用IDEA开发SpringBoot微服务时,经常需要开启多个服务实例以测试负载均衡,以下几种方法开启不同端口。 直接在配置文件中指定 # application.propertiesserver.port8001指定VM参数 点击Modify options,选择Add VM options,值…...
