dechaaar 发表于 2013-4-20 17:29
你是运行这段程序出的问题么?
把变量先全部定义好
arrow,tmPitch,FramArry
function [tmPitch,fx]=dbdoor(f)
FrameLen = 240;
FrameInc = 80;
%读入语音数据
[xd, fs] = wavread('d:\bishe\wav\signal.wav');
%单声道
x = xd(:,1);
%xlen=fix(length(x)/20);
%x=x(1:xlen);
%幅度归一化
x = double(x);
x = x/max(abs(x));
%整个录音的长度
t=(0:length(x)-1)/fs;
% 对音频信号进行预滤波 butter滤波
%[b,a] = butter(4,[300 3400]/(fs/2));
%fx=filter(b,a,x);
%预加重滤波器
fx=filter([1 -0.9375], 1, x);
%对数据进行分帧
FramArry = enframe(fx, FrameLen, FrameInc);
%arrow行即是帧数,colum列即是每帧数据的数值个数
[arrow,colum]= size(FramArry);
%把前10帧看作噪音,分析,取其阀值zrc,elt,eht
tmp1 = zeros(arrow,FrameLen);
tmp2 = zeros(arrow,FrameLen);
%两个10帧的矩阵,计算过零率
for i=1:arrow-1
tmp1(i,:) = FramArry(i,:);
tmp2(i,:) = FramArry(i+1,:);
end
signs = (tmp1.*tmp2) < 0; %过零
diffs = abs(tmp1 - tmp2) > 0.02;
zcr = sum(signs.*diffs, 2); %求出了每一帧的过零率
for i=3:arrow-3
zcr(i)=(zcr(i-2)+zcr(i-1)+3*zcr(i)+zcr(i+1)+zcr(i+2))/7;
end
ZRCT = max(max(zcr(1:10)), 20);
%能量幅值
amp = sum(abs(FramArry), 2);
for i=3:arrow-3
amp(i)=(amp(i-2)+amp(i-1)+3*amp(i)+amp(i+1)+amp(i+2))/7;
end
emax = max(abs(amp(1:20)));
emin = min(abs(amp(1:20)));
i1 = 3*(emax - emin) + emin;
i2 = 5*emin;
%能量阀值ELT为低能量阀值,EHT为高能量阀值
ELT = min(i1, i2);
EHT = 5*ELT;
%ELT = 2;
%EHT = 12;
%从第1帧往后扫描找出第一个|En|>ELT的点
tmPitch = zeros(1,arrow);
ctrl = 1;
i = 20;
while(ctrl)
%小于低能量阀值
pbegin = 0;
pend = 0;
while (i < arrow && amp(i) < ELT)
ELT=0.5*ELT+0.5*amp(i);
i = i+1;
end
pbegin = i; %记录为开始的语音
%计算其前后20帧的超过平均过零率的个数
if(i < arrow - 10)
time = sum(zcr(i-10:i+10) > ZRCT);
end
%向后检查15帧如果幅度回落,不是说话声音
for j = i:i+20
if(j <= arrow)
%达到高门限一定是语音段
if (amp(j) > EHT)
break;
%不是语音段
else if (amp(j) < ELT)
pbegin = 0;
break;
end
end
else
ctrl = 0; %最后20帧看作没用的信号
break;
end
end
i=j;
%不小于ELT而且过零率超过限定值,即是讲话段
if (time > 15 && pbegin ~= 0)
%幅度下降到1.5ELT时为语音的结束
while(i <= arrow && amp(i) > 1.5*ELT)
i = i + 1;
end
pend = i;
while(i <= arrow && amp(i) > ELT && amp(i) < 1.5*ELT)
ELT=0.5*ELT+0.5*amp(i);
i = i+1;
end
%从pbegin到pend是语音段,假如时长太短认为是噪音
%比20帧要大则为语音段
if ((pend - pbegin) > 20)
for j=pbegin:pend
tmPitch(j) = 1;
end
end
end
i = i + 1;
if (i > arrow)
ctrl = 0;
break;
end
end
noisy=zeros(1,arrow);
a=0;
b=0;
for j=1:arrow
if(tmPitch(j)==1&&tmPitch(j+1)==0)
a=tmPitch(j+1);
elseif(tmPitch(j)==0&&tmPitch(j+1)==1)
b=tmpPitch(j);
end
break
noisy=FramArry(a,b);
end
subplot(411);
plot(t,x);
title('原信号波形图');
ylabel('幅度');
xlabel('时间');
axis([0 fix(max(t)) min(x) max(x)]);
%subplot(312);
%plot(t,fx,'Color','red');
%title('滤波后波形图');
%ylabel('幅度');
%xlabel('时间');
%axis([0 fix(max(t)) min(x) max(x)]);
subplot(412)
tz = ((0:arrow-1)*80 + 160)/fs;
plot(tz,zcr);
%plot(tmPitch);
title('短时过零率');
ylabel('过零次数');
xlabel('时间');
axis([0 fix(max(t)) min(zcr)-1 max(zcr)+1]);
subplot(413)
ta = ((0:arrow-1)*80 + 160)/fs;
plot(ta,amp);
%plot(tmPitch);
title('短时能量');
ylabel('能量');
xlabel('时间');
axis([0 fix(max(t)) min(amp)-1 max(amp)+1]);
subplot(414)
tm = ((0:length(tmPitch)-1)*80 + 160)/fs;
plot(tm,tmPitch);
%plot(tmPitch);
title('短时能量');
ylabel('能量');
xlabel('时间');
axis([0 fix(max(t)) 0 1.5]);
这个是全部的程序