vad.conf
配置文件中可选参数
--vad-energy-threshold=5.0 # VAD 的能量阈值常数项,若小于这个值则为噪音,若大于则为语音信号
--vad-energy-mean-scale=0.5 # 如果设置为 s,设 m 为该音频所有帧的平均对数能量,则实际阈值 = s*m + vad-energy-threshold;
--vad-frames-context=0 # 中央帧每一侧的上下文帧数,在其能量被监控的窗口中
--vad-proportion-threshold=0.6 # 控制窗口内需要具有比阈值更多能量的帧比例的参数
计算代码
#include "ivector/voice-activity-detection.h"
#include "matrix/matrix-functions.h"
namespace kaldi {
void ComputeVadEnergy(const VadEnergyOptions &opts, const MatrixBase<BaseFloat> &feats, Vector<BaseFloat> *output_voiced) {
int32 T = feats.NumRows(); // 帧数
output_voiced->Resize(T); // vad输出结果
if (T == 0) {
KALDI_WARN << "Empty features";
return;
}
Vector<BaseFloat> log_energy(T); // 对数能量值
log_energy.CopyColFromMat(feats, 0); // column zero is log-energy. 特征的第零列是对数能量。
BaseFloat energy_threshold = opts.vad_energy_threshold; // vad判断阈值, 若小于这个值则为噪音,若大于则为语音信号
if (opts.vad_energy_mean_scale != 0.0) { // 若vad_energy_mean_scale不为0,确保其不为负数
KALDI_ASSERT(opts.vad_energy_mean_scale > 0.0);
energy_threshold += opts.vad_energy_mean_scale * log_energy.Sum() / T;
}
KALDI_ASSERT(opts.vad_frames_context >= 0);
KALDI_ASSERT(opts.vad_proportion_threshold > 0.0 && opts.vad_proportion_threshold < 1.0);
for (int32 t = 0; t < T; t++) {
const BaseFloat *log_energy_data = log_energy.Data();
int32 num_count = 0, den_count = 0, context = opts.vad_frames_context;
for (int32 t2 = t - context; t2 <= t + context; t2++) {
if (t2 >= 0 && t2 < T) {
den_count++; // 包含帧数
if (log_energy_data[t2] > energy_threshold)
num_count++; // log能量大于阈值的帧数
}
}
if (num_count >= den_count * opts.vad_proportion_threshold)
(*output_voiced)(t) = 1.0;
else
(*output_voiced)(t) = 0.0;
}
}
}
使用方法
sid/compute_vad_decision.sh --nj 1 --cmd "$train_cmd" --vad-config vad.conf文件路径 data目录路径 log目录路径 vad目录路径
utils/fix_data_dir.sh data目录路径
该脚本会从data目录路径中读取feats.scp文件,并根据vad.conf文件路径读取vad.conf配置文件;
然后会在vad中生成多个(根据nj值确定生成的文件数)vad.ark和vad.scp文件,并把log信息写入log文件保存在log目录下,最终会将所有vad.scp合并为一个总的vad.scp放在data目录下;