自适应回声抵消

2023-11-07 16:59
文章标签 适应 回声 抵消

本文主要是介绍自适应回声抵消,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 一、原理
    • 1、概述
    • 2、结构框图
    • 3、自适应算法
      • 3.1 LMS算法
        • 3.1.1 维纳滤波算法
        • 3.1.2 最陡梯度下降法
        • 3.1.3 LMS算法
      • 3.2 NLMS算法
  • 二、仿真
    • 1、仿真流程
    • 2、代码
    • 3、仿真结果
  • 参考

一、原理

1、概述

在密闭空间里与外界通信时,来自于对方的信号称之为远端信号,自己向对方表达的信号称之为近端信号。远端信号通过喇叭转变成声音信号,在密闭空间里多次反射后,会被麦克接收,与近端信号叠加在一起,传向对方。对方在听到近端信号的语音之外,也能听到自己的声音,即回声。
图1 自适应回声抵消示意图声学回声是指扬声器播出的声音在接受者听到的同时,也通过多种路径被麦克风拾取到。多路径反射的结果产生了不同延时的回声,包括直接回声和间接回声:
(1)直接回声:是指由扬声器播出的声音未经任何反射直接进入麦克风。这种回声的延时最短,它同远端说话者的语音能量,扬声器与麦克风之间的距离、角度 ,扬声器的播放音量,麦克风的拾取灵敏度等因素直接相关;
(2)间接回声:是指由扬声器播出的声音经过不同的路径(如房屋或房屋内的任何物体)的一次或多次反射后进入麦克风所产生的回声的集合。房屋内的任何物体的任何变动都会改变回声的通道。因此,这种回声的特点是多路径的、时变的。

自适应回声抵消(AEC,Adaptive Echo Cancellation) 的基本思想是估计回声路径的特征参数,产生一个模拟的回声路径,得出模拟回声信号,从接收信号中减去该信号,实现回声抵消。其关键就是得到回声路径的冲击响应h(n),由于回声路径通常是未知的和时变的,所以一般采用自适应滤波器来模拟回声路径。自适应回声抵消的显著特点是实时跟踪,实时性强。

2、结构框图

图2 自适应回声抵消结构框图

变量计算定义
x ( n ) x(n) x(n)远端信号
s ( n ) s(n) s(n)近端信号
y ( n ) y(n) y(n) y ( n ) = x ( n ) ∗ h ( n ) y(n)=x(n)*h(n) y(n)=x(n)h(n)回声信号
y ^ ( n ) \hat y(n) y^(n) y ^ ( n ) = x ( n ) ∗ h ^ ( n ) \hat y(n)=x(n)*\hat h(n) y^(n)=x(n)h^(n)模拟回声信号
d ( n ) d(n) d(n) d ( n ) = s ( n ) + y ( n ) d(n)=s(n)+y(n) d(n)=s(n)+y(n)参考信号
e ( n ) e(n) e(n) e ( n ) = d ( n ) − y ^ ( n ) e(n)=d(n)-\hat y(n) e(n)=d(n)y^(n)误差信号
H ( z ) \mathbf H(z) H(z)回声路径
H ^ ( z ) \mathbf {\hat H}(z) H^(z)模拟回声路径

自适应回声抵消就是通过自适应算法估计回声路径 H ( z ) \mathbf H(z) H(z)的特征参数,产生一个模拟的回声路径 H ^ ( z ) \mathbf {\hat H}(z) H^(z),得出模拟回声信号 y ^ ( n ) \hat y(n) y^(n),从参考信号 d ( n ) d(n) d(n)中减去该信号,实现回声抵消。

3、自适应算法

在自适应过程中,自适应算法根据误差信号 e ( n ) e(n) e(n),利用某种最优准则不断地调整滤波器抽头系数 h ^ \mathbf {\hat h} h^,最终使得滤波器的输出信号 y ^ ( n ) \hat y(n) y^(n)无限接近 y ( n ) y(n) y(n),抽头系数 h ^ \mathbf {\hat h} h^收敛于 h \mathbf h h

最有代表性的自适应算法有最小均方(LMS,Least Mean Square)算法、递归最小二乘(Recursive Least Square)算法。LMS算法因其结构简单、计算复杂度低和在平稳信号中具有良好的收敛性,成为应用最广泛的自适应算法。

3.1 LMS算法

3.1.1 维纳滤波算法

根据最小均方误差准则,该准则要求滤波器输出与期望信号之差的均方值最小,将目标函数(性能函数)定义为:
ε ( n ) = E [ ∣ e ( n ) ∣ 2 ] = E [ ∣ d ( n ) − h ^ T ( n ) x ( n ) ∣ 2 ] = E [ d 2 ( n ) ] − 2 R d x T h ^ ( n ) + h ^ T ( n ) R x h ^ ( n ) \begin{align} \varepsilon(n) & = E[|e(n)|^2]\\ & = E[|d(n)-\hat h^T(n)x(n)|^2]\\ & =E[d^2(n)]-2R_{dx}^T\hat h(n)+\hat h^T(n)R_x\hat h(n)\\ \end{align} ε(n)=E[e(n)2]=E[d(n)h^T(n)x(n)2]=E[d2(n)]2RdxTh^(n)+h^T(n)Rxh^(n)其中, R x = E [ x ( n ) x T ( n ) ] R_x=E[x(n)x^T(n)] Rx=E[x(n)xT(n)]为输入信号的自相关函数, R d x = E [ d ( n ) x T ( n ) ] R_{dx}=E[d(n)x^T(n)] Rdx=E[d(n)xT(n)]为输入信号和参考信号的互相关函数。

为了选择最优权系数 h ^ \hat h h^,使性能函数 ε ( n ) \varepsilon(n) ε(n)最小,一些常用的自适应算法都是基于梯度法的,用 ∇ \nabla 表示性能函数的梯度向量,式 ( 3 ) (3) (3) h ^ \hat h h^求导得:
∇ = ∂ ε ( n ) ∂ h ^ = 2 R x h ^ − 2 R d x (4) \nabla=\frac{\partial\varepsilon(n)}{\partial\hat h}=2R_x\hat h-2R_{dx}\tag4 =h^ε(n)=2Rxh^2Rdx(4)令上式等于0,得到最优权矢量:
h ^ 0 = R x − 1 R d x (5) \hat h^0=R_x^{-1}R_{dx}\tag5 h^0=Rx1Rdx(5)所得到的滤波器最优权矢量也即为维纳最优解,当自适应滤波器的权系数满足上式时,均方误差达到最小值。

3.1.2 最陡梯度下降法

要求得维纳最优解,需要求相关矩阵并计算相关矩阵的逆,这在实际应用中限制较多。最陡梯度下降法由于不需要对相关矩阵求逆,收敛速度较快,被广泛应用到实际工程当中。其算法可以表示为:
h ^ ( n + 1 ) = h ^ ( n ) + 1 2 μ ( − ∇ ) (6) \hat h(n+1)=\hat h(n)+\frac{1}{2}\mu(-\nabla)\tag6 h^(n+1)=h^(n)+21μ()(6)其中 μ \mu μ是调整步长的参数,它控制着系统的稳定性和算法的收敛速度,把式 ( 4 ) (4) (4)代入 ( 6 ) (6) (6)式,得到最陡梯度下降法的递推公式:
h ^ ( n + 1 ) = h ^ ( n ) + μ ( R d x − R x h ^ ) (7) \hat h(n+1)=\hat h(n)+\mu(R_{dx}-R_x\hat h)\tag7 h^(n+1)=h^(n)+μ(RdxRxh^)(7)用上面的递推公式能够让滤波器的权系数收敛到它的最佳状态,即维纳最优解。但是,每次迭代都需要求出其梯度矢量的准确值,要求输入信号和期望信号是随机平稳过程,这给具体实现带来了很大的困难。

3.1.3 LMS算法

LMS算法采用一种用梯度的估计值代替梯度的精确值的方法,具体实现是采用瞬时误差的平方来代替均方误差,则式 ( 4 ) (4) (4)的梯度估计值表达式为:
∇ ^ = ∂ [ e 2 ( n ) ] ∂ h ^ = − 2 e ( n ) x ( n ) (8) \hat\nabla=\frac{\partial[e^2(n)]}{\partial\hat h}=-2e(n)x(n)\tag8 ^=h^[e2(n)]=2e(n)x(n)(8)由式 ( 6 ) (6) (6)和式 ( 8 ) (8) (8)可以得到LMS算法的递推公式:
h ^ ( n + 1 ) = h ^ ( n ) + μ e ( n ) x ( n ) (9) \hat h(n+1)=\hat h(n)+\mu e(n)x(n)\tag9 h^(n+1)=h^(n)+μe(n)x(n)(9)式中, μ \mu μ为固定步长因子, μ \mu μ的大小很大程度上决定了算法的收敛与稳态性能。 μ \mu μ越大,算法收敛越快,但稳态误差也越大; μ \mu μ越小,算法收敛越慢,但稳态误差也越小。为保证算法稳态收敛,应使 μ \mu μ在以下范围取值:
0 < μ < 2 x T ( n ) x ( n ) (10) 0<\mu<\frac{2}{x^T(n)x(n)}\tag{10} 0<μ<xT(n)x(n)2(10)LMS算法的具体实现步骤如下:
1 ) 1) 1) 假设起始时刻 n = 0 n=0 n=0,自适应滤波器权矢量的初始值 h ^ ( 0 ) \hat h(0) h^(0)为任意值(一般设置为 0 0 0);
2 ) 2) 2) 计算误差信号 e ( n ) e(n) e(n)
3 ) 3) 3) 利用权矢量递推公式 h ^ ( n + 1 ) = h ^ ( n ) + μ e ( n ) x ( n ) \hat h(n+1)=\hat h(n)+\mu e(n)x(n) h^(n+1)=h^(n)+μe(n)x(n),更新权矢量;
4 ) 4) 4) 重复步骤 2 ) 2) 2) 3 ) 3) 3),直至达到平稳状态。

3.2 NLMS算法

LMS算法在自适应滤波中流行的主要原因是其计算简单,比其他常用的自适应算法更易于实现。但是总体而言,LMS算法复杂度低,它的收敛速度还是慢。而且是固定步长,这就需要在开始自适应滤波操作之前了解输入信号的统计信息。实际上,这是很难实现的。即使我们假设自适应回声抵消系统的唯一输入信号是语音,但仍有许多因素如信号输入功率和振幅会影响其性能,为改善LMS这个不足之处,科研人员提出一系列改进算法,NLMS算法就是其中一种。

NLMS算法是LMS算法的一个扩展,利用可变的步长因子代替固定的步长因子,就得到了NLMS算法,它通过计算最大步长值绕过了LMS固定步长的问题。
μ ( n ) = α x T ( n ) x ( n ) (11) \mu(n)=\frac{\alpha}{x^T(n)x(n)}\tag{11} μ(n)=xT(n)x(n)α(11)为了使算法收敛 α \alpha α应该满足:
0 < α < 2 (12) 0<\alpha<2\tag{12} 0<α<2(12)实际中,为了避免输入信号 x ( n ) x(n) x(n)的内积过小而使步长过大,进一步修改式 ( 12 ) (12) (12)为:
μ ( n ) = α c + x T ( n ) x ( n ) (13) \mu(n)=\frac{\alpha}{c+x^T(n)x(n)}\tag{13} μ(n)=c+xT(n)x(n)α(13)其中 c c c为一个很小的正常数。

NLMS算法的递推公式为:
h ^ ( n + 1 ) = h ^ ( n ) + α c + x T ( n ) x ( n ) e ( n ) x ( n ) (14) \hat h(n+1)=\hat h(n)+\frac{\alpha}{c+x^T(n)x(n)}e(n)x(n)\tag{14} h^(n+1)=h^(n)+c+xT(n)x(n)αe(n)x(n)(14)

二、仿真

1、仿真流程

仿真流程图

2、代码

修改自: https://github.com/kamejosh/Acoustic-Echo-Canceller/blob/master/nlms_finished.m.

clc;
clear all;
close all;
%% 回声路径% 频率
fs=8000;
M=fs/2 + 1;% 产生冲激响应
[B,A]=cheby2(4,20,[0.1 0.7]);
impulseResponseGenerator=dsp.IIRFilter('Numerator',[zeros(1,6) B],'Denominator',A);% 产生房间的冲激响应,即回声路径h(n)
roomImpulseResponse=impulseResponseGenerator((log(0.99*rand(1,M)+0.01).*sign(randn(1,M)).*exp(-0.002*(1:M)))');
roomImpulseResponse=roomImpulseResponse/norm(roomImpulseResponse)*4;
room=dsp.FIRFilter('Numerator',roomImpulseResponse');%% 近端语音信号% 读入近端语音信号s(n)
[v,Fs1]=audioread('D:\audio\nearspeech.wav');
near=v';%% 远端语音信号% 读入远端语音信号x(n)
[x,Fs2]=audioread('D:\audio\farspeech.wav');
far=x';%% 回声信号farEcho=room(far); % 间接回声x(n)*h(n)
farEcho=farEcho*0.2+far; % 回声信号=直接回声+间接回声% y(n)=x(n)+x(n)*h(n)%% 参考信号micSignal=farEcho+near; % d(n)=y(n)+s(n)
N=length(micSignal);%% LMS% 初始化
ANNCx1=zeros(1,N); % 自适应滤波器的状态
ANNCw1=zeros(1,M); % 自适应滤波器的权系数
e_cont1=zeros(1,N); % 误差信号
mu1=0.05; % 固定步长% 开始迭代
for epoch=1:NANNCx1=[far(epoch) ANNCx1(1:(M-1))]; % 更新滤波器输入ANNCy1=sum(ANNCx1.*ANNCw1); % 滤波器输出e_cont1(epoch)=micSignal(epoch)-ANNCy1; % 计算误差信号ANNCw1=ANNCw1+mu1*e_cont1(epoch)*ANNCx1; % 权系数递推公式 
end   %% NLMS% 初始化
alfa=0.004; % 避免步长过大 
c=0.04; % 避免输入信号内积过小
ANNCx2=zeros(1,N);
ANNCw2=zeros(1,M);
e_cont2=zeros(1,N);% 开始迭代
for epoch=1:Nmu2=alfa/(c+(far(epoch)'*far(epoch))); % 变步长ANNCx2=[far(epoch) ANNCx2(1:(M-1))];ANNCy2=sum(ANNCx2.*ANNCw2);e_cont2(epoch)=micSignal(epoch)-ANNCy2;ANNCw2=ANNCw2+mu2*e_cont2(epoch)*ANNCx2;
end%% 画图figure(1);
subplot(2,1,1);
plot(near);
xlabel('采样点');
ylabel('幅度');
xlim([1 N]);
ylim([-1 1]);
title('近端信号');
subplot(2,1,2);
plot(far);
xlabel('采样点');
ylabel('幅度');
xlim([1 N]);
ylim([-1 1]);
title('远端信号');
figure(2);
subplot(2,1,1);
plot(farEcho);
xlabel('采样点');
ylabel('幅度');
xlim([1 N]);
ylim([-1 1]);
title('回声信号');
subplot(2,1,2);
plot(micSignal);
xlabel('采样点');
ylabel('幅度');
xlim([1 N]);
ylim([-1 1]);
title('参考信号');
figure(3);
subplot(2,1,1);
plot(e_cont1);
xlabel('采样点');
ylabel('幅度');
xlim([1 N]);
ylim([-1 1]);
title('LMS误差信号');
subplot(2,1,2);
plot(e_cont2);
xlabel('采样点');
ylabel('幅度');
xlim([1 N]);
ylim([-1 1]);
title('NLMS误差信号');

3、仿真结果

近端语音信号和远端语音信号时域波形图。
近端信号和远端信号时域波形图回声信号和参考信号时域波形图。
回声信号和参考信号时域波形图LMS和NLMS算法输出的误差信号时域波形图。
在这里插入图片描述

参考

https://www.cnblogs.com/LXP-Never/p/11703440.html.


如有问题,恳请指正。

这篇关于自适应回声抵消的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/365023

相关文章

240907-Gradio插入Mermaid流程图并自适应浏览器高度

A. 最终效果 B. 示例代码 import gradio as grmermaid_code = """<iframe srcdoc='<!DOCTYPE html><html><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width" /><title>My static Spa

安卓实现弹出软键盘屏幕自适应调整

今天,我通过尝试诸多方法,最终实现了软键盘弹出屏幕的自适应。      其实,一开始我想通过EditText的事件来实现,后来发现,安卓自带的函数十分强大,只需几行代码,便可实现。实现如下:     在Manifest中设置activity的属性:android:windowSoftInputMode="adjustUnspecified|stateHidden|adjustResi

UGUI 背景自适应文本框

需求 UGUI背景自适应文本框UGUI背景图片随文本框长度变化 解决方案 仅文本框宽度自适应 背景节点配置: 背景节点下的Text子节点配置: 文本框宽高自适应 将Vertical Fit设置为Preferred Size 将Child Controls Size Height选项勾上

Openharmony 图片自适应全屏显示

前言: Deveco_studio 4.1 release 版本 我们想要图片全屏显示,并且不出现黑白边,可以参考以下代码 这段代码会自适应你的容器大小,你的容器时全屏,图片就会全屏 @Entry@Componentstruct Index {@State message: string = 'Hello World';build() {Column() {}.width('100%'

Cocos2d-x自适应Android屏幕分辨

ndroid下分辨率太多,不太可能为每种分辨率做一套资源,目前一般来说比较流行的是320*480, 800*400, 854*400。当然现在720P的也出来了,但至少目前不是主流机型^_^. 对于不支持的分辨率,我希望的是能够按照屏幕大小按比例缩放,即有了下面的代码。 1:ViewAutoScale 写了一个ViewAutoScale函数,如下:   #include "ViewAuto

【TPAMI 2024】单源领域自适应不可行,要做就做多源领域的,这样才酷!

Graphical Modeling for Multi-Source Domain Adaptation 题目:多源领域适应的图形建模 作者:Minghao Xu; Hang Wang; Bingbing Ni 摘要 多源领域自适应(MSDA)专注于将来自多个源领域的知识转移到目标领域,与常规的单源领域自适应相比,这是一个更实际且具有挑战性的问题。在这个问题中,对多个源领域和目标领域

等保2.0升级:企业如何快速适应新标准

随着《网络安全法》的实施以及网络空间安全形势的不断升级,我国的信息安全等级保护制度也在持续完善。等保2.0的出台,标志着我国信息安全等级保护体系进入了一个新的阶段。面对等保2.0的升级,企业应如何快速适应新标准,确保自身信息安全体系与国家政策的同步升级?本文将从理解新标准、评估现状、制定计划、执行与优化四个方面,探讨企业应对等保2.0升级的有效策略。 一、深入理解等保2.0新标准 等保2.0相

AS3.0 满屏幕自适应方法

AS3.0 满屏幕自适应方法   (2009-08-12 16:36:42) 转载▼ 标签:  it 分类: Actionscript3.0 网上AS3.0自适应网页的列子不多,所以自己做一个 html方面 使用发布以后在body中的<param>标签和<embed>标签的width和height属性都改为100%,<script>标签中的width和heigh

css 识别屏幕大小自适应

两种方法 (1)原生自适应  @media screen 表示当屏幕大于320px,并小于1156px是执行下面的css @media screen and (min-width: 320px) and (max-width: 1156px){.site-bg-dl {position: fixed;height: 100%;width: 100%;z-index: 0;backgrou

PointNet++改进策略 :模块改进 | PAConv,位置自适应卷积提升精度

题目:PAConv: Position Adaptive Convolution with Dynamic Kernel Assembling on Point Clouds来源:CVPR2021机构:香港大学论文:https://arxiv.org/abs/2103.14635代码:https://github.com/CVMI-Lab/PAConv 前言 PAConv,全称为位置自适应卷积