📋 实验概述
本实验实现基于动态时间规整(DTW)的孤立词语音识别系统,目标是识别中文数字 0-9 的语音。
理解语音识别的基本流程,掌握 MFCC 特征提取和 DTW 模板匹配算法。
完成代码填空后,必须先运行 train_template.m 生成模板文件 template.mat,然后才能运行 ex0_all.m 进行识别测试。
系统处理流程
图1:DTW语音识别系统的完整处理流程
为什么需要这些处理步骤?
🔊 语音信号的特点
- 高频能量衰减 → 需要预加重
- 非平稳信号 → 需要分帧处理
- 人耳感知非线性 → 需要Mel尺度
⏱️ 识别的难点
- 不同人说话语速不同
- 同一个词长度可能不同
- 需要DTW进行时间对齐
🔧 第一步:预加重 (Pre-emphasis)
语音信号在发声过程中,高频分量的能量会有明显衰减。预加重通过一阶高通滤波器提升高频能量,使频谱更加平坦。
预加重滤波器:
$$y[n] = x[n] - \alpha \cdot x[n-1]$$
其中 $\alpha = 0.97$ 是预加重系数,滤波器传递函数为 $H(z) = 1 - \alpha z^{-1}$
预加重效果可视化
图2:预加重前后对比 - 时域波形(上)与频率响应(下)
预加重本质是一个一阶差分滤波器,高频变化快的部分被增强,低频平缓的部分被削弱。
📦 第二步:分帧与加窗
2.1 为什么要分帧?
语音信号是非平稳的,但在短时间内(10-30ms)可以近似为短时平稳。分帧将长信号切分成短帧进行分析。
分帧参数:
$$帧数 = \left\lfloor \frac{信号长度 - 帧长}{帧移} \right\rfloor + 1$$
$$第 i 帧起始位置 = (i-1) \times 帧移 + 1$$
帧长
25 ms
16kHz → 400采样点
帧移
10 ms
16kHz → 160采样点
重叠率
60%
(400-160)/400
分帧过程可视化
图3:信号分帧示意 - 相邻帧有60%的重叠区域
2.2 为什么要加窗?
直接截取会产生频谱泄漏。窗函数使帧边缘平滑过渡到零。
汉宁窗(Hanning Window):
$$w[n] = 0.5 - 0.5 \cos\left(\frac{2\pi n}{N-1}\right)$$
图4:汉宁窗及其对信号帧的影响
🎵 第三步:MFCC 特征提取
MFCC(Mel-Frequency Cepstral Coefficients)模拟人耳对不同频率的感知特性。
MFCC 提取流程
图5:MFCC特征提取流程
3.1 FFT 与功率谱
$$P[k] = \frac{1}{N_{FFT}} |X[k]|^2$$
3.2 Mel 滤波器组
人耳对频率感知是非线性的:低频分辨率高,高频分辨率低。
Hz → Mel 转换:
$$m = 2595 \cdot \log_{10}\left(1 + \frac{f}{700}\right)$$
图6:Mel三角滤波器组 - 低频区密集,高频区稀疏
3.3 DCT 与倒谱系数
对Mel滤波器输出取对数后进行DCT,通常取第2-13阶系数。
12维 MFCC + 12维 Δ + 12维 ΔΔ = 36维
🔀 第四步:DTW 动态时间规整
4.1 为什么需要 DTW?
不同人说同一个词,时长往往不同。DTW通过非线性时间扭曲找到最佳对齐。
图7a:欧几里得距离 - 逐点对齐
图7b:DTW距离 - 最佳对齐
4.2 DTW 算法核心
局部距离(欧氏距离):
$$d(i,j) = \|template(:,i) - test(:,j)\|_2$$
累积距离递推公式:
$$D(i,j) = d(i,j) + \min\begin{cases} D(i-1, j) \\ D(i, j-1) \\ D(i-1, j-1) \end{cases}$$
边界条件:$D(0,0) = 0, \quad D(i,0) = D(0,j) = \infty$
4.3 DTW 动态规划演示
图8:DTW累积距离矩阵的动态规划填充过程
4.4 识别决策
将测试语音与所有模板进行DTW匹配,选择距离最小的模板作为识别结果。
图9:识别决策 - 选择DTW距离最小的模板
🧪 实验任务
根据代码模板中的提示,填写标记为?的部分。
📁 文件清单
📄 ex0_all.m
主程序已完成
📄 ex1_preemphasis.m
预加重需修改
📄 ex2_enframe.m
分帧需修改
📄 ex3_mfcc.m
MFCC提取需修改
📄 ex4_dtw.m
DTW计算需修改
📄 ex5_recognize.m
识别决策已完成
📄 ex6_vad.m
端点检测已完成
✅ test_Project4.p
自动批改程序
📝 需要填写的核心公式
| 文件 | 功能 | 需要实现的公式 |
|---|---|---|
ex1 | 预加重 | $y[n] = x[n] - \alpha \cdot x[n-1]$,使用filter([1, -α], 1, x) |
ex2 | 帧数 | $N = \lfloor(L-L_f)/L_s\rfloor + 1$ |
ex2 | 起始索引 | $start = (i-1) \times L_s + 1$ |
ex3 | 汉宁窗 | hann(N, 'periodic') |
ex3 | FFT | fft(frames_win, nfft) |
ex3 | 功率谱 | $P = |X|^2 / N_{fft}$ |
ex3 | DCT | dct(log_mel),取第2到13阶 |
ex4 | 欧氏距离 | norm(a - b) |
ex4 | DTW递推 | $D(i,j) = d(i,j) + \min\{...\}$ |
🚀 实验步骤
- 阅读本手册,理解语音识别流程
- 按顺序完成
ex1→ex2→ex3→ex4 - 运行
test_Project4.p检查正确性 - 运行
ex0_all.m测试完整流程 - 输入
9获得加密成绩,压缩提交
📝 总结
- 预加重:一阶高通滤波器平坦化语音频谱
- 分帧加窗:短时分析方法和窗函数作用
- MFCC:模拟人耳感知的特征提取
- DTW:动态规划解决时间对齐问题
📊 实验现象与分析
预期实验结果
使用 test/ 目录测试
10-30%
识别率较低
原因:测试集与训练集来源不同(不同说话人、录音环境)
使用 train/ 目录测试
70-90%
识别率较高
原因:同源数据,模板与测试来自相同分布
DTW是说话人相关的识别方法。当测试音频与训练模板来自不同说话人时,识别率会大幅下降。这是DTW方法的固有局限性,不是代码错误!
DTW 方法的局限性
❌ 说话人敏感
不同人说同一个词,声学特征差异大,DTW无法泛化到新说话人。
❌ 孤立词限制
只能识别单个词,无法处理连续语音流。
❌ 模板依赖
每个词都需要模板,词汇量扩展困难。
现代语音识别技术演进
| 时代 | 技术 | 特点 |
|---|---|---|
| 1970-1990 | DTW(本实验) | 说话人相关,模板匹配 |
| 1990-2010 | GMM-HMM | 统计建模,说话人无关 |
| 2015-2020 | 端到端深度学习 | 神经网络,序列到序列 |
| 2020-现在 | Whisper/Wav2Vec | 大规模预训练,接近人类水平 |
为什么现代语音助手(Siri、小爱同学)可以识别任何人的语音?它们使用了海量数据训练的深度学习模型,学习到语音的通用特征,而非依赖特定说话人的模板。