3、特征提取:MFCC、Filter Bank、Mel频谱等常用语音特征的计算原理与实现方法
在边缘设备上实现实时语音关键词唤醒(KWS)时,特征提取是连接原始音频波形与神经网络分类器之间的关键桥梁。麦克风采集到的是一维时域信号,而神经网络(无论是DNN、CNN还是Transformer)更擅长处理具有明确结构、低冗余、高判别性的输入。特征提取的目标就是将原始波形转换为紧凑、稳健且对说话人差异、环境噪声具有一定鲁棒性的声学表示。本章将深入剖析Mel频谱、Filter Bank(FBank)和MFCC(Mel频率倒谱系数)三种最主流特征的计算原理、实现细节以及在边缘设备上的工程取舍。
上图展示了从原始音频到特征输出的完整工程链路。在边缘设备(如Cortex-M4/M7、ESP32、低功耗DSP)上,每一步的计算都需要考虑内存占用、延迟和功耗。下面我们逐一拆解每个环节的原理与实现。
3.1 预处理:从连续波形到短时帧
核心原理:语音信号是非平稳的,但在10~30ms的短时间内可视为平稳。因此需要将连续音频流切分为“帧”,并采用“帧移”(通常10ms)保证帧间平滑过渡。预加重环节通过一阶高通滤波器(系数通常为0.97)提升高频分量,因为语音中的辅音和摩擦音能量集中在高频,而低频元音能量本身较强,预加重可以平衡频谱,使后续特征更均衡。
- 预加重: y[n] = x[n] - 0.97 * x[n-1]
- 分帧: 帧长25ms = 400个采样点,帧移10ms = 160个采样点
- 加窗: 对每帧乘以Hamming窗(w[n] = 0.54 - 0.46*cos(2πn/(N-1))),以减少频谱泄漏
在边缘设备上,预加重和加窗可以合并为一次乘加运算。例如在Cortex-M4上,使用CMSIS-DSP库的arm_mult_f32函数即可高效完成。需要注意,帧移与帧长的比例决定了特征的时间分辨率——帧移越小,特征序列越长,计算量越大。
3.2 频谱计算:FFT与功率谱
核心原理:对每一帧加窗后的信号执行N点FFT(通常N=512,对应32ms窗口,满足2的幂次要求),得到复数频谱X(k)。语音识别中通常使用功率谱|X(k)|²,因为它反映了各频率成分的能量分布,且对相位不敏感(人耳对相位不敏感)。
实现要点:在嵌入式环境中,FFT的实现有两种选择:一是使用硬件加速器(如ESP32的FFT加速),二是使用软件库(如KissFFT、CMSIS-DSP)。对于512点FFT,CMSIS-DSP在180MHz的Cortex-M4上大约需要0.5ms,满足实时性要求。需要注意,FFT输出的前N/2+1个点(即257个点)是有效频谱,对应0~8kHz(16kHz采样率下)。
// CMSIS-DSP 示例:16kHz采样,512点FFT
arm_rfft_fast_instance_f32 fft;
arm_rfft_fast_init_f32(&fft, 512);
arm_rfft_fast_f32(&fft, frame, fft_output, 0); // 0表示正变换
// 计算功率谱
for (int i = 0; i < 257; i++) {
power[i] = fft_output[2*i]*fft_output[2*i] + fft_output[2*i+1]*fft_output[2*i+1];
}
arm_rfft_fast_f32输出未归一化,幅度是实际的N/2倍。如果后续要计算能量,需要除以N;但若只用于相对比较(如Mel滤波),则无需归一化。
3.3 Mel滤波器组与Mel频谱
核心原理:人耳对频率的感知是非线性的——对低频变化敏感,对高频变化迟钝。Mel刻度模拟了这一特性,其转换公式为:mel(f) = 2595 * log10(1 + f/700)。Mel滤波器组是一组三角滤波器,在Mel刻度上等间距排列,每个滤波器覆盖一个频带,将FFT的线性频率映射到Mel刻度。
实现方法:假设我们要设计40个Mel滤波器(覆盖0~8kHz):
- 将频率范围[0, 8000]Hz转换为Mel刻度:mel(0)=0, mel(8000)=2840
- 在Mel刻度上等间距取42个点(40个滤波器需要42个边界点)
- 将42个点转换回Hz频率,并映射到最近的FFT bin索引
- 构造三角滤波器:第m个滤波器在边界点m-1、m、m+1处分别取0、1、0
Mel频谱的计算公式为:MelSpec[m] = log( Σ_{k=f(m-1)}^{f(m+1)} power[k] * H_m(k) ),其中H_m(k)是第m个滤波器的权重。取对数是为了模拟人耳对声音响度的对数感知,同时压缩动态范围。
| 滤波器参数 | 典型值 | 说明 |
|---|---|---|
| 滤波器数量 | 40 | KWS常用40维FBank |
| 最低频率 | 0 Hz | 可设为20Hz去除直流 |
| 最高频率 | 8000 Hz | 16kHz采样率的奈奎斯特频率 |
| FFT点数 | 512 | 频率分辨率约31.25Hz |
3.4 MFCC:从FBank到倒谱域
核心原理:MFCC在FBank的基础上,对log-Mel频谱执行离散余弦变换(DCT),然后保留前12~13个系数。DCT的作用是去相关——FBank各维度之间高度相关,而DCT可以将能量集中到前几个系数中,类似PCA。MFCC的倒谱域特性使其对信道失真(如麦克风频率响应差异)有一定鲁棒性。
计算步骤:
- 计算FBank(40维)
- 对40维向量执行DCT-II:
C[n] = Σ_{m=0}^{M-1} FBank[m] * cos(π*n*(m+0.5)/M) - 保留n=0~12的系数(共13维),其中C[0]代表整体能量,通常会被丢弃或替换为帧能量
- 可选:计算一阶差分(Δ)和二阶差分(ΔΔ),捕捉动态特征
在KWS任务中,MFCC的使用场景正在减少。原因是DCT去相关虽然有利于GMM-HMM等传统模型,但对于深度神经网络,FBank保留了更多原始信息,且CNN可以直接处理维度间的相关性。然而,MFCC在低信噪比环境下的鲁棒性仍具优势,因为DCT的低频系数对噪声不敏感。
背景:某智能音箱方案采用Cortex-M7(400MHz)作为协处理器,内存仅512KB,需实现“小爱同学”的实时唤醒。初始方案使用MFCC(13维+Δ+ΔΔ=39维),识别率在安静环境下达到95%,但在空调噪声(约45dB)下降至82%。
分析:MFCC的DCT截断丢失了高频细节,而“小爱”中的“爱”字含有丰富的共振峰信息,这些信息主要分布在FBank的高维部分。同时,39维特征需要3帧拼接(39×3=117维输入),增加了全连接层的参数量。
优化:改用40维FBank,不做DCT,直接输入CNN(2层卷积+1层全连接)。模型参数量从45K降至32K,内存占用减少28%。在相同噪声环境下,唤醒率提升至91%。代价是FBank对信道差异更敏感,需要额外的均值归一化(CMVN)处理。
复盘:对于边缘KWS,FBank+轻量CNN是更优选择。MFCC更适合传统GMM模型或极低功耗场景(如助听器)。若必须使用MFCC,建议保留前13维的同时,额外补充FBank的高频段能量作为辅助特征。
3.5 特征归一化与动态增强
核心原理:边缘设备面临的环境噪声和麦克风增益差异会导致特征分布偏移。常用的归一化方法包括:
- 均值归一化(CMVN):对每个特征维度减去训练集的均值,除以标准差。在流式处理中,可使用滑动窗口估计均值和方差。
- 批量归一化(BN):在神经网络内部对特征图归一化,适用于CNN。
- 能量归一化:将每帧的log能量作为额外特征,或对FBank进行L2归一化。
动态特征(Δ和ΔΔ)的计算公式为:Δ(t) = (x(t+2) - x(t-2)) / 4,需要缓存前后各2帧。在内存受限的MCU上,这增加了4帧的缓冲开销(40维×4帧×4字节=640字节),通常可以接受。
3.6 边缘设备上的实现优化与总结
计算量对比:以16kHz采样、40维FBank、10ms帧移为例,每秒需处理100帧。每帧的FFT(512点)约需0.5ms(Cortex-M4 @180MHz),Mel滤波约0.2ms,log运算约0.1ms,总计约0.8ms/帧,CPU占用率约8%。若增加MFCC的DCT(40×13乘加),额外增加0.05ms,差异不大。但MFCC的13维特征在后续神经网络中计算量更小,因此整体功耗可能更低。
内存优化策略:
- 使用int16定点数替代float32,特征值范围通常在[-10, 10]之间,可缩放为Q15格式,内存减半。
- Mel滤波器组权重使用uint16存储(归一化到0~65535),运行时右移16位。
- 环形缓冲区管理音频帧,避免数据拷贝。
总结复盘:特征提取没有最优方案,需要根据目标硬件、模型架构和场景噪声综合权衡。对于大多数KWS任务,推荐路径为:预加重 → 分帧加窗 → FFT → 功率谱 → Mel滤波(40维) → log → 均值归一化 → 输入CNN。MFCC可作为备选方案,在模型压缩或传统GMM场景下使用。无论选择哪种特征,务必在目标设备上进行量化测试,因为浮点与定点实现的差异可能影响最终唤醒率。