一、Boll的改进谱减法基本理论
1979年,S.F.Boll提出一种改进的谱减法。主要的改进点如下。
(1)在谱减法中使用信号的频谱幅值或功率谱
改进的谱减公式为
噪声段的平均谱值为
当y=1时,算法相当于用谱幅值做谱减法;当y=2时,算法相当于用功率谱做谱减法。式中,a为过减因子;β为增益补偿因子。
(2)计算平均谱值
在相邻帧之间计算平均值:
利用Yi(k)取代Xi(k),可以得到较小的谱估算方差。
(3)减少噪声残留
在减噪过程中保留噪声的最大值,从而在谱减法中尽可能地减少噪声残留,从而削弱“音乐噪声”。
此处,max|NR(k)|代表最大噪声残余。
二、基本谱减法的实验
Boll的改进谱减法函数SpectralSubIm
名称:SpectralSubIm
功能:基于Boll的改进谱减法语音降噪。
调用格式:
output = SpectralSubIm(signal,wind, inc, NIS, Gamma, Beta)
说明:输入参数signal是输入的含噪语音信号;wind为窗函数或窗长;inc是帧移;NIS是前导无话段帧数;Gamma和Beta是算法参数。output是降噪后的信号。
函数代码如下:
function output=SpectralSubIm(signal,wind,inc,NIS,Gamma,Beta)
nwin=length(wind);
if (nwin == 1) % 判断窗长是否为1,若为1,即表示没有设窗函数
W = wind; % 是,帧长=wind
wnd=hamming(W);
else
W = nwin; % 否,帧长=窗长
wnd=wind;
end
nfft=W;
y=enframe(signal,W,inc)';
Y=fft(y,nfft);
YPhase=angle(Y(1:fix(end/2)+1,:)); %含噪语音的相位
Y=abs(Y(1:fix(end/2)+1,:)).^Gamma; %功率谱
numberOfFrames=size(Y,2);
N=mean(Y(:,1:NIS)')'; %初始的能量谱均值D(k)
NRM=zeros(size(N)); %噪声残余量最大值
NoiseCounter=0;
NoiseLength=9; %噪声平滑因子
YS=Y; %平均谱值
for i=2:(numberOfFrames-1)
YS(:,i)=(Y(:,i-1)+Y(:,i)+Y(:,i+1))/3;
end
for i=1:numberOfFrames
[NoiseFlag, SpeechFlag, NoiseCounter, Dist]=vad_LogSpec(Y(:,i).^(1/Gamma),N.^(1/Gamma),NoiseCounter); %基于频谱距离的VAD检测
if SpeechFlag==0
N=(NoiseLength*N+Y(:,i))/(NoiseLength+1); %更新并平滑噪声
NRM=max(NRM,YS(:,i)-N); %更新最大的噪声残余
X(:,i)=Beta*Y(:,i);
else
D=YS(:,i)-N; %谱减
if i>1 && i<numberOfFrames %减少噪声残留项
for j=1:length(D)
if D(j)<NRM(j)
D(j)=min([D(j) YS(j,i-1)-N(j) YS(j,i+1)-N(j)]);
end
end
end
X(:,i)=max(D,0);
end
end
output=OverlapAdd2(X.^(1/Gamma),YPhase,W,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); % 信号的能量与噪声的能量之比,再求分贝值
案例、使用Boll改进的谱减法给带噪语音降噪
程序如下:
clear all; clc; close all;
[xx,fs]=audioread('C5_2_y.wav'); % 读入数据文件
xx=xx-mean(xx); % 消除直流分量
x=xx/max(abs(xx)); % 幅值归一化
SNR=10; % 设置信噪比
signal=awgn(x,SNR,'measured','db'); % 叠加噪声
snr1=SNR_Calc(x,signal); % 计算叠加噪声后的信噪比
N=length(x); % 信号长度
time=(0:N-1)/fs; % 设置时间刻度
IS=.15; % % 设置前导无话段长度
wlen=200; % 设置帧长为25ms
inc=80; % 设置帧移为10ms
Gamma=1; %幅度加权(改进谱减法的参数)
Beta=.03;
NIS=fix((IS*fs-wlen)/inc +1); % 求前导无话段帧数
output=SpectralSubIm(signal,wlen,inc,NIS,Gamma,Beta); % 调用SSBoll79函数做谱减
output=output/max(abs(output));
ol=length(output); % 把output补到与x等长
if ol<N
output=[output; zeros(N-ol,1)];
end
snr2=SNR_Calc(x,output); % 计算谱减后的信噪比
snr=snr2-snr1;
fprintf('snr1=%5.4f snr2=%5.4f snr=%5.4f\n',snr1,snr2,snr);
% 作图
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; ylim([-1 1]);
title('谱减后波形'); ylabel('幅值'); xlabel('时间/s');
运行结果如下:
实验使用到的语音数据下载链接如下:
传统语音增强——最小方均(LMS)自适应滤波算法-数据集文档类资源-CSDN下载
参考文献:语音信号处理实验教程;梁瑞宇、赵力、魏昕(编著)