端点检测.docx
《端点检测.docx》由会员分享,可在线阅读,更多相关《端点检测.docx(9页珍藏版)》请在冰点文库上搜索。
端点检测
语音信号处理实验一:
端点检测
姓名:
XXX学号:
XXXX班级:
XX
一、实验目的:
理解语音信号时域特征和倒谱特征求解方法及其应用。
二、实验原理与步骤:
任务一:
语音端点检测。
语音端点检测就是指从包含语音的一段信号中确定出语音的起始点和结束点。
正确的端点检测对于语音识别和语音编码系统都有重要的意义。
采用双门限比较法的两级判决法,具体如下
第一级判决:
1.先根据语音短时能量的轮廓选取一个较高的门限T1,进行一次粗判:
语音起止点位于该门限与短时能量包络交点所对应的时间间隔之外(即AB段之外)。
2.根据背景噪声的平均能量(用平均幅度做做看)确定一个较低的门限T2,并从A点往左、从B点往右搜索,分别找到短时能量包络与门限T2相交的两个点C和D,于是CD段就是用双门限方法根据短时能量所判定的语音段。
第二级判决:
以短时平均过零率为标准,从C点往左和从D点往右搜索,找到短时平均过零率低于某个门限T3的两点E和F,这便是语音段的起止点。
门限T3是由背景噪声的平均过零率所确定的。
注意:
门限T2,T3都是由背景噪声特性确定的,因此,在进行起止点判决前,T1,T2,T3,三个门限值的确定还应当通过多次实验。
任务二:
利用倒谱方法求出自己的基音周期。
三、实验仪器:
Cooledit、Matlab软件
四、实验代码:
取端点流程图
一:
clc,clear
[x,fs,nbits]=wavread('fighting.wav');%x为0~N-1即1~N
x=x/max(abs(x));%幅度归一化到[-1,1]
%参数设置
FrameLen=240;%帧长,每帧的采样点
inc=80;%帧移对应的点数
T1=10;%短时能量阈值,语音段
T2=5;%短时能量阈值,过渡段
T3=1;%过零率阈值,起止点
minsilence=6;%无声的长度来判断语音是否结束
silence=0;%用于无声的长度计数
minlen=15;%判断是语音的最小长度
state=0;%记录语音段状态0=静音,1=语音段,2=结束段
count=0;%语音序列的长度
%计算短时能量
shot_engery=sum((abs(enframe(x,FrameLen,inc))).^2,2);
%计算过零率
tmp1=enframe(x(1:
end-1),FrameLen,inc);%tmp1为二维数组=帧数*每帧的采样点FrameLen
tmp2=enframe(x(2:
end),FrameLen,inc);%
signs=(tmp1.*tmp2)<0;%signs为一维数组,符合的置1,否则置0
zcr=sum(signs,2);
%开始端点检测,找出A,B点
forn=1:
length(zcr)
ifstate==0%0=静音,1=可能开始
ifshot_engery(n)>T1%确信进入语音段
x1=max(n-count-1,1);%记录语音段的起始点
state=2;silence=0;
count=count+1;
elseifshot_engery(n)>T2||zcr(n)>T3%只要满足一个条件,可能处于过渡段
status=1;
count=count+1;
x2=max(n-count-1,1);
else%静音状态
state=0;count=0;
end
end
ifstate==2%1=语音段
ifshot_engery(n)>T2%保持在语音段
count=count+1;
elseifzcr(n)>T3%保持在语音段
x3=max(n-count-1,1);
else%语音将结束
silence=silence+1;
ifsilencecount=count+1;
elseifcountstate=0;
silence=0;
count=0;
else%语音结束
state=3;
end
end
end
ifstate==3%2=结束段
break;
end
end
x1,x2,x3%A、C、E坐标
x11=x1+count-1%B坐标
x22=x2+count-1%D坐标
x33=x3+count-1%F坐标
%画图
subplot(3,1,1)
plot(x)
axis([1length(x)-11])%标定横纵坐标
title('原始语音信号','fontsize',17);
xlabel('样点数');ylabel('Speech');
line([x3*incx3*inc],[-11],'Color','red');%画竖线
line([x33*incx33*inc],[-11],'Color','red');
subplot(3,1,2)
plot(shot_engery);
axis([1length(shot_engery)0max(shot_engery)])
title('短时能量','fontsize',17);
xlabel('帧数');ylabel('Energy');
line([x1x1],[min(shot_engery),T1],'Color','red');%画竖线
line([x11x11],[min(shot_engery),T1],'Color','red');%
line([x2x2],[min(shot_engery),T2],'Color','red');%
line([x22x22],[min(shot_engery),T2],'Color','red');%
line([1length(zcr)],[T1,T1],'Color','red','linestyle',':
');%画横线
line([1length(zcr)],[T2,T2],'Color','red','linestyle',':
');%
text(x1,-5,'A');%标写A、B、C、D
text(x11-5,-5,'B');
text(x2-10,-5,'C');
text(x22-5,-5,'D');
subplot(3,1,3)
plot(zcr);
axis([1length(zcr)0max(zcr)])
title('过零率','fontsize',17);
xlabel('帧数');ylabel('ZCR');
line([x3x3],[min(zcr),max(zcr)],'Color','red');%画竖线
line([x33x33],[min(zcr),max(zcr)],'Color','red');%
line([1length(zcr)],[T3,T3],'Color','red','linestyle',':
');%画横线
text(x3-10,-3,'E起点');%标写E、F
text(x33-40,-3,'F终点');
运行结果与分析:
x1=650,x11=734,x2=646,x22=752,x3=643,x33=763
得出的值x3
1、主要是学习了一些新的函数。
[x,fs,nbit]=wavread(wavFile);x就是音频信号;fs是采样频率,比如说16000就是每秒16000次;nbit是采样精度,比如说16就是指16位精度的采样。
y=enframe(x,FrameLen,inc);包含语音采样的以为数组x经过处理后得到二维数组y,
FrameLen为帧长,即每帧的采样点,inc为帧移对应的点数。
sum(x,2)表示矩阵x的横向相加,求每行的和,结果是列向量。
而缺省的sum(x)就是竖向相加,求每列的和,结果是行向量。
line([X1X2],[Y1Y2],S);%点A(X1,Y1)和点B(X2Y2)之间画一条直线,S为其它属性(颜色,线的粗细等)
2、端点检测可分为四段:
静音段、过渡段、语音段、结束。
实验时使用一个变量表示当前状态。
静音段,如果能量或过零率超过低门限,就开始标记起始点,进入过渡段。
过渡段当两个参数值都回落到低门限以下,就将当前状态恢复到静音状态。
而如果过渡段中两个参数中的任一个超过高门限,即被认为进入语音段。
处于语音段时,如果两参数降低到门限以下,而且总的计时长度小于最短时间门限,则认为是一段噪音,继续扫描以后的语音数据,否则标一记结束端点。
根据这些关系画出流程图,然后再编写程序就比较有条理,且思路清晰。
二:
clc,clear
[y,fs,nbits]=wavread('fighting.wav');
time=(1:
length(y))/fs;
frameSize=floor(40*fs/1000);%帧长
startIndex=round(10000);%起始序号,这个位置开始正好是语音开始
endIndex=startIndex+frameSize-1;%结束序号
frame=y(startIndex:
endIndex);%取出该帧
frameSize=length(frame);%求帧长
frame2=frame.*(hamming(frameSize));
frame2=frame;
dp=rceps(frame2);%求倒谱
ylen=length(dp);
cepstrum=dp(1:
ylen/2);%
%基音检测
LF=floor(fs/500);%设置基音搜索的范围
HF=floor(fs/70);%
cn=cepstrum(LF:
HF);%
[mx_cepind]=max(cn);
ifmx_cep>0.08&ind>LF%求基因周期
basic_T=(LF+ind)/fs;%由点转化为毫秒,即基音周期
else
basic_T=0;
end
fprintf('基因周期=%d\n',basic_T);%basic_T所求基因周期
%画图
subplot(2,1,1);
plot(frame);
axis([1frameSize-1*10.^(-3)1*10.^(-3)])
title('某个加窗信号');
subplot(2,1,2);
plot(cepstrum);
axis([1ylen/2-55])
title('倒谱图');
运行结果与分析:
1、根据倒谱图可以看出信号没有周期性,应该是清音,所有求出的结果为第一个峰值位置,即0,则基音周期为0/8000s=0,结果基本符合。
2、从自相关函数图中也可以看出在0点峰值最高。
3、总觉得“自相关函数”、“倒谱”、“分帧”、“基音周期”
等概念有些弄不清楚
五、心得体会:
1、开始frame2=frame.*(hamming(frameSize));总是出现Matrixdimensionsmustagree的错误。
后来找资料发现把语音的双声道改成单声道就可以了。
我想会不会是单声道是把相关的所有音频信号压缩后,用一种音轨播放的,而双声道是把相关的所有音频信号压缩后,把音频分高音音轨和低音音轨分别用两个音轨播放的,有两个声道的缘故,所以虽然双声道的frameSize打印出来时与单声道的一样,而实际上比单声道大,导致矩阵不匹配。
2、必须注意matlab数组的初值是从1开始的,C语言接触多了,总是会弄错,导致不必要的麻烦。
3、说实话,这个实验我觉得挺难。
一方面,本身概念不怎么理解,公式又很繁琐,另一方面,涉及到的新的函数很多,而且基本上都是有维数的,很抽象。
做出来的图像不符合预期,也很难找出错在什么地方。
matlab软件使用也不熟练。
语音这方面没有什么想法,就当是了解了解了。
如有侵权请联系告知删除,感谢你们的配合!