Bir önceki Ses (1) : Sesin ABC’si yazımızda sesin temel özelliklerine değinmiş ve en sonunda 440 Hz frekansındaki dördüncü oktavdaki La sesini herhangi bir enstrüman kullanmadan matematiksel fonksiyonlarla üretebilir miyiz sorusunu sormuştuk. Öyle ya madem ki ses sinyali matematiksel bir fonksiyon gibi t zaman iken f(t) fonksiyonuna benzemekte, o halde biz tersini yapıp matematiksel bir fonksiyonu ses dalgası olarak dinleyebilir miyiz diye merak edebiliriz.
2. Ses Dalgası Oluşturma
Konuşurken bir çok ses dalgası üretiriz. Ya da bir müzik parçası çalarken enstrümandan ses dalgaları oluşturmaktayız. Peki biz ses dalgasını bu analog yöntemlerle değil de sayısal olarak bilgisayarda üretebilir miyiz? Hiç bir girdi olmadan ses dalgasını bilgisayarda oluşturacağız, bunu yapmaya da lise matematik dersinde trigonometri konusunu öğrenirken oldukça sıkıcı bulduğumuz Sinüs fonksiyonunu ile başlayacağız.
Yukarıdaki grafikte gördüğümüz sinyalin dalga yapısı, bir aşağı bir yukarı salınması yönü ile Matematik dersinden hatırlayabileceğimiz sinüs (İng: sine) fonksiyonunun grafiğine benzemekte. Hatırlarsanız sinüs fonksiyonu -1 ile 1 arasında düzenli olarak salınır.
Her iki sinyalde benzer bir dalga yapısına sahip. O halde biz insan kulağının duyabileceği bir frekansta bir sinüs sinyalini, ses dalgası olarak dinlesek ne sonuç alırız? Bunu yapabilmek için ilk önce belirli bir süre için sinüs değerlerini ölçüp bir sinüs dalgası oluşturmalıyız.
Bir dalga, bir sinyalin zaman içerisinde bir dizi noktadaki değerinin ifadesidir. Örneğin sinyal değerini birinci noktada, ikinci noktada ve bu şekilde ilerleyerek örneğin yüzüncü noktada alırsak bu değerlerin dizisi 1 ile 100 arası tanımlanmış dalgayı oluşturur. Her bir nokta bir örnektir (İng: sample). Bir film şeridindeki her bir kare gibi ses için örnek de zamanda bir noktadır.
Örnekleme hızı (İng: sampling rate) ise bir saniyede kaç adet örnek olduğudur. Örneğin bir saniyede 22.000 örnek var ise bu dalganın örnekleme hızı 22.000 örnek/sn olarak ifade edilir. Örnekleme hızı ne kadar yüksek ise doğal olarak ses sinyali o kadar daha fazla değeri belirtilmiş olur, bu da daha yüksek bir kalite sunar.
Sinüs dalgasının formülü (belki hatırlarsınız) aşağıdaki şekildedir.
y(t) = A . sin (2 . Pi . f . t)
Burada bir t anı için sinüs değeri yani y(t); frekans f iken 2.Pi.f.t çarpımının genlikle çarpımıdır. Şimdilik genliği 1 alarak bir kenara bırakırsak 2 . Pi . f . t değeridir.
Eğer profesyonellerin kullandığı bir saniyede 48.000 örnekleme hızını kullanırsak, her saniyede bu değerleme 48.000 kez yapılmalı ve bu sayede bir saniyelik dalga değerleri belirlenmelidir. Sonuç olarak 0’dan 48.000 e dek bir zaman X eksenimiz olacak ve bu 48.000 nokta için y(t) yani Sinüs dalgasının aldığı değeri belirleyeceğiz.
İlk olarak üreteceğimiz değerler için Numpy dizisi kullanacağız. Dizilerle ile ilgili bu yazımızda, numpy ile ilgili de bu yazımızda bilgiler bulabilirsiniz. Bunun için numpy kütüphanesini ekleyelim.
[python]
import numpy as np
[/python]
Ürettiğimiz sinyalin grafiğini çizmek için de matplotlib kütüphanesinden pyplot bölümünü kullanacağız. Bu açıdan bu kütüphaneyi de eklememiz gerek.
[python]
import matplotlib.pyplot as plt
[/python]
Daha sonra yukarıda gösterilen Sinüs dalgasının formülünde bildiğimiz değerleri kodlayalım.
[python]
#Frekans 440 Hz
frekans = 440
#Örnek Adedi 48.000
örnek_adedi = 48000
#Örnekleme Hızı 48.000 Örnek/Saniye
örnekleme_hızı = 48000.0
pi = 22/7
[/python]
y(t) = A . sin (2 . Pi . f . t) formülünde, t yani zaman eksenindeki 48.000 noktaya geldik. Bunun için Python’daki range fonksiyonunu kullanacağız. range(48000) bize 0 ile 47999 arası 48000 elemanı içeren bir değer aralığı döndürür. X ekseninde 0’dan başlayıp her seferinde 1/48.000 kadar zaman ilerleyeceğimiz için y(t) değerini şu şekilde hesaplayabiliriz.
[python]
sinüs_dalgası =[ np.sin( 2 * pi * frekans * x/örnekleme_hızı)
for x in range(örnek_adedi)]
[/python]
Elde ettiğimiz sinüs_dalgası bir np dizisidir. Eğer print edersek
[0.0, 0.05758717080682187, 0.11498320770666581, 0.1719976111729182, 0.22844114833416268, …, 0.8074952317341164, 0.8401243591631721, 0.8699650833964405]
gibi 48.000 adet değer gösterir. Bunlar Sinüs fonksiyonumuzun 48.000 adet t değerine karşılık aldığı y(t) değerleridir. A değerini şu an için 1 aldığımızdan dolayı herhangi bir etkisi olmamaktadır. Ancak ses dalgasına geçtiğimizde duymak için genliği yükselteceğiz.
Şimdi elimizdeki bu fonksiyonun grafiğini pyplot yardımı ile çizelim.
[python]
x = range(örnek_adedi)
plt.plot(x, sinüs_dalgası)
plt.show()
[/python]
plot fonksiyonuna x ve y eksenleri değerlerini vereceğiz. pyplot bize aşağıdaki grafiği çizer. Tabi 48.000 nokta için çizdiğimizde fazla bir anlam çıkaramayabiliriz. Bu açıdan bir altta kodun tamamı gösterilmekte ve bu fonksiyonun sadece ilk 300 değeri gösterilmektedir.
Tüm kodu tek seferde gösterirsek
[python]
import numpy as np
import matplotlib.pyplot as plt
#Frekans 440 Hz
frekans = 440
#Örnek Adedi 48.000
örnek_adedi = 48000
#Örnekleme Hızı 48.000 Örnek/Saniye
örnekleme_hızı = 48000.0
pi = 22/7
sinüs_dalgası =[ np.sin( 2 * pi * frekans *
x/örnekleme_hızı)
for x in range(örnek_adedi)]
x = range(örnek_adedi)
plt.plot(x[:300], sinüs_dalgası[:300])
plt.show()
[/python]
Bu kod aşağıdaki grafiği çizmektedir.
Tamam bir sinyal oluşturduk gibi. Grafikte 0’dan 300’e kadar olan bölümü çizdik. Ancak biliyoruz ki 48.000 örneklik ve 1 saniye süren bir sinyale sahipiz. Şimdi bu sinyali bir ses dosyasıymış gibi WAV uzantısı ile kaydedelim. Bunun için ilk önce wave ve struct kütüphanelerini ekleyeceğiz.
[python]
import wave
import struct
[/python]
Sonrasında bir Wave dosyasını diske yazmak için Wave kütüphanesinden oluşturma fonksiyonu için parametreleri belirleyeceğiz.
[python]
# Veri Sıkıştırma Yok
sıkıştırma_tipi="NONE"
sıkıştırma_adı="not compressed"
# Genlik 16.000
genlik = 16000
# Tekli – Mono Kanal
kanal=1
# Veri büyüklüğü 2 Byte – 16 Bit
veri_büyüklüğü=2
[/python]
Burada ilk ele alacağımız konu veri_büyüklüğü. Her t değerine karşılık hesapladığımız y(t) değeri iki byte tutar tamsayı (İng: int) olarak saklanmaktadır.
İki byte bilgide de en fazla 2^16 – 1 = 32767 saklanabilir. Bu tam ölçü ses genliği olacaktır, biz örneğimizde yarı ölçü kullanacağız, bunun için A değerini 16000 alacağız.
Şu an herhangi bir veri sıkıştırma uygulamayacağız. Ses tek kanallı olacak.
İlk olarak diske yazacağımız dosyayı oluşturalım. ‘w’ yazma için açtığımızda diskte yeni bir dosya oluşturur.
[python]
ses_dosyası = wave.open(‘deneme.wav’, ‘w’)
[/python]
Daha sonra biraz önce bahsedilen dosya ile ilgili bilgileri tanımlayacağız.
[python]
ses_dosyası.setparams(( kanal,
veri_büyüklüğü,
int(örnekleme_hızı),
örnek_adedi,
sıkıştırma_tipi,
sıkıştırma_adı ))
[/python]
Son olarak ta elimizde bulunan sinus_dalgasi dizisindeki her bir değeri, iki byte büyüklüğündeki binary tipine veri döndüreceğiz ve tek tek, dosyaya yazacağız.
[python]
for s in sinus_dalgası:
ses_dosyası.writeframes(struct.pack(‘h’,
int(s * genlik)))
[/python]
Tüm kodu listelersek şu şekilde olacak.
[python]
import wave
import struct
# Veri Sıkıştırma Yok
sıkıştırma_tipi="NONE"
sıkıştırma_adı="not compressed"
# Genlik 16.000
genlik = 16000
# Tekli – Mono Kanal
kanal=1
# Veri büyüklüğü 2 Byte – 16 Bit
veri_büyüklüğü=2
ses_dosyası = wave.open(‘deneme.wav’, ‘w’)
ses_dosyası.setparams(( kanal,
veri_büyüklüğü,
int(örnekleme_hızı),
örnek_adedi,
sıkıştırma_tipi,
sıkıştırma_adı ))
for s in sinus_dalgası:
ses_dosyası.writeframes(struct.pack(‘h’,
int(s * genlik)))
[/python]
Eğer çalıştığımız kataloğa bakarsak deneme.wav isimli bir dosya bulacağız. Bu dosyayı ses çalıcı bir program ile çalabiliriz.
Eğer bu dosyayı Audacity yazılımına yükleyip büyütürsek aşağıdaki tam düzgün sinüs fonksiyonu ile karşılarız. Aslında bu beklediğimiz görünüm olmalı.
Wuuuhoooo. Matematiksel bir fonksiyon, duyabileceğimiz bir ses dalgasına dönüştü. Üstelik telefonu açtığımızda duyduğumuz klasik çalma sesi 440 Hz La notası. Eğer biz La notasını oluşturabildiysek, Grammy müzik ödülünü de alırız. Bir sonraki yazıda tüm notaları nasıl üreteceğimizi inceleyeceğiz.
Ses (3) : La’yı Üreten Grammy de Alır