WebRTC Voice Activity Detection

1 关于WebRTC VAD

1.1 WebRTC VAD简介

其实在WebRTC的VAD中用到了一个很重要的方法的思想,这个方法就是聚类。实际上我们都可以知道,分出来的只有两个类,一是语音二是噪声。我们要对每一帧信号都求语音和噪声的概率,然后根据概率来进行聚类。那么,选择怎样的特征来作为高斯分布的输入呢?这种特征的选取可是关系着VAD性能是好是坏。我们的思想就是寻找噪声和语音相差最大的特征,或者说尽可能大的特征。

众所周知,信号的处理分类主要有时域、频域和空域。首先从空域上看,WebRTC的VAD是基于单个麦克风的,噪声和语音没有空间区分度的概念;然后从时域上看,是时变信号,且短时信号变化率比较小,所以总的来说,频域的区分度是比较好的。

我们可以发现,噪声和语音在频谱上差异还是非常大的,且以一个一个的波峰和波谷来表现。基于此,WebRTC VAD将频带分为了6个子带:80Hz~250Hz,250Hz~500Hz,500Hz~1K,1K~2K,2K~3K,3K~4K,在程序里面分别对应了分别对应于feature_vector [0],feature_vector [1],feature_vector [2],feature_vector [3],feature_vector [4],feature_vector [5]。之所以最高为4k是因为,WebRTC在处理的时候采样率统一调整为了8kHz,所以根据奈奎斯特定理,用于的频率就是4kHz以下。

可以看到以1KHz为分界,向下500HZ,250Hz以及170HZ三个段,向上也有三个段,每个段是1KHz,这一频段涵盖了语音中绝大部分的信号能量,且能量越大的子带的区分度越细致。由于我国交流电标准是220V~50Hz,电源50Hz的干扰会混入麦克风采集到的数据中且物理震动也会带来影响,所以取了80Hz以上的信号。

WebRTC VAD使用的是GMM(高斯混合模型)进行分类,使Noise作为一类,Speech作为一类,两类求求后验概率,并且实时更新GMM参数。

WebRTC VAD只能工作在采样率为8000Hz的模式下,故对16kHz、32kHz、48kHz都需要进行重新采样来转换到8000Hz。目前程序仅支持8000Hz、16kHz、32kHz和48kHz。

总的来说,WebRTC VAD分为以下几步:

1.创建句柄(WebRtcVad_Create())。

2.初始化句柄(WebRtcVad_Init())。

3.设置VAD的工作模式(WebRtcVad_set_mode()),VAD的工作模式主要有以下四种:

表1.1 VAD的工作模式

4.判断当前语音文件的采样率,若采样率小于8000Hz,直接退出;若采样率不为8000Hz,则进行下采样,将高采样率重新采样到8000Hz,然后进行VAD判决;若采样率为8000Hz,则直接进行VAD判决。

5.进行VAD判决。首先计算6个子带的能量,分别保存到feature_vector[0]~feature_vector[5](WebRtcVad_CalculateFeatures())。然后通过高斯混合模型分别计算语音和非语音的概率,使用假设检验的方法确定信号的类型(GmmProbability())。首先通过高斯模型计算假设检验中的H0和H1(C代码是用h0_test和h1_test表示),通过门限判决vadflag; 然后更新概率计算所需要的语音均值(speech_means)、噪声的均值(noise_means)、语音方差(speech_stds) 和噪声方差(noise_stds)。

1.2 整体函数框图

图1.1 整体系统框图

2 函数关系图谱

2.1 主体函数关系

图2.1 主体函数关系

2.2 核心处理函数关系

图2.2 核心函数关系

3 逐个函数的讲解

3.1 WebRtcVad_CalculateFeatures()

WebRTCVAD中,对上面划分的每一个子带计算其能量,然后计算到目前为止总的能量(total_energy)。如果total_energy没有超过kMinEnergy,则对total_energy进行更新,更新的方法就是在kMinEnergy上面加个数字(程序里面是+1)。total_energy是在GmmProbability()中用作能量的指示符。

    这个函数里面用到了两个滤波器,一个滤波器是子带划分滤波器SplitFilter(),它就是将频率范围内数据分隔成两个频率范围,用于子带划分;一个是高通滤波器HighPassFilter(),用来过滤到0~80Hz信号的。

3.2 GmmProbability();

    首先需要设置一些阈值,然后判断total_power是否大于所设置的可以处理的能量标准kMinEnergy,如果不大于,自然没办法处理,如果大于则可以进行处理。处理主要有两部分:一、计算语音的可能性,然后根据此得出VAD判决;二、更新底层模型,做出决定。

具体来说,我们将每一个频率子带称为一个“通道”,假设噪声是H0,语音是H1。

那么对于每一个通道,我们使用由kNumGaussians组成的GMM对概率进行建模,每一个通道都具有不同的均值和标准差,具体取决于H0或H1。

第一步,计算出noise_probability和speech_probability。

第二步,计算对数似然比

可以近似处理为

shifts_h0-shifts_h1+log2(1+b1)-log2(1+b0)~=shifts_h0 - shifts_h1

注意:b0和b1都小于1,因此0<=log2(1+b0)<1.

第三步,使用谱均衡更新sum_log_likelihood_ratios,以用于更新全局VAD判决。

第四步,做出本地VAD判决。

第五步,计算更新GMM后使用的局部噪声概率,然后计算稍后在更新GMM时使用的本地语音概率。

对于每一个通道处理完之后,又要做以下操作:

第一步,做出全局VAD判决。

第二步,然后更新模型参数。

第三步,如果模型太过于接近,将它们分离。

第四步,控制语音和噪声均值不要漂移太多。

在完成上述处理之后,对结果进行平滑处理。具体框图如下:

图3.1 GmmProbability()函数的流程图

此文章为个人学习笔记整理所得,如有转载,敬请注明。下一期将更新关于WebRTC中AGC(自动增益控制)的学习笔记,敬请期待。