FFT把时间序列转换为频率分量,适合识别周期、谐波和频带能量变化。MFCC在频谱基础上压缩出更接近听觉尺度的表示,常用于关键词和设备声音。
频域方法依赖窗口长度、采样率、窗函数和幅值标定。频谱图清晰并不自动带来更好模型,仍要用独立数据和目标MCU验证。
|--------------------------------------------|
| FFT提供频率结构,频带能量进一步压缩,MFCC面向声音谱包络;三者保留的信息不同。 |
|----------------------------------------------------------------------------------------------------------------------------------------------------------|
| 完成本篇后,你应该能够 1. 解释FFT频点、频率分辨率、窗函数、频带能量和MFCC处理链。 2. 根据任务是机械周期还是声音谱包络,选择合适的频域表示。 3. 运行DFT实验,定位双频信号峰值并计算频带能量。 FFT是一种快速计算离散傅里叶变换的方法。它把时间序列换成各个频率分量的幅度和相位。 |

图1:FFT、频带能量与MFCC位于同一频域处理链的不同阶段
一、FFT适合周期与谐波结构
旋转机械、风扇和电机常在特定频率及其谐波上产生能量。FFT能够把这些周期成分从复杂时域波形中分离。频率分辨率由窗口物理时长决定,零填充只增加频谱采样点,不提高真正分辨能力。
实信号频谱具有共轭对称性,实际分析通常只使用0到奈奎斯特频率的一半。幅值归一化和单边谱系数需要在PC与MCU保持一致。
|---------------------------------------------------------|
| 频率分辨率 Δf = fₛ / N = 1 / Twindow 第k个频点对应 fₖ = k × fₛ / N |
二、窗函数控制频谱泄漏
有限窗口相当于截断连续信号。窗口内不是整数周期时,能量会扩散到邻近频点。Hann等窗函数能够降低旁瓣泄漏,但会改变主瓣宽度和幅值,需要配套标定。
训练端使用Hann窗、部署端使用矩形窗时,模型输入分布会发生系统性变化。窗函数系数、FFT长度和缩放方式都应纳入模型版本。
表1:三种频域表示的适用范围
| 表示 | 适合任务 | 主要代价 |
|---|---|---|
| 完整FFT谱 | 频率位置与谐波重要 | 输入维度和频点敏感性较高 |
| 频带能量 | 关注若干稳定频段 | 需要设计频带边界 |
| MFCC | 关键词、语音和设备声音 | 处理链与临时缓冲更复杂 |
三、频带能量用更小输入表达频域结构
当任务只关心几个频段,可以把多个FFT频点求和或求均方,形成频带能量。这样降低输入维度,也减弱单个频点受转速微小漂移的影响。
频带边界应基于物理机理和数据分布确定。边界过窄会对转速变化敏感,过宽会把不同故障成分混在一起。
C/CMSIS-DSP:计算实数FFT的核心调用
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| #include "arm_math.h" #define FFT_LEN 256 static arm_rfft_fast_instance_f32 rfft; static float time_dataFFT_LEN; static float spectrumFFT_LEN; void spectrum_init(void) { arm_rfft_fast_init_f32(&rfft, FFT_LEN); } void spectrum_run(void) { arm_rfft_fast_f32(&rfft, time_data, spectrum, 0); // 后续按项目约定计算单边幅值或频带能量。 } |
四、MFCC强调声音的谱包络
MFCC通常包含预加重或滤波、分帧、窗函数、FFT、Mel滤波器组、对数和DCT。它把高维频谱压缩为少量系数,适合关键词和设备声音分类。
板端需要评估FFT、滤波器组和临时缓冲。CMSIS-DSP提供FFT及部分MFCC相关函数,但具体API和缓冲要求应按项目锁定版本检查。
频率分辨率来自窗口时长,不单由采样率决定
N点FFT的频点间隔为Fs/N,也等于1/窗口秒数。Fs=1000 Hz、N=1000时分辨率1 Hz;若N=200,分辨率5 Hz。提高采样率但保持窗口秒数不变时,N同步增大,频率分辨率不变,只是可观察的最高频率提高。
真实频率不一定正好落在频点上,有限窗口会产生频谱泄漏。Hann窗让窗口两端平滑接近零,降低旁瓣泄漏,但会改变幅度和等效噪声带宽。训练与MCU必须使用相同窗函数和幅值标定。
实数输入的频谱具有共轭对称,通常只使用0到Fs/2。CMSIS-DSP实数FFT输出采用特定打包格式,读取幅值时要按文档处理DC、Nyquist和复数对,不能把数组直接当普通实数幅度。
|-------------------------------------------------|
| 频点k对应频率 fₖ = k×Fs/N 频率分辨率 Δf = Fs/N = 1/Twindow |
频带能量和MFCC分别压缩什么信息
频带能量把多个FFT频点求和,例如0~50 Hz、50~100 Hz和100~200 Hz。它减少输入维度并容忍峰值轻微漂移,适合转速变化范围已知的机械信号。频带边界应来自任务频率与采样率,不应随意等宽。
MFCC面向声音感知:预加重可选,分帧加窗后求功率谱,再经过Mel滤波器组、取对数和DCT得到谱包络系数。它弱化精确谐波位置,突出人耳频率尺度上的形状,常用于关键词与环境声音。
MFCC包含大量参数:帧长、帧移、FFT点数、Mel滤波器数量、频率上下限、对数底和保留系数数。任何一项不同都会改变张量。部署前用固定音频帧逐阶段比较窗后波形、功率谱、Mel能量和最终系数。
三类频域输入的选择线索
| 表示 | 适合证据 | 主要配置 |
|---|---|---|
| FFT幅度 | 明确频率和谐波 | Fs/N/窗函数/幅值 |
| 频带能量 | 频率范围与总能量 | 频带边界与归一化 |
| MFCC | 声音谱包络 | 帧、Mel、log、DCT |
五、落地检查
- 由任务频段确定采样率和窗口时长。
- 固定FFT长度、窗函数、幅值缩放和单边谱规则。
- 比较完整频谱与频带能量的模型效果和资源。
- 声音任务记录Mel滤波器组、对数下限和DCT系数数目。
- 使用黄金窗口核对PC与MCU每一级输出。
动手:从双频波形得到FFT峰值和频带能量
脚本生成10 Hz与27 Hz两种正弦叠加的信号,使用Hann窗并直接计算单边DFT功率。随后列出最强频点和三个频带能量比例。N=100,计算量足够小,代码便于理解。
实验环境与输入
- Python 3标准库。
- 保存为 `spectrum_bands.py` 并运行。
- DFT为教学实现;MCU实际项目可使用CMSIS-DSP FFT内核。
按顺序完成实验
- 运行脚本,确认最强频点接近10 Hz和27 Hz。
- 观察0~15 Hz与15~35 Hz频带包含主要能量。
- 把27 Hz改成27.5 Hz,比较频谱泄漏和相邻频点。
- 把N从100改成200并保持Fs=100,说明窗口加倍后频率分辨率从1 Hz变成0.5 Hz。
可直接运行:Hann窗、单边DFT和频带能量
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| import math FS = 100 N = 100 signal = 0.8\*math.sin(2\*math.pi\*10\*n/FS) + 0.4\*math.sin(2\*math.pi\*27\*n/FS) for n in range(N) hann = 0.5-0.5\*math.cos(2\*math.pi\*n/(N-1)) for n in range(N) windowed = x\*w for x, w in zip(signal, hann) power = \[\] for k in range(N//2 + 1): real = sum(x*math.cos(2*math.pi*k*n/N) for n, x in enumerate(windowed)) imag = -sum(x*math.sin(2*math.pi*k*n/N) for n, x in enumerate(windowed)) power.append(real*real + imag*imag) peaks = sorted(range(1, len(power)), key=power.getitem, reverse=True):4 print("strong bins:", (round(k\*FS/N, 2), round(power\[k, 1)) for k in peaks]) bands = (0, 15), (15, 35), (35, 50.1) total = sum(power1:) for low, high in bands: energy = sum(p for k, p in enumerate(power) if low <= k*FS/N < high and k > 0) print(f"band {low:4.1f}-{high:4.1f} Hz: {energy/total:.1%}") |
先读懂代码中的关键路径
- Hann窗逐点乘输入,降低窗口边界突变造成的远端泄漏。
- DFT输出功率使用real²+imag²,频带能量在相同定义下求和。
- 忽略DC频点能避免基线占据总能量,是否去DC取决于任务。
- 频带使用左闭右开区间,边界频点只进入一个频带。
你应该观察到什么
- 最强频点列表包含10 Hz和27 Hz附近,10 Hz能量更大。
- 前两个频带占据绝大多数能量,35 Hz以上频带接近零但受窗和数值影响不会严格为零。
- 非整数频率会把能量分散到相邻频点,Hann窗降低远处泄漏。
成功标准
- 你能从Fs、N和k计算频率,并明确单边谱范围。
- 频带边界与任务频率相关,PC与MCU使用相同窗函数和归一化。
- FFT或MFCC的预处理时间与工作区进入板端资源预算。
失败时从哪里查起
频域实现常见错误
| 现象 | 原因 | 处理 |
|---|---|---|
| 峰值频率翻倍或减半 | Fs或FFT长度写错 | 打印Fs、N和频点映射 |
| PC与MCU幅值比例不同 | 窗增益或单边谱缩放不同 | 统一幅值定义并用单频黄金信号 |
| MFCC完全不一致 | Mel边界、log或DCT参数不同 | 逐阶段比较中间数组 |
先用单频、双频和全零输入验证频域实现,再进入真实声音或振动数据,可以大幅降低排错复杂度。
把实验迁移到真实MCU项目
CMSIS-DSP RFFT的输出布局、缩放和数据类型与教学DFT不同。使用单频黄金信号先确认峰值频点,再确认幅值和频带比例。
MFCC移植要逐阶段对齐窗后波形、功率谱、Mel能量、log和DCT。最终系数错时从最早不同数组开始查。
把结果再向前推进一步
- 计算16 kHz、400点帧的帧长和频率分辨率。
- 根据一个机械任务设计三个非等宽频带,并说明边界来源。
- 列出MFCC从波形到系数的每个阶段及其版本参数。
|-----------------------------------------------------------------|
| 这篇文章的结论FFT、频带能量和MFCC分别保留频点、频段和谱包络信息。选择依据是任务物理特征、数据验证和MCU资源。 |
参考资料:
更新时间:2026 年 8 月 5 日