Goertzel Algoritması

Başlatan Serk@n, 24 Mart 2020, 15:28:15

Serk@n

Herkese iyi çalışmalar diliyorum.

Goertzel algoritması, CM8870 gibi entegreler kullanmadan sadece mikrodenetleyici ile DTMF frekanslarını tespit etmeye yarıyor. Üstelik sadece DTMF değil, istediğimiz her frekansın bir ses sinyalinde bulunup–bulunmadığını da tespit edebiliriz. Örneğin telefon hattında çevir sesi var mı, aranan numara meşgul mu gibi sorgulamalar yapabiliriz.

Uzun zamandır uğraştığım Geortzel algoritmasını çalıştırmayı nihayet başardım. Konuyla ilgilinen arkadaşlar olduysa birçok kişinin bu algoritmayı randımanlı bir şekilde çalıştıramadığından bahsettiğini duymuştur. Bunun sebebi küçük bir sırrın açıklanmamasıdır. Ben forumdaki arkadaşlara bir vefa borcu olarak hem bunu açıklamak hem de bu algoritmayı anlatmak istiyorum.

Şimdi yazılıma geçebiliriz. Örnek olarak 697 Hz. frekansın bir ses sinyalinde bulunup–bulunmadığını tespit edelim. Yazılımda 5 adım  var.

1. ADIM:
deger(208) adında, sıfır dahil 207 adet veri kaydedebileceğimiz bir dizin tanımlıyoruz.

Analog girişten okuduğumuz verileri, bu 207 adet deger dizisine kaydediyoruz. (Bu dizi, byte olarak tanımlanabilir.)

Buradaki 207 rakamı, ileride izahı yapılacağı üzere en fazla 207 değere ihtiyacımız olacağı içindir.

2. ADIM:
ornekhizi, ornekadedi, frekans adlarında tamsayı olarak; floatornekadedi adında ondalıklı sayı olarak dört değişken atıyoruz.

"ornekhizi" analog girişten aldığımız örnekleme hızıdır. (Ben bunun için 8000 Hz. kullandım. Yani Timer, her 125 uSn.de bir analog okuma yapıyor.)

"ornekadedi", örnek adedidir. (697 Hz.in tespiti için yukarıda aldığımız 207 numunenin 205 tanesini kullanacağız.)

"frekans", aradığımız frekans değeridir.

"floatornekadedi" ise "ornekadedi" değişkeninin ondalıklı sayı halidir. İleride lazım olacak.

ornekhizi=8000
ornekadedi=205
frekans=697
floatornekadedi= ornekadedi * 1.0

"Yukarıdaki değerlere bağlı olarak üç katsayımız ortaya çıkacak. Bu katsayılara ileriki adımlarda ihtiyaç olacak. Bunlar sine, cosine ve coeff. Katsayıların çıkması için k ve omega değişkenleri için de birkaç işlem yapacağız. (k tamsayı, diğerleri ondalıklı sayı olarak tanımlanacak) Bunun formülü de şu şekilde: "

k = int(0.5 + (floatornekadedi * frekans / ornekhizi))
omega = 2.0 * pi * k / floatornekadedi

"Yukarıdaki pi değeri bildiğimiz pi sayısı. Şimdi katsayılar için şu işlemleri yapıyoruz:"

sine = sin (omega)
cosine = cos (omega)
coeff = 2.0 * cosine

3. ADIM:

"Bu adımda üç adet ondalıklı sayı olarak q0, q1, q2 değişkenlerini tanımlıyoruz. Burada bir sayaç oluşturuyoruz. Sayaçtan önce değişkenleri sıfırlıyoruz. Ve sayaç içinde şu işlemler sürekli tekrarlanıyor:"

q0 = 0
q1 = 0
q2 = 0

For i = 0 to ornekadedi

q0 = coeff * q1 – q2 + deger(i)
q2 = q1
q1 = q0

Next i

4. ADIM:
"Sondan bir önceki adımda real, imag, magnitude olmak üzere üç değişkeni daha ondalıklı sayı olarak tanımlayıp şu işlemleri yapıyoruz:"

real = (q1 – q2 * cosine) / floatornekadedi
imag = (q2 * sine) / floatornekadedi
magnitude = sqrt( real * real + imag * imag)

Yani real ve imag değerlerini tespit ettikten sonra karelerini alıp topluyoruz, sonucun karekökünü alıyoruz.

5. ADIM:
magnitude değişkeninde çıkan sonuç bizim sinyalimizdeki 697 Hz. frekansının bulunma değeridir. Aynı işlemi 2. Adımdan itibaren 770, 852, 941, 1209, 1366, 1477, 1633 Hz. frekanslar için de yapıyoruz. Sonuçta iki magnitude değeri, diğer magnitude değerlerden çok bariz olarak farklı bir değere (yüksek) ulaşırsa, girişte bir DTMF sinyali alınmış demektir. Hangi iki sinyal diğerlerinden farklıysa buna göre basılan tuş tespit edilir. 

Şimdi gelelim küçük sırrımıza yani her frekans için ayrı ayrı uygulayacağımız "ornekadedi" değerlerine:

697––––205
770––––207
852––––206
941––––204
1209–––205
1336–––203
1477–––205
1633–––205
 
İnternet sitelerinde bu değerler frekans ayrımı yapmaksızın sabit 205 olarak veriliyor. Fakat bu, yukarıdaki tablodan da görüleceği üzere yalnızca bazı tuşları tespit edebiliyor. Burada birkaç rakam oynaması bile sonuçlarda ciddi değişikliklere neden oluyor. Algoritmanın sağlıksız çalışmasına sebebiyet veriyor.
Bildiklerimize göre hareket edersek bilmediklerimizi de öğrenebiliriz.

ahmet_zxc

bir zamanlar nasıl olduğunu anlayamadığım konu idi..

ellerinize kollarınıza sağlık..

sağlıcakla kalın.

çok teşekkürler.

Powered by EzPortal