一、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
%减少噪声残留项 - for j=1:length(D)
- if D(j)
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下载
参考文献:语音信号处理实验教程;梁瑞宇、赵力、魏昕(编著)