本文将讲解一下Kaldi的提取MFCC的源码,MFCC特征作为语音信号处理技术的常用特征之一,主要包含以下几个部分:
其中kaldi的提取的模块架构图如下
接口函数
featbin/compute-mfcc-feats.cc
输入:waveform---音频信号,wave_data.SampFreq() ----音频采样率,vtln_warp_local---vtln参数
输出:features--- MFCC特征
分帧、加窗、预加重
分帧、加窗、预加重的函数接口在feat/feature-common-inl.h ,
其具体实现在feat/feature-window.cc
分帧
ExtractWindow()
输入: sample_offset ----偏移量(一般为零) wave---音频信号 f---第几帧(帧数的下标)opts---分帧的配置参数(设置帧长、帧移动等参数) window_function---窗函数类型
输出:window---加窗后的帧信号 log_energy_pre_window---每个窗函数的log能量
作用:通过opts中设置的frame_length,frame_shift,计算每帧信号的起始点与终止点,并送入加窗函数ProcessWindow中。
预加重、加窗
输入:opts---分帧的配置参数(设置帧长、帧移动等参数) window_function---窗函数类型 window---加窗前的帧信号
输出:window---加窗后的帧信号 log_energy_pre_window---每个窗函数的log能量
作用:在ProcessWindow函数,kaldi先通过Preemphasize函数对加窗前的信号进行预加重,并通过MulElements函数,计算加窗后的帧信号window 并输出。
预加重
输入:waveform---加窗前的帧信号,preemph_coeff---预加重系数
输出:waveform---预加重后的帧信号
作用:waveform[i]=waveform[i]-a*waveform[n-1] , a = 预加重系数;
对于kaldi 其每帧的初始信号加重后为waveform[0]=waveform[0]-a*waveform[0]。
FFT 功率谱
feat/feature-mfcc.cc
FFT与计算功率谱的方法,各个函数介绍的很清楚,这边就在不在细说了~
其中RealFft函数为计算FFT函数,ComputePowerSpectrum函数为计算功率谱
Mel banks,并计算Mel频谱
其中红框内GetMelBanks函数为生成Mel滤波器组的函数,红框内Compute函数为功率谱函数经过滤波器后的输出
生成Mel banks
feat/mel-computations.cc
输入:opts---mel滤波器相关参数(滤波器组的个数等) frame_opts----分帧的配置参数(设置帧长、帧移动等参数) vtln_warp_local---vtln参数
输出:返回一个滤波器组
作用:通过对opts.low_freq与opts.high_freq进行梅尔坐标转换后,计算梅尔值域。根据滤波器组的个数num_bins,在梅尔至于建立若干个三角滤波器
其中每个滤波器中的每个点值为(如下)每个滤波器共有fft个点
if (mel <= center_mel)
weight = (mel - left_mel) / (center_mel - left_mel);
else
weight = (right_mel-mel) / (right_mel-center_mel);
计算Mel频谱
输入:power_spectrum---功率谱
输出;mel_energies_out---mel频谱输出
作用:mel滤波器组举证与功率频谱相乘
求倒谱
Log
Dct