1.一开始对于书中的初始化参数不是很理解:
特别是:
maxsilence = 15; % 初始化
minlen = 5;
status = 0;
count = 0;
silence = 0;
其中maxsilence是一段语音结束时静音区的最小长度。
minlen=minlin是有话段的最小长度。
status表示静音、语音段、结束标准。
count 是一个列表(python用习惯了),比如count(1)表示第一次检测到的有话段目前的有话的长度,所以后面才有不断的 count(xn) = count(xn) + 1操作(所以xn=1时候,里面的xn就是表示目前是检测到第一组有话段),就是检测到一个样本点是有话的,那就自己+1。
silence也是一个列表,和count差不多,也是表示目前检测到的静音部分的长度,有以后面才有(if silence(xn) < maxsilence % 静音还不够长,语音尚未结束)的判断,就是前面书本说的第二级判决中F+问题。
2.后面的el变量那段的问题,有原贴回答:
补充:
比如像使用了书本源代码运行后,结果:
(1)x1、x2变量都是第四个是0,是因为这个音频尾部有很长的静音 ,所以在前面的开始端点检测的for循环中,检测到第3组的结束点后,运行到了case 3,x1和x2都会同时被置0,表示语音结束,为下一段准备,这个时候可能循环没有结束,但是会一直在case{0,1}中,表示这一段都是静音。这样运行了
if x1(el)==0, el=el-1; end % 获得x1的实际长度
这一步后,相当于把第4组的x1,x2都删除了,看起来是只删除了x1,但是实际上因为有el=el-1这个操作,后面的循环
这里相当于不考虑第4组了,也就是课本案例的情况(后面好长的静音)。
(2)关于这段
if x2(el)==0 % 如果x2最后一个值为0,对它设置为fn
fprintf('Error: Not find endding point!\n');
x2(el)=fn;
end
就是消除那种“LZ录制的语音出现Error: Not find endding point,这主要在语音的结束部分不是无话段,即在语音没有完全结束时就终断了录音。LZ可以对已录制的语音读入后在最后补上几帧0值。”
意思就是倒数第一次循环
会进入case {0,1},if amp(n) > amp1或者elseif amp(n) > amp2 | ... % 可能处于语音段zcr(n) > zcr2,继续最后一次循环,这个时候n=fn,循环结束,但是x2还是保持0(从确认最后一组语音开始点开始,先一直保持0)
3.以上代码均来自书本
function [voiceseg,vsl,SF,NF]=vad_ezm1(x,wlen,inc,NIS)
x=x(:); % 把x转换成列数组
maxsilence = 15; % 初始化
minlen = 5;
status = 0;
count = 0;
silence = 0;
y=enframe(x,wlen,inc)'; % 分帧
fn=size(y,2); % 帧数
amp=sum(y.^2); % 求取短时平均能量
zcr=zc2(y,fn); % 计算短时平均过零率
ampth=mean(amp(1:NIS)); % 计算初始无话段区间能量和过零率的平均值
zcrth=mean(zcr(1:NIS));
amp2=2*ampth; amp1=4*ampth; % 设置能量和过零率的阈值
zcr2=2*zcrth;
%开始端点检测
xn=1;
for n=1:fn
switch status
case {0,1} % 0 = 静音, 1 = 可能开始
if amp(n) > amp1 % 确信进入语音段
x1(xn) = max(n-count(xn)-1,1);
status = 2;
silence(xn) = 0;
count(xn) = count(xn) + 1;
elseif amp(n) > amp2 | ... % 可能处于语音段
zcr(n) > zcr2
status = 1;
count(xn) = count(xn) + 1;
else % 静音状态
status = 0;
count(xn) = 0;
x1(xn)=0;
x2(xn)=0;
end
case 2, % 2 = 语音段
if amp(n) > amp2 & ... % 保持在语音段
zcr(n) > zcr2
count(xn) = count(xn) + 1;
else % 语音将结束
silence(xn) = silence(xn)+1;
if silence(xn) < maxsilence % 静音还不够长,语音尚未结束
count(xn) = count(xn) + 1;
elseif count(xn) < minlen % 语音长度太短,认为是静音或噪声
status = 0;
silence(xn) = 0;
count(xn) = 0;
else % 语音结束
status = 3;
x2(xn)=x1(xn)+count(xn);
end
end
case 3, % 语音结束,为下一个语音准备
status = 0;
xn=xn+1;
count(xn) = 0;
silence(xn)=0;
x1(xn)=0;
x2(xn)=0;
end
end
el=length(x1);
if x1(el)==0, el=el-1; end % 获得x1的实际长度
if x2(el)==0 % 如果x2最后一个值为0,对它设置为fn
fprintf('Error: Not find endding point!\n');
x2(el)=fn;
end
SF=zeros(1,fn); % 按x1和x2,对SF和NF赋值
NF=ones(1,fn);
for i=1 : el
SF(x1(i):x2(i))=1;
NF(x1(i):x2(i))=0;
end
speechIndex=find(SF==1); % 计算voiceseg
voiceseg=findSegment(speechIndex);
vsl=length(voiceseg);