一,逆DTMF說明即思路
DTMF的方法,思路即代碼在上文已經提到
由上文可知,一個按鍵中包含着兩個頻率的信號,為了將按鍵區分,可以對按鍵聲音進行fft即傅里葉變換(不嚴謹,應該叫dft變換),將變換后的結果與表中預設相比對可以得出按鍵的種類。
代碼的實現在預先知道按鍵的持續時間和間隔時間的情況下,對聲音數據進行分段,對一段聲音進行IFFT變換,由於DTMF行頻率和列頻率以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>=690&&I<=700&&B>=1200&&B<=1300
disp(1);
end
if I>=690&&I<=700&&B>=1300&&B<=1400
disp(2);
end
if I>=690&&I<=700&&B>=1400&&B<=1500
disp(3);
end
if I>=690&&I<=700&&B>=1600&&B<=1700
disp(A);
end
if I>=700&&I<=800&&B>=1200&&B<=1300
disp(4);
end
if I>=700&&I<=800&&B>=1300&&B<=1400
disp(5);
end
if I>=700&&I<=800&&B>=1400&&B<=1500
disp(6);
end
if I>=700&&I<=800&&B>=1600&&B<=1700
disp(B);
end
if I>=800&&I<=900&&B>=1200&&B<=1300
disp(7);
end
if I>=800&&I<=900&&B>=1300&&B<=1400
disp(8);
end
if I>=800&&I<=900&&B>=1400&&B<=1500
disp(9);
end
if I>=800&&I<=900&&B>=1600&&B<=1700
disp(C);
end
if I>=900&&I<=1000&&B>=1200&&B<=1300
disp('*');
end
if I>=900&&I<=1000&&B>=1300&&B<=1400
disp(0);
end
if I>=900&&I<=1000&&B>=1400&&B<=1500
disp('#');
end
if I>=900&&I<=1000&&B>=1600&&B<=1700
disp(D);
end
5,總代碼
%-----------------------------------------------------------------------
%clc
[h,Fs]=audioread('my_phone_number_sound_test.wav');%讀出信號,采樣率和采樣位數。
keytime=0.5;%按鍵持續時間
zerotime=0.5;%中間為零的時間
n=keytime*Fs;%按鍵摁下時的點數
n1=zerotime*Fs;%無按鍵時的點數
for i=1:11
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;%求歸一化后的頻率
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;
if I>=690&&I<=700&&B>=1200&&B<=1300
disp(1);
end
if I>=690&&I<=700&&B>=1300&&B<=1400
disp(2);
end
if I>=690&&I<=700&&B>=1400&&B<=1500
disp(3);
end
if I>=690&&I<=700&&B>=1600&&B<=1700
disp(A);
end
if I>=700&&I<=800&&B>=1200&&B<=1300
disp(4);
end
if I>=700&&I<=800&&B>=1300&&B<=1400
disp(5);
end
if I>=700&&I<=800&&B>=1400&&B<=1500
disp(6);
end
if I>=700&&I<=800&&B>=1600&&B<=1700
disp(B);
end
if I>=800&&I<=900&&B>=1200&&B<=1300
disp(7);
end
if I>=800&&I<=900&&B>=1300&&B<=1400
disp(8);
end
if I>=800&&I<=900&&B>=1400&&B<=1500
disp(9);
end
if I>=800&&I<=900&&B>=1600&&B<=1700
disp(C);
end
if I>=900&&I<=1000&&B>=1200&&B<=1300
disp('*');
end
if I>=900&&I<=1000&&B>=1300&&B<=1400
disp(0);
end
if I>=900&&I<=1000&&B>=1400&&B<=1500
disp('#');
end
if I>=900&&I<=1000&&B>=1600&&B<=1700
disp(D);
end
end
就每個頻率對比就完事了,給每個頻率一個范圍,我上面給的范圍很寬,可以是適當的壓縮。
三,結果分析
就用上篇文章產生的音頻,按鍵持續時間為0.5s,空白時間為0.5s

與產生的結果相同。
