Goertzel 算法模拟器 返回
信号处理模拟器

Goertzel 算法模拟器 — DTMF 单频率检测

用 Goertzel 法检测 DTMF 的 16 个按键。学习如何使用二阶 IIR 滤波器以 O(N) 计算 8 个 DFT bin,并根据行列最强频率判定按键的机制。

参数设置
DTMF 按键编号
噪声水平
采样频率 F_s
Hz
帧长 N

按键映射 — 0:'1' 1:'2' 2:'3' 3:'A' / 4:'4' 5:'5' 6:'6' 7:'B' / 8:'7' 9:'8' 10:'9' 11:'C' / 12:'*' 13:'0' 14:'#' 15:'D'

计算结果
检测按键
最强行频率
最强列频率
Goertzel 运算量 N·M
输入信号与 Goertzel 检测强度

上方 = 输入信号 x[n](蓝)/ 下方 = 8 个频率的 |X_k|(红 = 行,蓝 = 列,黄 = 最强)

理论与主要公式

Goertzel 算法对最接近目标频率 f 的 bin k = round(f·N/F_s),通过二阶 IIR 递推直接计算振幅²。

角频率 ω 与系数 c:

$$\omega = \frac{2\pi k}{N},\qquad c = 2\cos\omega$$

二阶 IIR 递推式(s_{-1} = s_{-2} = 0):

$$s_n = x_n + c\,s_{n-1} - s_{n-2}$$

N 个样本后的振幅²(bin 功率):

$$|X_k|^2 = s_{N-1}^2 + s_{N-2}^2 - c\,s_{N-1}\,s_{N-2}$$

1 个 bin 的运算量为 O(N),M 个频率则为 O(N·M)。与 FFT 的 O(N log N) 相比,需要检测的 bin 越少,Goertzel 越有利。

Goertzel 算法模拟器是什么

🙋
已经有 FFT 了,为什么还需要 Goertzel 这种另外的算法呢?
🎓
简单说,Goertzel 是「只想知道某一个频率 bin」时的专家。FFT 会把全部 N 个 bin 一次性算完,但 DTMF 检测只需要 8 个频率。Goertzel 每个 bin 只需 O(N),而且是只用 3 个变量的二阶 IIR 滤波器,非常适合嵌入式 MCU。在模拟器里切换按键时,你会发现真正需要的只是 1 个行 + 1 个列 = 2 个频率。
🙋
「二阶 IIR」是什么?听到「滤波器」总觉得有点畏惧……
🎓
不难的。只是每个样本递推一次 $s_n = x_n + c\,s_{n-1} - s_{n-2}$ 而已。系数 $c = 2\cos(2\pi k/N)$ 只需开头算一次。状态变量只有 $s_{n-1}$ 和 $s_{n-2}$ 两个,所以 3 个字的内存就够。最后用 $|X_k|^2 = s_{N-1}^2 + s_{N-2}^2 - c\,s_{N-1}s_{N-2}$ 得到振幅²。与 DSP 的乘累加指令配合极好。
🙋
在模拟器里把「噪声水平」调高时,柱状图变得不稳定。实际设备如何判定?
🎓
好问题。实际设备会把多个条件用 AND 组合:最强 bin 电平超过阈值、行与列电平比在 ±6 dB 以内、与次强电平之比(twist)在范围内、音调持续 40 ms 以上——同时满足才认定有效。即使噪声让最强 bin 瞬间切换,持续时间条件也能抑制误检。ITU-T Q.24 标准里详细规定了这些。
🙋
增加「帧长 N」会有什么变化?
🎓
N 越大,频率分辨率 $\Delta f = F_s/N$ 越细,相邻频率分离越好;但运算量也线性增加。F_s=8 kHz、N=205 时 $\Delta f \approx 39$ Hz,这是 DTMF 的经典选择。N 太小时 bin 会偏离 DTMF 各频率,检测强度下降。在模拟器里把 N 从 128 滑到 1024,你能看到柱状图的选择性变化。

常见问题

凡是只需检测特定频率的场景都广泛使用。例如电力系统的频率监测(50/60 Hz 的谐波分析)、工业传感器的载波检测、超声波测距的回波检测、无线电的 CTCSS/DCS 静噪解码、医疗设备的脉冲检测等。共同点是「不需要全部 N 个 bin,只想快速取出几个 bin」。
基本形式假设 k 为整数,但有 Generalized Goertzel 扩展,可对应任意实数 k。这样即使目标频率不在 DFT 栅格上,也能在抑制频谱泄漏的同时精确估计振幅。在电力系统频率估计等需要处理非整数 bin 频率的应用中尤为重要。
二阶 IIR 滤波器内部状态容易发散,帧长 N 越大,s_n 的动态范围越急剧增加。可预先对输入进行缩放(如 1/N 倍)防止溢出,或在每个样本使用带保护位的饱和运算。在 Q1.15 或 Q1.31 定点中,常将系数 c 舍入到 Q14 以控制误差。
可以。最后一步计算复数 DFT 值 X_k = s_{N-1} − e^{-jω} s_{N-2} 就能得到实部和虚部,atan2 给出相位角。本模拟器只做振幅检测,但 AM/FM 解调和同步检波需要相位,实现时使用复数输出版。省略相位可少一次乘法——这是 Goertzel 的简洁优势之一。

现实世界的应用

电话通信的 DTMF 解码:固定电话、IP 电话和自动语音应答(IVR)系统中,实时检测用户按键的标准方法就是 Goertzel 法。模拟线路把 DTMF 音叠加在语音上,接收端并行运行 8 个 Goertzel 滤波器,用电平比、持续时间、twist 等判定提取有效按键。VoIP 中虽有 RFC 2833 的数字 DTMF 传输方式,但为了互操作性 Goertzel 解码器仍然活跃使用。

电力系统谐波分析:电能质量监测器持续追踪 50 Hz/60 Hz 及其谐波(150/180、250/300、350/420 Hz 等)的振幅。不必对全部频率做 FFT,只用 Goertzel 对感兴趣的少数谐波持续计算,可降低 CPU 负载同时获得及时的报警判定。结合 Generalized Goertzel,即使系统频率从 50 Hz 略有漂移也能得到准确的振幅估计。

无线电的 CTCSS/DCS 音调检测:商用和业余无线电中,CTCSS 用特定的次声频音调(67〜250 Hz 范围约 50 种)做小组识别。接收机持续监控对应音调的 Goertzel 输出,超过阈值时才解除扬声器静音。检测少数低频音调正是 Goertzel 最擅长的领域。

嵌入式设备的载波检测:FSK 调制解调器的前导码检测、超声波传感器的回波强度测量、脉搏血氧仪的心跳同步等,常在 ARM Cortex-M 级 MCU 上用于「只想用 FFT 级精度测量几个频率」的场景。CMSIS-DSP 库也提供基于 arm_biquad_cascade_df1_q15 的 Goertzel 实现,利用硬件乘法器可在几 µs 内处理 1 帧。

常见误解与注意事项

最常见的误解是误以为「Goertzel 总比 FFT 快」。实际上有盈亏平衡点:当需要检测的频率数 M 超过约 log₂N 时,FFT 反而更划算。例如 N=1024 时 log₂N = 10。需要 10 个以上 bin 时,一次 FFT 一起算完更快。模拟器的「运算量」卡片显示的是 Goertzel 的 N·M,养成在脑海中和 FFT 的 N·log₂N 对比的习惯。只有「频率少」且「目标 bin 事先已知」时,Goertzel 才胜出。

其次常见的是低估「目标频率严格落在 DFT 栅格上」的重要性。标准 Goertzel 用 k = round(f·N/F_s) 取整,若目标频率 f 偏离 bin 中心会产生「扇贝损失」,振幅估计最多下降 3.9 dB(ΔdB ≈ 20log₁₀(sinc(0.5)))。DTMF 经典推荐 F_s=8000, N=205,正是因为 8 个 DTMF 频率全部接近 DFT 栅格的绝妙选择。在模拟器里改变 N 看到柱高变动,就是这个扇贝效应。

最后要注意不要把「Goertzel 输出大 = 检测成功」过于简单化。仅凭柱状图选出最强 bin,会在噪声和语音谐波下频繁误检。实际设备会用 AND 组合多个条件:行和列各自最强电平超过绝对阈值、两者比值在 ±6 dB 以内、与次强的比值(twist)在规定范围、音调持续 40 ms 以上、音调间断 40 ms 以上——全部满足才认定有效按键。在模拟器里把噪声调到 1.0,可以看到最强 bin 频繁切换,体会单纯取最强的危险性。