一、获取代码方式

获取代码方式1:
完整代码已上传我的资源: 【数字信号】基于matlab GUI DTMF信号生成与检测(带按键音)【含Matlab源码 1086期】

获取代码方式2:
通过订阅紫极神光博客付费专栏,凭支付凭证,私信博主,可获得此代码。

备注:订阅紫极神光博客付费专栏,可免费获得1份代码(有效期为订阅日起,三天内有效);

二、DTMF简介

1 含义
双音多频 DTMF(Dual Tone Multi Frequency),双音多频,由高频群和低频群组成,高低频群各包含4个频率。一个高频信号和一个低频信号叠加组成一个组合信号,代表一个数字。DTMF信令有16个编码。利用DTMF信令可选择呼叫相应的对讲机。
双音多频信号(DTMF),电话系统中电话机与交换机之间的一种用户信令,通常用于发送被叫号码。

在使用双音多频信号之前,电话系统中使用一连串的断续脉冲来传送被叫号码,称为脉冲拨号。脉冲拨号需要电信局中的操作员手工完成长途接续。
双音多频信号是贝尔实验室发明的,其目的是为了自动完成长途呼叫。
双音多频的拨号键盘是4×4的矩阵,每一行代表一个低频,每一列代表一个高频。每按一个键就发送一个高频和低频的正弦信号组合,比如’1’相当于697和1209赫兹(Hz)。交换机可以解码这些频率组合并确定所对应的按键。

DTMF编解码器在编码时将击键或数字信息转换成双音信号并发送,解码时在收到的DTMF信号中检测击键或数字信息的存在性。一个DTMF信号由两个频率 的音频信号叠加构成。这两个音频信号的频率来自两组预分配的频率组:行频组或列频组。每一对这样的音频信号唯一表示一个数字或符号。电话机中通常有16个 按键,其中有10个数字键0~9和6个功能键*、#、A、B、C、D。由于按照组合原理,一般应有8种不同的单音频信号。因此可采用的频率也有8种,故称 之为多频,又因它采用从8种频率中任意抽出2种进行组合来进行编码,所以又称之为“8中取2”的编码技术。根据CCITT的建议,国际上采用的多种频率为 687Hz、770Hz、852Hz、941Hz、1209Hz、1336Hz、1477Hz和1633Hz等8种。用这8种频率可形成16种不同的组 合,从而代表16种不同的数字或功能键,具体组合见表1。

在很多应用中都要求进行音调检测,例如:双音多频信号 (DTMF)解码,呼叫过程(拨号音、忙音等)解码,频率响应测试(发送一个音调,同时将结果读回)。在频率响应测试中,如果在一定频率范围内进行测量, 那么得到的频响曲线中可能会包含丰富的信息,例如从电话线的频响曲线可以知道线上是否有负载线圈(电感)。
尽管针对以上应用均有专用IC,但采用软件来实现这些芯片的功能时所需成本比采用专用芯片低很多。然而,很多嵌入式系统都不具备进行连续实时FFT处理的能力,这时就适合采用Goertzel算法。本文将对Goertzel基本算法和Goertzel优化算法进行讨论。
采 用Goertzel基本算法能得出与常规离散傅立叶变换(DFT)或FFT相同的频率实部和虚部。如果需要的话,还可以从该频率实部和虚部中算出幅度和相 位信息。Goertzel优化算法则比Goertzel基本算法更快也更简单,但Goertzel优化算法并不给出频率实部和虚部分量,它只能给出相关的 幅度平方。如果需要幅度信息,可通过对该结果开方得到,但该方法无法得到相位信息。

2 Goertzel基本算法
Goertzel 基本算法在每次采样后立即进行处理,在每个第N次采样进行一次音调检测。在采用FFT算法时,我们要对成块的采样进行处理,但这并不意味着必须按块来处理 数据。数字处理的时间很短,因此如果每次采样都存在一次中断,那么这些数字处理完全可以在中断服务程序(ISR)内完成。或者,如果系统中存在采样缓存, 那么可以持续采样,然后进行批处理。
在真正运行Goertzel算法之前,必须进行下面的初步计算:

  1. 决定采样率;
  2. 选择块大小,即N;
  3. 预先进行一次余弦和正弦计算;
  4. 预先计算一个系数。
    这些计算均可以预先完成,然后硬编码到程序中,从而节省RAM和ROM空间,也可以动态方式计算。

3 选择合适的采样率
实际上,采样率可能已经由应用本身决定了。例如,在电信应用中普遍采用8kHz的采样率,即每秒8,000个采样。又如,模数转换器(或编解码器)的工作频率可能是由一个我们无法控制的外部时钟或外部晶振决定。
但如果我们可以选择采样率,那么就必须遵循奈奎斯特采样定理:采样率至少不低于最高信号频率的两倍。这是是因为如果我们要检测多个频率,那么采用更高的采样率可能会得到更好的结果。而且我们都希望采样率与每一个感兴趣的频率之间均呈整数倍关系。

4 块大小的设置
Goertzel算法中的块大小N与相应的FFT中的点数类似,它控制了频率分辨率的大小。例如,若采样率为8kHz,而N为100个采样,那么频率分辨率就是80Hz。
这就可能使我们为了获取最大的频率分辨率而尽量将N取高。然而N越大,检测到每个音调所需的时间就越多,因为我们必须等所有这N个采样都完成后才能开始处理。例如,采样率为8kHz时,累积800个采样需要100ms。若想缩短检测音调的时间,就必须适当调整N的值。
影响N的选择的另一个因素是采样率和目标频率之间的关系。比较理想情况是目标频率在相应的频率分辨率的中点范围内,也就是说,我们希望目标频率是sample_rate/N比值的整数倍。值得庆幸的是,Goertzel算法中的N与FFT中不同,不必是2的整数次幂。

5 预计算常数
在采样率和块大小确定之后,只须通过下面5个简单的计算来得出处理时所需要的常数:
k = (Ntarget_freq)/sample_tate
w = (2
π/N)*k
cosine = cos w
sine = sin w
coeff = 2 * cosine
每一次采样处理中都需要3个变量,我们称其为Q0’、Q1’和Q2。Q1是前一次采样处理的Q0值,Q2是在两次采样前的Q0值(或Q1在本次采样前的值)。
在每个采样块的开始时,都必须将Q1和Q2初始化为0。每个采样都需要按照下面三个等式进行计算:
Q0 = coeff * Q1 - Q2 + sample
Q2 = Q1
Q1 = Q0
在进行N次预采样计算之后,可以检测到音调是否存在。
real = (Q1 - Q2 * cosine)
imag = (Q2 * sine)
magnitude2 = real2 + imag2
这时只需进行一次简单的幅度门限测试就可以判断出是否有音调存在。之后,将Q2和Q1复位到0,开始下一个块的处理。

6 Goertzel优化算法
Goertzel优化算法比Goertzel基本算法所需的计算量小,但这是以损失相位信息为代价。
在 Goertzel优化算法中每个采样处理完全一样,但处理的结果与Goertzel基本算法不同。在Goertzel基本算法中,通常需要计算信号的实部 和虚部,然后将实部和虚部的计算结果转换为相应的幅度平方。而在优化Goertzel算法中则不需计算实部和虚部,直接计算下式:
magnitude2 = Q12 + Q22-Q1Q2coeff

三、部分源代码

function varargout = GUI(varargin)
%          GUI Application M-file for GUI.fig
%        FIG = GUI launch GUI GUI.
%              GUI('callback_name', ...) invoke the named callback.
%
%  Date: 21/05/04     Time: 17:50
%  Email: pranamjanney@yahoo.comif nargin == 0  % LAUNCH GUIfig = openfig(mfilename,'reuse');% Use system color scheme for figure:set(fig,'Color',get(0,'defaultUicontrolBackgroundColor'));% Generate a structure of handles to pass to callbacks, and store it. handles = guihandles(fig);% Initialising structure variables to be used in programhandles.data = 0;           % used for storing the Num_of_samples valuehandles.data1 = 0;          % used for storing the Slider valueshandles.data3 = 0;          % used for storing the number of times the push button is pressedhandles.data4(1,8) = ' ';       % Array to store the numbers dialled handles.chk = 0;            %  To check if the Number of samples is used or notguidata(fig, handles);if nargout > 0varargout{1} = fig;endelseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACKtryif (nargout)[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyardelsefeval(varargin{:}); % FEVAL switchyardendcatchdisp(lasterr);endend% --------------------------------------------------------------------
function varargout = pushbutton1_Callback(h, eventdata, handles, varargin)% To check for N
if handles.chk == 0N = 205;
elseN = handles.data;           %  Number of samples
endNP = handles.data1;         % Noise Power
handles.data3 = handles.data3 + 1;  % to keep track of number of times push buttons are used% Generator
[x,v,snr] = generator(1,N,NP);
size(x);% Display SNR
set(handles.edit3,'String',snr)% To plot on GUI
f = 1:N;
axes(handles.Out_dtmf) % Select the proper axes
plot(f,x(1:N))
set(handles.Out_dtmf,'XMinorTick','on')
grid on% Decoder
[D,m] = decoder(x,N);
size(m);% To append each dialled digit into an array (max 8 numbers)
[handles.data4,handles.data3] = StringNum(handles.data4,D,handles.data3);% After 8th digit the next number is put into first digit place
if handles.data4 == ' ' handles.data4(handles.data3) = D;
end% To display the dialled numbers
set(handles.edit2,'String',handles.data4);         % The dialled number as decoded by the decoder% is displayed on the edit text% To plot the output
f = 1 : length(m);
axes(handles.G_output) % Select the proper axes
plot(f,m)
set(handles.G_output,'XMinorTick','on')
grid on
guidata(h,handles);% --------------------------------------------------------------------
function varargout = pushbutton2_Callback(h, eventdata, handles, varargin)% To check for N
if handles.chk == 0N = 205;
elseN = handles.data;           %  Number of samples
end       %  Number of samplesNP = handles.data1;         % Noise Power
handles.data3 = handles.data3 + 1;  % to keep track of number of times push buttons are used% Generator
[x,v,snr] = generator(2,N,NP);
size(x);% Display SNR
set(handles.edit3,'String',snr)% To plot on GUI
f = 1:N;
axes(handles.Out_dtmf) % Select the proper axes
plot(f,x(1:N))
set(handles.Out_dtmf,'XMinorTick','on')
grid on% Decoder
[D,m] = decoder(x,N);
size(m);% To append each dialled digit into an array (max 8 numbers)
[handles.data4,handles.data3] = StringNum(handles.data4,D,handles.data3);% After 8th digit the next number is put into first digit place
if handles.data4 == ' ' handles.data4(handles.data3) = D;
end% To display the dialled numbers
set(handles.edit2,'String',handles.data4);         % The dialled number as decoded by the decoder% is displayed on the edit text% To plot the output
f = 1 : length(m);
axes(handles.G_output) % Select the proper axes
plot(f,m)
set(handles.G_output,'XMinorTick','on')
grid on
guidata(h,handles);% --------------------------------------------------------------------
function varargout = pushbutton3_Callback(h, eventdata, handles, varargin)% To check for N
if handles.chk == 0N = 205;
elseN = handles.data;           %  Number of samples
endNP = handles.data1;         % Noise Power
handles.data3 = handles.data3 + 1;  % to keep track of number of times push buttons are used% Generator
[x,v,snr] = generator('A',N,NP);
size(x);% Display SNR
set(handles.edit3,'String',snr)% To plot on GUI
f = 1:N;
axes(handles.Out_dtmf) % Select the proper axes
plot(f,x(1:N))
set(handles.Out_dtmf,'XMinorTick','on')
grid on% Decoder
[D,m] = decoder(x,N);
size(m);% To append each dialled digit into an array (max 8 numbers)
[handles.data4,handles.data3] = StringNum(handles.data4,D,handles.data3);% After 8th digit the next number is put into first digit place
if handles.data4 == ' ' handles.data4(handles.data3) = D;
end% To display the dialled numbers
set(handles.edit2,'String',handles.data4);         % The dialled number as decoded by the decoder% is displayed on the edit text% To plot the output
f = 1 : length(m);
axes(handles.G_output) % Select the proper axes
plot(f,m)
set(handles.G_output,'XMinorTick','on')
grid on
guidata(h,handles);% --------------------------------------------------------------------
function varargout = pushbutton4_Callback(h, eventdata, handles, varargin)% To check for N
if handles.chk == 0N = 205;
elseN = handles.data;           %  Number of samples
end

四、运行结果

五、matlab版本及参考文献

1 matlab版本
2014a

2 参考文献
[1] 沈再阳.精通MATLAB信号处理[M].清华大学出版社,2015.
[2]高宝建,彭进业,王琳,潘建寿.信号与系统——使用MATLAB分析与实现[M].清华大学出版社,2020.
[3]王文光,魏少明,任欣.信号处理与系统分析的MATLAB实现[M].电子工业出版社,2018.

【数字信号】基于matlab GUI DTMF信号生成与检测(带按键音)【含Matlab源码 1086期】相关推荐

  1. 【图像去噪】基于matlab GUI butterworth+中值+维纳+小波图像去噪【含Matlab源码 520期】

    ⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[图像去噪]基于matlab GUI butterworth+中值+维纳+小波图像去噪[含Matlab源码 520期] 获取代码方式2: ...

  2. 【物理应用】基于matlab GUI气象参数计算综合指标和IAQI【含Matlab源码 2116期】

    ⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[物理应用]基于matlab GUI气象参数计算综合指标和IAQI[含Matlab源码 2116期] 点击上面蓝色字体,直接付费下载,即可 ...

  3. 【口罩识别】基于matlab GUI RGB滤波+YCbCr+肤色标定口罩识别【含Matlab源码 1895期】

    ⛄一.口罩识别简介 口罩规范佩戴识别是基于人脸口罩检测结果进行的,该部分的输入是人脸口罩检测的输出且是有佩戴口罩的人脸.首先,将人脸部分的图像提取出来:然后映射到YCrCb颜色空间并进行非线性变换,经 ...

  4. 基于JavaWeb Mybatis+MVC(JSP + servlet + javabean)的高校就业管理系统(含项目源码)

    基于JavaWeb Mybatis+MVC的高校就业管理系统 项目简介 基本功能简介 项目要求 概要设计 数据模型(E-R图) 数据库结构设计 主要页面展示 项目实现 创建项目 项目结构展示 项目关键 ...

  5. 【图像加密】基于matlab GUI正交拉丁方+二维Arnold置乱图像加密【含Matlab源码 813期】

    ⛄一.正交拉丁方置乱及二维Arnold置乱简介 0 引言 随着通讯技术的飞速发展, 越来越多的领域需要传送数字图像信号, 因此信息的传送安全问题显得越来越重要.通常应用于数字图像通信的两种保护技术为: ...

  6. 【目标检测】基于matlab GUI背景差分算法视频运动物体跟踪【含Matlab源码 1915期】

    一.背景差分法和帧间差分法的车辆运动目标检测简介 1 引言 运动目标检测是从图像序列中检测运动目标.通过运动目标检测可以得到图像中的运动目标,获取图像中的运动信息.运动目标检测在医学辅助诊断.航天航空 ...

  7. 【ACO三维路径规划】基于matlab GUI蚁群算法无人机三维路径规划【含Matlab源码 254期】

    一.无人机简介 0 引言 随着现代技术的发展,飞行器种类不断变多,应用也日趋专一化.完善化,如专门用作植保的大疆PS-X625无人机,用作街景拍摄与监控巡察的宝鸡行翼航空科技的X8无人机,以及用作水下 ...

  8. 【目标跟踪】基于matlab GUI帧差法结合卡尔曼滤波行人姿态识别【含Matlab源码 1127期】

    ⛄一.基于人体特征识别和卡尔曼滤波的行人跟踪算法简介 1 基于体型和行为姿态特征的人体识别算法 从红外图像中可以得到目标与背景之间的灰度级差别,从而区分出有生命特征的运动物体,但仅从亮度特征无法区别出 ...

  9. 【图像分割】基于matlab GUI医学图像均值聚类+OUST+区域生长法图像分割【含Matlab源码 2210期】

    一.图像分割简介 1 图像分割技术 图像分割 : 根据灰度 , 颜色 , 纹理等,将图像进行分割. 2 常用的分割技术 2.1 边缘检测法 边缘是图像的最重要的特征.边缘是指周围像素灰度有阶跃变化或屋 ...

  10. 【毕业设计/图像识别系列】基于凸包检测和重心距离法的指尖检测和识别【含Python源码】

    Date: 2022.5.23 文章目录 前言 0.代码获取方式 1.参考 2.算法原理 3.实现效果图 4.Python程序(核心) 前言 在大学毕业设计的时候,课题要求实现<基于凸包检测和重 ...

最新文章

  1. 盘点COVID-19新冠药物和疫苗研发进展
  2. 记录由Equal基础知识引起的内存泄露
  3. linux下命令行安装anaconda3+pytorch+fastai
  4. 《JAVA练习题目7》 定义一个素数生成器类PrimeGenerator,用于生成给定区间内的所有素数。(类PrimeGenerator都由类Main代替)
  5. 动态半导体ram依据什么存储信息_LPDDR4X和RAM两者有什么关系 它们有什么特点
  6. 使用关指定中断解决资源冲突问题
  7. GDCM:gdcm::FileAnonymizer的测试程序
  8. maven项目的一键构建
  9. CodeForces - 1370D Odd-Even Subsequence(二分+思维)
  10. springboot干什么的_Spring Boot 项目的这些文件都是干啥用的?
  11. libevent源码深度剖析一
  12. mysql.socket没有_mysql启动找不见socket
  13. [Java] 蓝桥杯ALGO-61 算法训练 奇偶判断
  14. 【渝粤教育】广东开放大学 微信平台开发与应用 形成性考核 (54)
  15. linux硬盘只读脚本 zabbix,Zabbix如何设置脚本告警
  16. css宋体代码_CSS字体代码
  17. 2011 年上半年软考5 月 信息系统项目管理师上午试题参考答案
  18. 基于VB6.0的MICAPS风云二号卫星云图转化实例(转载)
  19. 蓝桥杯 明码题解 【Java实现】
  20. 第7章第37节:七图排版:一张背景六张拼合布局 [PowerPoint精美幻灯片实战教程]

热门文章

  1. java连接zookeeper服务器出现“KeeperErrorCode = ConnectionLoss for ...”
  2. [UE4]关闭自动曝光
  3. 初步了解python
  4. 堆栈小应用(一):括号匹配程序
  5. 不同浏览器对URL最大长度的限制(转)
  6. WinForm系统 -- 系统架构
  7. HttpClient 4.0.x Tips
  8. MSSQL中如何用SQL语句查询字段类型?
  9. Linux下使用QQ和查看QQ空间
  10. 卡尔曼滤波(Kalman filtering)算法学习小记