哈尔滨理工大学学士学位论文 附录A
包括短时过零率、短时能量、FFT、低频能量比、子带熵、谱平坦测度以及功率谱密度的分析(14)。
function varargout = SpeechSeg2(varargin) gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @SpeechSeg2_OpeningFcn, ... 'gui_OutputFcn', @SpeechSeg2_OutputFcn, ... 'gui_LayoutFcn', [] , ... 'gui_Callback', []); if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1}); end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); else
gui_mainfcn(gui_State, varargin{:}); end
% End initialization code - DO NOT EDIT
% --- Executes just before SpeechSeg2 is made visible.
function SpeechSeg2_OpeningFcn(hObject, eventdata, handles, varargin) handles.output = hObject;
guidata(hObject, handles);
function varargout = SpeechSeg2_OutputFcn(hObject, eventdata, handles) varargout{1} = handles.output;
function pushbutton5_Callback(hObject, eventdata, handles) global WAVFILE WAVALL FS NBITS N; global a flag; % flag:播放标志 flag=0;
- 26 -
哈尔滨理工大学学士学位论文 [filename, pathname, filterindex] = uigetfile('*.wav', '选择原始语音文件'); WAVFILE=[pathname filename];
%读取原始语音文件
[WAVALL,FS,NBITS]=wavread(WAVFILE); N=length(WAVALL);
%显示相关参数,包括:采样率、量化位数、通道数、时长 % 默认通道数应为1,不为1画图时会报错 set(handles.text29,'String',FS); set(handles.text31,'String',NBITS);
set(handles.text33,'String',min(size(WAVALL))); set(handles.text35,'String',N*1000/FS);
axes(handles.axes1); tt=1:N; tt=tt/FS;
H1=plot(tt,WAVALL); % disp(length(t)); axis([0 N/FS -1 1]);
% 分帧,用以计算过零率、能量和FFT frmlen=30*FS/1000; %帧长30ms frminc=frmlen/2; % 50% overlapping
sfrm=enframe(WAVALL,frmlen,frminc); [a b]=size(sfrm)
% set(handles.slider1,'Max',a); %slider1控制FFT结果一帧一帧地显示,其范围应为1~a
% set(handles.slider1,'Min',1); flow=zeros(a,1); he=zeros(a,1); msf=zeros(a,1); psd=zeros(a,1);
zcr=zeros(a,1); for i=1:a
flow(i)=sflow(sfrm(i,:),50,800,FS); %低频能量比 he(i)=she(sfrm(i,:)); %子带熵
msf(i)=smsf(sfrm(i,:)); %谱平坦测度
- 27 -
哈尔滨理工大学学士学位论文 psd(i)=spsd(sfrm(i,:),FS); %功率谱密度 zcr(i)=szcr(sfrm(i,:)); %过零率 end
zcrBigger=medsmooth((zcr>0)*200,15); % 静音段zcr几乎等于零,剔除,并对结果进行15点中值滤波 state=0;
xcount=0; %语音段的数目
for i=1:a %这个for循环对分割出来的语音段进行计数,比如测试语音
test.wav,得到的结果是4段,并记录每段的起止帧
switch state case 0
if(zcrBigger(i)>0) state=1; else
state=0; end
continue; case 1
if(zcrBigger(i)>0)
state=2; %连续两个点大于0了,表示确定进入一个语音段
xcount=xcount+1; xstart(xcount)=i-1; else
state=0; end
continue; case 2
if(zcrBigger(i)>0) %已经得到语音段起点,后面的点继续大于0,说明还在语音段中,继续保持状态2 state=2; if(i==a)
xend(xcount)=i; end else
state=3;%前一点为语音段,本点等于0,说明可能是静音了
- 28 -
哈尔滨理工大学学士学位论文 end
continue; case 3
if(zcrBigger(i)>0) %没能连续两点等于0,说明可能是误判,继续保持“在语音段中”的判决状态 state=2; else
state=0; %连续两点等于0,确定已离开语音段 xend(xcount)=i-1; end
continue; end end
zcrLen=10; %对zcr分帧的帧长 zcrInc=zcrLen/2;
zcrFrm=enframe(zcr,zcrLen,zcrInc); [zcra zcrb]=size(zcrFrm); zcrVar=zeros(zcra,1); for i=1:zcra
zcrVar(i)=var(zcrFrm(i,:)); %求zcr的方差 end
zcrVarPlot=zeros(a,1); for i=1:zcra
zcrVarPlot( (i-1)*zcrInc+1 : i*zcrInc )=ones(zcrInc,1)*zcrVar(i); if i==zcra
zcrVarPlot( (i-1)*zcrInc+1 : a )=ones(a-(i-1)*zcrInc,1)*zcrVar(i); end end
zcrVarPlot=zcrVarPlot.*zcrBigger/200; zcrVarEngAvr=zeros(xcount,1); zcrVarEngPlot=zeros(xcount,N); xtype=zeros(xcount,1);
MusicFrmNum=0; SilenceFrmNum=0; SpeechFrmNum=0; for i=1:xcount
zcrVarEngAvr(i)=sum( zcrVarPlot( xstart(i) : xend(i) ) )/( xend(i) - xstart(i) +1 );
- 29 -
哈尔滨理工大学学士学位论文
%求过零率方差曲线上每段语音内的均值
if( zcrVarEngAvr(i) > 300 ) %这里的1000是经验值 xtype(i)=2;
SpeechFrmNum = SpeechFrmNum + xend(i) - xstart(i) +1; else
xtype(i)=1;
MusicFrmNum = MusicFrmNum + xend(i) - xstart(i) +1; End
% 下面在axes1中给不同段着不同的颜色 axes(handles.axes1); hold on;
zcrVarEngPlot(i,(xstart(i)-1)*frminc+1:xend(i)*frminc+frmlen-frminc)= WAVALL( ( xstart(i)-1 )* frminc + 1 : xend(i)*frminc+frmlen-frminc ); if(xtype(i)==1)
plot(tt,zcrVarEngPlot(i,:),'r'); elseif(xtype(i)==2)
plot(tt,zcrVarEngPlot(i,:),'y'); end end
plot(tt,zeros(N,1),'b')
set(handles.text39,'String',MusicFrmNum*frminc*1000/FS); set(handles.text42,'String',SpeechFrmNum*frminc*1000/FS);
set(handles.text45,'String',(N-MusicFrmNum*frminc-SpeechFrmNum*frminc)*1000/FS);
% 画出低频能量比曲线 t=1:a;
axes(handles.axes2); plot(t,flow); axis tight;
% 画出子带熵曲线 axes(handles.axes3); plot(t,he); axis tight; % hold on;
- 30 -