《MATLAB语音信号分析与合成(第二版)》是中科院声学所的大佬宋知用老师数十年经验积累下的呕心之作,对于语音信号处理相关感兴趣的同学,日后希望在语音信号分析、处理与合成相关领域进行一定研究的话,可以以此进行入门。
语音信号处理是数字信号处理的一个重要分支。本书含有许多数字信号处理的方法和 MATLAB函数。 全书共10章。第1-4章介绍语音信号处理的一些基本分析方法和手段,以及相应的MATLAB函数;第5-9章介绍语音信号预处理和特征的提取,包括消除趋势项和基本的减噪方法,以及端点检测、基音的提取和共 振峰的提取,并利用语音信号处理的基本方法,给出了多种提取方法和相应的 MATLAB程序;第10章结合 各种参数的检测介绍了语音信号的合成、语音信号的变速和变调处理,还介绍了时域基音同步叠加( TD PSOLA)的语音合成,并给出了相应的MATLAB程序。附录A中给出了调试复杂程序的方法和思路。 本书可作为从事语音信号处理的本科高年级学生、研究生或科研工程技术人员的辅助读物,也可作为从 事信号处理研究与应用的科研工程技术人员的参考用书。
我的研究生导师的主攻方向就是语音信号处理相关,虽然自己研究生期间的大论文方向是数字图像处理,但所谓语音图像不分家,自己在老师的研究生主讲课小波变换上虽然划水,但在后期导师的语音信号处理的课程设计和工程应用上自己在语音上还算入了一点小门道,在结课测试中拿到了小组第一,导师还特地发了三百大洋的伙食经费以资鼓励。
也正是因此,研二时,导师让接手了的一个校企项目,将语音识别落地到嵌入式平台,从MATLAB仿真优化,到嵌入式实现,到最小系统落地,从软著到专利,再到文章,整个项目全程主导,直到研三,彼时还是不够认真,虽然是项目主导者,但也是请教了许多同学和精通嵌入式的师弟。而今毕业将近四年之后,想来当时的项目其实并不算特别复杂,但自己却也并没有完全将整个实践过程吃透,也算有一点遗憾了(关于这个项目,后期有机会再详聊)。
这次重新捡起语音识别,正好入手了宋老师的这本书,算是自己重新复习一遍吧,主要以介绍各章节中源码为主,这是本书的第二章的4个仿真应用实例,话不多说,开始!
书中经常会调用的一些函数(自编函数或取自其他应用工具箱中的函数)已集中在basic_tbx工具箱中,在运行本书的程序前请把该工具箱设置(用set path设置)在工作路径下;
当要运行EMD处理时,要把emd工具箱设置在工作路径下;
当要运行主体延伸基音检测时,要把Pitch_ztlib工具箱设置在工作路径下;
当要进行时域基音同步叠加语音合成时,要把psola_lib工具箱设置在工作路径下;
当要应用本书提供的语音数据时,最好把speech_signal设置在工作路径下。
本书的所有函数和程序都在MATLAB R2009a版本下调试通过。(我用的是MATLAB2018a,有些函数已经更新,所以我会进行修改,以便调试通过)
路径设置的方法如下:
打开MATLAB,点击“主页”,找到设置路径
将上述文件夹路径全部添加到MATLAB搜索路径中
添加完毕,保存,开始仿真。
%
% pr2_3_1
clear all; clc; close all;
filedir=[]; % 设置路径
filename='bluesky3.wav'; % 设置文件名
fle=[filedir filename]; % 构成完整的路径和文件名
%[x,Fs]=wavread(filename); % 读入数据文件
[x,Fs]=audioread(filename); % 读入数据文件
wlen=200; inc=80; % 给出帧长和帧移
win=hanning(wlen); % 给出海宁窗
N=length(x); % 信号长度
X=enframe(x,win,inc)'; % 分帧
fn=size(X,2); % 求出帧数
time=(0:N-1)/Fs; % 计算出信号的时间刻度
for i=1 : fn
u=X(:,i); % 取出一帧
u2=u.*u; % 求出能量
En(i)=sum(u2); % 对一帧累加求和
end
subplot 211; plot(time,x,'k'); % 画出时间波形
title('语音波形');
ylabel('幅值'); xlabel(['时间/s' 10 '(a)']);
frameTime=frame2time(fn,wlen,inc,Fs); % 求出每帧对应的时间
subplot 212; plot(frameTime,En,'k') % 画出短时能量图
title('短时能量');
ylabel('幅值'); xlabel(['时间/s' 10 '(b)']);
%
% pr2_3_2
clear all; clc; close all;
filedir=[]; % 设置路径
filename='bluesky3.wav'; % 设置文件名
fle=[filedir filename]; % 构成完整的路径和文件名
%[xx,Fs]=wavread(fle); % 读入数据文件
[xx,Fs]=audioread(fle); % 读入数据文件
x=xx-mean(xx); % 消除直流分量
wlen=200; inc=80; % 设置帧长、帧移
win=hanning(wlen); % 窗函数
N=length(x); % 求数据长度
X=enframe(x,win,inc)'; % 分帧
fn=size(X,2); % 获取帧数
zcr1=zeros(1,fn); % 初始化
for i=1:fn
z=X(:,i); % 取得一帧数据
for j=1: (wlen- 1) ; % 在一帧内寻找过零点
if z(j)* z(j+1)< 0 % 判断是否为过零点
zcr1(i)=zcr1(i)+1; % 是过零点,记录1次
end
end
end
time=(0:N-1)/Fs; % 计算时间坐标
frameTime=frame2time(fn,wlen,inc,Fs); % 求出每帧对应的时间
% 作图
subplot 211; plot(time,x,'k'); grid;
title('语音波形');
ylabel('幅值'); xlabel(['时间/s' 10 '(a)']);
subplot 212; plot(frameTime,zcr1,'k'); grid;
title('短时平均过零率');
ylabel('幅值'); xlabel(['时间/s' 10 '(b)']);
%
% pr2_4_1
clear all; clc; close all;
filedir=[]; % 设置路径
filename='bluesky3.wav'; % 设置文件名
fle=[filedir filename]; % 构成完整的路径和文件名
%[x,Fs]=wavread(fle); % 读入数据文件
[x,Fs]=audioread(filename); % 读入数据文件
wlen=200; inc=80; win=hanning(wlen);% 设置帧长,帧移和窗函数
N=length(x); time=(0:N-1)/Fs; % 计算时间
y=enframe(x,win,inc)'; % 分帧
fn=size(y,2); % 帧数
frameTime=(((1:fn)-1)*inc+wlen/2)/Fs; % 计算每帧对应的时间
W2=wlen/2+1; n2=1:W2;
freq=(n2-1)*Fs/wlen; % 计算FFT后的频率刻度
Y=fft(y); % 短时傅里叶变换
clf % 初始化图形
%=====================================================%
% Plot the STFT result % 画出语谱图
%=====================================================%
set(gcf,'Position',[20 100 600 500]);
axes('Position',[0.1 0.1 0.85 0.5]);
imagesc(frameTime,freq,abs(Y(n2,:))); % 画出Y的图像
axis xy; ylabel('频率/Hz');xlabel('时间/s');
title('语谱图');
m = 64;
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));
%=====================================================%
% Plot the Speech Waveform % 画出语音信号的波形
%=====================================================%
axes('Position',[0.07 0.72 0.9 0.22]);
plot(time,x,'k');
xlim([0 max(time)]);
xlabel('时间/s'); ylabel('幅值');
title('语音信号波形');
%
% pr2_4_2
clear all; clc; close all;
filedir=[]; % 设置路径
filename='bluesky3.wav'; % 设置文件名
fle=[filedir filename]; % 构成完整的路径和文件名
%[wavin0,fs,nbits]=wavread(fle); % 读入数据文件
[wavin0,fs]=audioread(fle); % 读入数据文件
nwind=240; noverlap=160; inc=nwind-noverlap; % 设置帧长为240,重叠为160,帧移为80
w_nwind=hanning(200); w_noverlap=195; % 设置段长为200,段重叠为195
nfft=200; % FFT长度为200
% 对每帧用pwelch_2计算短时功率谱密度
[Pxx] = pwelch_2(wavin0, nwind, noverlap, w_nwind, w_noverlap, nfft);
frameNum=size(Pxx,2); % 取来帧数
frameTime=frame2time(frameNum,nfft,inc,fs); % 计算每帧对应的时间
freq=(0:nfft/2)*fs/nfft; % 计算频率刻度
% 作图
imagesc(frameTime,freq,Pxx); axis xy
ylabel('频率/Hz');
xlabel('时间/s');
title('短时功率谱密度函数')
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));
语音信号的短时平稳性是其非常重要的一个特性,其中短时能量、短时平均过零率、语谱图、短时功率谱密度函数是语音信号分析的基础,需要对其进行深入了解熟悉,进入下一阶段学习方不至于吃力,对本章内容感兴趣或者想充分学习了解的,建议去研习书中第二章节的内容。后期会对其中一些知识点在自己理解的基础上进行讨论补充,欢迎大家一起学习交流。
关于宋老师:宋知用——默默传授MATLAB与信号处理知识的老人家
本系列文章列表如下:
《MATLAB语音信号分析与合成(第二版)》:第2章 语音信号的时域、频域特性和短时分析技术
《MATLAB语音信号分析与合成(第二版)》:第3章 语音信号在其他变换域中的分析技术和特性
《MATLAB语音信号分析与合成(第二版)》:第4章 语音信号的线性预测分析
《MATLAB语音信号分析与合成(第二版)》:第5章 带噪语音和预处理
《MATLAB语音信号分析与合成(第二版)》:第6章 语音端点的检测(1)
《MATLAB语音信号分析与合成(第二版)》:第6章 语音端点的检测(2)
《MATLAB语音信号分析与合成(第二版)》:第7章 语音信号的减噪
《MATLAB语音信号分析与合成(第二版)》:第8章 基音周期的估算方法
《MATLAB语音信号分析与合成(第二版)》:第9章 共振峰的估算方法
《MATLAB语音信号分析与合成(第二版)》:第10章 语音信号的合成算法