编写原因
课程作业,菜狗乱写,希望能给学弟学妹们一些微不足道的参考,本人是一名普通大学生,根据课程学习了一些代码编写知识,本篇是数字信号综合实验内容之一,内容是识别一段音频中的电话号码。之所以写下这篇文章是因为我想起了当初什么都不懂时去做课程实验(某数电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或东拉西扯一堆拼接过来给自己找麻烦。当然,如果真的有什么所谓的雷同而影响到别人的博客,联系我,立刻删除,摆烂大学生不想惹祸上身。爱门。