安卓dtmf识别_电话拨键号码(DTMF信号)识别

1、流程

安卓dtmf识别_电话拨键号码(DTMF信号)识别_第1张图片 图1 流程图

2、MATLAB实现

(1)主程序

clear all

clc

[x0,Fs]=audioread('1234567890.wav');

%sound(x0,Fs);

N=length(x0); %采样点

k=(0:N-1);

f=(k/N-1/2)*Fs;

X0=fft(x0);

figure

subplot(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);

figure

subplot(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); %求过零率

figure

subplot(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

end

end

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; %右端点

end

end

left_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);

figure

subplot(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')

end

subplot(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')

end

subplot(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')

end

title('信号过零率'),xlabel('帧编号'),ylabel('过零次数')

%------------------------------------提取信号,识别号码

Ass=15; %单个检测阈值

ferror=-10:10; %频率误差

fsL=[697 770 852 941]; %信号低频

fsH=[1209 1336 1477]; %信号高频

number=zeros(1,length(leftend1)); %存号码

figure

for 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])

end

disp('该号码为:')

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 Frequency

Fstop1 = 500; % First Stopband Frequency

Fpass1 = 697; % First Passband Frequency

Fpass2 = 1477; % Second Passband Frequency

Fstop2 = 1600; % Second Stopband Frequency

Astop1 = 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

end

end

end

(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、程序结果

安卓dtmf识别_电话拨键号码(DTMF信号)识别_第2张图片 图2 原始按键音

安卓dtmf识别_电话拨键号码(DTMF信号)识别_第3张图片 图3 滤波后的按键音

安卓dtmf识别_电话拨键号码(DTMF信号)识别_第4张图片 图4 短时能量与过零率

安卓dtmf识别_电话拨键号码(DTMF信号)识别_第5张图片 图5 有效信号区域

安卓dtmf识别_电话拨键号码(DTMF信号)识别_第6张图片 图6 分割信号

安卓dtmf识别_电话拨键号码(DTMF信号)识别_第7张图片

图7 各按键音频率

安卓dtmf识别_电话拨键号码(DTMF信号)识别_第8张图片 图8 识别结果

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

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

你可能感兴趣的:(安卓dtmf识别)