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、程序结果
图7 各按键音频率
在此程序中,端点检测并未用到短时过零率,是通过短时能量进行判断的,短时过零率仅仅是用来辅助判断。由于本人录音时间较长,且每段信号所含信息相同,因此可以用短时能量进行糙的端点检测,若进行更细致的检测则需要使用双门限检测,甚至是多门限检测法。由于电话号码当中并未出现A、B、C、D四个信号,因此滤波时可将高于1477Hz的频率滤除,滤波是为了排除杂波的影响。
识别结果如图8所示,录音顺序确为“1234567890”,表明该程序是正确的。