博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
语音特征提取学习笔记--对比kaldi、htk、w2l的语音提取过程。
阅读量:2122 次
发布时间:2019-04-30

本文共 12488 字,大约阅读时间需要 41 分钟。

前言

任何模式识别系统的第一个问题都是选择什么样的特征作为系统的输入,与语音识别也不例外,为了准确地反映待测系统的特性,并且让识别系统本身容易处理和分类,语音专家经过了几十年的研究,各种各样的语音特性提取也被提出来,而在经典的GMM-HMM模型中,MFCC是绝对的C位。不过在KALDI和HTK软件中,除了MFCC,其实还提供了其他一些特性提取方法,其中就包括PLP和FilterBank。本文又加入了w2l,目前最流行的开源人工智能网络ASR工具集,横向比较中,了解和学习一下语音提取技术的特点和发展。

基本概念

Cepstrum

倒谱,这个单词就是从spectrum的前四个字母反过来写衍生的,数学上定义为信号的傅里叶变换谱经对数运算后再进行的傅里叶反变换。由于一般傅里叶谱是复数谱,因而又称复倒谱。倒谱分析有时也被称为逆频率分析(quefrency 阿nalysis),属于同态滤波的范畴(liftering)。但这个mel倒谱和MFCC还不是一个概念。本段落剩下部分主要翻译网文[8]的内容,阐述倒谱的一些特征。

假设x(n)为时间域信号,X(k)是复数频谱,P(k)是功率谱 ,A(n)是自相关序列,C(n)为倒谱。省却复杂的数学运算,用 D F T DFT DFT I D F T IDFT IDFT表示傅立叶的正反变换,那么复频谱可以如下表示
D F T ( x ( n ) ) ⇒ X ( k ) DFT(x(n))\Rightarrow X(k) DFT(x(n))X(k)
逆变换则表示为:
I D F T ( X ( K ) ) ⇒ x ( n ) IDFT(X(K))\Rightarrow x(n) IDFT(X(K))x(n)
周期性的功率谱概念是有一个历史的,傅立叶级数提出后,首先在人们观测自然界中的周期现象时得到应用。19世纪末,Schuster提出用傅立叶级数的幅度平方作为函数中功率的度量,并将其命名为“周期图”(periodogram)。这是经典谱估计的最早提法,这种提法至今仍然被沿用,只不过现在是用快速傅立叶变换(FFT)来计算离散傅立叶变换(DFT),用DFT的幅度平方作为信号中功率的度量。
∣ D F T ( x ( n ) ) ∣ 2 ⇒ P ( k ) |DFT(x(n))|^2\Rightarrow P(k) DFT(x(n))2P(k)
功率谱的傅立叶逆变换实际上是一个自相关序列[Wiener–Khinchin theorem]。
I D F T ( P ( k ) ) ⇒ A ( n ) IDFT(P(k))\Rightarrow A(n) IDFT(P(k))A(n)
而在逆变换之前先做一个对数,那么逆变换的结果就是倒谱。
I D F T ( l o g ( P ( k ) ) ) ⇒ C ( n ) IDFT(log(P(k)))\Rightarrow C(n) IDFT(log(P(k)))C(n)
在这里插入图片描述在上述图片中,展示了原始语音信号的一帧数据、对数功率谱、自相关序列和倒谱。倒谱当中的峰值对应自相关序列当中的一个峰值,但是更为清晰。这个峰值的位置在58sample位置处,对应的基音频率为(16000/58)=275Hz (信号采样率为16kHz)。这是一个相当高的基音频率,原始语音信号是从一位女性说话人得到的。因为倒谱的强峰值,所以经常被用于基音检测。

LPCC(Linear Predictive Cepstral Coefficient)

这种所谓的线性预测倒谱系数几乎和计算倒谱的方法一致,除了利用平滑自回归(smoothed Auto-Regression)功率谱代替了前文提到的周期图谱估计。对于一个10阶的AR谱估计过程,利用Levinson Durbin algorithm计算前10个自相关系数得到10个线性预测系数。另外还有一种直接通过LPC码来得到LPCC的办法,可以参考[8],不是本篇重点,不做深入研究。需要提到的一点是Linear Prediction Coefficients (LPCs) and Linear Prediction Cepstral Coefficients (LPCCs)曾经是基于HMM模型ASR系统主流的语音特征提取方式,后来才被MFCC取代的。

MFCC

Mel Frequency Cepstral Ceofficient目前最主流的语音信号特征提取方式,相比ceptrum的流程,主要是增加了mel滤波,另外用DCT替换了IFFT。网上介绍的文章太多,流程列一下,详细略。[9]

preemphasis( y ( t ) = x ( t ) − α x ( t − 1 ) y(t)=x(t)-\alpha x(t-1) y(t)=x(t)αx(t1)
Frame the signal into short frames.(typical size 25ms, stripe 10ms)
For each frame calculate the periodogram estimate of the power spectrum.
Apply the mel filterbank to the power spectra, sum the energy in each filter.
Take the logarithm of all filterbank energies.
Take the DCT of the log filterbank energies.
Keep DCT coefficients 2-13, discard the rest.

MFSC

log mel-frequency spectral Coefficients比MFCC要简单,其实就是将MFCC的最后DCT部分省掉,只分析fiterbanks energies的对数,所以有的文献也将其称为Filter Banks。又因为这里也是对谱分析,所以不准确的说法也被称作spectrogram(语谱图),确切地说法可以叫做。mel对数语谱图。因为据说在人工智能神经网络的训练中,有证据[11]显示这个语音特征要比MFCC表现的优秀,所以在三种平台都支持MFSC(Filter Banks)的提取。

Spectrogram

经典的语谱图[12]是指经过短时傅立叶变换之后,将频域的能量信号影射成灰度(颜色)直方图,按照时间顺序绘制的二维图形,其中横轴为时间,纵轴为频率,每个频率线段的灰度深浅(颜色亮暗)表示该时刻对应的频谱分量的能量强弱。下图是经过mel滤波器组的log 功率谱,在语音识别过程往往更关注这个声谱图。

在这里插入图片描述

PLP:Perceptual Linear Predictive,感知线性预测)

是一种基于听觉模型的特征参数。简单的说,就是通过在不同的说话者之间变换他们语音频谱到最小的差别,同时又保留了重要的话音信息。该特征参数是全极点模型预测多项式的一组系数,等效于一种LPC( Linear Prediction Coefficient , 线性预测系数) 特征, 它们的不同之处是PLP 技术将人耳听觉试验获得的一些结论, 通过近似计算的方法进行了工程化处理, 应用到频谱分析中, 将输入的语音信号经听觉模型处理后所得到的信号替代传统的LPC 分析所用的时域信号。经过这样处理后的语音频谱考虑到了人耳的听觉特点, 因而有利于抗噪语音特征提取。[1] 其中,PLP和MFCC一个明显的区别是PLP选择了Bark频率尺度,MFCC则采用的mel频率尺度。

RASTA:Relative Spectral Transform

这是在语音信道中,一项针对频率子带的带同滤波分离技术,其目的是消除短期噪声波动,以及去除由于静态频谱污染而导致的频率固定偏移。经常将RASTA-PLP一起来使用。有两篇论文可以学习,H. Hermansky, “Perceptual linear predictive (PLP) analysis of speech”, H. Hermansky and N. Morgan, “RASTA processing of speech”。

Mel频率定标

暂略。

Bark频率

Bark(巴克)频率尺度是以Hz为单位,把频率映射到心理声学的24个临界频带上,第25个临界频带占据约:16K~20kHz的频率,1个临界频带的宽度等于一个Bark,简单的说,Bark尺度是把物理频率转换到心理声学的频率。

在这里插入图片描述

CMVN(Cepsturm Mean and Variance Normalization)

VTLN (特征级声道长度归一化)[3]

Kaldi 程序compute-mfcc-feats和compute-plp-feats接收一个VTLN(vocal tract length normalization )弯折因子选项。在目前的脚本中,这仅用作线性版的VTLN的初始化线性转换的一种方法。VTLN通过移动三角频率箱的中心频率的位置来实现。移动频率箱的弯折函数是一个在频域空间分段线性的函数。为理解它,记住以下数量关系:

0 <= low-freq <=vtln-low < vtln-high < high-freq <= nyquist

此处,low-freq和high-freq分别是用于标准MFCC或PLP计算的最低和最高频率(忽略更低和更高的频率)。vtln-low和vtln-high是用于VTLN的截止频率,它们的功能是确保所有梅尔滤波器有合适的宽度。

我们实现的VTLN弯折函数是一个分段线性函数,三个部分映射区间[low-freq,high-freq]至[low-freq, high-freq]。记弯折函数为W(f),f是频率。中段映射f到f/scale,scale是VTLN弯折因子(通常范围为0.8到1.2)。x轴上低段和中段的连接点是满足min(f,W(f)) = vtln-low的f点。x轴上中段和高端的连接点是满足max(f, W(f)) = vtln-high的f点。要求低段和高段的斜率和偏移是连续的且W(low-freq)=low-freq, W(high-freq)=high-freq。这个弯折函数和HTK的不同;HTK的版本中,"vtln-low"和"vtln-high"的数量关系是x轴上可以不连续的点,这意味着变量"vtln-high"必须基于弯折因子的可能范围的先验知识谨慎选择(否则梅尔滤波器可能为空)。

一个合理的设置如下(以16kHz采样的语音为例);注意这反映的是我们理解的合理值,并非任何非常细致的调试实验的结果。

low-freq vtln-low vtln-high high-freq nyquist

40 60 7200 7800 8000

HTK 的语音提取过程

HTK的代码是C语言,语音提取是一个集成工具HCopy实现的,这个工具可以利用配置文件和脚本文件(文件名)实现批处理。 HTK支持FFT和LPC两种语音信号的的分析,MFCC是基于FFT变换的对数谱分析,目前主流的选择。

在这里插入图片描述HCopy配置文件内容:

# Coding parametersTARGETKIND = MFCC_0TARGETRATE = 100000.0SAVECOMPRESSED = TSAVEWITHCRC = TWINDOWSIZE = 250000.0USEHAMMING = TPREEMCOEF = 0.97NUMCHANS = 26CEPLIFTER = 22NUMCEPS = 12ENORMALISE = F

MFCC_0表示MFCC 用C0作为功率分量,10ms的帧周期(HTK 采用100ns单位),25ms的采样窗,以为着15ms的overlap。输出采用带crc检验的压缩格式,汉明窗,系数为0.97的一阶预加重,滤波器池有16个通道,产生12个MFCC系数,cep滤波系数22。如果处理静态文件ENORMALISE 默认是TRUE,因为最好对音频文件做归一化。实时数据处理需要关闭。[4]

具体阅读代码,涉及HCopy.c,HParms.c两级文件OpenSpeechFile->OpenParmFile->OpenBuffer->OpenAsChannel->FillBufFromChannel->GetFrameFromChannel->ConvertFrame, 在ConvertFrame函数里可以了解htk支持的语音特征

switch(btgt){   case LPC:      Wave2LPC(cf->s,cf->a,cf->k,&re,&te);      v = cf->a; bsize = cf->lpcOrder;      break;   case LPREFC:      Wave2LPC(cf->s,cf->a,cf->k,&re,&te);      v = cf->k; bsize = cf->lpcOrder;      break;   case LPCEPSTRA:      Wave2LPC(cf->s,cf->a,cf->k,&re,&te);      LPC2Cepstrum(cf->a,cf->c);      if (cf->cepLifter > 0)         WeightCepstrum(cf->c, 1, cf->numCepCoef, cf->cepLifter);      v = cf->c; bsize = cf->numCepCoef;      break;   case MELSPEC:   case FBANK:      Wave2FBank(cf->s, cf->fbank, rawE?NULL:&te, cf->fbInfo);      v = cf->fbank; bsize = cf->numChans;      break;   case MFCC:      Wave2FBank(cf->s, cf->fbank, rawE?NULL:&te, cf->fbInfo);      FBank2MFCC(cf->fbank, cf->c, cf->numCepCoef);      if (cf->cepLifter > 0)         WeightCepstrum(cf->c, 1, cf->numCepCoef, cf->cepLifter);      v = cf->c; bsize = cf->numCepCoef;      break;   case PLP:      Wave2FBank(cf->s, cf->fbank, rawE ? NULL : &te, cf->fbInfo);      FBank2ASpec(cf->fbank, cf->as, cf->eql, cf->compressFact, cf->fbInfo);      ASpec2LPCep(cf->as, cf->ac, cf->lp, cf->c, cf->cm);      if (cf->cepLifter > 0)         WeightCepstrum(cf->c, 1, cf->numCepCoef, cf->cepLifter);      v = cf->c;      bsize = cf->numCepCoef;      break;   default:      HError(6321,"ConvertFrame: target %s is not a parameterised form",             ParmKind2Str(cf->tgtPK,buf));}

上述格式的简单解释如下:

0 		 WAVEFORM 		 sampled waveform 1 		 LPC 		 linear prediction filter coefficients 2 		 LPREFC 		 linear prediction reflection coefficients 3 		 LPCEPSTRA 		 LPC cepstral coefficients 4 		 LPDELCEP 		 LPC cepstra plus delta coefficients 5 		 IREFC 		 LPC reflection coef in 16 bit integer format  6 		 MFCC 		 mel-frequency cepstral coefficients 7 		 FBANK 		 log mel-filter bank channel outputs 8 		 MELSPEC 		 linear mel-filter bank channel outputs 9 		 USER 		 user defined sample kind 10 		 DISCRETE 		 vector quantised data 11		PLP         PLP cepstral coefficients

对于语音识别来说,最主流的LPC,MFCC,FBANK(MFSC)和PLP都是支持的。语音特征提取的实现代码在HSig.c文件实现,函数实现非常简洁,按功能分如下类别:

1.Initialisation2.Windowing and PreEmphasis3.Linear Prediction Coding Operations4.FFT Based Operations5.MFCC Related Operations6.PLP Related Operations7.Feature Level Operations

Kaldi 语音提取过程

HTK实现简单,Kaldi相比之下要复杂很多,当然也实现了很多扩展功能,另外是C++代码实现的,学习起来难度也大一点。现粗略的研究一下kaldi的文件系统,关于语音提取的核心代码都存放在src/feat目录下面,摘取目录下的文件:

-rw-rw-r--  1    6961 2月  25  2019 feature-common.h-rw-rw-r--  1    3552 2月  25  2019 feature-common-inl.h-rw-rw-r--  1    4654 2月  25  2019 feature-fbank.cc-rw-rw-r--  1    5738 2月  25  2019 feature-fbank.h-rw-rw-r--  1  602408 2月  26  2019 feature-fbank.o-rw-rw-r--  1   14375 2月  25  2019 feature-fbank-test.cc-rw-rw-r--  1   14081 2月  25  2019 feature-functions.cc-rw-rw-r--  1    8240 2月  25  2019 feature-functions.h-rw-rw-r--  1  641416 2月  26  2019 feature-functions.o-rw-rw-r--  1    3473 2月  25  2019 feature-functions-test.cc-rw-rw-r--  1    5751 2月  25  2019 feature-mfcc.cc-rw-rw-r--  1    5992 2月  25  2019 feature-mfcc.h-rw-rw-r--  1  623984 2月  26  2019 feature-mfcc.o-rw-rw-r--  1   21832 2月  25  2019 feature-mfcc-test.cc-rw-rw-r--  1    7092 2月  25  2019 feature-plp.cc-rw-rw-r--  1    6682 2月  25  2019 feature-plp.h-rw-rw-r--  1  739936 2月  26  2019 feature-plp.o-rw-rw-r--  1    4842 2月  25  2019 feature-plp-test.cc-rw-rw-r--  1    6183 2月  25  2019 feature-sdc-test.cc-rw-rw-r--  1    3085 2月  25  2019 feature-spectrogram.cc-rw-rw-r--  1    3990 2月  25  2019 feature-spectrogram.h-rw-rw-r--  1  463488 2月  26  2019 feature-spectrogram.o-rw-rw-r--  1    8552 2月  25  2019 feature-window.cc-rw-rw-r--  1    9226 2月  25  2019 feature-window.h-rw-rw-r--  1  452104 2月  26  2019 feature-window.o-rw-rw-r--  1   12811 2月  25  2019 mel-computations.cc-rw-rw-r--  1    6326 2月  25  2019 mel-computations.h-rw-rw-r--  1  580752 2月  26  2019 mel-computations.o-rw-rw-r--  1   23051 2月  25  2019 online-feature.cc-rw-rw-r--  1   22674 2月  25  2019 online-feature.h-rw-rw-r--  1 1377288 2月  26  2019 online-feature.o-rw-rw-r--  1   12798 2月  25  2019 online-feature-test.cc-rw-rw-r--  1   69223 2月  25  2019 pitch-functions.cc-rw-rw-r--  1   20893 2月  25  2019 pitch-functions.h-rw-rw-r--  1 1279120 2月  26  2019 pitch-functions.o-rw-rw-r--  1   23617 2月  25  2019 pitch-functions-test.cc-rw-rw-r--  1   15836 2月  25  2019 resample.cc-rw-rw-r--  1   12167 2月  25  2019 resample.h-rw-rw-r--  1  608376 2月  26  2019 resample.o-rw-rw-r--  1   10045 2月  25  2019 resample-test.cc-rw-rw-r--  1    4797 2月  25  2019 signal.cc-rw-rw-r--  1    2048 2月  25  2019 signal.h-rw-rw-r--  1  482464 2月  26  2019 signal.o-rw-rw-r--  1    2013 2月  25  2019 signal-test.cc-rw-rw-r--  1   12372 2月  25  2019 wave-reader.cc-rw-rw-r--  1    7544 2月  25  2019 wave-reader.h-rw-rw-r--  1  286704 2月  26  2019 wave-reader.o-rw-rw-r--  1    6902 2月  25  2019 wave-reader-test.cc

可以看出支持fbank,mfcc,spectrogram,pitch和mel单独实现,做的事情要比htk多,而且工具包有兼容HTK的选项,说明kaldi在语音特征提取方面更丰富,扩展性更好。

W2l语音提取过程

w2l给予人工智能神经网络的ASR平台,语音特征提取的代码在/src/libraries/features目录,文件组织也比较清晰:

-rw-rw-r-- 1 1251 9月  18 15:51 Ceplifter.cpp-rw-rw-r-- 1  841 9月  18 15:51 Ceplifter.h-rw-rw-r-- 1 1392 9月  18 15:51 CMakeLists.txt-rw-rw-r-- 1  949 9月  18 15:51 Dct.cpp-rw-rw-r-- 1  781 9月  18 15:51 Dct.h-rw-rw-r-- 1 2669 9月  18 15:51 Derivatives.cpp-rw-rw-r-- 1 1016 9月  18 15:51 Derivatives.h-rw-rw-r-- 1  854 9月  18 15:51 Dither.cpp-rw-rw-r-- 1  991 9月  18 15:51 Dither.h-rw-rw-r-- 1 4519 9月  18 15:51 FeatureParams.h-rw-rw-r-- 1 2284 9月  18 15:51 Mfcc.cpp-rw-rw-r-- 1 2420 9月  18 15:51 Mfcc.h-rw-rw-r-- 1 3475 9月  18 15:51 Mfsc.cpp-rw-rw-r-- 1 1121 9月  18 15:51 Mfsc.h-rw-rw-r-- 1 4742 9月  18 15:51 PowerSpectrum.cpp-rw-rw-r-- 1 1603 9月  18 15:51 PowerSpectrum.h-rw-rw-r-- 1 1488 9月  18 15:51 PreEmphasis.cpp-rw-rw-r-- 1  688 9月  18 15:51 PreEmphasis.h-rw-rw-r-- 1 2514 9月  18 15:51 SpeechUtils.cpp-rw-rw-r-- 1  638 9月  18 15:51 SpeechUtils.h-rw-rw-r-- 1 2979 9月  18 15:51 TriFilterbank.cpp-rw-rw-r-- 1 1322 9月  18 15:51 TriFilterbank.h-rw-rw-r-- 1 1631 9月  18 15:51 Windowing.cpp-rw-rw-r-- 1  730 9月  18 15:51 Windowing.h

可以看出w2l支持MFCC和MFSC两种语音特征提取,其他的暂时没有支持。

小结

本文对三种平台的语音提取简单对比学习了一下。因为HTK是c代码实现,可以非常好的为嵌入式平台移植提供参考,但license受保护,学习和移植的时候需要遵守和注意。另外两个平台是用C++实现的,阅读和移植参考稍微麻烦,但是license比较友好,可以这个代码移植来使用,只能说各有所长吧。

参考文献

1.《噪声条件下的语音特征PLP 参数的提取》魏艳,张雪英, 太原理工大学 信息工程学院

2. 《基于Mel倒谱和Bark谱失真距离的汉语音质客观评价研究》云霞,西南交通大学,硕士论文
3. 《kaldi中的特征提取》https://blog.csdn.net/wbgxx333/article/details/25778483
4. 《htkbook-3.5.alpha-1》
5. 《音频处理中的尺度–Bark尺度与Mel尺度》https://blog.csdn.net/icoolmedia/article/details/51594776
6. 《【自动语音识别课程】第二课 语音信号分析》https://blog.csdn.net/joey_su/article/details/36414877
7. 《Speech Processing for Machine Learning: Filter banks, Mel-Frequency Cepstral Coefficients (MFCCs) and What’s In-Between》https://haythamfayek.com/2016/04/21/speech-processing-for-machine-learning.html
8. 《A Tutorial on Cepstrum and LPCCs》http://www.practicalcryptography.com/miscellaneous/machine-learning/tutorial-cepstrum-and-lpccs/
9. 《Mel Frequency Cepstral Coefficient (MFCC) tutorial》http://www.practicalcryptography.com/miscellaneous/machine-learning/guide-mel-frequency-cepstral-coefficients-mfccs/
10. https://github.com/jameslyons/python_speech_features
11. 《Deep Neural Network acoustic models for ASR》Abdel-rahman Mohamed
12. 《Theory and Applications of Digital Speech Processing》Lawrence R. Rabiner,Ronald W. Schafer

你可能感兴趣的文章
Leetcode C++《热题 Hot 100-28》19.删除链表的倒数第N个节点
查看>>
Leetcode C++《热题 Hot 100-29》22.括号生成
查看>>
Leetcode C++《热题 Hot 100-40》64.最小路径和
查看>>
Leetcode C++《热题 Hot 100-41》75.颜色分类
查看>>
Leetcode C++《热题 Hot 100-42》78.子集
查看>>
Leetcode C++《热题 Hot 100-43》94.二叉树的中序遍历
查看>>
Leetcode C++ 《第175场周赛-1 》5332.检查整数及其两倍数是否存在
查看>>
Leetcode C++ 《第175场周赛-2 》5333.制造字母异位词的最小步骤数
查看>>
Leetcode C++ 《第175场周赛-3》1348. 推文计数
查看>>
Leetcode C++《热题 Hot 100-44》102.二叉树的层次遍历
查看>>
Leetcode C++《热题 Hot 100-45》338.比特位计数
查看>>
读书摘要系列之《kubernetes权威指南·第四版》第一章:kubernetes入门
查看>>
Leetcode C++《热题 Hot 100-46》739.每日温度
查看>>
Leetcode C++《热题 Hot 100-47》236.二叉树的最近公共祖先
查看>>
Leetcode C++《热题 Hot 100-48》406.根据身高重建队列
查看>>
《kubernetes权威指南·第四版》第二章:kubernetes安装配置指南
查看>>
Leetcode C++《热题 Hot 100-49》399.除法求值
查看>>
Leetcode C++《热题 Hot 100-51》152. 乘积最大子序列
查看>>
[Kick Start 2020] Round A 1.Allocation
查看>>
Leetcode C++ 《第181场周赛-1》 5364. 按既定顺序创建目标数组
查看>>