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
這些激進模式是和以下引數是息息相關的。
- <comman_audio/vad/vad_core.c>
- // Mode 0, Quality.
- staticconst int16_t kOverHangMax1Q[3] = { 8, 4, 3 };
- staticconst int16_t kOverHangMax2Q[3] = { 14, 7, 5 };
- staticconst int16_t kLocalThresholdQ[3] = { 24, 21, 24 };
- staticconst int16_t kGlobalThresholdQ[3] = { 57, 48, 57 };
- // Mode 1, Low bitrate.
- staticconst int16_t kOverHangMax1LBR[3] = { 8, 4, 3 };
- staticconst int16_t kOverHangMax2LBR[3] = { 14, 7, 5 };
- staticconst int16_t kLocalThresholdLBR[3] = { 37, 32, 37 };
- staticconst int16_t kGlobalThresholdLBR[3] = { 100, 80, 100 };
- // Mode 2, Aggressive.
- staticconst int16_t kOverHangMax1AGG[3] = { 6, 3, 2 };
- staticconst int16_t kOverHangMax2AGG[3] = { 9, 5, 3 };
- staticconst int16_t kLocalThresholdAGG[3] = { 82, 78, 82 };
- staticconst int16_t kGlobalThresholdAGG[3] = { 285, 260, 285 };
- // Mode 3, Very aggressive.
- staticconst int16_t kOverHangMax1VAG[3] = { 6, 3, 2 };
- staticconst int16_t kOverHangMax2VAG[3] = { 9, 5, 3 };
- staticconst int16_t kLocalThresholdVAG[3] = { 94, 94, 94 };
- 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最為敏感)
- // High pass filtering, with a cut-off frequency at 80 Hz, if the |data_in| is
- // sampled at 500 Hz.
- //
- // - data_in [i] : Input audio data sampled at 500 Hz.
- // - data_length [i] : Length of input and output data.
- // - filter_state [i/o] : State of the filter.
- // - data_out [o] : Output audio data in the frequency interval
- // 80 - 250 Hz.
- staticvoid HighPassFilter(const int16_t* data_in, size_t data_length,
- int16_t* filter_state, int16_t* data_out) {
- size_t i;
- const int16_t* in_ptr = data_in;
- int16_t* out_ptr = data_out;
- int32_t tmp32 = 0;
- // The sum of the absolute values of the impulse response:
- // The zero/pole-filter has a max amplification of a single sample of: 1.4546
- // Impulse response: 0.4047 -0.6179 -0.0266 0.1993 0.1035 -0.0194
- // The all-zero section has a max amplification of a single sample of: 1.6189
- // Impulse response: 0.4047 -0.8094 0.4047 0 0 0
- // The all-pole section has a max amplification of a single sample of: 1.9931
- // Impulse response: 1.0000 0.4734 -0.1189 -0.2187 -0.0627 0.04532
- for (i = 0; i < data_length; i++) {
- // All-zero section (filter coefficients in Q14).
- tmp32 = kHpZeroCoefs[0] * *in_ptr;
- tmp32 += kHpZeroCoefs[1] * filter_state[0];
- tmp32 += kHpZeroCoefs[2] * filter_state[1];
- filter_state[1] = filter_state[0];
- filter_state[0] = *in_ptr++;
- // All-pole section (filter coefficients in Q14).
- tmp32 -= kHpPoleCoefs[1] * filter_state[2];
- tmp32 -= kHpPoleCoefs[2] * filter_state[3];
- filter_state[3] = filter_state[2];
- filter_state[2] = (int16_t) (tmp32 >> 14);
- *out_ptr++ = filter_state[2];
- }
- }
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計算概率。
- int WebRtcVad_CalcVad8khz(VadInstT* inst, const int16_t* speech_frame,
- size_t frame_length)
- {
- int16_t feature_vector[kNumChannels], total_power;
- // Get power in the bands
- total_power = WebRtcVad_CalculateFeatures(inst, speech_frame, frame_length,
- feature_vector);
- // Make a VAD
- inst->vad = GmmProbability(inst, feature_vector, total_power, frame_length);
- return inst->vad;
- }
計算流程
高斯模型有兩個引數H0和H1,它們分表示的是噪聲和語音,判決測試使用LRT(likelihood ratio test)。分為全域性和區域性兩種情況。
a)高斯概率計算採用的高斯公式如下:
這裡其實採用了兩個引數高斯分佈,但是假設了這兩個引數是相互獨立的:
這裡要做個簡化以減少計算量。將這兩個高斯看成是不相關的,
這裡可以看到做了三個簡化,第一個是把指數前的係數省掉了,這是因為在做似然比檢驗時,可以消掉,第二個簡化是假設這兩個高斯分佈是不相關的,第三個簡化是將乘法近似化簡成加法。使用高斯分佈這個在kaldi中也有例子,kaldi中基於GMM的語言模型分成三種,第一種是類似這裡的獨立同分布模型,第二種是互相關對角陣元素非零,第三種是全高斯互相關模型。
用多個高斯來近似一個語音包絡這種方法,在插值時也用到,即用多個sinc函式進行分數位插值。
c)對數似然比,分為全域性和區域性,全域性是六個子帶之加權之和,而區域性是指每一個子帶則是區域性,所以語音判決會先判斷子帶,子帶判斷沒有時會判斷全域性,只要有一方過了,就算有語音,公式表達如下:
後記:
和判決準則相關的引數在vad_core.c檔案,他們是:
- // Spectrum Weighting
- staticconst int16_t kSpectrumWeight[kNumChannels] = { 6, 8, 10, 12, 14, 16 };
- staticconst int16_t kNoiseUpdateConst = 655; // Q15
- staticconst int16_t kSpeechUpdateConst = 6554; // Q15
- staticconst int16_t kBackEta = 154; // Q8
- // Minimum difference between the two models, Q5
- staticconst int16_t kMinimumDifference[kNumChannels] = {
- 544, 544, 576, 576, 576, 576 };
- // Upper limit of mean value for speech model, Q7
- staticconst int16_t kMaximumSpeech[kNumChannels] = {
- 11392, 11392, 11520, 11520, 11520, 11520 };
- // Minimum value for mean value
- staticconst int16_t kMinimumMean[kNumGaussians] = { 640, 768 };
- // Upper limit of mean value for noise model, Q7
- staticconst int16_t kMaximumNoise[kNumChannels] = {
- 9216, 9088, 8960, 8832, 8704, 8576 };
- // Start values for the Gaussian models, Q7
- // Weights for the two Gaussians for the six channels (noise)
- staticconst int16_t kNoiseDataWeights[kTableSize] = {
- 34, 62, 72, 66, 53, 25, 94, 66, 56, 62, 75, 103 };
- // Weights for the two Gaussians for the six channels (speech)
- staticconst int16_t kSpeechDataWeights[kTableSize] = {
- 48, 82, 45, 87, 50, 47, 80, 46, 83, 41, 78, 81 };
- // Means for the two Gaussians for the six channels (noise)
- staticconst int16_t kNoiseDataMeans[kTableSize] = {
- 6738, 4892, 7065, 6715, 6771, 3369, 7646, 3863, 7820, 7266, 5020, 4362 };
- // Means for the two Gaussians for the six channels (speech)
- staticconst int16_t kSpeechDataMeans[kTableSize] = {
- 8306, 10085, 10078, 11823, 11843, 6309, 9473, 9571, 10879, 7581, 8180, 7483
- };
- // Stds for the two Gaussians for the six channels (noise)
- staticconst int16_t kNoiseDataStds[kTableSize] = {
- 378, 1064, 493, 582, 688, 593, 474, 697, 475, 688, 421, 455 };
- // Stds for the two Gaussians for the six channels (speech)
- staticconst int16_t kSpeechDataStds[kTableSize] = {
-
相關推薦
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
N76E003之ADC電量檢測(程式、分析、電路)
模數轉換器即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語句的鬆手檢測上