2、语音特征提取(上):预加重、分帧、加窗、短时傅里叶变换

各位好,欢迎来到语音特征提取的上半部分。说实话,语音信号处理里,特征提取是真正决定系统上限的环节。我见过不少同学模型调得飞起,结果前端特征一塌糊涂,最后精度死活上不去。今天咱们就把预加重、分帧、加窗和STFT这几个基本功彻底讲透。

核心认知:语音信号是非平稳的,但它在10~30ms的短时片段内可以看作平稳信号。这就是所有短时处理技术的理论基础。

2.1 预加重:为什么要先“提亮”高频?

先问一个问题:你说话时,高频能量和低频能量哪个大?

答案是低频。人的声门脉冲激励信号,其频谱大约以每倍频程6dB的速度衰减。也就是说,发同一个音,2000Hz的能量可能只有200Hz的十分之一。如果不做处理,后续分析时高频信息会被低频完全淹没。

预加重就是为了解决这个问题。它本质上是一个一阶高通滤波器:

y[n] = x[n] - α · x[n-1]

α通常取0.95~0.97。我习惯用0.97,这个值在大多数语音数据集上表现最稳。

我的经验:曾经有个项目,做远场语音识别,模型在低频噪声环境下频频出错。后来我把预加重系数从0.95调到0.98,高频细节更突出,识别率直接涨了3个点。别小看这一步。

预加重的作用可以总结为三点:

  • 补偿高频衰减——让频谱更平坦,便于后续分析
  • 数值稳定——避免高频分量在FFT时被舍入误差吃掉
  • 提升信噪比——尤其对清音(如/s/、/ʃ/)这类高频为主的音素

注意:预加重不是万能的。如果信号本身高频噪声严重(比如录音设备底噪大),预加重反而会放大噪声。这时候我建议先做降噪,再做预加重。

2.2 分帧:把连续信号切成“小段”

语音信号是时变的——你发“啊”和“一”时,声道形状完全不同。但如果你只取20ms来看,声道几乎没动,信号特性基本稳定。这就是分帧的物理依据。

分帧有两个关键参数:

参数 典型值 说明
帧长 20~30ms 太短则频率分辨率不够;太长则失去平稳性
帧移 10~15ms 相邻帧重叠60%~70%,保证连续性

举个例子:采样率16kHz,帧长25ms就是400个采样点,帧移10ms就是160个点。每帧比上一帧前进160点,重叠240点。

# 伪代码示意
fs = 16000
frame_len = int(0.025 * fs)   # 400点
hop_len = int(0.010 * fs)     # 160点
num_frames = (len(signal) - frame_len) // hop_len + 1

for i in range(num_frames):
    start = i * hop_len
    frame = signal[start : start + frame_len]

避坑指南:我曾经在嵌入式设备上做实时语音处理,帧移设得太小导致计算量爆炸。后来发现,对于大多数任务,帧移取帧长的40%就够用了。别盲目追求高重叠率。

2.3 加窗:为什么不能直接切?

直接切帧会带来一个问题——频谱泄漏。你想想看,截断一段信号相当于在时域乘了一个矩形窗,矩形窗的频谱是sinc函数,旁瓣很高。这会导致本应集中在某个频率的能量“泄漏”到其他频率上。

汉明窗(Hamming Window)就是用来解决这个问题的。它的公式是:

w[n] = 0.54 - 0.46 · cos(2πn / (N-1)),  0 ≤ n ≤ N-1

汉明窗的特点:主瓣宽度适中,旁瓣衰减大(约-43dB)。相比矩形窗,它能有效抑制频谱泄漏。

其他常用窗函数对比:

窗类型 主瓣宽度 旁瓣衰减 适用场景
矩形窗 最窄 -13dB 频率分辨率优先,不关心泄漏
汉明窗 中等 -43dB 语音分析最常用
汉宁窗 中等 -32dB 与汉明窗类似,两端更平滑
布莱克曼窗 最宽 -58dB 需要极低旁瓣时

我的建议:除非你有特殊需求,否则语音特征提取默认用汉明窗。我在多个项目里对比过,汉明窗在识别率和鲁棒性之间平衡得最好。

2.4 短时傅里叶变换(STFT):时频分析的基石

好了,前面三步做完,我们得到了加窗后的每一帧信号。现在要问:这一帧里包含哪些频率成分?

答案就是做FFT。对每一帧做N点FFT,得到该帧的频谱。把所有帧的频谱按时间堆叠起来,就得到了一个时频矩阵——这就是STFT。

数学上,STFT定义为:

X[m, k] = Σ x[n] · w[n - m] · e^(-j·2π·k·n / N)

其中m是帧索引,k是频率索引,w是窗函数。

STFT的输出通常用两种方式表示:

  • 幅度谱:|X[m, k]|,反映各频率的能量大小
  • 功率谱:|X[m, k]|²,幅度谱的平方,物理意义更直接

实际应用中,我们一般只取前N/2+1个频率点(因为FFT结果是对称的)。比如512点FFT,只取前257点。

重要提醒:FFT点数N一般取2的幂次,且不小于帧长。如果帧长400点,我建议做512点FFT(补零到512)。补零不会增加频率分辨率,但能让频谱更平滑。

2.5 完整流程与知识图谱

下面这张图把整个流程串起来了。从原始波形到STFT时频矩阵,每一步都在解决一个具体问题。

语音特征提取(上)—— 核心流程 原始语音信号 预加重 分帧 加窗(汉明窗) STFT(FFT) 时频矩阵(语谱图) 为什么需要? 补偿高频衰减 提升频谱平坦度 α=0.95~0.97 参数选择 帧长:20~30ms 帧移:10~15ms 重叠60%~70% 窗函数对比 汉明窗:旁瓣-43dB 矩形窗:旁瓣-13dB 语音默认用汉明窗

2.6 实际项目中的参数选择

说了这么多理论,最后给点实在的。不同任务下,参数怎么选?我列个表:

任务类型 采样率 帧长 帧移 FFT点数 窗函数
语音识别(ASR) 16kHz 25ms 10ms 512 汉明窗
说话人识别 16kHz 20ms 10ms 512 汉明窗
语音增强 16kHz 32ms 8ms 512 汉宁窗
音乐分析 44.1kHz 46ms 23ms 2048 布莱克曼窗

我的经验:如果你刚开始做语音项目,直接用16kHz采样率、25ms帧长、10ms帧移、512点FFT、汉明窗。这套参数在90%的场景下都够用。等遇到具体问题了,再针对性地调。