音频算法speex中的aec分析以及解析
算法原理:
Speex的AEC是以NLMS(Normalized Least Mean Square)为基础,用MDF(multidelay block frequency domain)频域实现,最终推导出最优步长估计:残余回声与误差之比。最优步长等于残余回声方差与误差信号方差之比。 只有改与泄露系数相关部分的代码,才是对效果影响最大的地方,因为根据泄露系数,最终会估计出滤波器的最优步长。
使用实例:
测试代码:
#include "speex/speex_echo.h"
#include "speex/speex_preprocess.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> #define NN 128
#define TAIL 1024 int 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 = ; if (argc != )
{
fprintf(stderr, "testecho mic_signal.sw speaker_signal.sw output.sw\n");
exit();
}
echo_fd = fopen(argv[], "rb");
ref_fd = fopen(argv[], "rb");
e_fd = fopen(argv[], "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);
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 ;
}
命令: ./testecho speaker1.wav micin1.wav out1.wav
测试结果:
最新的speex的aec效果非常的好,超出了我的想象,回声消除效果不是一般的好,看来是speex更新了不少,因为自从2007年之后,speex很长一段时间都没有更新过代码。有兴趣的同学可以听一下消回声后的和之前的音频对比。
代码解析:
初始化中,第一个参数是每次处理的帧长度,这个一般是从10ms(80) 到30ms(240) 的处理长度,太长和太短都不是很好,filter_length 也是一个长度,它实际上就是speaker到rec之间的时间差。这个在不同设备上是不同的,跟产品的使用场景,结构,以及软件耗时有关系,一般的是可以测试出来的。
SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length)
系统默认的消回声采样是8k的,如下所示,假如你想改变采样频率,
/* This is the default sampling rate */
427 st->sampling_rate = 8000;
428 st->spec_average = DIV32_16(SHL32(EXTEND32(st->frame_size), 15), st->sampling_rate);
要使用下面的函数:speex_preprocess_state_init(NN,sampleRate)
接下来是要配置消回声的参数设置,一般是采样率设置。
speex_echo_ctl(st, SPEEX_ECHO_SET_SAMPLING_RATE, &sampleRate);
参数都可以以下这些:
46 /** Obtain frame size used by the AEC */
47 #define SPEEX_ECHO_GET_FRAME_SIZE 3
48
49 /** Set sampling rate */
50 #define SPEEX_ECHO_SET_SAMPLING_RATE 24
51 /** Get sampling rate */
52 #define SPEEX_ECHO_GET_SAMPLING_RATE 25
53
54 /* Can't set window sizes */
55 /** Get size of impulse response (int32) */
56 #define SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE 27
57
58 /* Can't set window content */
59 /** Get impulse response (int32[]) */
60 #define SPEEX_ECHO_GET_IMPULSE_RESPONSE 29
最重要的函数登场了:这个函数,非常的好用,估计只要看一下入参,你就知道怎么使用了。具体的使用就看上面的例子吧。
void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *in, const spx_int16_t *far_end, spx_int16_t *out)
假如在预处理中有些参数设置,需要调用预处理函数再把输出的结果处理一下,假如预处理没有了,那就不需要了。
speex_preprocess_run(den, e_buf);
其实,代码流程就这么简单,但是,想把系统效果调试的很好,还是要花不少功夫的。
注意事项:
1 AEC的线性算法处理不了Non-linear distortion(非线性失真)
2 在其它预处理前 先调用AEC
3 speex的aec并不是很适合音响系统里,音响中要慎用。耳机中效果还挺好。
4 实验用的音频数据就不放到这里了,有谁需要可以留言邮箱,我发个你。
音频算法speex中的aec分析以及解析的更多相关文章
- 音频软件开发中的debug方法和工具
本文系作者原创.如转载,请注明出处. 谢谢! 音频软件开发同其他软件开发一样,都需要去调试.音频软件调试同其他软件调试方法有相同的地方,也有不同的地方,同时调试时还需要借助一些专门的工具,有了这些方法 ...
- WebRTC 音频算法 附完整C代码
WebRTC提供一套音频处理引擎, 包含以下算法: AGC自动增益控制(Automatic Gain Control) ANS噪音抑制(Automatic Noise Suppression) AEC ...
- 音频压缩(Speex使用&Opus简介)--转
博客地址:http://blog.csdn.net/kevindgk GitHub地址:https://github.com/KevinDGK/MyAudioDemo 一简介 二局域网语音配置 三Sp ...
- OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波
http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...
- 第2章 rsync算法原理和工作流程分析
本文通过示例详细分析rsync算法原理和rsync的工作流程,是对rsync官方技术报告和官方推荐文章的解释. 以下是本文的姊妹篇: 1.rsync(一):基本命令和用法 2.rsync(二):ino ...
- Android 中图片压缩分析(上)
作者: shawnzhao,QQ音乐技术团队一员 一.前言 在 Android 中进行图片压缩是非常常见的开发场景,主要的压缩方法有两种:其一是质量压缩,其二是下采样压缩. 前者是在不改变图片尺寸的情 ...
- HanLP中人名识别分析
HanLP中人名识别分析 在看源码之前,先看几遍论文<基于角色标注的中国人名自动识别研究> 关于命名识别的一些问题,可参考下列一些issue: 名字识别的问题 #387 机构名识别错误 关 ...
- rsync算法原理和工作流程分析
本文通过示例详细分析rsync算法原理和rsync的工作流程,是对rsync官方技术报告和官方推荐文章的解释.本文不会介绍如何使用rsync命令(见rsync基本用法),而是详细解释它如何实现高效的增 ...
- HanLP中人名识别分析详解
HanLP中人名识别分析详解 在看源码之前,先看几遍论文<基于角色标注的中国人名自动识别研究> 关于命名识别的一些问题,可参考下列一些issue: l ·名字识别的问题 #387 l ·机 ...
随机推荐
- Bootstrap 固定在顶部导航条
@{ Layout = null;}<!DOCTYPE html><html><head> <meta name="viewport&q ...
- js 动态生成div显示id
<!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- datacontract helper
public static class DataContractHelper { public static void ToDCFile<T>(this T obj, string pat ...
- 同城快递公司Postmates近日完成1亿美元融资,美国外卖餐饮迎来一波融资热潮
美国外卖市场尚未出现一家独大的巨头,一部分原因是与中国的外卖平台相比,在美国,外卖平台要克服的难题可能更多. 4个月之前才完成3亿美元融资的美国同城快递公司Postmates近日又完成1亿美元融资,估 ...
- 零元学Expression Blend 4 - Chapter 36 来玩捉迷藏吧!!!看看ScrollBar的Disabled与Hidden之差异
原文:零元学Expression Blend 4 - Chapter 36 来玩捉迷藏吧!!!看看ScrollBar的Disabled与Hidden之差异 本次要针对Disabled以及Hidden作 ...
- delphi多版本安装方法
delphi tokyo和其他版本并存的安装方法 1.安装delphi 10.2 tokyo 破解后写入D:\Program Files (x86)\Embarcadero\Studio\19.0\b ...
- 开源libco库:单机千万连接、支撑微信8亿用户的后台框架基石
微信于2013年开源的ibco库,是微信后台大规模使用的c/c++协程库,2013年至今稳定运行在微信后台的数万台机器上.libco在2013年的时候作为腾讯六大开源项目首次开源,ibco支持后台敏捷 ...
- 进程交互还可以使用QSharedMemory
官方例子: http://doc.qt.io/qt-5/qtcore-ipc-sharedmemory-example.html 查了一下,QSharedMemory没有自带任何信号.我的想法: 1. ...
- 使用VS2010开发Qt程序的4点经验(QT4到QT5的升级,更改sln文件,切换工程使用的Qt库,在VS的Solution Explorer视图中建立文件夹)
导读 相比于Qt Creator,我更喜欢用VS2010来进行开发.虽然启动时间相对较慢,但是VS下强大的快捷键和丰富的插件,以及使用多年的经验,都让我觉得在开发过程中得心应手.其中最重要的一点是,有 ...
- hdu4616_Game_树形DP
以为很水的一道题,花了大半天的时间才搞定,比赛的时候卡在这题上了,伤不起啊... 题意:给一棵树,每个结点中有礼物,每个礼物有一个权值,某些结点中会有陷阱,你可以从任何一点出发,每个结点最多只能经过一 ...