回声消除NLMS算法详解

        在视频或电话会议中,本地用户的声音在被本地麦克风采集后,通过系统传到远端,通过远端的扬声器播放,此时远端麦克风不可避免地会采集到扬声器播放的声音,又通过系统传回本地,并通过本地扬声器播放出来,本地用户就通过本地扬声器听到了自己的声音,这明显降低了会议通信质量。

        为了提高语音的质量,就必须进行回声消除。当参考信号已知时,归一化最小均方(Normalized Least Mean Square,NLMS)算法能很好消除回声,它由最小均方算法扩展而来。

1 NLMS算法原理

        回声消除系统基本结构如图1所示。

                        

                                                 图1  回声消除系统基本结构

        设置自适应滤波器系数w的所有初始值为0,即w(0) = 0,其长度为M。对输入信号进行采样,每次迭代取M个数据进行处理,输入矢量为

                        x(n) = [x1(n) x2(n) … xM(n)]T = [x(n)x(n-1) … x(n-M+1)]T

        加权矢量为

                        w = [w1 w2… w3]

        系统输出y(n)为

                        y(n) = wx(n)

        y(n)相对于期望信号d(n)的误差为

                        e(n) = d(n) – y(n) = d(n) -wx(n)

        运用最小均方误差准则,就是求使得E[|e(n)|^2]最小时的w,因为是通过对其求导并令其等于0求得的,而|e(n)|在最小点不可导,所以使用的是|e(n)|^2。对于LMS算法,其滤波器系数迭代公式为

                        w(n+1) = w(n) + 2µe(n)x(n)

其中µ是步长因子,0 < µ < 1/ xT(n)x(n),在LMS算法中其值是固定的,因而收敛速度较慢。

        在LMS的基础上,用可变的步长因子代替固定的步长因子,就得到了NLMS算法,其迭代方程为

                        w(n+1) = w(n) + µ(n)e(n)x(n)=w(n) +ηe(n)x(n)/(δ+xT(n)x(n))

 

其中η是修正的步长常量,0 < η < 2,δ为一个较小的整数,一般取0.0001,防止输入数据矢量x(n)的内积过小使得µ(n)过大而引起稳定性能下降。NLMS算法的收敛速度较快,效果较LMS算法好。

2 性能仿真

        用matlab编写程序仿真算法性能,分别对比NLMS算法与LMS算法的性能和不同步长参数η下NLMS算法的性能。代码如下:

 
 
clear all;
close all;
clc;
snr= 20;
order= 8;
Hn =[ 0.8783 - 0.5806 0.6537 - 0.3223 0.6577 - 0.0582 0.2895 - 0.2710 0.1278 - 0.1508 0.0238 - 0.1814 0.2519 - 0.0396 0.0423 - 0.0152 0.1664 - 0.0245 0.1463 - 0.0770 0.1304 - 0.0148 0.0054 - 0.0381 0.0374 - 0.0329 0.0313 - 0.0253 0.0552 - 0.0369 0.0479 - 0.0073 0.0305 - 0.0138 0.0152 - 0.0012 0.0154 - 0.0092 0.0177 - 0.0161 0.0070 - 0.0042 0.0051 - 0.0131 0.0059 - 0.0041 0.0077 - 0.0034 0.0074 - 0.0014 0.0025 - 0.0056 0.0028 - 0.0005 0.0033 - 0.0000 0.0022 - 0.0032 0.0012 - 0.0020 0.0017 - 0.0022 0.0004 - 0.0011 0 0 ];
Hn=Hn( 1:order);
N= 1000;
EE= zeros(N, 1); Loop= 150; mu= 0.5;
EE1= zeros(N, 1);EE2= zeros(N, 1);EE3= zeros(N, 1);
for nn= 1:Loop
r= sign( rand(N, 1)- 0.5);
output=conv(r,Hn);
output=awgn(output,snr, 'measured');
win= zeros( 1,order);
win1= zeros( 1,order);
win2= zeros( 1,order);
win3= zeros( 1,order);
error= zeros( 1,N)';
error1= zeros( 1,N)';
error2= zeros( 1,N)';
error3= zeros( 1,N)';
 
for i=order:N
input=r( i:- 1: i-order+ 1);
y( i)=win*input;
e=output( i)-win*input;
e1=output( i)-win1*input;
e2=output( i)-win2*input;
e3=output( i)-win3*input;
fai= 0.0001;
if i< 200
mu= 0.32;
else
mu= 0.15;
end
win=win+ 0.3*e*input'/(fai+input'*input); % 不同步长的NLMS
win1=win1+ 0.8*e1*input'/(fai+input'*input);
win2=win2+ 1.3*e2*input'/(fai+input'*input);
win3=win3+ 1.8*e3*input'/(fai+input'*input);
error( i)=error( i)+e^ 2;
error1( i)=error1( i)+e1^ 2;
error2( i)=error2( i)+e2^ 2;
error3( i)=error3( i)+e3^ 2;
% y1(i)=win1*input;
% e1=output(i)-win1*input;
% win1=win1+0.2*e1*input'; % LMS
% error1(i)=error1(i)+e1^2;
end
EE=EE+error;
EE1=EE1+error1;
EE2=EE2+error2;
EE3=EE3+error3;
end
error=EE/Loop;
error1=EE1/Loop;
error2=EE2/Loop;
error3=EE3/Loop;
 
% figure;
% error=10*log10(error(order:N));
% error1=10*log10(error1(order:N));
% plot(error,'r');
% hold on;
% plot(error1,'b.');
% axis tight;
% legend('NLMS算法','LMS算法');
% title('NLMS算法和LMS算法误差曲线');
% xlabel('样本');
% ylabel('误差/dB');
% grid on;
%
% figure;
% plot(win,'r');
% hold on;
% plot(Hn,'b');
% grid on;
% axis tight;
% figure;
% subplot(2,1,1);
% plot(y,'r');
% subplot(2,1,2);
% plot(y1,'b');
figure;
error= 10* log10(error(order:N));
error1= 10* log10(error1(order:N));
error2= 10* log10(error2(order:N));
error3= 10* log10(error3(order:N));
hold on;
plot(error, 'r');
hold on;
plot(error1, 'b');
hold on;
plot(error2, 'y');
hold on;
plot(error3, 'g');
axis tight;
legend( 'η = 0.3', 'η = 0.8', 'η = 1.3', 'η = 1.8');
title( '不同步长对NLMS算法的影响');
xlabel( '样本');
ylabel( '误差/dB');
grid on;

 来自CODE的代码片

NLMS算法性能仿真.m

 

        输入信号为加了高斯噪声后的随机信号,首先我们对比一下NLMS算法和LMS算法的性能差异,取η = 1,δ = 0.001,µ = 0.2,得到两种算法的误差曲线如图2所示

                        

                                                    图2  NLMS算法和LMS算法误差曲线

        图2中下降曲线的斜率反映了算法的收敛速度,稳定后的误差反映了算法的精度。由图可知,NLMS算法的收敛速度快于LMS算法,且NLMS算法精度也大于LMS算法。

        然后分析步长大小对算法性能的影响。以NLMS算法为基础,分别分析当η= 0.3,η = 0.9,η = 1.3,η = 1.8(0< η < 2)时算法的收敛特性,得到误差曲线如图3所示。

                          

                                                    图3 不同步长对NLMS算法的影响
        由图3可看出,随着步长的增大,算法收敛速度先有所提高,之后又下降,而算法精度却逐渐减小。

        由以上两组仿真实验可以看出,算法自适应收敛时收敛速度和精度是一对矛盾,步长大,即收敛系数大,收敛速度可能有所改善,但精度却变差,反之亦然。

        由于LMS算法中步长是不变的,所以很难找到一个适当的步长来解决这一矛盾;而NLMS算法则采用变步长的方式在保证精度的情况下缩短自适应收敛过程。实际应用中要不断调整步长,以得到算法的最优性能。

3 算法效果

        分别采用NLMS算法和LMS算法来处理混响语音信号。此时输入信号是一段混响9秒的语音信号,参考信号是无混响的语音信号。为了有较快的收敛速度和精度,在NLMS迭代开始时设置步长η为0.32使算法较快收敛,之后设置步长η为0.15以得到较高精度。在LMS迭代中设置步长µ=0.1。代码如下:

       

 
 
clear all
close all
clc
 
hold off
sysorder= 50; %抽头数
[inp,sr]=mp3read( 'T60=9.0.mp3'); %输入
inp=inp(:);
 
[d,sr] = mp3read( 'T60=0.mp3');
d=d(:);
totallength= size(d, 1); %步长
N= length(inp);
%k=0:1382493;
k= 0: 691246;
 
%算法开始
w= zeros(sysorder, 1); %初始化
w1= zeros(sysorder, 1); %初始化
error= zeros(N, 1); %初始化
EE= zeros(N, 1);
Loop= 15000;
 
for n=sysorder:N
u=inp(n:- 1:n-sysorder+ 1); %u的矩阵
%u=inp(n-sysorder+1:n);
%NLMS算法
y(n)=w'*u; %系统输出
r(n)=u'*u; %自相关矩阵
e(n)=d(n)-y(n); %误差
srr(n)= 10* log10(d(n)/(inp(n)-d(n)));
srr1(n)= 10* log10(d(n)/(y(n)-d(n)));
%e(n)=inp(n)-y(n); %误差
fai= 1e-10; %修正参数,防止r(n)过小导致步长值太大
if n< 2000
mu= 0.32;
else
mu= 0.15;
end
w= 0.8*w+mu*u*e(n)/(r(n)+fai); %NLMS迭代方程
error(n)=error(n)+e(n)^ 2;
 
%LMS算法
y1(n)=w1'*u;
e1(n)=d(n)-y1(n);
w1= 0.8*w1+ 0.1*u*e1(n); %LMS迭代方程
end
EE=EE+error;
error=EE/Loop;
error=error.^ 2;
error(n)=error'*error;
 
% for i=sysorder:N1
% u1=inp2(i:-1:i-sysorder+1);
% y_out(i)=w'*u1;
% end
%srr=10*log10(d/(inp-d));
%srr1=10*log10(d/(y-d));
 
y=y(:);
y1=y1(:);
e=e(:);
e1=e1(:);
srr=srr(:);
srr1=srr1(:);
%y_out=y_out(:);
 
inp1= reshape(inp, 691247, 2);
%inp3=reshape(inp2,342191,2);
d1= reshape(d, 691247, 2);
y_nlms= 2* reshape(y, 691247, 2);
y_lms= 2* reshape(y1, 691247, 2);
%y_out1=20*reshape(y_out,342191,2);
error= 10* log10(error);
e_nlms= reshape(e, 691247, 2);
e_lms= reshape(e1, 691247, 2);
error_nlms= reshape(error, 691247, 2);
srr2= reshape(srr, 691247, 2);
srr3= reshape(srr1, 691247, 2);
 
figure( 1);
subplot( 3, 1, 1);
plot(k,inp1);
title( '系统输出波形对比');
xlabel( '样本n');
ylabel( '混响9秒信号波形');
subplot( 3, 1, 2);
plot(k,y_nlms, 'r');
xlabel( '样本n');
ylabel( 'NLMS输出信号波形');
subplot( 3, 1, 3);
plot(k,y_lms, 'g');
axis([ 0 691246 - 1 1]);
xlabel( '样本n');
ylabel( 'LMS输出信号波形');
 
sound(d1,sr);
sound(inp1,sr);
sound(y_nlms,sr);
mp3write(y_nlms,sr, 'nlms.mp3');
sound(y_lms,sr);
mp3write(y_lms,sr, 'lms.mp3');

 来自CODE的代码片

回声消除算法效果.m

 

        其处理后波形图如图4所示。

                        

                                                      图4 NLMS算法和LMS算法去混响

        由图4可看出,NLMS算法和LMS算法均成功的去掉了混响,实际听音表明NLMS算法得到的语音很清晰,LMS算法得到语音则有些失真。

转自:http://blog.csdn.net/yjjat1989/article/details/21614269

你可能感兴趣的:(声音信号处理)