最近在折腾语音端点检测的时候发现个有意思的方法——频带方差检测。这玩意儿特别适合对付环境噪声,原理简单粗暴但有效。今天咱们就手撕代码看看它怎么玩转语音段定位
基于matlab的频带方差端点检测噪声频谱中各频带之间变化很平缓语音各频带之间变化较激烈。 据此特征语音和噪声就极易区分。 计算短时频带方差实质就是计算某一帧信号的各频带能量之间的方差。 这种以短时频带方差作为参数检测语音段起止端点的方法即称为频带方差检测法。 程序已调通可直接运行。先说说核心逻辑噪声的频谱在各个频带之间能量变化平缓而语音信号不同频带能量波动剧烈。就像平静湖面和湍急溪流的区别用方差这个统计量就能量化这种差异。直接上硬货Matlab代码走起function [start_point, end_point] band_variance_vad(signal, fs) frame_len 0.025 * fs; % 25ms每帧 n_overlap 0.5 * frame_len; nfft 512; % 分帧加窗 frames buffer(signal, frame_len, n_overlap, nodelay); window hamming(frame_len); frames_windowed frames .* window; % 划分频带示例分为4个子带 freq_bands [0 1000; 1000 2000; 2000 3000; 3000 4000]; band_energy zeros(size(freq_bands,1), size(frames_windowed,2)); for f 1:size(frames_windowed,2) spec abs(fft(frames_windowed(:,f), nfft)).^2; for b 1:size(freq_bands,1) idx round(freq_bands(b,:)/fs*nfft); band_energy(b,f) sum(spec(idx(1)1:idx(2))); end end % 计算频带方差 band_var var(band_energy); % 动态阈值 noise_level median(band_var(band_var0.1)); threshold noise_level * 3.5; % 端点检测 voiced band_var threshold; start_point find(diff([0 voiced])0); end_point find(diff([voiced 0])0); end代码有几个关键点值得唠唠频带划分这块儿用了简单粗暴的固定划分实际可以按临界频带搞更科学。但咱们demo嘛怎么方便怎么来。注意这里的频带范围要根据采样率调整别傻乎乎超过奈奎斯特频率。能量计算用了平方幅度谱相当于直接做Parseval定理的时频能量转换。这里有个小技巧绝对能量值不重要频带间的相对变化才是关键。方差计算直接用了var函数但注意数据是沿着频带维度计算的。比如某帧的4个子带能量是[0.1, 0.9, 0.2, 0.8]方差自然比噪声帧的[0.3, 0.4, 0.35, 0.38]大得多。动态阈值这块儿用了中位数抗干扰乘个系数3.5是经验值。实测时可以录制几秒纯噪声让程序自学习比固定阈值更靠谱。基于matlab的频带方差端点检测噪声频谱中各频带之间变化很平缓语音各频带之间变化较激烈。 据此特征语音和噪声就极易区分。 计算短时频带方差实质就是计算某一帧信号的各频带能量之间的方差。 这种以短时频带方差作为参数检测语音段起止端点的方法即称为频带方差检测法。 程序已调通可直接运行。测试效果的时候我拿手机录了段带背景白噪声的语音。原始信号长这样[raw, fs] audioread(noisy_speech.wav); subplot(2,1,1); plot(raw); title(原始信号); % 调用我们的VAD [start, stop] band_variance_vad(raw, fs); % 绘制检测结果 subplot(2,1,2); plot(band_var); hold on; plot([1 length(band_var)], [threshold threshold], r--); stem(start, 2*ones(size(start)), g); stem(stop, 2*ones(size(stop)), r);运行结果非常直观——噪声段的方差曲线像条死鱼般平静一旦出现语音立刻起跳。绿色竖线标记起点红色标记终点跟实际发音位置基本吻合。不过要注意这方法在两种情况下会翻车一是突发性强噪声比如摔门声二是音乐伴奏环境。这时候需要结合过零率、基频检测等其他特征做联合判决。最后说个调参小技巧如果发现检测到的语音段有碎片化别急着调阈值先看看分帧长度是否合适。帧长太短会导致方差计算不稳定建议从20ms开始试配合3~5个子带划分效果更佳。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2475076.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!