语音的特征提取

获得语音信号的fbank特征和MFCC特征的一般步骤是:预加重、分帧、加窗、短时傅里叶变换(STFT)、mel滤波、去均值等。对fbank做离散余弦变换(DCT)即可获得mfcc特征。
PS:“log mel-filter bank outputs”和“FBANK features”说的是同一个东西。

在这里插入图片描述

Step0 MFCC

倒谱参数:

MFCCs(Mel Frequency Cepstral Coefficents):是在Mel标度频率域提取出来的倒谱参数,是一种在自动语音和说话人识别中广泛使用的特征。

Mel标度描述了人耳频率的非线性特性,它与频率的关系可用下式近似表示:
M e l ( f ) = 2595 × l g ( 1 + f 700 ) Mel(f)=2595×lg(1+\frac{f}{700}) Mel(f)=2595×lg(1+700f)
在这个频域内,人对音调的感知度为线性关系。

Step1 预加重

针对录音时高频信号丢失:

在音频录制过程中,高频信号更容易衰减,而像元音等一些因素的发言包含了较多的高频信号的成分,高频信号的丢失,可能会导致音素的共振峰并不明显,使得声学模型对这些音素的建模能力不强。

预加重处理其实是将语音信号通过一个高通滤波器,可以提高信号高频部分的能量,给定时域输入信号x[n],预加重之后信号为:
y ( t ) = x ( t ) − α x ( t − 1 ) , 0.9 ≤ α ≤ 1.0 y(t)=x(t)-\alpha x(t-1), 0.9\le \alpha \le 1.0 y(t)=x(t)αx(t1),0.9α1.0
公式理解:

信号频率的高低主要是由信号电平变化的速度所决定,对信号做一阶差分时,高频部分(变化快的地方)差分值大,低频部分(变化慢的地方)差分值小,达到平衡频谱的作用。

pre_emphasis = 0.97
sig = np.append(sig[0], sig[1:] - pre_emphasis * sig[:-1])
plot_time(sig, fs)

Step2 分针加窗

分帧:帧长0.025s、帧移0.01s

  • 为了减少语音信号整体的非稳态、时变的影响,从而对语音信号进行分段处理,其中每一段称为一帧,一般取25ms。
  • 为了使帧与帧之间平滑过渡,保持其连续性,分帧一般采用交叠分段的方法,保证相邻两帧相互重叠一部分。相邻两帧的起始位置的时间差称为帧移,一般取10ms.
frame_size, frame_stride = 0.025, 0.01
frame_length, frame_step = int(round(frame_size * sample_rate)), int(round(frame_stride * sample_rate))
signal_length = len(emphasized_signal)
num_frames = int(np.ceil(np.abs(signal_length - frame_length) / frame_step)) + 1

pad_signal_length = (num_frames - 1) * frame_step + frame_length
z = np.zeros((pad_signal_length - signal_length))
pad_signal = np.append(emphasized_signal, z)

indices = np.arange(0, frame_length).reshape(1, -1) + np.arange(0, num_frames * frame_step, frame_step).reshape(-1, 1)
frames = pad_signal[indices]
print(frames.shape)

加窗:

  • 在分帧之后,为了让帧两端平滑地衰减,取得更高质量的频谱。
  • 之后会对加窗的数据进行FFT,它假设一个窗内的信号是代表一个周期的信号(也就是说窗的左端和右端应该大致能连在一起)。而通常一小段音频数据没有明显的周期性,加后,数据形状就有点周期的感觉了。
  • 常用的窗有:矩形窗、汉明(Hamming)窗、汉宁窗(Hanning)

以汉明窗为例,其窗函数为:
w ( n , α ) = { ( 1 − α ) − α × c o s ( 2 π n N − 1 ) , 0 ≤ n ≤ N − 1 0 , n = else w(n,\alpha) = \begin{cases} (1-\alpha)-\alpha×cos(\frac{2\pi n}{N-1}),0\le n\le N-1\\ 0,n =\text{else}\\ \end{cases} w(n,α)={(1α)α×cos(N12πn),0nN10,n=else
N是窗的宽度。一般 α \alpha α取0.46。

hamming = np.hamming(frame_length)
# hamming = 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(0, frame_length) / (frame_length - 1))
frames *= hamming

Step3 STFT

了解FFT
对于每一帧的加窗信号,进行N点FFT变换,也成短时傅里叶变换STFT,N通常取256或512,然后用如下的公式计算能量谱:
P = ∣ F F T ( x i ) ∣ 2 N P=\frac{|FFT(x_{i})|^{2}}{N} P=NFFT(xi)2

NFFT = 512
mag_frames = np.absolute(np.fft.rfft(frames, NFFT))
pow_frames = ((1.0 / NFFT) * (mag_frames ** 2))

Step4 提取FBank特征

在能量谱上应用Mel滤波器组,就能提取到FBank特征。

Mel滤波器组就是一系列的三角形滤波器,通常有40个或80个,在中心频率点响应值为1,在两边的滤波器中心点衰减到0。

具体的公式可写为
H m ( k ) = { 0 k < f ( m − 1 ) k − f ( m − 1 ) f ( m ) − f ( m − 1 ) f ( m − 1 ) ≤ k < f ( m ) 1 k = f ( m ) f ( m + 1 ) − k f ( m + 1 ) − f ( m ) f ( m ) < k ≤ f ( m + 1 ) 0 k > f ( m + 1 ) H_{m}(k)= \begin{cases} 0&k< f(m-1)\\ \frac{k-f(m-1)}{f(m)-f(m-1)}&f(m-1)\le k <f(m)\\ 1&k=f(m)\\ \frac{f(m+1)-k}{f(m+1)-f(m)}&f(m)<k\le f(m+1)\\ 0&k>f(m+1) \end{cases} Hm(k)=0f(m)f(m1)kf(m1)1f(m+1)f(m)f(m+1)k0k<f(m1)f(m1)k<f(m)k=f(m)f(m)<kf(m+1)k>f(m+1)
最后在能量谱上应用Mel滤波器组,其公式为:
Y t ( m ) = ∑ k = 1 N H m ( k ) ∣ X t ( k ) ∣ 2 Y_{t}(m)=\sum_{k=1}^{N}H_{m}(k)|X_{t}(k)|^{2} Yt(m)=k=1NHm(k)Xt(k)2
其中,k表示FFT变换后的编号,m表示mel滤波器的编号。

low_freq_mel = 0
high_freq_mel = 2595 * np.log10(1 + (sample_rate / 2) / 700)
nfilt = 40
mel_points = np.linspace(low_freq_mel, high_freq_mel, nfilt + 2)  # 所有的mel中心点,为了方便后面计算mel滤波器组,左右两边各补一个中心点
hz_points = 700 * (10 ** (mel_points / 2595) - 1)
fbank = np.zeros((nfilt, int(NFFT / 2 + 1)))  # 各个mel滤波器在能量谱对应点的取值
bin = (hz_points / (sample_rate / 2)) * (NFFT / 2)  # 各个mel滤波器中心点对应FFT的区域编码,找到有值的位置
for i in range(1, nfilt + 1):
    left = int(bin[i-1])
    center = int(bin[i])
    right = int(bin[i+1])
    for j in range(left, center):
        fbank[i-1, j+1] = (j + 1 - bin[i-1]) / (bin[i] - bin[i-1])
    for j in range(center, right):
        fbank[i-1, j+1] = (bin[i+1] - (j + 1)) / (bin[i+1] - bin[i])

Step5 MFCC特征

num_ceps = 12
mfcc = dct(filter_banks, type=2, axis=1, norm='ortho')[:, 1:(num_ceps+1)]
cep_lifter = 23
(nframes, ncoeff) = mfcc.shape
n = np.arange(ncoeff)
lift = 1 + (cep_lifter / 2) * np.sin(np.pi * n / cep_lifter)
mfcc *= lift

一般对于ASR来说,对MFCC进行一个正弦提升(sinusoidal liftering)操作,可以提升在噪声信号中最后的识别率:
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值