Kaldi特徵提取之-VAD

Kaldi特徵提取之-VAD

背景

  • VAD即 Voice Activity Detection, 用於檢測靜音和非靜音。通過使用VAD,我們可以找到有效語音段,剔除靜音段,在語音識別等過程中可以大大減少要處理的數據量。VAD通常有多種方法,簡單的如幀能量或者幀幅度,複雜的還可以用神經網絡。下圖是一段語音的波形圖,VAD可以將圖中紅色框內的地方剔除。

    這裏寫圖片描述

VAD檢測

  • 注意:以下所有方法都以幀爲單位進行,幀長度爲N

  • 方法一: 幀幅度(絕對值和)
    這種方法計算最爲簡單,但是如果背景聲音比較大,則效果會比較差,計算公式如下:

    amplitudesi=j=1N|framei(j)|
    這裏寫圖片描述
    對比上下兩幅圖可以看到一些規律,靜音區對應的幅度較低,通過設置low_thres和high_thres 可以過濾掉一部分靜音。
  • 方法二:幀能量(平方和)
    這種計算方法也比較簡單,和方法一的性質基本一致,但是可以增大聲音強度的對比度。計算公式如下:

    energyi=j=1Nframei(j)2
    這裏寫圖片描述
    對比中間和最下邊的圖,可以發現方法二加強了聲音幅度的對比度。同樣的,還是通過設置合理的low_thres和high_thres過濾掉一部分靜音。
  • 方法三:短時過零率分析
    短時過零率表示一幀語音中語音信號波形穿過橫軸(零電平)的次數。對於連續語音信號(模擬信號),過零意味着時域波形通過時間軸;對於離散信號(數字信號),相鄰採樣值改變符號即意味着過零,過零率就是樣本符號改變的次數。計算公式如下:

    Zi=12j=2N|sgn(framei(j))sgn(framei(j1))|sgn
    這裏寫圖片描述從圖中可以看出,過零率在沒有噪聲的位置表現良好,但是在有噪聲的地方表現並不好,坑干擾能力比較差。
  • 方法四: 能量+滑動窗口(Kaldi)

    • 首先,需要說明的是,這裏的能量是方法一或者方法二的計算結果,這裏我們假設使用的是方法二計算。代碼如下:

      void ComputeVadEnergy(const VadEnergyOptions &opts,
                        const MatrixBase<BaseFloat> &feats,
                        Vector<BaseFloat> *output_voiced) {
        int32 T = feats.NumRows();
        output_voiced->Resize(T);
        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;
        if (opts.vad_energy_mean_scale != 0.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++;
            }
          }
          if (num_count >= den_count * opts.vad_proportion_threshold)
            (*output_voiced)(t) = 1.0;
          else
            (*output_voiced)(t) = 0.0;
        }
      }  
      參數 意義
      vad_energy_threshold 能量閾值
      vad_energy_mean_scale 平均能量的放大(縮小)係數
      vad_frames_context 窗口長度的一半
      vad_proportion_threshold 窗口內超過閾值的幀數的比例

      效果如下圖:
      這裏寫圖片描述

    • 與其他方法不同之處在於,kaldi利用了前後幀的關係,而不是孤立的單獨考察每一幀。

  • 方法五 : 神經網絡

    • 隨着神經網絡的興起,也有些人開始用CNN、DNN做VAD。用神經網絡的優點是:神經網絡表達能力強大,具有良好的抗噪聲能力,而且我們可以把識別範圍外的所有其他都當做是Sil,當然這種情況下就不再是嚴格意義上的VAD;缺點是:計算量比較大,有點得不償失的感覺。
  • 難點分析

    • 上面幾種方法大都需要設置各種閾值,這是一個難點。閾值太小,過濾效果不明顯;閾值太大,可能會過濾掉有效語音。實際使用中,通常閾值會設置的比較鬆,避免過濾掉有用信息。合理的閾值設置,需要考慮實際使用情況,用一個較大的數據集進行統計,得到一個合理的閾值。

資源

參考

  1. VAD
  2. 神經網絡
  3. 過零率
  4. 語音信號處理,第三版,4.3節
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章