📄 vad.asv
字号:
function [x1,x2]=vad(x)
%幅度归一化到[-1,1]
x=double(x);%将数据转化成双精度数
x=x/max(abs(x));%通过除以最大的值,使得数据归化
%常数设置
framelen=300;%帧长,对应于30ms
frameinc=100;%每帧的偏移量,对应于10ms
amp1=10;
amp2=2;
zcr1=10;
zcr2=5;
maxsilence=3;%3*10ms=30ms
minlen=15; %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);
%tmp1和tmp2都由归一化数据分帧得到,两者相差一个采样点
signs=(tmp1.*tmp2)<0;%signs用于存储相邻两个采样点是否相同,即是否过零
diffs=(tmp1-tmp2)>0.02;
%diffs用于度量相邻两个采样点的距离,若距离大于门限0.02,则为1,否则为2
%将两个矩阵点相乘,得到同时满足两个条件的采样点矩阵,然后按帧求和,就得到过零率
zcr=sum(signs.*diffs,2);%参数2表示求行和
%计算短时信号
%在计算短时能量之前要先将语音信号通过一个一阶高通滤波器1-0.9375z^(-1)
%目的是滤除低频干扰,同时有消除直流漂移,抑制随机噪声等效果。
%这里求出的是绝对值能量,实际上就是平均幅度
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|zcr(n)>zcr1 %确信进入语音段
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;
x2=x1+count-1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -