搞清语音是怎么产生的对于我们理解语音有很大帮助。人通过声道产生声音,声道的shape(形状?)决定了发出怎样的声音。声道的shape包括舌头,牙齿等。如果我们可以准确的知道这个形状,那么我们就可以对产生的音素phoneme进行准确的描述。声道的形状在语音短时功率谱的包络中显示出来。而MFCCs就是一种准确描述这个包络的一种特征。
也就是说MFCC 最初的出现,是为了描述音频信号短时功率谱的包络, 而这个包络中有声道形状的信息在里面;
1.基本概念
MFCC是Mel-Frequency Cepstral Coefficients的缩写,
顾名思义MFCC特征提取包含两个关键步骤:
转化到梅尔频率,然后进行倒谱分析。
1.1 梅尔频率
梅尔刻度是一种基于人耳对等距的音高(pitch)变化的感官判断而定的非线性频率刻度。和频率的赫兹的关系如下:
m = 2595 log 10 ( 1 + x y ) m=2595 \log_{10} (1+ \frac{x}{y} ) m=2595log10(1+yx)
所以当在梅尔刻度上面上是均匀分度的话,对于的赫兹之间的距离将会越来越大,所以梅尔刻度的滤波器组的尺度变化如下:
梅尔刻度的滤波器组在低频部分的分辨率高,跟人耳的听觉特性是相符的,这也是梅尔刻度的物理意义所在。
这一步的含义是:
- 首先对时域信号进行傅里叶变换转换到频域,
- 然后再使用梅尔频率刻度的滤波器组对应频域信号进行切分。
- 最后每个频率段对应一个数值。
1.2 倒谱的概念
倒谱的含义是:对时域信号做傅里叶变换,然后取log,然后再进行反傅里叶变换。
可以分为复倒谱、实倒谱和功率倒谱,我们用的是功率倒谱。
倒谱分析可用于将信号分解,两个信号的卷积转化为两个信号的相加。
举例如下:
对应上图的频域信号,可以拆分成两部分的乘积:频谱的包络和频谱的细节。
频谱的峰值即为共振峰,它决定了信号频域的包络,是辨别声音的重要信息,所以进行倒谱分析目的就是获得频谱的包络信息。
包络部分对应的是频谱的低频信息,
而细节部分对应的是频谱的高频信息。
1.3 频谱中高频信息和低频信息的分离
假设上面的频率谱X(k),时域信号为x(n)那么满足:
X
(
k
)
=
D
F
T
(
x
(
n
)
)
X(k)=DFT(x(n))
X(k)=DFT(x(n))
考虑将频域X(k)拆分为两部分的乘积:
X
(
k
)
=
H
(
k
)
E
(
k
)
X(k)=H(k)E(k)
X(k)=H(k)E(k)
假设两部分对应的时域信号分别是h(n)和e(n),那么满足:
x
(
n
)
=
h
(
n
)
∗
e
(
n
)
x(n)=h(n)∗e(n)
x(n)=h(n)∗e(n)
此时我们是无法区分开
h
(
n
)
和
e
(
n
)
h(n)和e(n)
h(n)和e(n)。
对频域两边取log:
l
o
g
(
X
(
k
)
)
=
l
o
g
(
H
(
k
)
)
+
l
o
g
(
E
(
k
)
)
log(X(k))=log(H(k))+log(E(k))
log(X(k))=log(H(k))+log(E(k))
然后进行反傅里叶变换:
I D F T ( l o g ( X ( k ) ) ) = I D F T ( l o g ( H ( k ) ) ) + I D F T ( l o g ( E ( k ) ) ) IDFT(log(X(k)))=IDFT(log(H(k)))+IDFT(log(E(k))) IDFT(log(X(k)))=IDFT(log(H(k)))+IDFT(log(E(k)))
假设此时得到的时域信号如下:
x
′
(
n
)
=
h
′
(
n
)
+
e
′
(
n
)
x'(n)=h'(n)+e'(n)
x′(n)=h′(n)+e′(n)
虽然此时获得时域信号x’(n)即为倒谱,已经和原始的时域信号x(n)不一样,但是可以把时域信号的卷积关系转化为了线性加关系。
倒谱分析已经将两部分对应的时域信号的卷积关系转化为了线性加关系,所以只需要将倒谱通过一个低通滤波器即可获得包络部分对应的时域信号h’(t)。
2.基本流程
2.1 预加重
预加重,是为了消除发声过程中,声带和嘴唇造成的效应,来补偿语音信号受到发音系统所压抑的高频部分。并且能突显高频的共振峰。
简单理解就是在频域上面都乘以一个系数,这个系数跟频率成正相关,所以高频的幅值会有所提升。
实际上就是通过了一个 H ( z ) = 1 − k z − 1 H(z)=1-kz^{-1} H(z)=1−kz−1 高通滤波器。
实现
s
n
′
=
s
n
−
k
∗
s
n
−
1
s_n'=s_n - k*s_{n-1}
sn′=sn−k∗sn−1
2.2 加窗
目的
用于平滑信号,使用汉明窗加以平滑的话,相比于矩形窗函数,会减弱FFT以后旁瓣大小以及频谱泄露。
实现
使用汉明窗对信号进行加窗处理
s
n
′
=
{
0.54
−
0.46
c
o
s
(
2
π
(
n
−
1
)
N
−
1
)
}
∗
s
n
s_n'=\{0.54-0.46cos(\frac{2\pi(n-1)}{N-1})\}*s_n
sn′={0.54−0.46cos(N−12π(n−1))}∗sn
2.3 频域转换
目的:
将时域信号转化到频域进行后续的频率分析
实现:
幅度谱:
S
i
(
k
)
=
∑
n
=
1
N
s
i
(
n
)
e
−
j
2
π
k
n
/
N
,
1
≤
k
≤
K
S_i(k)=\sum_{n=1}^{N} s_i(n)e^{-j2\pi kn/N} , 1\le k \le K
Si(k)=n=1∑Nsi(n)e−j2πkn/N,1≤k≤K
功率谱:
P
i
(
k
)
=
1
N
∣
S
i
(
k
)
2
∣
P_i(k)=\frac{1}{N}|S_i(k)^2|
Pi(k)=N1∣Si(k)2∣
3. Mel 语谱图
使用梅尔刻度滤波器组过滤:
将 功率谱与梅尔滤波器进行点积,得到 Mel 语谱图;
目的:
因为频域信号有很多冗余,滤波器组可以对频域的幅值进行精简,每一个频段用一个值来表示。
实现:
对于FFT得到的幅度谱,分别跟每一个滤波器进行频率相乘累加,得到的值即为该帧数据在在该滤波器对应频段的能量值。如果滤波器的个数为22,那么此时应该得到22个能量值;
4. MFCC
4.1 Mel 语谱图取log
由于人耳对声音的感知并不是线性的,用log这种非线性关系更好描述。取完log以后才可以进行倒谱分析。
4.2 离散余弦变换
DCT和DFT类似,但是只使用实数,不涉及复数运算。信号经过DCT变换以后,能量会集中到低频部分,可以用于图像压缩。
目的
按照倒谱的定义,该步需要进行反傅里叶变换然后通过低通滤波器获得最后的低频信号。这里使用DCT直接就可以获取频率谱的低频信息。
由于滤波器之间是有重叠的,所以前面的获得的能量值之间是具有相关性的,DCT还可以对数据进行降维压缩和抽象,获得最后的特征参数。相比于傅里叶变换,离散余弦变换的结果没有虚部,更好计算。
实现
c
i
=
2
N
∑
j
=
1
N
m
j
c
o
s
(
i
π
N
(
j
−
0.5
)
)
c_i = \sqrt{ \frac{2}{N} } \sum_{j = 1}^N m_j cos( \frac{i\pi}{N} (j -0.5) )
ci=N2j=1∑Nmjcos(Niπ(j−0.5))
4.3 差分
目的
由于语音信号是时域连续的,分帧提取的特征信息只反应了本帧语音的特性,为了使特征更能体现时域连续性,可以在特征维度增加前后帧信息的维度。常用的是一阶差分和二阶差分。
实现
d
t
=
∑
θ
=
1
θ
θ
(
c
t
+
θ
−
c
t
−
θ
)
2
∑
θ
=
1
θ
θ
2
d_t = \frac{ \sum_{\theta = 1}^{\theta} \theta( c_{t+\theta} - c_{t - \theta} ) } { 2 \sum_{\theta = 1}^{\theta} \theta^2 }
dt=2∑θ=1θθ2∑θ=1θθ(ct+θ−ct−θ)
5. MFCC静态特征值
Mel 谱系数: 取对数+ DCT
上述第六步中获取的滤波器组特征,便是Mel 谱系数;
由于定义的是倒谱系数;
倒谱: 即将频谱系数取对数, 在进行傅氏变换(或DCT 变换);
倒谱的作用: 将时域中的 卷积 在 倒谱域中变成加法( 对应于 时域中的卷积 在频域 中是 乘法一样;)
便将上述的Mel 谱系数, 取对数, 在进行DCT 变换 ;
解释:
上述取对数,DCT的 变换操作 相当于将实际上是频域的信号当成时域信号强行进行频域变换,得到的是频域信号在伪频域的幅频相应;
前2-13个系数代表的是包络,因为他们在伪频域上是低频信号,所以在前面,后面的系数是伪频域的高频信号,代表的是spectral details,在语音识别的时候,对我们帮助更大的是包络,因为包含了formants等信息。
C n = ∑ k = 1 M l o g X [ k ] ∗ c o s ( π ( k − 0.5 ) n / M ) , n = 1 , 2 , 3.... L ; C_n = \sum_{k = 1}^M logX[k] * cos( \pi (k- 0.5 ) n / M ), n = 1,2,3 ....L; Cn=k=1∑MlogX[k]∗cos(π(k−0.5)n/M),n=1,2,3....L;
由上述公式 求得的是 MFCC 特征值, 将其作为静态特征;
在 语音辨识中, 得到的Mel 倒谱系数 只保存前 2- 13 个, 其余暂且不用, 研究表明其他系数代表了系数中高阶的变化,在 自动语音识别中作用不大;
6. MFCC动态特征值
对上述的 MFCC的静态特征 做一阶 和 二阶 差分, 便得到相应的 动态特征;
- 首先标准的倒谱参数MFCC只反映了语音参数的静态特性,实际应用于语音识别时,我们通常会再加上一阶差分二阶差分(也有人称之为差量倒频谱参数),以显示倒频谱参数对时间的变化。
它的意义为倒频谱参数相对于时间的斜率,也就是代表倒频谱参数在时间上的动态变化。一般在 PC 上进行的语音识别,就是使用静态特征+一阶差分+二阶差分;通常会把动、静态特征结合起来以有效提高系统的识别性能。差分参数的计算可以采用下面的公式:
上式中,d(t)表示第t个一阶微分,c(t)表示第t个倒谱系数,Q表示倒谱系数的阶数,K表示一阶导数的时间差,可取1或2。将上式的结果再代入就可以得到加速系数。
⾄此,计算到了⾳频⽂件每⼀帧的39个Mel频率倒谱系数(13个MFCC+13个一阶微分系数+13个加速系数),这些即为一个语音文件的特征数据,这些特征数据可以运用在之后的分类中。
-
提取动态特征的时候,一般都采用一阶二阶差分。
一阶差分:离散函数中连续相邻两项之差;定义X(k),则Y(k)=X(k+1)-X(k)就是此函数的一阶差分,物理意义就是当前语音帧与前一帧之间的关系, 体现帧与帧(相邻两帧)之间的联系;二阶差分:在一阶差分的基础上,连续一阶差分的差值Z(k)=Y(k+1)-Y(k)=X(k+2)-2*X(k+1)+X(k)为此函数的二阶差分。二阶差分表示的是一阶差分与一阶差分之间的关系。即前一阶差分与后一阶差分之间的关系,体现到帧上就是相邻三帧之间的动态关系。
-
关于一阶差分表达式和MFCC的差分系数,何强,何英的“Matlab扩展编程”一书中。该函数使用的一阶差分和LZ所指的不完全一样,用下式所表示。在许多文献中常数C不完全一样。 书中的c为常数1/3
7. 对比MFSC和MFCC
MFSC(log mel-frequency spectral Coefficients)相比于MFCC,缺少了DCT这一步处理。
相比于MFSC,MFCC具有以下优势:
对特征进行了去相关和压缩,更适合Diagonal covariance GMMs这种建模方式。
劣势:
MFCC: 数据量少,但是对于DNN这种训练方式,发现MFSC的效果要比MFCC好。
主要原因:
MFSC具有相关性,表现在频谱上面的较为平滑;
MFSC具有更高的维度;
8. 代码
def melspectrogram(
y=None,
sr=22050,
S=None,
n_fft=2048,
hop_length=512,
win_length=None,
window="hann",
center=True,
pad_mode="reflect",
power=2.0,
**kwargs,
):
y:输入时域下的音频信号。shape= (n,)
sr:采样频率
n_fft:FFT窗口个数,默认2048
hop_length:连续帧之间的采样数,默认512
window:使用加窗的类型,默认为汉宁窗
return:梅尔频谱
def mfcc(
y=None,
sr=22050,
S=None,
n_mfcc=20,
dct_type=2,
norm="ortho",
lifter=0,
**kwargs
):
y:输入时域下的音频信号
sr:采样频率
n_mfcc:返回mfcc特征的数量
dct_type:DCT(离散余弦变换)的类型,默认为2
return:返回mfcc特征序列,这里主要设置sr和n_mfcc(你要提取特征的个数)
参考文章:
https://www.cnblogs.com/LXP-Never/p/11602510.html;
https://www.cnblogs.com/LXP-Never/p/10918590.html;
https://blog.csdn.net/weixin_50547200/article/details/117294164#t10;