电话拨键号码(DTMF信号)识别
发布日期:2021-05-07 14:37:58 浏览次数:27 分类:技术文章

本文共 6478 字,大约阅读时间需要 21 分钟。

1、流程

图1 流程图

2、MATLAB实现

(1)主程序

clear allclc[x0,Fs]=audioread('1234567890.wav');%sound(x0,Fs);N=length(x0);                              %采样点k=(0:N-1);f=(k/N-1/2)*Fs;X0=fft(x0);figuresubplot(2,1,1),plot(x0)title('原始按键音(时域)'),xlabel('t'),ylabel('振幅')subplot(2,1,2),plot(f,abs(fftshift(X0)));xlim([0,4000])title('原始按键音(频域)'),xlabel('f/Hz'),ylabel('幅度')                                 % -----------------------------------------带通滤波 Hd=band_pass;                              %带通滤波器x1=filter(Hd,x0);                          %滤波%sound(x1,Fs)X1=fft(x1);figuresubplot(2,1,1),plot(x1)title('滤波后的按键音(时域)'),xlabel('t'),ylabel('振幅')subplot(2,1,2),plot(f,abs(fftshift(X1))),xlim([0,2000])title('滤波后的按键音(频域)'),xlabel('f/Hz'),ylabel('幅度') % -------------------------------------------过零率与短时能量len=2000;                                   %帧长d=50;                                       %帧重叠样点长s=fra(len,len-d,x1);                        %分帧,s为帧数es=s.^2;                                    %一帧内各样点能量energy=sum(es,2);                           %一帧的能量,行求和zcr=zcro(s);                                %求过零率figuresubplot(3,1,1),plot(x1)title('按键音1234567890'),ylabel('幅度')subplot(3,1,2),plot(energy)title('短时能量'),xlabel('帧编号'),ylabel('E')subplot(3,1,3),plot(zcr)title('信号过零率'),xlabel('帧编号'),ylabel('过零次数')%-------------------------------------------端点检测flag=energy;                                %有效信号标志Ethresh=0.02;                               %短时能量阈值flag(find(energy>Ethresh))=1;flag(find(energy<=Ethresh))=0;                         desired_signal=[];                          %有效信号标志desired_signal(1)=0;                       for i=1:length(flag)    for j=2:i        if flag(j-1)*flag(j)==0            desired_signal(i)=0;        else            desired_signal(i)=1;        end    endend figure,plot(desired_signal),ylim([0,1.2])title('有效信号标志(0无效,1有效)'),xlabel('帧编号'),ylabel('y')for i=2:length(desired_signal)    if desired_signal(i)-desired_signal(i-1)==1        left(i)=i;                      %左端点    elseif desired_signal(i)-desired_signal(i-1)==-1        right(i)=i;                     %右端点    endendleft_end=find(left~=0);                 %左端点right_end=find(right~=0);               %右端点%---------------------------------------分帧后的恢复,分割信号[leftend1,leftend2]=inverse_fra(left_end,len-d,len);[rightend1,rightend2]=inverse_fra(right_end,len-d,len);figuresubplot(3,1,1),plot(x1)title('按键音1234567890'),ylabel('幅度'),xlabel('t')for i=1:length(leftend1)    line([leftend1(i) leftend1(i)],[-0.1 0.1],'Color','red')    line([rightend1(i) rightend1(i)],[-0.1 0.1],'Color','red')endsubplot(3,1,2),plot(energy),ylim([-0.1,0.6])title('短时能量'),xlabel('帧编号'),ylabel('E')for i=1:length(left_end)    line([left_end(i) left_end(i)],[-0.1 1],'Color','red')    line([right_end(i) right_end(i)],[-0.1 1],'Color','red')endsubplot(3,1,3),plot(zcr)for i=1:length(left_end)    line([left_end(i) left_end(i)],[-200,200],'Color','red')    line([right_end(i) right_end(i)],[-200,200],'Color','red')endtitle('信号过零率'),xlabel('帧编号'),ylabel('过零次数')%------------------------------------提取信号,识别号码Ass=15;                                       %单个检测阈值ferror=-10:10;                                %频率误差fsL=[697 770 852 941];                        %信号低频fsH=[1209 1336 1477];                         %信号高频number=zeros(1,length(leftend1));             %存号码figurefor i=1:length(leftend1)    x=x1(leftend1(i):rightend1(i));    N=length(x);    fk=(0:N-1)/N*Fs;    X=abs(fft(x));    if max(X(floor(N*(fsL(1)+ferror)/Fs)))>Ass & max(X(floor(N*(fsH(1)+ferror)/Fs)))>Ass        number(i)=1;    elseif max(X(floor(N*(fsL(1)+ferror)/Fs)))>Ass & max(X(floor(N*(fsH(2)+ferror)/Fs)))>Ass        number(i)=2;    elseif max(X(floor(N*(fsL(1)+ferror)/Fs)))>Ass & max(X(floor(N*(fsH(3)+ferror)/Fs)))>Ass        number(i)=3;    elseif max(X(floor(N*(fsL(2)/Fs)+ferror)))>Ass & max(X(floor(N*(fsH(1)+ferror)/Fs)))>Ass        number(i)=4;    elseif max(X(floor(N*(fsL(2)/Fs)+ferror)))>Ass & max(X(floor(N*(fsH(2)+ferror)/Fs)))>Ass        number(i)=5;    elseif max(X(floor(N*(fsL(2)/Fs)+ferror)))>Ass & max(X(floor(N*(fsH(3)+ferror)/Fs)))>Ass        number(i)=6;    elseif max(X(floor(N*(fsL(3)/Fs)+ferror)))>Ass & max(X(floor(N*(fsH(1)+ferror)/Fs)))>Ass        number(i)=7;    elseif max(X(floor(N*(fsL(3)/Fs)+ferror)))>Ass & max(X(floor(N*(fsH(2)+ferror)/Fs)))>Ass        number(i)=8;    elseif max(X(floor(N*(fsL(3)/Fs)+ferror)))>Ass & max(X(floor(N*(fsH(3)+ferror)/Fs)))>Ass        number(i)=9;    elseif X(floor(N*(fsL(4)/Fs)+ferror))>Ass & X(floor(N*(fsH(2)+ferror)/Fs))>Ass        number(i)=0;    end    subplot(3,4,i),plot(fk,X),title('按键音(频域)'),xlim([500,1500])enddisp('该号码为:')disp(num2str(number))                        %转换为字符串输出

(2)带通滤波器,此滤波器是使用fdatool生成

function Hd = band_pass%BAND_PASS Returns a discrete-time filter object.% MATLAB Code% Butterworth Bandpass filter designed using FDESIGN.BANDPASS.% Generated by MATLAB(R) 9.0 and the Signal Processing Toolbox 7.2.% Generated on: 18-Dec-2019 14:51:03% All frequency values are in Hz.Fs = 44100;  % Sampling FrequencyFstop1 = 500;         % First Stopband FrequencyFpass1 = 697;         % First Passband FrequencyFpass2 = 1477;        % Second Passband FrequencyFstop2 = 1600;        % Second Stopband FrequencyAstop1 = 20;          % First Stopband Attenuation (dB)Apass  = 1;           % Passband Ripple (dB)Astop2 = 30;          % Second Stopband Attenuation (dB)match  = 'stopband';  % Band to match exactly% Construct an FDESIGN object and call its BUTTER method.h  = fdesign.bandpass(Fstop1, Fpass1, Fpass2, Fstop2, Astop1, Apass, ...                      Astop2, Fs);Hd = design(h, 'butter', 'MatchExactly', match);% [EOF]

(3)分帧

function [f] = fra(len,inc,x)%fra 对语音信号分帧%   len-帧长,inc-非重叠样点长度,x-语音信号fh=fix((size(x,1)-len+inc)/inc);  %计算帧数f=zeros(fh,len);                  %行为帧长,列为帧数i=1;n=1;while i

(4)过零率

function [f] = zcro(x)%zcro 计算过零率%   f-过零率,x-帧长f=zeros(size(x,1),1);for i=1:size(x,1)    z=x(i,:);    for j=1:(length(z)-1)        if z(j)*z(j+1)<0            f(i)=f(i)+1;        end    endendend

(5)分帧后的复原

function [end1,end2] = inverse_fra(k,inc,len)%inverse_fra 将帧数编号时,还原到原始语音部分%输出   end1-起始端点,end2-结束端点%输入   k-帧编号,inc-帧非重叠样点长度,len-帧长end1=(k-1)*inc+1;end2=(k-1)*inc+len;end

3、程序结果

图2 原始按键音
图3 滤波后的按键音
图4 短时能量与过零率
图5 有效信号区域
图6 分割信号
图7 各按键音频率

       

图8 识别结果

        在此程序中,端点检测并未用到短时过零率,是通过短时能量进行判断的,短时过零率仅仅是用来辅助判断。由于本人录音时间较长,且每段信号所含信息相同,因此可以用短时能量进行糙的端点检测,若进行更细致的检测则需要使用双门限检测,甚至是多门限检测法。由于电话号码当中并未出现A、B、C、D四个信号,因此滤波时可将高于1477Hz的频率滤除,滤波是为了排除杂波的影响。

识别结果如图8所示,录音顺序确为“1234567890”,表明该程序是正确的。

上一篇:通信系统通信过程仿真(联合信源信道编码)
下一篇:窄带随机过程的产生

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2025年03月17日 05时37分31秒