1. 程式人生 > >WebRTC之語音活動檢測(VAD)演算法

WebRTC之語音活動檢測(VAD)演算法

VAD(Voice Activity Detection)演算法的作用是檢測語音,在遠場語音互動場景中,VAD面臨著兩個難題:

1.    如何成功檢測到最低能量的語音(靈敏度)。
2.    如何在多噪環境下成功檢測(漏檢率和虛檢率)。
漏檢反應的是原本是語音但是沒有檢測出來,而虛檢率反應的是不是語音訊號而被檢測成語音訊號的概率。相對而言漏檢是不可接受的,而虛檢可以通過後端的ASR和NLP演算法進一步過濾,但是虛檢會帶來系統資源利用率上升,隨之系統的功耗和發熱會進一步增加,而這會上升為可移動和隨聲攜帶裝置的一個難題。
本文基於WebRTC的AEC演算法,WebRTC的VAD模型採用了高斯模型,這一模型應用極其廣泛。

高斯分佈

高斯分佈又稱為正態分佈(Normal distribution/Gaussian distribution)。
若隨機變數X服從一個數學期望為μ,標準差為σ^2的高斯分佈,則:
X~N(μ,σ^2)
其概率密度函式為:
f(x)=1/(√2π σ) e^(-〖(x-u)〗^2/(2σ^2 ))
高斯在webRTC中的使用:
f(x_k |Z,r_k)=1/√2π e^(-(x_k-u_z )^2/(2σ^2 ))
x_k是選取的特徵向量,webRTC中指x_k是六個子帶的能量(子帶是80~250Hz,250~500Hz,500Hz~1K, 1~2K,2~3K,3~4KHz,變數feature_vector存放的就是子帶能量序列),r_k是均值u_z和方差σ的引數結合,這兩個引數決定了高斯分佈的概率。Z=0情況是計算噪聲的概率,Z=1是計算是語音的概率。

這裡採用最高頻率是4KHz的原因是,webRTC中程式將輸入(48KHz,32HKz,16KHz)都下采樣到8KHz,這樣根據奎斯特頻率定理,有用的頻譜就是4KHz以下。

當然也可以採用8KHz截止頻率,這樣就需要自己訓練和修改高斯模型的引數了,這個演算法我試過,要比基於DNN的方法好用,靈活性大些,體現在引數自適應更新上,舉例來說,在夜晚安靜家庭場景中,噪聲的均值就比較低的,白天周邊環境噪聲多了時,噪聲特徵的均值也會隨之調整,針對DNN的方法,引數一旦訓練完畢,那麼適用的場景的就定了,如果要增大適用場景,首先要收集目標場景的資料,標註好的資料重新訓練(通常要增加引數數量),這樣的過程會導致1.資料收整合本高,2.引數過多計算代價大(VAD一般是一直工作的)。

Webrtc採用的是GMM模型

等待視訊連結地址。

WebRTC演算法流程

1. 設定VAD激進模式

共四種模式,用數字0~3來區分,激程序度與數值大小正相關。
0: Normal,1:low Bitrate, 2:Aggressive;3:Very Aggressive
這些激進模式是和以下引數是息息相關的。

  1. <comman_audio/vad/vad_core.c>  
  2. // Mode 0, Quality.
  3. staticconst int16_t kOverHangMax1Q[3] = { 8, 4, 3 };  
  4. staticconst int16_t kOverHangMax2Q[3] = { 14, 7, 5 };  
  5. staticconst int16_t kLocalThresholdQ[3] = { 24, 21, 24 };  
  6. staticconst int16_t kGlobalThresholdQ[3] = { 57, 48, 57 };  
  7. // Mode 1, Low bitrate.
  8. staticconst int16_t kOverHangMax1LBR[3] = { 8, 4, 3 };  
  9. staticconst int16_t kOverHangMax2LBR[3] = { 14, 7, 5 };  
  10. staticconst int16_t kLocalThresholdLBR[3] = { 37, 32, 37 };  
  11. staticconst int16_t kGlobalThresholdLBR[3] = { 100, 80, 100 };  
  12. // Mode 2, Aggressive.
  13. staticconst int16_t kOverHangMax1AGG[3] = { 6, 3, 2 };  
  14. staticconst int16_t kOverHangMax2AGG[3] = { 9, 5, 3 };  
  15. staticconst int16_t kLocalThresholdAGG[3] = { 82, 78, 82 };  
  16. staticconst int16_t kGlobalThresholdAGG[3] = { 285, 260, 285 };  
  17. // Mode 3, Very aggressive.
  18. staticconst int16_t kOverHangMax1VAG[3] = { 6, 3, 2 };  
  19. staticconst int16_t kOverHangMax2VAG[3] = { 9, 5, 3 };  
  20. staticconst int16_t kLocalThresholdVAG[3] = { 94, 94, 94 };  
  21. staticconst int16_t kGlobalThresholdVAG[3] = { 1100, 1050, 1100 };  
它們在計算高斯模型概率時用到。

2. 幀長設定

A)    共有三種幀長可以用到,分別是80/10ms,160/20ms,240/30ms,實際上目前只支援10ms的幀長。
B)    其它取樣率的48k,32k,24k,16k會重取樣到8k來計算VAD。
       之所以選擇上述三種幀長度,是因為語音訊號是短時平穩訊號,其在10ms~30ms之間可看成平穩訊號,高斯馬爾科夫等訊號處理方法基於的前提是訊號是平穩的,在10ms~30ms,平穩訊號處理方法是可以使用的。

3. 高斯模型中特徵向量選取

在WebRTC的VAD演算法中用到了聚類的思想,只有兩個類,一個類是語音,一個類是噪聲,對每幀訊號都求其是語音和噪聲的概率,根據概率進行聚類,當然為了避免一幀帶來的誤差也有一個統計量判決在演算法裡,那麼問題來了,選擇什麼樣的特徵作為高斯分佈的輸入呢?這關係到聚類結果的準確性,也即VAD效能,毋庸置疑,既然VAD目的是區分噪聲和語音,那麼噪聲訊號和語音訊號這兩種訊號它們的什麼特徵相差最大呢?選擇特徵相差比較大自然能得到比較好的區分度。
  眾所周知,訊號的處理分類主要有時域,頻域和空域,從空域上看,webRTC的VAD是基於單麥克的,噪聲和語音沒有空間區分度的概念,在多麥克風場景,確實基於多麥克風的VAD演算法,從時域上看,而者都是時變訊號,且短時訊號變化率比較小,所以推算來推算去只有頻域的區分度可能是比較好的。

汽車噪聲頻譜

粉紅噪聲頻譜

白噪聲頻譜

語音聲譜

 從以上四個圖中,可以看到從頻譜來看噪聲和語音,它們的頻譜差異還是比較大,且以一個個波峰和波谷的形式呈現。
  WebRTC正式基於這一假設,將頻譜分成了6個子帶。它們是:
    80Hz~250Hz,250Hz~500Hz,500Hz~1K,1K~2K,2K~3K,3K~4K。分別對應於feature[0],feature[1],feature[2],...,feature[5]。
可以看到以1KHz為分界,向下500HZ,250Hz以及170HZ三個段,向上也有三個段,每個段是1KHz,這一頻段涵蓋了語音中絕大部分的訊號能量,且能量越大的子帶的區分度越細緻。
  我國交流電標準是220V~50Hz,電源50Hz的干擾會混入麥克風採集到的資料中且物理震動也會帶來影響,所以取了80Hz以上的訊號。

在webRTC計算的函式在filter_bank.c檔案中,前面說的基於啟用的DNN也可以是基於fbank特徵。

高通濾波器設計

高通濾波器的作用有兩點:1.濾除直流分量,2提升高頻成分(人耳對3.5KHz最為敏感)

  1. // High pass filtering, with a cut-off frequency at 80 Hz, if the |data_in| is
  2. // sampled at 500 Hz.
  3. //
  4. // - data_in      [i]   : Input audio data sampled at 500 Hz.
  5. // - data_length  [i]   : Length of input and output data.
  6. // - filter_state [i/o] : State of the filter.
  7. // - data_out     [o]   : Output audio data in the frequency interval
  8. //                        80 - 250 Hz.
  9. staticvoid HighPassFilter(const int16_t* data_in, size_t data_length,  
  10.                            int16_t* filter_state, int16_t* data_out) {  
  11.   size_t i;  
  12.   const int16_t* in_ptr = data_in;  
  13.   int16_t* out_ptr = data_out;  
  14.   int32_t tmp32 = 0;  
  15.   // The sum of the absolute values of the impulse response:
  16.   // The zero/pole-filter has a max amplification of a single sample of: 1.4546
  17.   // Impulse response: 0.4047 -0.6179 -0.0266  0.1993  0.1035  -0.0194
  18.   // The all-zero section has a max amplification of a single sample of: 1.6189
  19.   // Impulse response: 0.4047 -0.8094  0.4047  0       0        0
  20.   // The all-pole section has a max amplification of a single sample of: 1.9931
  21.   // Impulse response: 1.0000  0.4734 -0.1189 -0.2187 -0.0627   0.04532
  22.   for (i = 0; i < data_length; i++) {  
  23.     // All-zero section (filter coefficients in Q14).
  24.     tmp32 = kHpZeroCoefs[0] * *in_ptr;  
  25.     tmp32 += kHpZeroCoefs[1] * filter_state[0];  
  26.     tmp32 += kHpZeroCoefs[2] * filter_state[1];  
  27.     filter_state[1] = filter_state[0];  
  28.     filter_state[0] = *in_ptr++;  
  29.     // All-pole section (filter coefficients in Q14).
  30.     tmp32 -= kHpPoleCoefs[1] * filter_state[2];  
  31.     tmp32 -= kHpPoleCoefs[2] * filter_state[3];  
  32.     filter_state[3] = filter_state[2];  
  33.     filter_state[2] = (int16_t) (tmp32 >> 14);  
  34.     *out_ptr++ = filter_state[2];  
  35.   }  
  36. }  
WebRTC在設計該濾波器上還是很有技巧的,技巧有二:
1.    定點數計算,指兩個方面,一是濾波係數量化,而是計算過程的定點化,高斯模型計算也使用了這一技巧。
2.    舍入技巧,減少運算量。
下面就來看看,這些技巧是如何使用的,首先根據程式碼的註釋可以看出,
全零點和全極點脈衝響應的實際上是浮點數,它們脈衝響應分別是:
0.4047 -0.8094  0.4047  0       0        0
1.0000  0.4734 -0.1189 -0.2187 -0.0627   0.04532
所以可見應該是六階方程,但是超過3階後,零點全零,極點數值較小,這時適當增大第三個數值,達到減少計算次數的目的。

量化是按照2的十四次方進行定點化。這是因為最差情況下,零極點的放大倍數不超過兩倍,所以16位數可以表示的下來。其零極點繪圖如下:


對這兩個圖的解釋就忽略了,能夠看懂上述程式碼和兩張圖的意義,就可以更改濾波器的特性了,對不要相位資訊的,採用IIR比FIR達到相同的增益平坦度需要的階數要少。關於高通濾波器的設計還有疑問的可以留言共同交流。頻響如下:

WebRtcVad_CalculateFeatures函式計算每個子帶的能量。能量結果存放在features數組裡,然後呼叫GmmProbability計算概率。

  1. int WebRtcVad_CalcVad8khz(VadInstT* inst, const int16_t* speech_frame,  
  2.                           size_t frame_length)  
  3. {  
  4.     int16_t feature_vector[kNumChannels], total_power;  
  5.     // Get power in the bands
  6.     total_power = WebRtcVad_CalculateFeatures(inst, speech_frame, frame_length,  
  7.                                               feature_vector);  
  8.     // Make a VAD
  9.     inst->vad = GmmProbability(inst, feature_vector, total_power, frame_length);  
  10.     return inst->vad;  
  11. }  

計算流程

高斯模型有兩個引數H0和H1,它們分表示的是噪聲和語音,判決測試使用LRT(likelihood ratio test)。分為全域性和區域性兩種情況。

a)高斯概率計算採用的高斯公式如下:

這裡其實採用了兩個引數高斯分佈,但是假設了這兩個引數是相互獨立的:

這裡要做個簡化以減少計算量。將這兩個高斯看成是不相關的,

這裡可以看到做了三個簡化,第一個是把指數前的係數省掉了,這是因為在做似然比檢驗時,可以消掉,第二個簡化是假設這兩個高斯分佈是不相關的,第三個簡化是將乘法近似化簡成加法。使用高斯分佈這個在kaldi中也有例子,kaldi中基於GMM的語言模型分成三種,第一種是類似這裡的獨立同分布模型,第二種是互相關對角陣元素非零,第三種是全高斯互相關模型。

用多個高斯來近似一個語音包絡這種方法,在插值時也用到,即用多個sinc函式進行分數位插值。

c)對數似然比,分為全域性和區域性,全域性是六個子帶之加權之和,而區域性是指每一個子帶則是區域性,所以語音判決會先判斷子帶,子帶判斷沒有時會判斷全域性,只要有一方過了,就算有語音,公式表達如下:

後記:

和判決準則相關的引數在vad_core.c檔案,他們是:

  1. // Spectrum Weighting
  2. staticconst int16_t kSpectrumWeight[kNumChannels] = { 6, 8, 10, 12, 14, 16 };  
  3. staticconst int16_t kNoiseUpdateConst = 655; // Q15
  4. staticconst int16_t kSpeechUpdateConst = 6554; // Q15
  5. staticconst int16_t kBackEta = 154; // Q8
  6. // Minimum difference between the two models, Q5
  7. staticconst int16_t kMinimumDifference[kNumChannels] = {  
  8.     544, 544, 576, 576, 576, 576 };  
  9. // Upper limit of mean value for speech model, Q7
  10. staticconst int16_t kMaximumSpeech[kNumChannels] = {  
  11.     11392, 11392, 11520, 11520, 11520, 11520 };  
  12. // Minimum value for mean value
  13. staticconst int16_t kMinimumMean[kNumGaussians] = { 640, 768 };  
  14. // Upper limit of mean value for noise model, Q7
  15. staticconst int16_t kMaximumNoise[kNumChannels] = {  
  16.     9216, 9088, 8960, 8832, 8704, 8576 };  
  17. // Start values for the Gaussian models, Q7
  18. // Weights for the two Gaussians for the six channels (noise)
  19. staticconst int16_t kNoiseDataWeights[kTableSize] = {  
  20.     34, 62, 72, 66, 53, 25, 94, 66, 56, 62, 75, 103 };  
  21. // Weights for the two Gaussians for the six channels (speech)
  22. staticconst int16_t kSpeechDataWeights[kTableSize] = {  
  23.     48, 82, 45, 87, 50, 47, 80, 46, 83, 41, 78, 81 };  
  24. // Means for the two Gaussians for the six channels (noise)
  25. staticconst int16_t kNoiseDataMeans[kTableSize] = {  
  26.     6738, 4892, 7065, 6715, 6771, 3369, 7646, 3863, 7820, 7266, 5020, 4362 };  
  27. // Means for the two Gaussians for the six channels (speech)
  28. staticconst int16_t kSpeechDataMeans[kTableSize] = {  
  29.     8306, 10085, 10078, 11823, 11843, 6309, 9473, 9571, 10879, 7581, 8180, 7483  
  30. };  
  31. // Stds for the two Gaussians for the six channels (noise)
  32. staticconst int16_t kNoiseDataStds[kTableSize] = {  
  33.     378, 1064, 493, 582, 688, 593, 474, 697, 475, 688, 421, 455 };  
  34. // Stds for the two Gaussians for the six channels (speech)
  35. staticconst int16_t kSpeechDataStds[kTableSize] = {  
  36. 相關推薦

    WebRTC語音活動檢測VAD演算法

    VAD(Voice Activity Detection)演算法的作用是檢測語音,在遠場語音互動場景中,VAD面臨著兩個難題: 1.    如何成功檢測到最低能量的語音(靈敏度)。2.    如何在多噪環境下成功檢測(漏檢率和虛檢率)。漏檢反應的是原本是語音但是沒有檢測出

    資料結構程式效能檢測:三種排序演算法·對比

    先上程式碼: #include<stdio.h> #include<time.h> # define MAX_SIZE 1001 void sort(int *a, int n); void sort2(int *a, int n)

    最小生成樹普里姆prim演算法C++實現

    最小生成樹之普里姆(Prim)演算法   最小生成樹:是在一個給定的無向圖G(V,E)中求一棵樹T,使得這棵樹擁有圖G中的所有頂點,且所有邊都是來自圖G中的邊,並且滿足整棵樹的邊權之和最小。 如上圖給出了一個圖G及其最小生成樹T,其中紅色的線即為最小生成樹的邊。最小生成樹

    作業系統頁面置換演算法先進先出FIFO演算法

    import java.util.LinkedList; import java.util.List; public class FIFO {public static void main(String[] args) {int framesize = 5;   //幀數量int[] s = { 1, 2,

    Windows 活動目錄AD服務器系統升級到2012環境介紹及準備

    AD 升級 activedirectory DHCP 1. AD服務器相關配置信息1 2 1.1 系統版本角色名稱操作系統版本語言數量ADWindows server 2003 sp2CN2ADWindows server 2012 R2CN21.2 主機名和IP地址服務器主機名IP地

    Windows 活動目錄AD服務器系統升級到2012域控升級

    AD acticedirectory 升級 活動目錄 域控 4.域控升級4.1服務器加域1. 修改AD2008的IP地址為10.10.1.11,AD2012服務器的IP地址為:10.10.1.122. 打開計算機屬性窗口,點擊“更改設置”修改計算機名稱分別為AD20

    N76E003ADC電量檢測程式、分析、電路

    模數轉換器即A/D轉換器,或簡稱ADC,通常是指一個將模擬訊號轉變為數字訊號的電子元件。 先來看看N76E003 ADC工作方式 再看下相關暫存器,方便理解上圖 現在我們只需要配置好以上幾個暫存器,就可以開始使用ADC了,為了保證程式的及時性,我們採取A

    深度學習物體檢測R-CNN

    作者Rgb 在這之前大部分物體檢測演算法都是基於傳統的影象處理方法,這是第一篇將深度學習用到物體檢測上的文章,直接影響是2012年ALEXNET在比賽中的重大成功。 簡單來說,RCNN使用以下四步實現目標檢測: a. 在影象中用slective search 方法 確定

    webrtc QOS方法Sender Side BWE待續

    背景介紹 BWE(Bandwidth Estimation)可能是WebRTC視訊引擎中最關鍵的部分。BWE模組負責決定你可以傳送多大位元速率視訊不會使網路擁塞,以防止視訊質量下降。 最初該演算法比較簡單,主要基於接收端的丟包率,來判斷髮送端使用多大位元速率視訊比較合適。

    論文筆記:語音情感識別語音特徵聲譜圖,log梅爾譜,MFCC,deltas

    一:原始訊號 從音訊檔案中讀取出來的原始語音訊號通常稱為raw waveform,是一個一維陣列,長度是由音訊長度和取樣率決定,比如取樣率Fs為16KHz,表示一秒鐘內取樣16000個點,這個時候如果音訊長度是10秒,那麼raw waveform中就有160000個值,值的大小通常表示的是振幅。 二:(線性

    論文筆記:語音情感識別語音特徵集eGeMAPS,ComParE,09IS,BoAW

    一:LLDs特徵和HSFs特徵 (1)首先區分一下frame和utterance,frame就是一幀語音。utterance是一段語音,是比幀高一級的語音單位,通常指一句話,一個語音樣本。utterance由多幀語音組成,通常對一個utterance做分幀來得到多幀訊號。 (2)LLDs(low level

    人臉識別人臉檢測--Haar特徵原理及實現

    本文主要由於OpenCV的haartraining程式,對haar特徵的補充及程式碼註釋。 Haar特徵的原理是什麼? Haar特徵分為三類:邊緣特徵、線性特徵、中心特徵和對角線特徵,組合成特徵模板。特徵模板內有白色和黑色兩種矩形,並定義該模板的特徵值為白色矩形畫

    人臉識別人臉檢測--人臉識別樣本製作及訓練測試

    閒得沒事,折騰下opencv 人臉識別,從樣本製作到評估。 1.直接copy opencv裡的原始碼,建立工程,新增opencv庫,可以直接cmake原始碼,但我之所以自己建立工程,是想多學習,並且降低與原始碼框架的耦合度。 這裡如果出現_imp__CreateToo

    雙門限法語音端點檢測Python實現

    寫在前面 花了幾天時間寫完了第一個視聽覺訊號處理的實驗,其實還挺簡單的,在這裡分享一下。 本文介紹一下利用雙門限法進行語音端點檢測的方法,該方法主要利用了語音的短時能量和短時過零率,關於這兩個語音特徵如何求解,前兩篇文章已經介紹過了(短時能量和短時過零率),這裡

    人臉識別人臉檢測--adaboost總結,整理

    20170706新增: 各種Adaboost variants的比較以及不均衡問題 1.這邊有個淺顯的解釋。 2.簡單解釋到程式碼實現。 3.相對來說,這個看起來不是個人總結。 4.手動C程式碼Adaboost + stump弱

    物件檢測行人檢測1

    問題定義 物件檢測技術是計算機視覺研究中一個重要的研究課題。這個問題所處理資料主要是圖片(對於視訊則是抽取成關鍵幀然後對每一幀進行處理),行人檢測則作為物件檢測的子問題,與通用物件檢測的不同點在於所檢測類別僅有行人。整個檢測過程的目標在於為圖片中所有的行人新

    機器學習案例實戰信用卡欺詐檢測從零開始,附資料,程式碼

    機器學習案例實戰之信用卡欺詐檢測故事背景:原始資料為個人交易記錄,但是考慮資料本身的隱私性,已經對原始資料進行了類似PCA的處理,現在已經把特徵資料提取好了,接下來的目的就是如何建立模型使得檢測的效果達到最好,這裡我們雖然不需要對資料做特徵提取的操作,但是面對的

    人臉識別疲勞檢測閾值法、KNN分類和K-means聚類

    Table of Contents 1、均值法 2、中值法 3、KNN 結合上一節在獲得人眼特徵點後需要對睜眼閉眼狀態做出判斷,方法的選擇需要經驗結合公平的評價方法,使用大量測試集得到不同方法下的精確度並做出比較: 1、均值法 50幀睜眼資料取均值,得到不同閾

    目標檢測-Caffe-SSD系列資料的處理-PASCAL VOC

    目標檢測任務之資料的處理 常見的目標檢測資料集之PASCAL VOC 1 . PASCAL VOC資料集介紹 資料集名稱 訓練集(本地訓) 測試集(本地測) PAS

    51微控制器外設——按鍵的檢測帶有標誌位的按鍵識別法

    前面提到了獨立按鍵的掃描方法(延時,消抖的方法),可見這種方法很大程度上可以實現按鍵的準確掃描。但是仔細一看,可以發現,它有一個缺點——存在while語句的鬆手檢測! 試想,倘若我們一直按著按鍵不鬆手,那我們的程式毫無疑問的一直卡在了while語句的鬆手檢測上