DTFT的方法,思路即代码在上文已经提到
DTFTmatlab实现
由上文可知,一个按键中包含着两个频率的信号,为了将按键区分,可以对按键声音进行fft即傅里叶变换(不严谨,应该叫dft变换),将变换后的结果与表中预设相比对可以得出按键的种类。
代码的实现在预先知道按键的持续时间和间隔时间的情况下,对声音数据进行分段,对一段声音进行IFFT变换,由于DTFT行频率和列频率以1000Hz为界,可以在进行完IFFT变换后,以1000Hz为界将频谱分为两部分,与预设的频率进行比对。
在得到IFFT频率时,由于存在噪声和频谱泄漏现象,所以并不能得到理想的频谱,所以可以使用Max函数,找寻频谱范围内频率的最大值。
二,代码1,读取声音文件
先确定声音序列和按键持续时间和空白时间
[h,Fs]=audioread('my_phone_number_sound_test.wav');%读出信号,采样率和采样位数。
keytime=0.5;%按键持续时间
zerotime=0.5;%中间为零的时间
n=keytime*Fs;%按键摁下时的点数
n1=zerotime*Fs;%无按键时的点数
2,对数据进行IFFT变换
y=h(1+n1*(i-1)+n*(i-1):n+n1*(i-1)+n*(i-1));%确定声音处理的区间
H=fft(y);%快速傅里叶变换
h_d=abs(H/n);%求fft的幅值,并转变为双边谱的幅值(fft的幅值与输入的点数有关,除于n保证原来的幅值)
h_d1= h_d(1:n/2+1);%将双边谱变为单边谱
h_d1(2:end-1)=2*h_d1(2:end-1);%双边谱变为单边谱幅度乘2
f=Fs*(0:n/2)/n;%求归一化后的频率
3,频率获取
f=Fs*(0:n/2)/n;%求归一化后的频率h_d2=h_d1(1:n/8);%由f可知,f的范围为0到4000,n/8的范围为0到1000[M,I] = max(h_d2);I=Fs*I/n;%求出最大值所对应的频率h_d3=h_d1(n/8:n/4-1);%频率范围为1000到2000[A,B] = max(h_d3);B=Fs*B/n+1000;
注意:最大值或者数据位置并不代表着所对应的频率,要进行f=Fs*(0:n/2)/n的处理。
4,很简单的但很繁琐频率判断
if I>&#61;690&&I<&#61;700&&B>&#61;1200&&B<&#61;1300disp(1);endif I>&#61;690&&I<&#61;700&&B>&#61;1300&&B<&#61;1400disp(2);endif I>&#61;690&&I<&#61;700&&B>&#61;1400&&B<&#61;1500disp(3);endif I>&#61;690&&I<&#61;700&&B>&#61;1600&&B<&#61;1700disp(A);endif I>&#61;700&&I<&#61;800&&B>&#61;1200&&B<&#61;1300disp(4);endif I>&#61;700&&I<&#61;800&&B>&#61;1300&&B<&#61;1400disp(5);endif I>&#61;700&&I<&#61;800&&B>&#61;1400&&B<&#61;1500disp(6);endif I>&#61;700&&I<&#61;800&&B>&#61;1600&&B<&#61;1700disp(B);endif I>&#61;800&&I<&#61;900&&B>&#61;1200&&B<&#61;1300disp(7);endif I>&#61;800&&I<&#61;900&&B>&#61;1300&&B<&#61;1400disp(8);endif I>&#61;800&&I<&#61;900&&B>&#61;1400&&B<&#61;1500disp(9);endif I>&#61;800&&I<&#61;900&&B>&#61;1600&&B<&#61;1700disp(C);endif I>&#61;900&&I<&#61;1000&&B>&#61;1200&&B<&#61;1300disp(&#39;*&#39;);endif I>&#61;900&&I<&#61;1000&&B>&#61;1300&&B<&#61;1400disp(0);endif I>&#61;900&&I<&#61;1000&&B>&#61;1400&&B<&#61;1500disp(&#39;#&#39;);endif I>&#61;900&&I<&#61;1000&&B>&#61;1600&&B<&#61;1700disp(D);end
5&#xff0c;总代码
%-----------------------------------------------------------------------
%clc
[h,Fs]&#61;audioread(&#39;my_phone_number_sound_test.wav&#39;);%读出信号&#xff0c;采样率和采样位数。
keytime&#61;0.5;%按键持续时间
zerotime&#61;0.5;%中间为零的时间
n&#61;keytime*Fs;%按键摁下时的点数
n1&#61;zerotime*Fs;%无按键时的点数
for i&#61;1:11y&#61;h(1&#43;n1*(i-1)&#43;n*(i-1):n&#43;n1*(i-1)&#43;n*(i-1));%确定声音处理的区间H&#61;fft(y);%快速傅里叶变换h_d&#61;abs(H/n);%求fft的幅值&#xff0c;并转变为双边谱的幅值(fft的幅值与输入的点数有关&#xff0c;除于n保证原来的幅值)h_d1&#61; h_d(1:n/2&#43;1);%将双边谱变为单边谱h_d1(2:end-1)&#61;2*h_d1(2:end-1);%双边谱变为单边谱幅度乘2f&#61;Fs*(0:n/2)/n;%求归一化后的频率h_d2&#61;h_d1(1:n/8);%由f可知&#xff0c;f的范围为0到4000&#xff0c;n/8的范围为0到1000[M,I] &#61; max(h_d2);I&#61;Fs*I/n;%求出最大值所对应的频率h_d3&#61;h_d1(n/8:n/4-1);%频率范围为1000到2000[A,B] &#61; max(h_d3);B&#61;Fs*B/n&#43;1000;if I>&#61;690&&I<&#61;700&&B>&#61;1200&&B<&#61;1300disp(1);endif I>&#61;690&&I<&#61;700&&B>&#61;1300&&B<&#61;1400disp(2);endif I>&#61;690&&I<&#61;700&&B>&#61;1400&&B<&#61;1500disp(3);endif I>&#61;690&&I<&#61;700&&B>&#61;1600&&B<&#61;1700disp(A);endif I>&#61;700&&I<&#61;800&&B>&#61;1200&&B<&#61;1300disp(4);endif I>&#61;700&&I<&#61;800&&B>&#61;1300&&B<&#61;1400disp(5);endif I>&#61;700&&I<&#61;800&&B>&#61;1400&&B<&#61;1500disp(6);endif I>&#61;700&&I<&#61;800&&B>&#61;1600&&B<&#61;1700disp(B);endif I>&#61;800&&I<&#61;900&&B>&#61;1200&&B<&#61;1300disp(7);endif I>&#61;800&&I<&#61;900&&B>&#61;1300&&B<&#61;1400disp(8);endif I>&#61;800&&I<&#61;900&&B>&#61;1400&&B<&#61;1500disp(9);endif I>&#61;800&&I<&#61;900&&B>&#61;1600&&B<&#61;1700disp(C);endif I>&#61;900&&I<&#61;1000&&B>&#61;1200&&B<&#61;1300disp(&#39;*&#39;);endif I>&#61;900&&I<&#61;1000&&B>&#61;1300&&B<&#61;1400disp(0);endif I>&#61;900&&I<&#61;1000&&B>&#61;1400&&B<&#61;1500disp(&#39;#&#39;);endif I>&#61;900&&I<&#61;1000&&B>&#61;1600&&B<&#61;1700disp(D);end
end
就每个频率对比就完事了&#xff0c;给每个频率一个范围&#xff0c;我上面给的范围很宽&#xff0c;可以是适当的压缩。
三&#xff0c;结果分析就用上篇文章产生的音频&#xff0c;按键持续时间为0.5s&#xff0c;空白时间为0.5s
与产生的结果相同。
四&#xff0c;函数用法audioread