MATLAB识别座机拨号号码(DTMF信号)

编写原因

课程作业,菜狗乱写,希望能给学弟学妹们一些微不足道的参考,本人是一名普通大学生,根据课程学习了一些代码编写知识,本篇是数字信号综合实验内容之一,内容是识别一段音频中的电话号码。之所以写下这篇文章是因为我想起了当初什么都不懂时去做课程实验(某数电FPGA实验)的无助,偶然之间发现一位学长在此留下的指引,向他学习,人家真材实料,我就洒洒水。代码没啥技术含量,大家看个乐子就行。

DTMF编码

网上有很详细的介绍,我这里就不多说了,直接上代码。

主要代码

1.主函数
close all;
clear ;
clc

Filename='文件名';
[audio_1,Fs] = audioread(Filename);%读取音频文件
audio=audio_1(:,1);
sound(audio,Fs);%播放音频文件

%% 预设相关形参
result="The phone number is:";
MAX=1/4*max(audio);
audiolength=length(audio);
t=1:1:audiolength;
length=11;


%% 实现信号分段和分别检测
for i = 1:length
    unanalyse=zeros(1,10000);%数据采集
    num=1;
    issampling=0;%判读是否在采集声音信号段
    for j = 1:audiolength
        pan=0;
        if (audio(j) > MAX) && (issampling == 0)%标记开始位
            issampling = 1;
            unanalyse(num) = audio(j);
            audio(j) = 0;
            num = num + 1;
            continue;
        end
        if issampling == 1%采集数据并确定数据长度
            unanalyse(num) = audio(j);
            audio(j)=0;
            num=num+1;
            if audio(j+1) < MAX
                for s = 1:7000%判断长度
                    if audio(j+s) < MAX
                        pan=pan+1;%无效信号标志位
                    end
                end
            end
        end
        if pan == 7000
            break;
        end
    end
    keynum=detect(unanalyse,10000,Fs);%计算每段截取信号代表的数字
    result=strcat(result,keynum);%将数字加到字符串末尾
end

disp(result);

简单说一下奥,这里我用的是作业中自带的音频信号。文件就是一段拨号录音。

里面的MAX是用来咱们信号每段的开始点的,后面那个‘pan’就是为了判定是否已经截完一个音的信号,因为每个按键之间有一定的间隔,这段时间内,原信息的数值远小于按键响时的数值。当然,这些参数大家可以根据自己的音频进行修改。

2.调用函数(detect.m)

用来判断截取信息所对应的按键

function [keynum]=detect(audio,audiolength,Fs)
t=1:1:audiolength;
% figure(1)
% subplot(2,1,1)
% plot(t,audio)
audio=filter(filter_1,audio);%滤除噪声干扰
% subplot(2,1,2)
% plot(t,audio);
audio_fft=abs(fft(audio));
figure(2)
% plot(t,audio_fft);
% 
% fre_h1=ceil(1209*audiolength/Fs);
% fre_h2=ceil(1336*audiolength/Fs);
% fre_h3=ceil(1477*audiolength/Fs);
% fre_h4=ceil(1633*audiolength/Fs);
% 
% fre_L1=ceil(697*audiolength/Fs);
% fre_L2=ceil(770*audiolength/Fs);
% fre_L3=ceil(852*audiolength/Fs);
% fre_L4=ceil(941*audiolength/Fs);

audio_test=audio_fft;
%% 取fft的前半段结果分析双频数值
for i=ceil(audiolength/2):audiolength
    audio_fft(i)=0;
end
[max_1,index_1]=max(audio_fft);
fre_1=ceil((index_1+1)/audiolength*48000);
for i=0:40%设置40就是相当于设置一个频率计算的容错范围,把你算出来的高/低频信号减去,方便对第二个频率进行分析,下面同理
    audio_fft(index_1+i)=0;
    audio_fft(index_1-i)=0;
end
%之所以写这一块是因为有些音频他干扰比较离谱,会影响分析
if fre_1>1000 && fre_1<1100
    [max_1,index_1]=max(audio_fft);
    fre_1=ceil((index_1+1)/audiolength*48000);
end
[max_2,index_2]=max(audio_fft);
fre_2=ceil((index_2+1)/audiolength*48000);
for i=0:40
    audio_fft(index_2+i)=0;
    audio_fft(index_2-i)=0;
end
if fre_2>1000 && fre_2<1100
    [max_2,index_2]=max(audio_fft);
    fre_2=ceil((index_2+1)/audiolength*48000);
end

%分辨高频低频
if fre_1<fre_2
    tab=fre_1;
    fre_1=fre_2;
    fre_2=tab;
end
%俩参数代指高低频对应位置,判断按键类型
low=0;
high=0;
%确认信号双频这块写的就比较随意了,因为分析等各种原因,总会与实际产生不少误差,写的比较夸张,理解原理就行
if fre_1 >1200 && fre_1 < 1300
    high=1;
elseif fre_1 >1330 && fre_1 < 1370
    high=2;
elseif fre_1 >1450 && fre_1 < 1500
    high=3;
elseif fre_1 >1600 && fre_1 < 1670
    high=4;
end

if fre_2 >600 && fre_2 < 734
    low=1;
elseif fre_2 >734 && fre_2 < 810
    low=2;
elseif fre_2 >810 && fre_2 < 896
    low=3;
elseif fre_2 >896 && fre_2 < 1000
    low=4;
end
%把按键赋给输出值
if high == 1 && low == 1
    keynum='1';
elseif high == 2 && low ==1
    keynum='2';
elseif high == 3 && low ==1
    keynum='3';
elseif high == 4 && low ==1
    keynum='A';
elseif high == 1 && low ==2
    keynum='4';
elseif high == 2 && low ==2
    keynum='5';
elseif high == 3 && low ==2
    keynum='6';
elseif high == 4 && low ==2
    keynum='B';
elseif high == 1 && low ==3
    keynum='7';
elseif high == 2 && low ==3
    keynum='8';
elseif high == 3 && low ==3
    keynum='9';
elseif high == 4 && low ==3
    keynum='C';
elseif high == 1 && low ==4
    keynum='*';
elseif high == 2 && low ==4
    keynum='0';
elseif high == 3 && low ==4
    keynum='#';
elseif high == 4 && low ==4
    keynum='D';
end
end
3.滤波器

我用的这个是个低通滤波器,把小于500HZ的噪声全滤除了,当然有更好的选择,大家根据实际进行调整,MATLAB中自带设计滤波器的工具(命令行打filterDesigner),用法网上很多。

function Hd = filter_1
%UNTITLED 返回离散时间滤波器对象。

% MATLAB Code
% Generated by MATLAB(R) 9.10 and Signal Processing Toolbox 8.6.
% Generated on: 09-Dec-2023 11:13:57

% FIR Window Bandpass filter designed using the FIR1 function.

% All frequency values are in Hz.
Fs = 48000;  % Sampling Frequency

Fstop1 = 500;             % First Stopband Frequency
Fpass1 = 600;             % First Passband Frequency
Fpass2 = 2000;            % Second Passband Frequency
Fstop2 = 2500;            % Second Stopband Frequency
Dstop1 = 0.001;           % First Stopband Attenuation
Dpass  = 0.057501127785;  % Passband Ripple
Dstop2 = 0.0001;          % Second Stopband Attenuation
flag   = 'scale';         % Sampling Flag

% Calculate the order from the parameters using KAISERORD.
[N,Wn,BETA,TYPE] = kaiserord([Fstop1 Fpass1 Fpass2 Fstop2]/(Fs/2), [0 ...
                             1 0], [Dstop1 Dpass Dstop2]);

% Calculate the coefficients using the FIR1 function.
b  = fir1(N, Wn, TYPE, kaiser(N+1, BETA), flag);
Hd = dfilt.dffir(b);

% [EOF]
% [EOF]

补充说明

第一次写博客,也不太懂规矩,上述代码基本上都是了解原理后自行编写的,如有雷同应该纯属意外,我也不会闲的没事copy或东拉西扯一堆拼接过来给自己找麻烦。当然,如果真的有什么所谓的雷同而影响到别人的博客,联系我,立刻删除,摆烂大学生不想惹祸上身。爱门。

  • 16
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值