本题需要使用MATLAB中的Voice Activity Detector (VAD)工具箱,以下是实现代码:

%% 读取音频文件
[x, fs] = audioread('Beijing_l.wav');
x = x(:,1); % 取一个声道

%% 设置参数
frameLen = 256; % 帧长
frameShift = 128; % 帧移
win = hamming(frameLen); % 窗函数
p1 = 0.75; % 一级门限
p2 = 0.5; % 二级门限
n1 = 10; % 一级门限计数器阈值
n2 = 3; % 二级门限计数器阈值

%% 分帧并计算能量
xFrame = buffer(x, frameLen, frameLen-frameShift, 'nodelay');
xFrame = xFrame .* repmat(win, 1, size(xFrame, 2));
e = sum(abs(xFrame).^2);

%% 计算一级门限和二级门限
T1 = p1 * mean(e);
T2 = p2 * mean(e);

%% 二级判决法端点检测
n = 1; % 当前帧序号
state = 'silence'; % 当前状态
startIdx = []; % 起始点
endIdx = []; % 终止点
count = 0; % 门限计数器
for i = 1:length(e)
    if strcmp(state, 'silence')
        % 静音状态
        if e(i) > T1
            % 能量超过一级门限,进入语音状态
            state = 'speech';
            count = 0;
            startIdx(n) = (i-1)*frameShift+1;
            % 绘制一级门限
            line([startIdx(n)/fs startIdx(n)/fs], [0 max(e)], 'Color', 'blue', 'LineStyle', '-');
        end
    else
        % 语音状态
        if e(i) > T2
            % 能量超过二级门限,计数器加1
            count = count + 1;
        else
            % 能量低于二级门限,计数器清零
            count = 0;
        end
        if count >= n2
            % 门限计数器超过阈值,进入静音状态
            state = 'silence';
            endIdx(n) = i*frameShift;
            % 绘制二级门限
            line([endIdx(n)/fs endIdx(n)/fs], [0 max(e)], 'Color', 'blue', 'LineStyle', '-');
            % 绘制端点
            line([startIdx(n)/fs startIdx(n)/fs], [0 max(e)], 'Color', 'red', 'LineStyle', '-');
            line([endIdx(n)/fs endIdx(n)/fs], [0 max(e)], 'Color', 'red', 'LineStyle', '-');
            n = n + 1;
        end
    end
end

运行后,会绘制出语音波形图,并在图中用蓝色横线标出各级门限,用红色竖线标出端点。可以观察到,二级判决法能够有效地检测出语音段和静音段,并将其分割出来

matlab使用二级判决法的端点检测VADBeijing_lwav文件计算各级门限值并用蓝色横线标出各级门限以及用红色竖线在语音波形上标出端点。

原文地址: https://www.cveoy.top/t/topic/eO7i 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录