自适应回声抵消

一、原理

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:N
    ANNCx1=[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:N
    mu2=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.


如有问题,恳请指正。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值