赞
踩
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<fh %帧间循环
- j=1;
- while j<len %帧内循环
- f(i,j)=x(n);
- j=j+1;
- n=n+1;
- end
- n=n-len+inc; %下一帧开始的位置
- i=i+1;
- end
- end

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