Matlab|语音处理|端点侦测(2)

来源:互联网 发布:log4j2 json 配置 编辑:程序博客网 时间:2024/06/10 15:33

之前参考了网上的资料,参考了别人的写法之后,自己整理出来的版本。


一个主程式+一个端点侦测函数,自己整理的版本和网上的版本比较,多出来的功能是用一个for,连贯的把句子的每个音节切出来,存入数组。


主程式:

    global wav_file;    global x1;    global x2;    wav_file = 'sunday.wav';  % input audio filename    inc=90;    start=[];               %阵列存声音开端    finish=[];              %阵列存声音尾端    % Read speech samples, sampling rate and precision from file    [ speech, fs, nbits ] = wavread( wav_file );   %%%%%%%%%%%%%%%%%%%%%%%%%%端点侦测开始%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    x3=1;    for i=1:length(speech)        if(length(speech)-(x3*inc)<6000)        %此段语音长度小于6000的时候就视为已经没有音节存在,跳出           break;        end        [speech1,fs]=wavread(wav_file,[x3*inc,length(speech)]);        [x1 ,x2]=vad(speech1);                figure        start=[start,x1+x3];    %开端存入阵列                x3=x2+x3;               finish=[finish,x3];     %尾端存入阵列           end        fprintf('端点侦测后的起始点:\n');    for i=1:size(finish,2)        fprintf('start=%d\t',start(i));        fprintf('end=%d\n',finish(i));    end%%%%%%%%%%%%%%%%%%%%%%%%%%端点侦测结束%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 


端点侦测函数:(vad.m)


function [x1 ,x2] = vad(x)%幅度归一化到[-1,1] x = double(x);x = x / max(abs(x));%常数设置FrameLen = 256;FrameInc = 90;amp1 = 10;          %短时能量阈值amp2 = 2;           %即设定能量的两个阈值。zcr1 = 10;          %过零率阈值zcr2 = 5;           %过零率的两个阈值,感觉第一个没有用到。maxsilence = 6;  % 3*10ms  = 30ms  用无声的长度来判断语音是否结束minlen  = 4;    % 15*10ms = 150ms 判断是语音的最小长度status  = 0;     %记录语音段的状态count   = 0;     %语音序列的长度silence = 0;     %无声的长度%计算过零率tmp1  = enframe(x(1:length(x)-1), FrameLen, FrameInc);tmp2  = enframe(x(2:length(x))  , FrameLen, FrameInc);signs = (tmp1.*tmp2)<0;diffs = (tmp1 -tmp2)>0.02;zcr   = sum(signs.*diffs, 2);%计算短时能量%amp = sum(abs(enframe(filter([1 -0.9375], 1, x), FrameLen, FrameInc)), 2);amp = sum((abs(enframe(x, FrameLen, FrameInc))).^2, 2);%调整能量门限amp1 = min(amp1, max(amp)/16);amp2 = min(amp2, max(amp)/8);%开始端点检测for n=1:length(zcr) %Length(zcr)得到的是整个信号的帧数。   goto = 0;   switch status   case {0,1}                   % 0 = 静音, 1 = 可能开始      if amp(n) > amp1          % 确信进入语音段         x1 = max(n-count-1,1); % 记录语音段的起始点         status  = 2;         silence = 0;         count   = count + 1;      elseif amp(n) > amp2 || zcr(n) > zcr2 % 可能处于语音段         status = 1;         count  = count + 1;      else                       % 静音状态         status  = 0;         count   = 0;      end   case 2,                       % 2 = 语音段      if amp(n) > amp2 || zcr(n) > zcr2     % 保持在语音段         count = count + 1;      else                       % 语音将结束         silence = silence+1;         if silence < maxsilence % 静音还不够长,尚未结束            count  = count + 1;         elseif count < minlen   % 语音长度太短,认为是噪声            status  = 0;            silence = 0;            count   = 0;         else                    % 语音结束            status  = 3;         end      end   case 3,      break;   endend   count = count-silence/2;x2 = x1 + count -1;     %记录语音段结束点%后边的程序是找出语音端,然后用红线给标出来.%subplot(3,1,1)plot(x)axis([1 length(x) -1 1])%限制x轴与y轴的范围。ylabel('Speech');line([x1*FrameInc x1*FrameInc], [-1 1], 'Color', 'red');line([x2*FrameInc x2*FrameInc], [-1 1], 'Color', 'green');%注意下line函数的用法:基于两点连成一条直线,就清楚了。%subplot(3,1,2)%plot(amp);%axis([1 length(amp) 0 max(amp)])%ylabel('Energy');%line([x1 x1], [min(amp),max(amp)], 'Color', 'red');%line([x2 x2], [min(amp),max(amp)], 'Color', 'green'); %subplot(3,1,3)%plot(zcr);%axis([1 length(zcr) 0 max(zcr)])%ylabel('ZCR');%line([x1 x1], [min(zcr),max(zcr)], 'Color', 'red');%line([x2 x2], [min(zcr),max(zcr)], 'Color', 'green');



0 0