最近,微信公众号好像癫痫发作了。 插入的图片很模糊,看不清公式。 幸运的是,在 的帮助下,我找到了一个可以完美转换 LaTeX 公式的浏览器插件。 虽然写文章需要手写LaTeX公式。 工作量翻了好几倍,但看上去舒服多了。
当我们要计算某个频段的能量时,FFT一般是首选。 但当我们不关注所有频段,而只关注某个频段时,FFT的大量计算量使其并不是更好的选择。 那么有没有办法不用FFT就能计算出该频段的能量呢? 答案当然是肯定的,这就是我们今天要介绍的Gozer算法()。
一、Gozer算法
Gozer算法将离散傅立叶变换视为一组滤波器。 它对输入信号与滤波器中的脉冲响应进行卷积运算,得到滤波器的输出,进而可以得到频域中某点的频率。 该算法利用旋转因子的周期性,将离散傅里叶变换转化为线性滤波运算。首先回顾一下DFT的定义
在
我们知道W是一个周期为N的函数,那么式(1)可以改写为如下形式
将常量N替换为变量n,可得
其中 Fk(n) 在 Gozer 算法中定义为
写成卷积的形式
式(5)可以看作f(n)与复数指数exp(-j2kπ/N)的卷积,其中k表示时间序列中心频率对应的索引,这意味着DFT的输出可以被视为时间序列通过窄带滤波器的输出。
二. 计算步骤
Step1:确定采样率和目标频率后,我们需要预先计算一些常数:
Step2:然后我们定义三个变量Q0、Q1和Q2
Step3:我们安装以下方法进行计算
Step4:最后即可得到目标频率的幅值
从计算步骤可以看出,Gozer算法本质上是一个二极点IIR滤波器。
三. 应用
Gozer算法有什么用? 它是电话系统中电话和交换机之间的一种用户信令。 它通常用于使用双音多频信号(DTMF)发送被叫号码。 双音多频拨号键盘为4×4矩阵,每行代表低频,每列代表高频。 每次按键都会发送高频和低频正弦信号的组合,例如“1”相当于 697 和 1209 赫兹 (Hz)。 开关可以使用基于Gozer算法的解码方法对这些频率组合进行解码并确定相应的键。
我们首先生成数字1234对应的DTMF信号,结果如下图
然后我们使用Gozer算法进行解码,简单来说就是计算DTMF频率对应的能量,其中最大值对应DTMF的个数
goertzel_filter(CONSTANTS[0], CONSTANTS[1], internalArray, &T[0], &T[1], SAMPLES);
goertzel_filter(CONSTANTS[2], CONSTANTS[3], internalArray, &T[2], &T[3], SAMPLES);
goertzel_filter(CONSTANTS[4], CONSTANTS[5], internalArray, &T[4], &T[5], SAMPLES);
goertzel_filter(CONSTANTS[6], CONSTANTS[7], internalArray, &T[6], &T[7], SAMPLES);
goertzel_filter(CONSTANTS[8], CONSTANTS[9], internalArray, &T[8], &T[9], SAMPLES);
goertzel_filter(CONSTANTS[10], CONSTANTS[11], internalArray, &T[10], &T[11], SAMPLES);
goertzel_filter(CONSTANTS[12], CONSTANTS[13], internalArray, &T[12], &T[13], SAMPLES);
goertzel_filter(CONSTANTS[14], CONSTANTS[15], internalArray, &T[14], &T[15], SAMPLES);
goertzel_filter(CONSTANTS[16], CONSTANTS[17], internalArray, &T[16], &T[17], SAMPLES);
本文代码可通过公众号菜单栏“代码”获取。
参考:
[1]。
[2]。
[3]。