> 文档中心 > 《MATLAB语音信号分析与合成(第二版)》:第5章 带噪语音和预处理

《MATLAB语音信号分析与合成(第二版)》:第5章 带噪语音和预处理

《MATLAB语音信号分析与合成(第二版)》:第5章 带噪语音和预处理

  • 前言
  • 1. 数据与函数路径设置
  • 2. MATLAB仿真一:语音信号加高斯白噪声
  • 3. MATLAB仿真二:语音信号加正弦噪
  • 4. MATLAB仿真三:语音信号叠加噪声
  • 5. MATLAB仿真四:语音信号消除趋势项一
  • 6. MATLAB仿真五:语音信号消除趋势项二
  • 7. MATLAB仿真六:语音信号滤波去噪一
  • 8. MATLAB仿真七:语音信号滤波去噪二
  • 9. MATLAB仿真八:语音信号滤波去噪三
  • 小结

前言

《MATLAB语音信号分析与合成(第二版)》是中科院声学所的大佬宋知用老师数十年经验积累下的呕心之作,对于语音信号处理相关感兴趣的同学,日后希望在语音信号分析、处理与合成相关领域进行一定研究的话,可以以此进行入门。

语音信号处理是数字信号处理的一个重要分支。本书含有许多数字信号处理的方法和 MATLAB函数。 全书共10章。第1-4章介绍语音信号处理的一些基本分析方法和手段,以及相应的MATLAB函数;第5-9章介绍语音信号预处理和特征的提取,包括消除趋势项和基本的减噪方法,以及端点检测、基音的提取和共 振峰的提取,并利用语音信号处理的基本方法,给出了多种提取方法和相应的 MATLAB程序;第10章结合 各种参数的检测介绍了语音信号的合成、语音信号的变速和变调处理,还介绍了时域基音同步叠加( TD PSOLA)的语音合成,并给出了相应的MATLAB程序。附录A中给出了调试复杂程序的方法和思路。 本书可作为从事语音信号处理的本科高年级学生、研究生或科研工程技术人员的辅助读物,也可作为从 事信号处理研究与应用的科研工程技术人员的参考用书。

我的研究生导师的主攻方向就是语音信号处理相关,虽然自己研究生期间的大论文方向是数字图像处理,但所谓语音图像不分家,自己在老师的研究生主讲课小波变换上虽然划水,但在后期导师的语音信号处理的课程设计和工程应用上自己在语音上还算入了一点小门道,在结课测试中拿到了小组第一,导师还特地发了三百大洋的伙食经费以资鼓励。

这次重新捡起语音识别,正好入手了宋老师的这本书,算是自己重新复习一遍吧,主要以介绍各章节中源码为主,这是本书的第五章的8个仿真应用实例,话不多说,开始!

1. 数据与函数路径设置

书中经常会调用的一些函数(自编函数或取自其他应用工具箱中的函数)已集中在basic_tbx工具箱中,在运行本书的程序前请把该工具箱设置(用set path设置)在工作路径下;

当要运行EMD处理时,要把emd工具箱设置在工作路径下;

当要运行主体延伸基音检测时,要把Pitch_ztlib工具箱设置在工作路径下;

当要进行时域基音同步叠加语音合成时,要把psola_lib工具箱设置在工作路径下;

当要应用本书提供的语音数据时,最好把speech_signal设置在工作路径下。

本书的所有函数和程序都在MATLAB R2009a版本下调试通过。(我用的是MATLAB2015b,有些函数已经更新,所以我会进行修改,以便调试通过)

路径设置的方法如下:

打开MATLAB,点击“主页”,找到设置路径
在这里插入图片描述

将上述文件夹路径全部添加到MATLAB搜索路径中
在这里插入图片描述
添加完毕,保存,开始仿真。

2. MATLAB仿真一:语音信号加高斯白噪声

%% pr5_3_1clear all; clc; close all;filedir=[];    % 指定文件路径filename='bluesky3.wav';     % 指定文件名fle=[filedir filename];      %[s,fs]=wavread(fle);  % 读入数据文件[s,fs]=audioread(fle);  % 读入数据文件s=s-mean(s);   % 消除直流分量s=s/max(abs(s));      % 幅值归一化N=length(s);   % 求出数据长度time=(0:N-1)/fs;      % 求出时间刻度subplot 411; plot(time,s,'k');      % 画出纯语音信号的波形图title('纯语音信号'); ylabel('幅值')SNR=[15 5 0];  % 信噪比的取值区间for k=1 : 3     snr=SNR(k);% 设定信噪比    [x,noise]=Gnoisegen(s,snr);     % 求出相应信噪比的高斯白噪声,构成带噪语音    subplot(4,1,k+1); plot(time,x,'k'); ylabel('幅值');% 作图    snr1=SNR_singlech(s,x);  % 计算出带噪语音中的信噪比    fprintf('k=%4d  snr=%5.1f  snr1=%5.4f\n',k,snr,round(snr1*1e4)/1e4);    title(['带噪语音信号 设定信噪比=' num2str(snr) 'dB  计算出信噪比=' ... num2str(round(snr1*1e4)/1e4) 'dB']);endxlabel('时间/s')
function [y,noise] = Gnoisegen(x,snr)% Gnoisegen函数是叠加高斯白噪声到语音信号x中% [y,noise] = Gnoisegen(x,snr)% x是语音信号,snr是设置的信噪比,单位为dB% y是叠加高斯白噪声后的带噪语音,noise是被叠加的噪声noise=randn(size(x));% 用randn函数产生高斯白噪声Nx=length(x); % 求出信号x长signal_power = 1/Nx*sum(x.*x);     % 求出信号的平均能量noise_power=1/Nx*sum(noise.*noise);% 求出噪声的能量noise_variance = signal_power / ( 10^(snr/10) );    % 计算出噪声设定的方差值noise=sqrt(noise_variance/noise_power)*noise;% 按噪声的平均能量构成相应的白噪声y=x+noise;    % 构成带噪语音
function snr=SNR_singlech(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);   % 信号的能量与噪声的能量之比,再求分贝值

在这里插入图片描述

3. MATLAB仿真二:语音信号加正弦噪

%% pr5_3_2clear all; clc; close all;filedir=[];    % 指定文件路径filename='bluesky3.wav';     % 指定文件名fle=[filedir filename];      % [s,fs]=wavread(fle);  % 读入数据文件[s,fs]=audioread(fle);  % 读入数据文件s=s-mean(s);   % 消除直流分量s=s/max(abs(s));      % 幅值归一化N=length(s);   % 求出数据长度time=(0:N-1)/fs;      % 求出时间刻度subplot 411; plot(time,s,'k');      % 画出纯语音信号的波形图title('纯语音信号'); ylabel('幅值')SNR=[5 0 -5];  % 信噪比的取值区间for k=1 : 3     snr=SNR(k);% 设定信噪比    data=sin(2*pi*100*time); % 产生一个正弦信号    [x,noise]=add_noisedata(s,data,fs,fs,snr); % 按信噪比构成正弦信号叠加到语音上    subplot(4,1,k+1); plot(time,x,'k'); ylabel('幅值');  % 作图    ylim([-2 2]);    snr1=SNR_singlech(s,x);  % 计算出带噪语音中的信噪比    fprintf('k=%4d  snr=%5.1f  snr1=%5.4f\n',k,snr,snr1);    title(['带噪语音信号 设定信噪比=' num2str(snr) 'dB  计算出信噪比=' ... num2str(round(snr1*1e4)/1e4) 'dB']);endxlabel('时间/s')    
function [signal,noise]=add_noisedata(s,data,fs,fs1,snr)s=s(:);     % 把信号转换成列数据s=s-mean(s);% 消除直流分量sL=length(s);      % 求出信号的长度if fs~=fs1  % 若纯语音信号的采样频率与噪声的采样频率不相等    x=resample(data,fs,fs1);     % 对噪声重采样,使噪声采样频率与纯语音信号的采样频率相同else    x=data;endx=x(:);     % 把噪声数据转换成列数据x=x-mean(x);% 消除直流分量xL=length(x);      % 求噪声数据长度if xL>=sL   % 如果噪声数据长度与信号数据长度不等,把噪声数据截断或补足    x=x(1:sL);else    disp('Warning: 噪声数据短于信号数据,以补0来补足!')    x=[x; zeros(sL-xL,1)];endSr=snr;Es=sum(s.*s);      % 求出信号的能量Ev=sum(x.*x);      % 求出噪声的能量a=sqrt(Es/Ev/(10^(Sr/10)));      % 计算出噪声的比例因子noise=a*x;  % 调整噪声的幅值signal=s+noise;    % 构成带噪语音

在这里插入图片描述

4. MATLAB仿真三:语音信号叠加噪声

%% pr5_3_3clear all; clc; close all;filedir=[];    % 指定文件路径filename='bluesky3.wav';     % 指定文件名fle=[filedir filename];      % [s,fs]=wavread(fle);  % 读入数据文件[s,fs]=audioread(fle);  % 读入数据文件s=s-mean(s);   % 消除直流分量s=s/max(abs(s));      % 幅值归一化N=length(s);   % 求出数据长度time=(0:N-1)/fs;      % 求出时间刻度subplot 411; plot(time,s,'k');      % 画出纯语音信号的波形图title('纯语音信号'); ylabel('幅值')filepath_name='factory1.wav';SNR=[5 0 -5];  % 信噪比的取值区间for k=1 : 3     snr=SNR(k);% 设定信噪比    [x,noise]=add_noisefile(s,filepath_name,snr,fs); % 按信噪比构成噪声叠加到语音上    subplot(4,1,k+1); plot(time,x,'k'); ylabel('幅值');  % 作图    ylim([-2 2]);    snr1=SNR_singlech(s,x);  % 计算出带噪语音中的信噪比    fprintf('k=%4d  snr=%5.1f  snr1=%5.4f\n',k,snr,snr1);    title(['带噪语音信号 设定信噪比=' num2str(snr) 'dB  计算出信噪比=' ... num2str(round(snr1*1e4)/1e4) 'dB']);endxlabel('时间/s')    
function [y,noise] = add_noisefile(s,filepath_name,SNR,fs)s=s(:); % 把信号转换成列数据s=s-mean(s);   % 消除直流分量% [wavin,fs1,nbits]=wavread(filepath_name);   %读入噪声文件的数据[wavin,fs1]=audioread(filepath_name);   %读入噪声文件的数据wavin=wavin(:);% 把噪声数据转换成列数据if fs1~=fs     % 纯语音信号的采样频率与噪声的采样频率不相等    wavin1=resample(wavin,fs,fs1);  % 对噪声重采样,使噪声采样频率与纯语音信号的采样频率相同else    wavin1=wavin;endwavin1=wavin1-mean(wavin1);  % 消除直流分量ns=length(s);  % 求出s的长度noise=wavin1(1:ns);   % 把噪声长度截断为与s等长noise=noise-mean(noise);     % 噪声去除直流分量signal_power = 1/ns*sum(s.*s);      % 求出信号的能量noise_power=1/ns*sum(noise.*noise); % 求出噪声的能量noise_variance = signal_power / ( 10^(SNR/10) );   % 求出噪声设定的方差值noise=sqrt(noise_variance/noise_power)*noise;      % 调整噪声幅值y=s+noise;     % 构成带噪语音

在这里插入图片描述

5. MATLAB仿真四:语音信号消除趋势项一

%% pr5_4_1 clear all; clc; close all;% [x,fs,nbit]=wavread('bluesky31.wav');     % 读入bluesky31.wav文件[x,fs]=audioread('bluesky31.wav');     % 读入bluesky31.wav文件t=(0:length(x)-1)/fs;% 设置时间y=detrend(x); % 消除线性趋势项y=y/max(abs(y));     % 幅值归一化subplot 211; plot(t,x,'k'); % 画出带有趋势项的语音信号xtitle('带趋势项的语音信号');xlabel('时间/s'); ylabel('幅值');subplot 212; plot(t,y,'k'); % 画出消除趋势项的语音信号yxlabel('时间/s'); ylabel('幅值');title('消除趋势项的语音信号');

在这里插入图片描述

6. MATLAB仿真五:语音信号消除趋势项二

%% pr5_4_2  clear all; clc; close all;% [x,fs,nbit]=wavread('bluesky32.wav');     % 读入bluesky32.wav文件[x,fs]=audioread('bluesky32.wav');     % 读入bluesky31.wav文件[y,xtrend]=polydetrend(x, fs, 2);  % 调用polydetrend消除趋势项t=(0:length(x)-1)/fs;% 设置时间subplot 211; plot(t,x,'k'); % 画出带有趋势项的语音信号xline(t,xtrend,'color',[.6 .6 .6],'linewidth',3); % 画出趋势项曲线ylim([-1.5 1]);title('带趋势项的语音信号');legend('带趋势项的语音信号','趋势项信号',4)xlabel('时间/s'); ylabel('幅值');subplot 212; plot(t,y,'k'); % 画出消除趋势项的语音信号yxlabel('时间/s'); ylabel('幅值');title('消除趋势项的语音信号');

在这里插入图片描述

7. MATLAB仿真六:语音信号滤波去噪一

%% pr5_5_1 clear all; clc; close all;fp=500; fs=750;    % 设置滤波器的通带和阻带频率Fs=8000; Fs2=Fs/2; % 采样频率Wp=fp/Fs2; Ws=fs/Fs2;     % 把通带和阻带频率归一化Rp=3; Rs=50;% 通带波纹和阻带衰减[n,Wn]=cheb2ord(Wp,Ws,Rp,Rs);    % 求取滤波器阶数[b,a]=cheby2(n,Rs,Wn);    % 设计契比雪夫II型低通滤波器系数[db,mag,pha,grd,w]=freqz_m(b,a); % 求滤波器的频率响应曲线filedir=[]; % 指定文件路径filename='bluesky3.wav';  % 指定文件名fle=[filedir filename]    % 构成路径和文件名的字符串% [s,fs]=wavread(fle);      % 读入数据文件[s,fs]=audioread(fle);  % 读入数据文件s=s-mean(s);% 消除直流分量s=s/max(abs(s));   % 幅值归一化N=length(s);% 求出信号长度t=(0:N-1)/fs;      % 设置时间y=filter(b,a,s);   % 把语音信号通过滤波器wlen=200; inc=80; nfft=512;      % 设置帧长,帧移和nfft长win=hann(wlen);    % 设置窗函数d=stftms(s,win,nfft,inc); % 原始信号的STFT变换fn=size(d,2);      % 获取帧数frameTime=(((1:fn)-1)*inc+nfft/2)/Fs;   % 计算每帧对应的时间--时间轴刻度W2=1+nfft/2;% 计算频率轴刻度n2=1:W2;freq=(n2-1)*Fs/nfft;d1=stftms(y,win,nfft,inc);% 滤波后信号的STFT变换% 作图figure(1)      plot(w/pi*Fs2,db,'k','linewidth',2)grid; axis([0 4000 -100 5]);title('低通滤波器的幅值响应曲线')xlabel('频率/Hz'); ylabel('幅值/dB');figure(2)      subplot 211; plot(t,s,'k'); title('纯语音信号:男声“蓝天,白云”')xlabel(['时间/s' 10 '(a)']); ylabel('幅值')subplot 212; imagesc(frameTime,freq,abs(d(n2,:))); axis xytitle('纯语音信号的语谱图')xlabel(['时间/s' 10 '(b)']); ylabel('频率/Hz')m = 256;LightYellow = [0.6 0.6 0.6];MidRed = [0 0 0];Black = [0.5 0.7 1];Colors = [LightYellow; MidRed; Black];colormap(SpecColorMap(m,Colors));figure(3)     subplot 211; plot(t,y,'k'); title('滤波后的语音信号')xlabel(['时间/s' 10 '(a)']); ylabel('幅值')subplot 212; imagesc(frameTime,freq,abs(d1(n2,:))); axis xytitle('滤波后语音信号的语谱图')xlabel(['时间/s' 10 '(b)']); ylabel('频率/Hz')m = 256;LightYellow = [0.6 0.6 0.6];MidRed = [0 0 0];Black = [0.5 0.7 1];Colors = [LightYellow; MidRed; Black];colormap(SpecColorMap(m,Colors)); ylim([0 1000]);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8. MATLAB仿真七:语音信号滤波去噪二

%% pr5_5_2 clear all; clc; close all;As=50;Fs=8000; Fs2=Fs/2; % 阻带最小衰减和采样频率fp=75; fs=60;     % 通带阻带频率df=fp-fs;  % 求取过渡带M0=round((As-7.95)/(14.36*df/Fs))+2;   % 按式(5-5-4)求凯泽窗长M=M0+mod(M0+1,2); % 保证窗长为奇数wp=fp/Fs2*pi; ws=fs/Fs2*pi;     % 转为圆频率wc=(wp+ws)/2;     % 求取截止频率beta=0.5842*(As-21)^0.4+0.07886*(As-21);% 按式(5-5-5)求出beta值fprintf('beta=%5.6f\n',beta);   % 显示beta的数值w_kai=(kaiser(M,beta))'; % 求凯泽窗hd=ideal_lp(pi,M)-ideal_lp(wc,M);      % 求理想滤波器的脉冲响应(高通滤波器的组合)b=hd.*w_kai;      % 理想脉冲响应与窗函数相乘[h,w]=freqz(b,1,4000);   % 求频率响应db=20*log10(abs(h));filedir=[];% 指定文件路径filename='bluesky3.wav';  % 指定文件名fle=[filedir filename]    % 构成路径和文件名的字符串% [s,fs]=wavread(fle);      % 读入数据文件[s,fs]=audioread(fle);  % 读入数据文件s=s-mean(s);% 消除直流分量s=s/max(abs(s));   % 幅值归一化N=length(s);% 求出信号长度t=(0:N-1)/fs;      % 设置时间ns=0.5*cos(2*pi*50*t);    % 计算出50Hz工频信号x=s+ns';    % 语音信号和50Hz工频信号叠加snr1=SNR_singlech(s,x)    % 计算叠加50Hz工频信号后的信噪比y=conv(b,x);% FIR带陷滤波,输出为y% 作图figure(1)plot(w/pi*Fs2,db,'k','linewidth',2); grid;axis([0 150 -100 10]);title('幅频响应曲线');xlabel('频率/Hz');ylabel('幅值/dB');figure(2)     subplot 311; plot(t,s,'k'); title('纯语音信号:男声“蓝天,白云”')xlabel('时间/s'); ylabel('幅值')axis([0 max(t) -1.2 1.2]);subplot 312; plot(t,x,'k'); title('带50Hz工频信号的语音信号')xlabel('时间/s'); ylabel('幅值')axis([0 max(t) -1.2 1.2]);z=y(fix(M/2)+1:end-fix(M/2));    % 消除conv带来的滤波器输出延迟的影响snr2=SNR_singlech(s,z)    % 计算滤波后语音信号的信噪比subplot 313; plot(t,z,'k');title('消除50Hz工频信号后的语音信号')xlabel('时间/s'); ylabel('幅值')axis([0 max(t) -1.2 1.2]);

在这里插入图片描述
在这里插入图片描述

9. MATLAB仿真八:语音信号滤波去噪三

%% pr5_5_3 clear all; clc; close all;As=50;Fs=8000; Fs2=Fs/2;  % 最小衰减和采样频率fs1=49; fs2=51;    % 阻带频率fp1=45; fp2=55;    % 通带频率df=min(fs1-fp1,fp2-fs2);  % 求过渡带宽M0=round((As-7.95)/(14.36*df/Fs))+2;    % 按式(5-5-4)求凯泽窗长M=M0+mod(M0+1,2);  % 保证窗长为奇数wp1=fp1/Fs2*pi; wp2=fp2/Fs2*pi;  % 转换成归一化圆频率ws1=fs1/Fs2*pi; ws2=fs2/Fs2*pi;wc1=(wp1+ws1)/2; wc2=(wp2+ws2)/2;% 求截止频率beta=0.5842*(As-21)^0.4+0.07886*(As-21);% 按式(5-5-5)求出beta值fprintf('beta=%5.6f\n',beta);M=M-1;      % 阶次和窗长差1b=fir1(M,[wc1 wc2]/pi,'stop',kaiser(M+1,beta));  % 计算FIR滤波器系数[h,w]=freqz(b,1,4000);    % 求幅值的频率响应db=20*log10(abs(h));filedir=[]; % 指定文件路径filename='bluesky3.wav';  % 指定文件名fle=[filedir filename]    % 构成路径和文件名的字符串% [s,fs]=wavread(fle);      % 读入数据文件[s,fs]=audioread(fle);  % 读入数据文件s=s-mean(s);% 消除直流分量s=s/max(abs(s));   % 幅值归一化N=length(s);% 求出信号长度t=(0:N-1)/fs;      % 设置时间ns=0.5*cos(2*pi*50*t);    % 计算出50Hz工频信号x=s+ns';    % 语音信号和50Hz工频信号叠加snr1=SNR_singlech(s,x)    % 计算叠加50Hz工频信号后的信噪比y=conv(b,x);% FIR带陷滤波,输出为yz=y(fix(M/2)+1:end-fix(M/2));    % 消除conv带来的滤波器输出延迟的影响snr2=SNR_singlech(s,z)    % 计算滤波后语音信号的信噪比% 作图figure(1)      plot(w/pi*Fs2,db,'k','linewidth',2);title('幅频响应曲线');xlabel('频率/Hz');ylabel('幅值/dB');grid on;  axis([0 100 -60 5])figure(2)subplot 311; plot(t,s,'k'); title('纯语音信号:男声“蓝天,白云”')xlabel('时间/s'); ylabel('幅值')axis([0 max(t) -1.2 1.2]);subplot 312; plot(t,x,'k'); title('带50Hz工频信号的语音信号')xlabel('时间/s'); ylabel('幅值')axis([0 max(t) -1.2 1.2]);subplot 313; plot(t,z,'k'); title('消除50Hz工频信号后的语音信号')xlabel('时间/s'); ylabel('幅值')axis([0 max(t) -1.2 1.2]);

在这里插入图片描述
在这里插入图片描述

小结

语音信号的滤波预处理是显示生活中我们最常遇见的,实际应用场景下,噪声无处不在,而且各种各样的噪声,千奇百怪,非常让人头疼,本章就是介绍常见的噪声类型,以及最常用的滤波处理方法,实现语音滤波噪声,进而实现语音增强的效果。

最近正好在处理一个环境噪声影响语音识别的问题,确实比较头疼,只能一步一步先从简单的滤波开始,后期在进行比较深入的复杂环境的符合噪声处理吧。对本章内容感兴趣或者想充分学习了解的,建议去研习书中第五章节的内容。后期会对其中一些知识点在自己理解的基础上进行讨论补充,欢迎大家一起学习交流。

关于宋老师:宋知用——默默传授MATLAB与信号处理知识的老人家

本系列文章列表如下:
《MATLAB语音信号分析与合成(第二版)》:第2章 语音信号的时域、频域特性和短时分析技术
《MATLAB语音信号分析与合成(第二版)》:第3章 语音信号在其他变换域中的分析技术和特性
《MATLAB语音信号分析与合成(第二版)》:第4章 语音信号的线性预测分析
《MATLAB语音信号分析与合成(第二版)》:第5章 带噪语音和预处理
《MATLAB语音信号分析与合成(第二版)》:第6章 语音端点的检测(1)
《MATLAB语音信号分析与合成(第二版)》:第6章 语音端点的检测(2)
《MATLAB语音信号分析与合成(第二版)》:第7章 语音信号的减噪
《MATLAB语音信号分析与合成(第二版)》:第8章 基音周期的估算方法
《MATLAB语音信号分析与合成(第二版)》:第9章 共振峰的估算方法
《MATLAB语音信号分析与合成(第二版)》:第10章 语音信号的合成算法