Goertzel算法
Goertzel算法由Gerald Goertzel在1958年提出,用於數字信號處理,是屬於離散傅里葉變換的范疇,目的是從給定的采樣中求出某一特定頻率信號的能量,用於有效性的評價。
這個算法有幾個關鍵的參數:
- 采樣率R,指的是需要分析的數據每秒鍾有多少個采樣
- 目標頻率f,指的是需要檢測並評價的這個頻率的值
- 檢測區段采樣值數量N,也就是每N個采樣這個算法會對頻率f給出評價
- 檢測區段包含目標頻率的完整周期個數K
很顯然,上述參數應該有這樣的關系:
K = Nf / R
這個K值應該是一個整數,而且要大小合適。如果太大,不利於檢測的時效,如果太小,則檢測可能不准確。例如十幾甚至二十幾左右應該相對合理。例如R為8000,需要檢測800hz的頻率,N取值100,那么K為10,很不錯。但是,需要檢測的頻率有時候並不那么整,例如697,那么N應該取值多少呢?N在1000以內,無法得到一個整數K,我們只能退而求其次,找一個四舍五入誤差最小的。例如N取115,K的計算結果為10.019375,四舍五入為10,而且有較小的誤差。
有了上述的參數,然后我們來計算每個采樣在一個目標頻率一個周期中所占的弧度ω。既然N個采樣表達了K個周期(2π),那么ω應該這樣計算:
ω = 2πK / N
這里需要注意的是,因為K值可能經過了四舍五入,所以上述兩個公式必須先后計算,一定不能合在一起化簡把K約掉!
然后,我們可以得到后期計算會頻繁遇到的系數C:
C = 2cos(ω) = 2cos(2πK / N)
以上參數,我們都可以事先計算好,不必在每個采樣分析中再次計算。之后,就開始針對N個采樣進行分析計算
首先初始化:
Q1 = 0
Q2 = 0
然后按照順序針對N個采樣每一個值S(我認為這個S一般是一個16位的有符號整數,取值范圍在-32768到32767之間,如果你得到的是已經進行過編碼的媒體流,例如G.711編碼,那么需要首先解碼。當然也許采樣值就是-128到127之間的單字節整數,那么這樣對計算結果中的P值會影響巨大,DTMF識別的時候一些判斷參數可能要調整),做如下計算:
Q0 = CQ1 - Q2 + S
Q2 = Q1
Q1 = Q0
上述計算完成之后,我們就可以得到在這N個采樣中所體現的頻率f的能量值P:
P = Q12 + Q22 - CQ1Q2
DTMF識別
以上是goertzel算法的全部思想。如果我們要將其用於DTMF識別,還需要做一些工作。DTMF識別,我們需要根據給定的一段時間的采樣,能夠最大限度地排除噪音的干擾,將有效的DTMF信號識別出來
我們知道DTMF有8個頻率:697, 770, 852, 941, 1209, 1336, 1477, 1633,通過前4個頻率和后4個頻率的兩兩組合,確定16個符號。那么我們在對給定一段時間的采樣進行處理的時候,就需要先將其分為每段為N個采樣的多個采樣區段,然后對每一區段針對8個頻率分別運用goertzel算法進行計算得到每個頻率的能量P
為了完成這些能量的計算,我們需要在開始針對8個不同的頻率分別計算系數C,而參數N的選擇非常關鍵,因為8個頻率的K值都不同,我們要盡可能使得8個頻率的K值四舍五入之后都誤差盡可能小,經過檢驗,在采樣率為8000的時候,N=205應該是一個最佳值,你可以做一個測試:
N=
針對N個采樣值,對8個頻率分別計算出了能量P之后,我們就可以開始評估這些能量值是否足以表明這N個采樣中含有某個DTMF符號
DTMF符號和頻率的對應關系如下:
f | 1209 | 1336 | 1477 | 1633 |
679 | 1 | 2 | 3 | A |
770 | 4 | 5 | 6 | B |
852 | 7 | 8 | 9 | C |
941 | * | 0 | # | D |
我們從1209, 1336, 1477和1633四個頻率對應的能量P中取最大值,記作Px,從679,770,852和941四個頻率對應的能量P中取出最大值Py。那么Px和Py對應的頻率組合極有可能代表識別出一個DTMF符號。但是,我們還需要做一系列的判斷,來進一步評估:
- Px和Py是否足夠強大?我們可以設定一個門限,如果么Px和Py這兩個任何一個低於這個門限,那么N個采樣被評估為沒有識別出DTMF符號。參考資料[2]中建議這個門限值為4*105。但是如果采樣值的取值范圍是-32768到32767的話,實際上計算出來的P值會非常大,這個門限設為4*109都可以。
- Px和Py的差別是否太大?正常的DTMF信號,這兩個能量應該接近,那么如果差別較大,我們視為無效。參考資料[2]中建議的方法為:如果Py < Px * 0.398,那么認為無效。如果Px < Py * 0.158也認為無效。但是實際上,我們將0.158改為0.5,識別效果更佳。
- 其它頻率的能量P有沒有很多接近Px和Py的?參考資料[2]中建議的方法為:首先取近Px和Py中較大的那個,設為Pm,如果其他頻率的P值有2個以上達到了Pm的15.8%,那么認為是噪音導致,視為無效。
參考資料:
[1] https://en.wikipedia.org/wiki/Goertzel_algorithm
[2] https://en.wikipedia.org/w/index.php?title=Goertzel_algorithm&oldid=17802166