- 设计目的和设计要求
在接收到的语音信号大多含有噪声,并且噪声有大有小。由于在处理语音信号(例如语音识别,语音编码)之前往往要对带噪的语音进行减噪。这实质上就是语音信号处理中的语音增强。本组在此选用基本谱减法进行语音降噪。一般来说,随着信噪比的减小,减噪方法处理的效果也随之变差,而且往往会使语音信号丢字或者波形失真。基本谱减法虽然简单易行,有一定效果,但要在信噪比很低的情况下进行降噪,还需寻找更有效的语音增强方法。
具体设计要求为通过读入“bluessky.wav”数据(内容为:蓝天,白云,碧绿的大海),叠加上5dB的白噪声,通过调用谱减法函数simplesubspec对带噪语音进行减噪。
- 原理、结构和功能
设语音信号的时间序列为x(n),加窗分帧处理后得到第i。帧语音信号为xi(m),帧长为 N。任何一帧语音信号xi(m)做DFT后为
k=0,1,2...,N-1.
要对Xi求出每个分量的幅值和相角,幅值为|Xi(k)|,它的相角为:
在减谱中要把这两组数都给保存。
已知前导无话段(噪声段)时长为IS,对应的帧数为NIS,可以求出该噪声段的平均能量值为
谱减算法为
式中,a和b是两个常数,a称为过减因子;b称为增益补偿因子。
求出了谱减后幅值为丨Xi(k)丨,结合了保存的X’angle(k),就能经快速傅里叶逆变换(In-Werse Fast Fourier Tramsform,IFFT)求出谱减后的语音序列xi(m)。属中利用了谱最佳信号对相位不灵敏的特性,把谱减前的相位角信息直接用到谱减后的信号中。
基本谱减法的原理如图所示:
根据原理图可把减谱法的计算编写成一个函数,方便使用。
名称:simplesubspec
功能:用基本谱减法对带噪语音进行减噪
调用格式:output = simplesubspec(signal,wlen,inc,NIS,a,b)
说明:输入参数 signal 是带噪语音序列;wlen是帧长;inc是帧移;NIS是前导无话段的帧数;a是过减因子;b为增益补偿因子。输出参数output是谱减法减噪后的语音序列。
程序在Matlab章节具体说明。
通过读入“bluessky.wav”数据(内容为:蓝天,白云,碧绿的大海),叠加上5dB的白噪声,通过调用谱减法函数simplesubspec对带噪语音进行减噪。
- MATLAB程序(包含注释)
simplesubspec函数
function output=simplesubspec(signal,wlen,inc,NIS,a,b)
wnd=hamming(wlen); % 设置窗函数
N=length(signal); % 计算信号长度
y=enframe(signal,wnd,inc)'; % 分帧
fn=size(y,2); % 求帧数
y_fft = fft(y); % FFT
y_a = abs(y_fft); % 求取幅值
y_phase=angle(y_fft); % 求取相位角
y_a2=y_a.^2; % 求能量
Nt=mean(y_a2(:,1:NIS),2);
% 计算噪声段平均能量
nl2=wlen/2+1; % 求出正频率的区间
for i = 1:fn; % 进行谱减
for k= 1:nl2
if y_a2(k,i)>a*Nt(k)
temp(k) = y_a2(k,i) - a*Nt(k);
else
temp(k)=b*y_a2(k,i);
end
U(k)=sqrt(temp(k));
% 把能量开方得幅值
end
X(:,i)=U;
end;
output=OverlapAdd2(X,y_phase(1:nl2,:),wlen,inc);
% 合成谱减后的语音
Nout=length(output);
% 把谱减后的数据长度补足与输入等长
if Nout>N
output=output(1:N);
elseif Nout<N
output=[output; zeros(N-Nout,1)];
end
output=output/max(abs(output)); % 幅值归一
说明:程序中参数a和b按输入参数带入,可根据语音的具体情况进行改变。程序中调用到的函数OverlapAdd2是重叠相加法。
主函数
%
% pr7_2_1
clear all; clc; close all;
filedir=[]; % 指定文件路径
filename='bluesky1.wav'; % 指定文件名
fle=[filedir filename]
% 构成路径和文件名的字符串
[xx,fs]=wavread(fle); % 读入数据文件
xx=xx-mean(xx); % 消除直流分量
x=xx/max(abs(xx)); % 幅值归一化
IS=0.25;
% 设置前导无话段长度
wlen=200; % 设置帧长为25ms
inc=80; % 设置帧移为10ms
SNR=5; % 设置信噪比SNR
N=length(x); % 信号长度
time=(0:N-1)/fs; % 设置时间
signal=Gnoisegen(x,SNR); % 叠加噪声
snr1=SNR_singlech(x,signal); % 计算初始信噪比
overlap=wlen-inc; % 求重叠区长度
NIS=fix((IS*fs-wlen)/inc +1);
% 求前导无话段帧数
a=4; b=0.001; % 设置参数a和b
output=simplesubspec(signal,wlen,inc,NIS,a,b);% 谱减
snr2=SNR_singlech(x,output);
% 计算谱减后的信噪比
snr=snr2-snr1;
fprintf('snr1=%5.4f snr2=%5.4f snr=%5.4f\n',snr1,snr2,snr);
wavplay(signal,fs);
pause(1)
wavplay(output,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');
- 程序运行结果和解释说明
纯语音波形
带噪语音 信噪比=5dB
谱减后波形
运行程序后得到消噪后的波形如上图所示。
调用Gnoisegen函数产生带躁语音,调用SNR_singlech函数计算信噪比。程序中调用函数simplesubspec,其中a和b参数分别为a=4,b=0.001。
计算出信噪比的变化:初始信噪比为5 dB,谱减后的信噪比为11.3 dB,信噪比增加了6.3 dB。Snr1=5.0000 snr2=11.3051 snr=6.3051
- 最终结果和结论
噪声是完全随机的,有可能在某个时段某条谱线的谱值会大于a×D(k),相滅后并没有把噪声完全消除,而把它的峰值保留下来了,称为噪声残留,在谱减后的合成语音中就造成了“音乐噪声”。
消噪后的语音有明显的“音乐噪声”,增加过减因子a的数值,有时能减少“音乐噪声”,但过大时也会使波形失真,因此同样要选用一个折中的值。又由于在语音信号上叠加随机噪声,每一次叠加上的随机噪声都是不相同的,所以计算减噪后信噪比的结果snr2都不完全一样,会有一些偏差。