一、基于先验信噪比的维纳滤波语音降噪算法的基本概念
改进的维纳滤波器为基于先验信噪比的维纳滤波器,其原理框图下图所示。
对于第m帧带噪语音信号ym(n)=sm(n)+nm(n)
式中,sm(n)是第m帧纯净语音信号;nm(n)为第m帧噪声信号。维纳滤波器就是在最小方均误差准则(MSE)下实现对语音信号sm(n)的估计。在sm(n)与nm(n)不相关且均为平稳随机过程条件下,对上式进行离散傅里叶变换,得Y(m,k)=S(m,k)+N(m,k)
谱增益函数为
式中,ζ(m,k)(SNRpo)为先验信噪比;m为帧号;k为频点。
则第m帧增强语音可表示为
采用直接判决(Decision-Directed)法来估计先验信噪比SNRprio,即
SNRprio(m,k)=a・ SNRprio(m-1,k)+(1-a) ・max(SNRpost(m,k) -1,0)
式中,SNRpost表示后验信噪比;Y(m,k)表示估计的第m帧信号的功率谱;(m,k)表示估
计的第m帧噪声功率谱。
二、先验信噪比的维纳滤波语音增强实验
先验信噪比的维纳滤波函数Weina_Im
名称:Weina_Im
功能:基于先验信噪比的维纳滤波算法。
调用格式:
enhanced = Weina_Im(x,wind,inc,NIS,alpha)
说明:输入参数x是输入的含噪语音信号;wlen为窗函数或窗长;inc是帧移;NIS是前导无话段帧数;alpha是信噪比平滑参数。enhanced是降噪后的信号。
函数代码如下:
% 维纳滤波enhancement=Weina_Im(y_fft,framesize,framenum,length);
% MS估计噪声功率谱, D-D法估计先验概率, 不需要估计纯净信号功率
% y_fft:分帧语音的FFT变换,
% framesize:帧长
% framenum:总帧数,
% length:语音长度
% enhancement:增强后的语音
% --------------------------------------------------------------------------------------------------------------
function enhancement=Weina_Im(x,wind,inc,NIS,alpha)
Length=length(x);
nwin=length(wind); % 取窗长
if (nwin == 1) % 判断窗长是否为1,若为1,即表示没有设窗函数
framesize= wind; % 是,帧长=win
wnd=hamming(framesize); % 设置窗函数
else
framesize = nwin; % 否,帧长=窗长
wnd=wind;
end
y=enframe(x,wnd,inc)'; % 分帧
framenum=size(y,2); % 求帧数
y_fft = fft(y); % FFT
y_a = abs(y_fft); % 求取幅值
y_phase=angle(y_fft); % 求取相位角
y_fft2=y_a.^2; % 求能量
noise=mean(y_fft2(:,1:NIS),2); % 计算噪声段平均能量
snr_x_q=0.96; %前一帧先验信噪比,初始值设为0.96
for i=1:framenum
Mag_y=y_a(:,i);
snr_h=y_fft2(:,i)./noise;%(:,i); %计算后验信噪比
snr_x=alpha.*snr_x_q+(1-alpha).*max(snr_h-1,0); %先验信噪比,利用"D-D"法 ,framesize*1
Hw=snr_x./(1+snr_x); %维纳滤波
M=Mag_y.*Hw; %维纳后的幅度值
Mn=M.*exp(1i.*y_phase(:,i)); %插入相位
snr_x_q=M.^2./noise;%(:,i); %更新估计的前一帧先验信噪比
signal(:,i)=real(ifft(Mn));
end
enhancement=filpframe(signal',wnd,inc);
信噪比计算函数SNR_Calc
名称:SNR_Calc
功能:计算信噪比。
调用格式:
snr=SNR_Calc(x,xn)
说明:输入信号x是输入的纯净语音信号;xn是输入的含噪信号。输出参数snr是计算的信噪比。
函数程序如下:
function snr=SNR_Calc(I,In)
% 计算带噪语音信号的信噪比
% I 是纯语音信号
% In 是带噪的语音信号
% 信噪比计算公式是
% snr=10*log10(Esignal/Enoise)
I=I(:)'; % 把数据转为一列
In=In(:)';
Ps=sum((I-mean(I)).^2); % 信号的能量
Pn=sum((I-In).^2); % 噪声的能量
snr=10*log10(Ps/Pn); % 信号的能量与噪声的能量之比,再求分贝值
案例、用先验信噪比的维纳滤波算法给语音减噪
程序如下:
clear all; clc; close all;
[xx, fs] = wavread('C5_3_y.wav'); % 读入数据文件
xx=xx-mean(xx); % 消除直流分量
x=xx/max(abs(xx)); % 幅值归一化
IS=0.25; % 设置前导无话段长度
wlen=200; % 设置帧长为25ms
inc=80; % 设置帧移为10ms
SNR=5; % 设置信噪比SNR
NIS=fix((IS*fs-wlen)/inc +1); % 求前导无话段帧数
alpha=0.95;
signal=awgn(x,SNR,'measured','db'); % 叠加噪声
output=Weina_Im(x,wlen,inc,NIS,alpha) ;
output=output/max(abs(output));
len=min(length(output),length(x));
x=x(1:len);
signal=signal(1:len);
output=output(1:len);
snr1=SNR_Calc(x,signal); % 计算初始信噪比
snr2=SNR_Calc(x,output); % 计算降噪后的信噪比
snr=snr2-snr1;
fprintf('snr1=%5.4f snr2=%5.4f snr=%5.4f\n',snr1,snr2,snr);
% 作图
time=(0:len-1)/fs; % 设置时间
subplot 311; plot(time,x,'k'); grid; axis tight;
title('纯语音波形'); ylabel('幅值')
subplot 312; plot(time,signal,'k'); grid; axis tight;
title(['带噪语音 信噪比=' num2str(SNR) 'dB']); ylabel('幅值')
subplot 313; plot(time,output,'k');grid;%hold on;
title('滤波后波形'); ylabel('幅值'); xlabel('时间/s');
运行结果如下:
实验使用到的语音数据下载链接如下:
传统语音增强——最小方均(LMS)自适应滤波算法-数据集文档类资源-CSDN下载
参考文献:语音信号处理实验教程;梁瑞宇、赵力、魏昕(编著)