?音多?信?
(英語:
Dual-Tone Multi-Frequency
,簡稱:
DTMF
),??系?中
??机
?
交?机
之?的一?
信令
,最常用于撥號時?送被叫??
[1]
。不過雙音多頻的發明,除了縮短撥號時間,也擴展了撥號之外的功能,例如自動
總機
、
互動式語音應答
。
在?音多?信?普及之前,??系?中使用一?串的??????送被叫??,??
????
。????需要?信局中的操作?手工完成?途接?。由脈衝撥號到雙音複頻這幾年轉換期當中,新設計的電話機?了能相容於兩種系統,大都設計?複頻/脈衝(TONE / PULSE)兩用。
?音多?信?是
????室
?明的,其目的是?了自?完成?途呼叫。
因?傳統的
????
,只能把信號送到電話接上的這一台
電信交換
機,但長距通話時,往往必須經由多台電信交換機才能完成,雙音多頻信號可以克服這個障?,利用本來就用來傳送聲音的電話線傳送使用者的按鍵信號。
因?雙音多頻的發明,讓自動
總機
與
互動式語音應答
得以發展,此類設備可以在接聽電話後自動宣讀預錄的語音,再依據發話端的按鍵信號做相對回應。
多?信?
[
??
]
按?
[
??
]
?音多?的????是
的矩?,有
個數字鍵和
個字符鍵,每個數字或字符都是由兩個單頻信號的組合來進行傳輸,因此鍵盤上每個按鍵所對應的信號都可以表示?
,其中
和
分別表示按鍵所在的行和列對應的頻率?。換句話說每一行代表一?
高
?,每一列代表一?
低
?。也就是說每按一??就?送一?
高
?和
低
?的正弦信??合,比如'1'相?于697和1209
赫?
(Hz)。交?机可以解??些?率?合??定所??的按?。
AT&T貝爾實驗室提出用
DTMF
信號作?音頻電話的撥號信號,因?這種方式可以提供更高的撥號速率,且容易被自動檢測和識別。但反之,DTMF信號的這個優點也?容易變成致命的缺點,因?容易被交換機檢測和識別,也就意味著容易被意圖?之第三方破解。破解的原理?簡單,只要能?計出DTMF信號中兩個單頻信號的頻率?,再根據底下
電話機鍵盤的頻率陣列表格
的對應關係就可以反推出按鍵?。
?音多???
|
1209 Hz
|
1336 Hz
|
1477 Hz
|
1633 Hz
|
697 Hz
|
1
|
2
|
3
|
A
|
770 Hz
|
4
|
5
|
6
|
B
|
852 Hz
|
7
|
8
|
9
|
C
|
941 Hz
|
*
|
0
|
#
|
D
|
注意:ABCD四個字母?不使用於撥號鍵盤,但常做?機器對機器的控制信號,例如DTMF格式的來話顯示。
按鍵識別實驗
[
??
]
根據撥號音識別號碼的關鍵就在於準確?計出DTMF信號的頻率?。有?多種方法可以?計DTMF信號的頻率?,在此?例兩種實現方法,一種是基於"帶通濾波器"的方法,?一種方法?基於"
格策爾演算法
(Goertzel algorithm)"。
1.帶通濾波器算法:
濾波器算法識別按鍵的關鍵是設計8個帶通濾波器,每個帶通濾波器的中心頻率對應著低/高頻組的各個頻率點。將待識別的撥號音也就是DTMF的信號波型依次通過這8個帶通濾波器。理論上只有頻率成分與濾波器中心頻率一致的信號才會通過,在濾波器輸出端檢測能量最大者?可判斷出低/高頻序號,最後再通過電話機鍵盤的頻率陣列表格的對應關係?可反推出按鍵?。
以下展示使用帶通濾波器算法應用於
MATLAB
程式碼:
clear
clc
fs
=
8000
;
t
=(
0
:
800
)
/
fs
;
fcolumns1
=
697
;
fcolumns2
=
770
;
fcolumns3
=
852
;
fcolumns4
=
941
;
frow1
=
1209
;
frow2
=
1336
;
frow3
=
1477
;
num0
=
sin
(
2
*
pi
*
fcolumns4
*
t
)
+
sin
(
2
*
pi
*
frow2
*
t
);
%數字0
num1
=
sin
(
2
*
pi
*
fcolumns1
*
t
)
+
sin
(
2
*
pi
*
frow1
*
t
);
%數字1
num2
=
sin
(
2
*
pi
*
fcolumns1
*
t
)
+
sin
(
2
*
pi
*
frow2
*
t
);
%數字2
num3
=
sin
(
2
*
pi
*
fcolumns1
*
t
)
+
sin
(
2
*
pi
*
frow3
*
t
);
%數字3
num4
=
sin
(
2
*
pi
*
fcolumns2
*
t
)
+
sin
(
2
*
pi
*
frow1
*
t
);
%數字4
num5
=
sin
(
2
*
pi
*
fcolumns2
*
t
)
+
sin
(
2
*
pi
*
frow2
*
t
);
%數字5
num6
=
sin
(
2
*
pi
*
fcolumns2
*
t
)
+
sin
(
2
*
pi
*
frow3
*
t
);
%數字6
num7
=
sin
(
2
*
pi
*
fcolumns3
*
t
)
+
sin
(
2
*
pi
*
frow1
*
t
);
%數字7
num8
=
sin
(
2
*
pi
*
fcolumns3
*
t
)
+
sin
(
2
*
pi
*
frow2
*
t
);
%數字8
num9
=
sin
(
2
*
pi
*
fcolumns3
*
t
)
+
sin
(
2
*
pi
*
frow3
*
t
);
%數字9
numStar
=
sin
(
2
*
pi
*
fcolumns4
*
t
)
+
sin
(
2
*
pi
*
frow1
*
t
);
%符號*
numJin
=
sin
(
2
*
pi
*
fcolumns4
*
t
)
+
sin
(
2
*
pi
*
frow3
*
t
);
%符號#
blank
=
zeros
(
size
(
num1
));
%間隔
f
=
[
fcolumns1
fcolumns2
fcolumns3
fcolumns4
frow1
frow2
frow3
];
f_Low
=
[
fcolumns1
fcolumns2
fcolumns3
fcolumns4
];
f_High
=
[
frow1
frow2
frow3
];
%設計帶通濾波器(low frequency)
N
=
400
;
Bandwidth
=
70
;
B_Low
=
zeros
(
4
,
N
+
1
);
%存放低頻組的濾波器係數
for
i
=
1
:
4
Wo
=
f_Low
(
i
);
wc1
=
(
Wo
-
Bandwidth
/
2
)
*
2
*
pi
/
fs
;
wc2
=
(
Wo
+
Bandwidth
/
2
)
*
2
*
pi
/
fs
;
B_Low
(
i
,
:)
=
fir2
(
N
,[
0
,
wc1
/
pi
,
wc2
/
pi
,
1
],[
0
,
1
,
1
,
0
]);
end
%設計帶通濾波器(high frequency)
N
=
200
;
Bandwidth
=
110
;
B_High
=
zeros
(
3
,
N
+
1
);
%存放高頻組的濾波器係數
for
i
=
1
:
3
Wo
=
f_High
(
i
);
wc1
=
(
Wo
-
Bandwidth
/
2
)
*
2
*
pi
/
fs
;
wc2
=
(
Wo
+
Bandwidth
/
2
)
*
2
*
pi
/
fs
;
B_High
(
i
,
:)
=
fir2
(
N
,[
0
,
wc1
/
pi
,
wc2
/
pi
,
1
],[
0
,
1
,
1
,
0
]);
end
DialNum
=
num1
;
%DTMF訊號
sound
(
DialNum
);
%計算當前信號與各個頻率點的距離(low frequency)
Diatance_Low
=
zeros
(
1
,
4
);
for
i
=
1
:
4
Output
=
filter
(
B_Low
(
i
,
:),
1
,
DialNum
);
Diatance_Low
(
1
,
i
)
=
max
(
abs
(
fft
(
Output
)));
end
[
maxnum_low
,
index_low
]
=
max
(
Diatance_Low
(
1
,
:));
%計算當前信號與各個頻率點的距離(high frequency)
Diatance_High
=
zeros
(
1
,
3
);
for
i
=
1
:
3
Output
=
filter
(
B_High
(
i
,
:),
1
,
DialNum
);
Diatance_High
(
1
,
i
)
=
max
(
abs
(
fft
(
Output
)));
end
[
maxnum_high
,
index_high
]
=
max
(
Diatance_High
(
1
,
:));
%判斷按鍵
if
index_low
==
1
&&
index_high
==
1
keynum
=
'1'
;
elseif
index_low
==
1
&&
index_high
==
2
keynum
=
'2'
;
elseif
index_low
==
1
&&
index_high
==
3
keynum
=
'3'
;
elseif
index_low
==
2
&&
index_high
==
1
keynum
=
'4'
;
elseif
index_low
==
2
&&
index_high
==
2
keynum
=
'5'
;
elseif
index_low
==
2
&&
index_high
==
3
keynum
=
'6'
;
elseif
index_low
==
3
&&
index_high
==
1
keynum
=
'7'
;
elseif
index_low
==
3
&&
index_high
==
2
keynum
=
'8'
;
elseif
index_low
==
3
&&
index_high
==
3
keynum
=
'9'
;
elseif
index_low
==
4
&&
index_high
==
2
keynum
=
'0'
;
elseif
index_low
==
4
&&
index_high
==
1
keynum
=
'*'
;
elseif
index_low
==
4
&&
index_high
==
3
keynum
=
'#'
;
end
keynum
2.格策爾演算法(Goertzel algorithm):
理論上DTMF信號只會在兩個固定的頻率點上出現能量,如何準確又高效地?計這兩個頻率?(低/高頻組)是識別撥號音的關鍵。傳統的頻譜?計方法得到的是一個頻率區間內所有頻率點的?計結果,而對於DTMF信號我們只在乎那8個固定頻率點上的功率譜?計?。而Goertzel算法就是?計DTMF信號功率譜最經典又實用的方法,這個算法只?計DTMF信號特定頻率點上的功率譜。
以下展示
MATLAB
利用Goertzel演算法?計DTMF信號的範例:
clear
clc
fs
=
8000
;
t
=(
0
:
2000
)
/
fs
;
fcolumns1
=
697
;
fcolumns2
=
770
;
fcolumns3
=
852
;
fcolumns4
=
941
;
frow1
=
1209
;
frow2
=
1336
;
frow3
=
1477
;
num0
=
sin
(
2
*
pi
*
fcolumns4
*
t
)
+
sin
(
2
*
pi
*
frow2
*
t
);
%數字0
num1
=
sin
(
2
*
pi
*
fcolumns1
*
t
)
+
sin
(
2
*
pi
*
frow1
*
t
);
%數字1
num2
=
sin
(
2
*
pi
*
fcolumns1
*
t
)
+
sin
(
2
*
pi
*
frow2
*
t
);
%數字2
num3
=
sin
(
2
*
pi
*
fcolumns1
*
t
)
+
sin
(
2
*
pi
*
frow3
*
t
);
%數字3
num4
=
sin
(
2
*
pi
*
fcolumns2
*
t
)
+
sin
(
2
*
pi
*
frow1
*
t
);
%數字4
num5
=
sin
(
2
*
pi
*
fcolumns2
*
t
)
+
sin
(
2
*
pi
*
frow2
*
t
);
%數字5
num6
=
sin
(
2
*
pi
*
fcolumns2
*
t
)
+
sin
(
2
*
pi
*
frow3
*
t
);
%數字6
num7
=
sin
(
2
*
pi
*
fcolumns3
*
t
)
+
sin
(
2
*
pi
*
frow1
*
t
);
%數字7
num8
=
sin
(
2
*
pi
*
fcolumns3
*
t
)
+
sin
(
2
*
pi
*
frow2
*
t
);
%數字8
num9
=
sin
(
2
*
pi
*
fcolumns3
*
t
)
+
sin
(
2
*
pi
*
frow3
*
t
);
%數字9
numStar
=
sin
(
2
*
pi
*
fcolumns4
*
t
)
+
sin
(
2
*
pi
*
frow1
*
t
);
%符號*
numJin
=
sin
(
2
*
pi
*
fcolumns4
*
t
)
+
sin
(
2
*
pi
*
frow3
*
t
);
%符號#
blank
=
zeros
(
size
(
num1
));
%間隔
f
=[
fcolumns1
fcolumns2
fcolumns3
fcolumns4
frow1
frow2
frow3
];
freq_indices
=
round
(
f
/
fs
*
length
(
t
))
+
1
;
%DTMF信號%
CellPhoneNum
=[
num1
blank
num3
blank
num9
blank
num8
blank
num0
blank
num7
blank
num6
blank
num6
blank
num5
blank
num2
blank
num4
];
CellPhoneNum
=
0.2
*
randn
(
size
(
CellPhoneNum
))
+
CellPhoneNum
;
sound
(
CellPhoneNum
);
for
i
=
1
:
2
:
21
DialNumber
=
CellPhoneNum
(((
i
-
1
)
*
length
(
t
)
+
1
):
i
*
length
(
t
));
dft_data
=
goertzel
(
DialNumber
,
freq_indices
);
temp
=
sort
(
abs
(
dft_data
),
'descend'
);
%?最大的兩個頻率點數?
temp_index1
=
find
(
abs
(
dft_data
)
==
temp
(
1
));
temp_inedx2
=
find
(
abs
(
dft_data
)
==
temp
(
2
));
if
temp_index1
<
temp_inedx2
%保證 temp_index1代表低頻,temp_index2代表高頻
index_low
=
temp_index1
;
index_high
=
temp_inedx2
;
else
index_low
=
temp_inedx2
;
index_high
=
temp_index1
;
end
%判斷按鍵
if
index_low
==
1
&&
index_high
==
5
keynum
=
'1'
;
elseif
index_low
==
1
&&
index_high
==
6
keynum
=
'2'
;
elseif
index_low
==
1
&&
index_high
==
7
keynum
=
'3'
;
elseif
index_low
==
2
&&
index_high
==
5
keynum
=
'4'
;
elseif
index_low
==
2
&&
index_high
==
6
keynum
=
'5'
;
elseif
index_low
==
2
&&
index_high
==
7
keynum
=
'6'
;
elseif
index_low
==
3
&&
index_high
==
5
keynum
=
'7'
;
elseif
index_low
==
3
&&
index_high
==
6
keynum
=
'8'
;
elseif
index_low
==
3
&&
index_high
==
7
keynum
=
'9'
;
elseif
index_low
==
4
&&
index_high
==
6
keynum
=
'0'
;
elseif
index_low
==
4
&&
index_high
==
5
keynum
=
'*'
;
elseif
index_low
==
4
&&
index_high
==
7
keynum
=
'#'
;
end
PhoneCell_Indent
(
round
(
i
/
2
))
=
keynum
;
end
display
(
PhoneCell_Indent
)
%顯示識別結果
特殊音?
[
??
]
特別頻率
事件
|
低頻
|
高頻
|
週期(on / off)
|
忙音
|
480 Hz
|
620 Hz
|
0.5 s / 0.5 s
|
回?音
(美及英式)
|
440 Hz
|
480 Hz
|
1 s / 4 s
|
撥號音
(美及英式)
|
350 Hz
|
440 Hz
|
持續長音
|
?式音?:
事件
|
低頻
|
高頻
|
忙音
(?洲大部)
|
425 Hz
|
----
|
回?音
(英?和???)
|
400 Hz
|
450 Hz
|
回?音
(?洲大部)
|
425 Hz
|
----
|
??音
(英?)
|
350 Hz
|
450 Hz
|
??音
(?洲大部)
|
425 Hz
|
----
|
?見
[
??
]
- ^
Z., Dodd, Annabel. The essential guide to telecommunications 5th. Upper Saddle River, NJ: Prentice Hall. 2012.
ISBN
9780137058914
.
OCLC 779863446
.