语音信号预处理(三)

承接(二)打算以后有时间补充原理
端点检测

function frameout=enframe(x,win,inc)

nx=length(x(:));            % 取数据长度
nwin=length(win);           % 取窗长
if (nwin == 1)              % 判断窗长是否为1,若为1,即表示没有设窗函数
   len = win;               % 是,帧长=win
else
   len = nwin;              % 否,帧长=窗长
end
if (nargin < 3)             % 如果只有两个参数,设帧inc=帧长
   inc = len;
end
nf = fix((nx-len+inc)/inc); % 计算帧数
frameout=zeros(nf,len);            % 初始化
indf= inc*(0:(nf-1)).';     % 设置每帧在x中的位移量位置
inds = (1:len);             % 每帧数据对应1:len
frameout(:) = x(indf(:,ones(1,len))+inds(ones(nf,1),:));   % 对数据分帧
if (nwin > 1)               % 若参数中包括窗函数,把每帧乘以窗函数
    w = win(:)';            % 把win转成行数据
    frameout = frameout .* w(ones(nf,1),:);  % 乘窗函数
end
function [x1,x2,FrameInc,amp,zcr] = vad(x) 
 
%幅度归一化到[-1,1] 
x = double(x); 
x = x / max(abs(x)); 
 
%常数设置 
FrameLen = 240; 
FrameInc = 80; 
 
amp1 = 10; 
amp2 = 2; 
zcr1 = 10; 
zcr2 = 5; 
 
maxsilence = 8;  % 3*10ms  = 30ms 
minlen  = 15;    % 15*10ms = 150ms 
status  = 0; 
count   = 0; 
silence = 0; 
 
%计算过零率 
tmp1  = enframe(x(1:end-1), FrameLen, FrameInc); 
tmp2  = enframe(x(2:end)  , 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); 
 
%调整能量门限 
amp1 = min(amp1, max(amp)/4); 
amp2 = min(amp2, max(amp)/8); 
 
%开始端点检测 
x1 = 0;  
x2 = 0; 
for n=1: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; 
   end 
end    
 
count = count-silence/2; 
x2 = x1 + count -1; 


function soundSegment=findSegment(express)
if express(1)==0
    voicedIndex=find(express);                     % 寻找express中为1的位置
else
    voicedIndex=express;
end

soundSegment = [];
k = 1;
soundSegment(k).begin = voicedIndex(1);            % 设置第一组有话段的起始位置
for i=1:length(voicedIndex)-1,
	if voicedIndex(i+1)-voicedIndex(i)>1,          % 本组有话段结束
		soundSegment(k).end = voicedIndex(i);      % 设置本组有话段的结束位置
		soundSegment(k+1).begin = voicedIndex(i+1);% 设置下一组有话段的起始位置  
		k = k+1;
	end
end
soundSegment(k).end = voicedIndex(end);            % 最后一组有话段的结束位置
% 计算每组有话段的长度
for i=1 :k
    soundSegment(i).duration=soundSegment(i).end-soundSegment(i).begin+1;
end

function frameTime=FrameTimeC(frameNum,framelen,inc,fs)
% 分帧后计算每帧对应的时间
frameTime=(((1:frameNum)-1)*inc+framelen/2)/fs;

function y=multimidfilter(x,m)
a=x;
for k=1 : m
    b=medfilt1(a, 5); 
    a=b;
end
y=b;
%双门限法端点检测
[s1,fs]=audioread('R.wav');  %都是单声道哦,怎么录单声道博客里说过了
% 读入数据文件
subplot 311
[x1,x2,FrameInc,amp,zcr] = vad(s1);
plot(s1) 
title('原信号','fontsize',10);
ylabel('幅度','fontsize',10);
xlabel('样点数','fontsize',10);
axis([1 length(s1) -0.2 0.2]) 
line([x1*FrameInc x1*FrameInc],[-0.1 0.1] , 'Color', 'red'); 
line([x2*FrameInc x2*FrameInc],[-0.1 0.1] ,'Color', 'red'); 
subplot 312
plot(amp); 
title('短时能量','fontsize',10);
ylabel('能量值','fontsize',10);
xlabel('帧数','fontsize',10);
axis([1 length(amp) 0 max(amp)]) 
line([x1 x1], [min(amp),max(amp)], 'Color', 'red'); 
line([x2 x2], [min(amp),max(amp)], 'Color', 'red'); 
subplot 313
plot(zcr); 
title('过零率','fontsize',10);
ylabel('过零次数','fontsize',10);
xlabel('帧数','fontsize',10);
axis([1 length(zcr) 0 max(zcr)]) 
line([x1 x1], [min(zcr),max(zcr)], 'Color', 'red'); 
line([x2 x2], [min(zcr),max(zcr)], 'Color', 'red'); 

你可能感兴趣的:(语音信号预处理(三))