经典课程指导:《数字处理系统课程设计与实践》指导(2)DTMF之二 算法讲解
既然可以在固定位置上完成信号的频点检测,计算量自然将远小于FFT。那么能不能进一步减小计算量呢?在这里我隆重推出Goertzel算法。这个算法当年也耗了本人两天时间才真正消化和使用,那么对于本科生呢?则需要更长时间才能学透!
如果大家想要这些资料,请留言写下邮箱,我会统一发给读者。本文重点讲解Goertzel算法。他山之石,可以攻玉!大家务必要多看论文,这有助于学习的加速。文末有本人写的程序。
Goertzel 算法是一种用于计算离散傅里叶变换(DFT)特定项的高效算法。它主要用于在特定频率点上计算信号的频谱分量,而无需计算整个 DFT。该算法的基本思想是通过迭代的方式来计算信号在特定频率点的频谱值。它使用一个二阶滤波器来实现对特定频率的选择性响应,从而有效地计算出该频率点的幅度和相位信息。为何要用这个算法呢?主要是为了减少计算量。
Goertzel 算法和离散傅里叶变换算法在计算点频率值时的计算量差异取决于多个因素,包括数据长度、频率分辨率要求等。一般来说,Goertzel 算法在计算特定频率点的值时,计算量相对较小。对于长度为 N 的数据序列,DFT 需要进行 N 次复数乘法和 N-1 次复数加法来计算每个频率点的值。而 Goertzel 算法通常只需要进行较少的乘法和加法操作,尤其是当只关注特定的一个或几个频率点时,其优势更为明显。对于长度为N序列,Goertzel 算法计算特定频率点的值时,大约有2N-1乘法和2N-2加法。但计算过程中,Goertzel 算法涉及的是固定数的乘法,而DFT涉及的是变化数的乘法,会占用更多的存储空间!在大部分情况下,Goertzel 算法可以比 DFT 算法节省大量的资源,尤其是在实时处理和资源受限的环境中。例如,对于特定频率的检测,Goertzel 算法可以通过迭代的方式逐步计算,避免了对整个频率范围进行全面的 DFT 计算。这种迭代计算的方式在处理长数据序列时,可以显著减少计算量。for row = 1:length(rowFrequencies) for col = 1:length(colFrequencies)[rowMagnitude, rowPhase] = goertzel(inputSignal, rowFrequencies(row), fs, length(inputSignal));[colMagnitude, colPhase] = goertzel(inputSignal, colFrequencies(col), fs, length(inputSignal)); if rowMagnitude > threshold && colMagnitude > threshold disp(['Detected DTMF signal: ', num2str(row + 3*(col - 1))]);function [magnitude, phase] = goertzel(signal, targetFreq, fs, numSamples) q0 = coeff*q1 - q2 + signal(n); realPart = q1 - q2*cos(w0*k); magnitude = sqrt(realPart^2 + imagPart^2); phase = atan2(imagPart, realPart);