Main Content

使用格兹尔算法进行 DFT 估计

此示例说明如何使用格兹尔函数来实现基于 DFT 的 DTMF 检测算法。

双音多频 (DTMF) 信令是语音通信控制的基础,在世界范围内广泛用于在现代电话通讯中拨打号码和配置交换机。它也用于语音邮件、电子邮件和电话银行等系统。

生成 DTMF 音调

一个 DTMF 信号由两个正弦波(即音调)的总和组成,频率取自两个互斥的组。选择这些频率是为了防止接收机将任何谐波错误地检测为其他 DTMF 频率。每对音调包含一个低组频率(697 Hz、770 Hz、852 Hz、941 Hz)和一个高组频率(1209 Hz、1336 Hz、1477 Hz),并表示唯一符号。分配给电话拨号盘按钮的频率如下所示:

为电话拨号盘上的每个按钮生成并绘制一个 DTMF 信号。每个信号的采样率为 8 kHz,持续时间为 100 毫秒。

symbol = {'1','2','3','4','5','6','7','8','9','*','0','#'};
[tones, Fs, f, lfg, hfg] = helperDTMFToneGenerator(symbol, false);
helperDFTEstimationPlot1(tones, symbol, Fs, f);

播放 DTMF 音调

例如,播放电话号码 508-647-7000 对应的音调。符号 "0" 对应第 11 个音调。

% To hear, uncomment these lines:

% for i = [5 11 8 6 4 7 7 11 11 11]
%     p = audioplayer(tones(:,i),Fs,16);
%     play(p)
%     pause(0.5)
% end

使用格兹尔算法估计 DTMF 音调

ITU 标准定义的 DTMF 信号的最短持续时间为 40 毫秒。因此,最多有 0.04×8000 = 320 个采样可供估计和检测。DTMF 解码器需要估计这些短信号中包含的频率。

求解此估计问题的一个常见方法是计算接近七个基本音调的离散时间傅里叶变换 (DFT) 采样。对于基于 DFT 的解,已证明使用频域中的 205 个采样可以最小化原始频率和估计 DFT 的点之间的误差。

Nt = 205;
original_f = [lfg(:);hfg(:)]  % Original frequencies
original_f = 7×1

         697
         770
         852
         941
        1209
        1336
        1477

k = round(original_f/Fs*Nt);  % Indices of the DFT
estim_f = round(k*Fs/Nt)      % Frequencies at which the DFT is estimated
estim_f = 7×1

         702
         780
         859
         937
        1210
        1327
        1483

为了最小化原始频率和估计 DFT 的点之间的误差,我们截断音调,只保留 205 个采样或 25.6 毫秒用于进一步处理。

tones = tones(1:205,:);

此时,我们可以使用快速傅里叶变换 (FFT) 算法来计算 DFT。然而,格兹尔算法在这种情形下常用的原因是估计 DFT 所需的采样点数量少。在本例中,格兹尔算法比 FFT 算法更高效。

for toneChoice = 1:12
    % Select tone
    tone = tones(:,toneChoice);
    % Estimate DFT using Goertzel
    ydft(:,toneChoice) = goertzel(tone,k+1); % Goertzel uses 1-based indexing   
end

绘制对应于电话拨号盘的网格上每个音调的格兹尔的 DFT 幅值。

helperDFTEstimationPlot2(ydft,symbol,f, estim_f);

检测 DTMF 音调

可通过测量上述估计的七个频率上的能量来进行数字音调检测。通过简单地提取较低和较高频率组中最大能量的分量可分离每个符号。

附录

此示例中使用以下辅助函数。

另请参阅