当前位置:   article > 正文

电话拨键号码(DTMF信号)识别_dtmf拨号判读 csdn

dtmf拨号判读 csdn

1、流程

图1 流程图

2、MATLAB实现

(1)主程序

  1. clear all
  2. clc
  3. [x0,Fs]=audioread('1234567890.wav');
  4. %sound(x0,Fs);
  5. N=length(x0); %采样点
  6. k=(0:N-1);
  7. f=(k/N-1/2)*Fs;
  8. X0=fft(x0);
  9. figure
  10. subplot(2,1,1),plot(x0)
  11. title('原始按键音(时域)'),xlabel('t'),ylabel('振幅')
  12. subplot(2,1,2),plot(f,abs(fftshift(X0)));xlim([0,4000])
  13. title('原始按键音(频域)'),xlabel('f/Hz'),ylabel('幅度')
  14. % -----------------------------------------带通滤波
  15. Hd=band_pass; %带通滤波器
  16. x1=filter(Hd,x0); %滤波
  17. %sound(x1,Fs)
  18. X1=fft(x1);
  19. figure
  20. subplot(2,1,1),plot(x1)
  21. title('滤波后的按键音(时域)'),xlabel('t'),ylabel('振幅')
  22. subplot(2,1,2),plot(f,abs(fftshift(X1))),xlim([0,2000])
  23. title('滤波后的按键音(频域)'),xlabel('f/Hz'),ylabel('幅度')
  24. % -------------------------------------------过零率与短时能量
  25. len=2000; %帧长
  26. d=50; %帧重叠样点长
  27. s=fra(len,len-d,x1); %分帧,s为帧数
  28. es=s.^2; %一帧内各样点能量
  29. energy=sum(es,2); %一帧的能量,行求和
  30. zcr=zcro(s); %求过零率
  31. figure
  32. subplot(3,1,1),plot(x1)
  33. title('按键音1234567890'),ylabel('幅度')
  34. subplot(3,1,2),plot(energy)
  35. title('短时能量'),xlabel('帧编号'),ylabel('E')
  36. subplot(3,1,3),plot(zcr)
  37. title('信号过零率'),xlabel('帧编号'),ylabel('过零次数')
  38. %-------------------------------------------端点检测
  39. flag=energy; %有效信号标志
  40. Ethresh=0.02; %短时能量阈值
  41. flag(find(energy>Ethresh))=1;
  42. flag(find(energy<=Ethresh))=0;
  43. desired_signal=[]; %有效信号标志
  44. desired_signal(1)=0;
  45. for i=1:length(flag)
  46. for j=2:i
  47. if flag(j-1)*flag(j)==0
  48. desired_signal(i)=0;
  49. else
  50. desired_signal(i)=1;
  51. end
  52. end
  53. end
  54. figure,plot(desired_signal),ylim([0,1.2])
  55. title('有效信号标志(0无效,1有效)'),xlabel('帧编号'),ylabel('y')
  56. for i=2:length(desired_signal)
  57. if desired_signal(i)-desired_signal(i-1)==1
  58. left(i)=i; %左端点
  59. elseif desired_signal(i)-desired_signal(i-1)==-1
  60. right(i)=i; %右端点
  61. end
  62. end
  63. left_end=find(left~=0); %左端点
  64. right_end=find(right~=0); %右端点
  65. %---------------------------------------分帧后的恢复,分割信号
  66. [leftend1,leftend2]=inverse_fra(left_end,len-d,len);
  67. [rightend1,rightend2]=inverse_fra(right_end,len-d,len);
  68. figure
  69. subplot(3,1,1),plot(x1)
  70. title('按键音1234567890'),ylabel('幅度'),xlabel('t')
  71. for i=1:length(leftend1)
  72. line([leftend1(i) leftend1(i)],[-0.1 0.1],'Color','red')
  73. line([rightend1(i) rightend1(i)],[-0.1 0.1],'Color','red')
  74. end
  75. subplot(3,1,2),plot(energy),ylim([-0.1,0.6])
  76. title('短时能量'),xlabel('帧编号'),ylabel('E')
  77. for i=1:length(left_end)
  78. line([left_end(i) left_end(i)],[-0.1 1],'Color','red')
  79. line([right_end(i) right_end(i)],[-0.1 1],'Color','red')
  80. end
  81. subplot(3,1,3),plot(zcr)
  82. for i=1:length(left_end)
  83. line([left_end(i) left_end(i)],[-200,200],'Color','red')
  84. line([right_end(i) right_end(i)],[-200,200],'Color','red')
  85. end
  86. title('信号过零率'),xlabel('帧编号'),ylabel('过零次数')
  87. %------------------------------------提取信号,识别号码
  88. Ass=15; %单个检测阈值
  89. ferror=-10:10; %频率误差
  90. fsL=[697 770 852 941]; %信号低频
  91. fsH=[1209 1336 1477]; %信号高频
  92. number=zeros(1,length(leftend1)); %存号码
  93. figure
  94. for i=1:length(leftend1)
  95. x=x1(leftend1(i):rightend1(i));
  96. N=length(x);
  97. fk=(0:N-1)/N*Fs;
  98. X=abs(fft(x));
  99. if max(X(floor(N*(fsL(1)+ferror)/Fs)))>Ass & max(X(floor(N*(fsH(1)+ferror)/Fs)))>Ass
  100. number(i)=1;
  101. elseif max(X(floor(N*(fsL(1)+ferror)/Fs)))>Ass & max(X(floor(N*(fsH(2)+ferror)/Fs)))>Ass
  102. number(i)=2;
  103. elseif max(X(floor(N*(fsL(1)+ferror)/Fs)))>Ass & max(X(floor(N*(fsH(3)+ferror)/Fs)))>Ass
  104. number(i)=3;
  105. elseif max(X(floor(N*(fsL(2)/Fs)+ferror)))>Ass & max(X(floor(N*(fsH(1)+ferror)/Fs)))>Ass
  106. number(i)=4;
  107. elseif max(X(floor(N*(fsL(2)/Fs)+ferror)))>Ass & max(X(floor(N*(fsH(2)+ferror)/Fs)))>Ass
  108. number(i)=5;
  109. elseif max(X(floor(N*(fsL(2)/Fs)+ferror)))>Ass & max(X(floor(N*(fsH(3)+ferror)/Fs)))>Ass
  110. number(i)=6;
  111. elseif max(X(floor(N*(fsL(3)/Fs)+ferror)))>Ass & max(X(floor(N*(fsH(1)+ferror)/Fs)))>Ass
  112. number(i)=7;
  113. elseif max(X(floor(N*(fsL(3)/Fs)+ferror)))>Ass & max(X(floor(N*(fsH(2)+ferror)/Fs)))>Ass
  114. number(i)=8;
  115. elseif max(X(floor(N*(fsL(3)/Fs)+ferror)))>Ass & max(X(floor(N*(fsH(3)+ferror)/Fs)))>Ass
  116. number(i)=9;
  117. elseif X(floor(N*(fsL(4)/Fs)+ferror))>Ass & X(floor(N*(fsH(2)+ferror)/Fs))>Ass
  118. number(i)=0;
  119. end
  120. subplot(3,4,i),plot(fk,X),title('按键音(频域)'),xlim([500,1500])
  121. end
  122. disp('该号码为:')
  123. disp(num2str(number)) %转换为字符串输出

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

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

(3)分帧

  1. function [f] = fra(len,inc,x)
  2. %fra 对语音信号分帧
  3. % len-帧长,inc-非重叠样点长度,x-语音信号
  4. fh=fix((size(x,1)-len+inc)/inc); %计算帧数
  5. f=zeros(fh,len); %行为帧长,列为帧数
  6. i=1;n=1;
  7. while i<fh %帧间循环
  8. j=1;
  9. while j<len %帧内循环
  10. f(i,j)=x(n);
  11. j=j+1;
  12. n=n+1;
  13. end
  14. n=n-len+inc; %下一帧开始的位置
  15. i=i+1;
  16. end
  17. end

(4)过零率

  1. function [f] = zcro(x)
  2. %zcro 计算过零率
  3. % f-过零率,x-帧长
  4. f=zeros(size(x,1),1);
  5. for i=1:size(x,1)
  6. z=x(i,:);
  7. for j=1:(length(z)-1)
  8. if z(j)*z(j+1)<0
  9. f(i)=f(i)+1;
  10. end
  11. end
  12. end
  13. end

(5)分帧后的复原

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

3、程序结果

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

图7 各按键音频率

       

图8 识别结果

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

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

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号