14/06/2003
25/04/2010
Giriş
OpenAL'in
heyecan verici dünyasına hoş geldiniz! OpenAL, API’nin
büyük takipçileri olmasına rağmen tam potansiyele
ulaşmamış, hala büyüme aşamasındadır.
Bunun büyük sebeplerinden biri, hala özgül kartlar
için tümleşik donanım hızlandırıcılarının
olmamasıdır. Bununla birlikte, Creative Labs OpenAL projesinin
önemli iştirakçisidir ve yine en büyük ses kartı
imalatçılarının biridir. Ki bu yakın zamanda
donanım akümülatörü için ümit vericidir. OpenAL'in
diğer bir büyük iştirakçisi Loki eşekler
cennetine gitti. Bundan dolayı Linux platformlarında OpenAL'in
geleceği belirsizdir. Yinede pek bilinmeyen birkaç web sitesinin
tenha köşelerinden Linux binarylerini elde edebilirsiniz.
OpenAL
, yine de çoğu büyük ticari ürünlerce
fark edilmiş değil , yanı sıra gelişimi üzebilir.
Bildiğim kadarıyla OpenAL'ı kullanan tek pc oyunu Metal Gear 2
(Gerçi geçenlerde Unreal2’ninde
kullandığını keşfettim). Popüler modelleme
programı, Blender3D, tüm sesler için OpenAL'i
kullandığı yine bilinmekte. Bunlar dışında
diğer sadece OpenAL kullanımı sdk örnekleri ve
İnternette birkaç anlaşılmaz derstedir.
Ama
ona yönel, OpenAL birçok potansiyele sahiptir. Daha
düşük düzeyli donanımla
çalışmayı isteyen(ve bu meşruda olabilir)
birçok başka ses kütüphanesi vardır ama OpenAL'in
tasarımcıları tasarımda onu üstün bir API yapan
bazı şeyler yaptı. Onlar her şeyden önce
şimdiye kadar tasarlanmış en iyisi olan OpenGL API'i taklit
etti. API stili esnektir, bu sayede farklı kodlama metotları ve
donanım uyarlamaları bundan faydalanacaktır. OpenGL ‘i
tecrübe etmiş çoğu kişi oldukça
hızlı OpenAL'de gelişebilecektir. OpenAL aynı zamanda
birçok diğer API'nin sahip olamadığı 3D surround ses
yaratma avantajına sahiptir. Her şeyin üstünde aynı
zamanda kusursuzca EAX ve AC3'e erişme yeteneğine sahiptir.
Bildiğim hiçbir diğer ses kütüphanesi bu
yeteneğe sahip değildir.
OpenAL’ı
kullanmak için hala burada bir sebep bulamadıysanız o zaman
bunlarda diğerleridir. O tamamen harikadır. API güzel görünür
ve kodlarınızla güzel bütünleşecektir. Onunla
birçok harika ses
efektleri yapabileceksiniz. Tabi önce temeli
öğrenmeliyiz.
Velhasıl
hadi kodlara bakalım!
#include <conio.h>
#include <stdlib.h>
#include <al.h>
#include <alc.h>
#include <alu.h>
#include <alut.h>
OpenAL
headerları ile OpenGL headerları arasındaki benzerliği fark
etmişinizdir. "gl.h", "glu.h", ve
"glut.h" gibi aynen "al.h", "alu.h", ve
"alut.h" vardır, tabi birde "alc.h" var. Alc, Audio
Library Context’in kısaltmasıdır ki farklı platformlar
arası ses aygıtlarını yönetir. Ve de, farklı
pencerelerce bir aygıtın paylaşılması durumunu
yönetir. Alc'i OpenGL'de herhangi bir şeye benzetmeyi
istiyorsanız, muhtemelen en çok wgl ve glX eklentilerine
benzetilebilir. Alut kütüphanesi bizim için onu içten
yönettiğinden Alc'e çok girmeyeceğiz, ve şimdilik
ona henüz dokunmayacağız. Aynı şekilde,
küçük demolarımızda ihtiyaç
duymayacağımız bazı matematik işlevselliğini
sağlayan Alu'uda çok fazla kullanmayacağız.
// Bufferlar ses datasını tutar.
ALuint Buffer;
// Sourceler ses yayılma
noktalarıdır.
ALuint Source;
OpenGL
İle aşina olanlar, bir program tarafından kullanılan
texturelerı yönetmek için "texture objeleri"(veya
texture isimleri) kullanıldığını bilir. OpenAL, ses
dosyaları için benzer şeyi yapar. Aslında OpenAL'de 3
çeşit nesne vardır. Birincisi Buffer , ses verisinin kendini
ve sesin nasıl çalınacağı hakkındaki tüm
bilgileri depolar, ve ikincisi source, sesin yayıldığı
uzayda bir noktadır. Bir sourcenin, ses dosyasının kendisi
olmadığını anlamak önemlidir. Bir source sadece
bağlanılan bir bufferdan ses datasını çalar. Source
aynı zamanda "pozisyon ve hız" gibi spesyal
özellikleri belirler.
Henüz
bahsetmediğim üçüncü nesne listenerdır.
Kullanıcının ,'sizin', konumunu temsil eden sadece bir listener
vardır. Ses dosyasının nasıl duyulacağını
source özellikleriyle beraber listener özellikleri saptar. Misal,
onların ilgili pozisyonları sesin şiddetini saptar.
// Sourcenin Pozisyonu.
ALfloat SourcePos[] = { 0.0, 0.0, 0.0 };
// Sourcenin hızı.
ALfloat SourceVel[] = { 0.0, 0.0, 0.0 };
// listenerın pozisyonu.
ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 };
// listenerın hızı.
ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 };
// listenerın yönü. (ilk 3 eleman
"-de,-da", ikinci 3lü "üs")
ALfloat ListenerOri[] = { 0.0, 0.0, -1.0,
0.0, 1.0, 0.0 };
Yukarıdaki
kodda , source ve listener nesnelerinin "pozisyon ve
hızını" belirtiyoruz. Bu diziler, kartezyan
koordinatları temelli vektördür. Tartışmasız
aynı şeyi yapan bir "yapı veya sınıf" geliştirebilirdiniz.
Bu örnekte, basitlik için dizileri kullandım.
ALboolean LoadALData()
{
// alutLoadWAVFile
çağrısı sonrası otomatik dolacak
değişkenler.
ALenum format;
ALsizei size;
ALvoid* data;
ALsizei freq;
ALboolean loop;
Burada
bir dosyadan ses datamızın hepsini yükleyen bir fonksiyonu
yaratacağız. Buradaki değişkenler, alutLoadWaveFile'ın
bize sağlayacağı bazı bilgileri depolamak için
gereklidir.
// buffera wav
datasını yükle.
alGenBuffers(1, &Buffer);
if (alGetError() !=
AL_NO_ERROR)
return AL_FALSE;
alutLoadWAVFile("wavdata/FancyPants.wav", &format, &data,
&size, &freq, &loop);
alBufferData(Buffer, format,
data, size, freq);
alutUnloadWAV(format, data,
size, freq);
'alGenBuffers'
fonksiyonu, buffer nesnesini yaratıp ona geçtiğimiz
değişkene onu depolayacak. Her şeyin sorunsuz gittiğinden
emin olmak için bir hata kontrolü yapmak önemli. OpenAL,
buffer nesnesini oluşturamadığında bellek israfı olur.
Bu durumda hata biti set edilir.
Alut
kütüphanesi burada çok yararı dokunmaktadır. Bizim
için dosyayı açıp buffer yaratmada ihtiyaç
duyduğumuz tüm bilgileri bize sağlar. Ve biz buffera
bütün bu veriyi dahil ettikten sonra bu veriden kurtulmamıza da
yardım eder. Tamamen temiz ve etkin bir şekilde
çalışır.
// source ile
bufferı bağla.
alGenSources(1, &Source);
if (alGetError() !=
AL_NO_ERROR)
return AL_FALSE;
alSourcei (Source,
AL_BUFFER, Buffer );
alSourcef (Source,
AL_PITCH, 1.0f );
alSourcef (Source,
AL_GAIN, 1.0f );
alSourcefv(Source,
AL_POSITION, SourcePos);
alSourcefv(Source,
AL_VELOCITY, SourceVel);
alSourcei (Source,
AL_LOOPING, loop );
Buffer
nesnesini oluşturduğumuzla aynı biçimde bir source
nesnesini oluştururuz. Sonra, çalma zamanı
kullanılacak source özelliklerini tanımlarız. Bu
özelliklerden en önemlisi, kullanacağı
bufferdır. Bu, source'e çalınacak ses dosyasını
söyler. Bu durumda sadece bir taneye sahip olunduğuna biz ona
bağlarız. Aynı şekilde, source'e daha önce
tanımladığımız onun "pozisyon ve
hızını" söyleriz.
'alGenBuffers'
ve 'alGenSources' hakkında bir şey de. Bazı örnek kodlarda
bu fonksiyonların yaratılan bufferlar / sourcelerin nosu için
bir tam sayı değeri döndüreceğini gördüm.
Ben zannedersem bunun daha sonraki sürümlerde dahil edilmeyen bir
hata kontrol etme özelliği olduğunu
düşünüyorum. Eğer başka kodlarda bunun
yapıldığını görürseniz de siz
kullanmayın. Eğer kontrol yapmak istiyorsanız bunun yerine 'alGetError'
kullan (yukarda yaptığımız gibi).
// diğer hata
kontrolü yapılır ve dönülür.
if (alGetError() ==
AL_NO_ERROR)
return AL_TRUE;
return AL_FALSE;
Fonksiyon
sonunda her şeyin yolunda olduğundan emin olmak için bir daha
kontrol yaparız, sonra sonucu döndürürüz.
void SetListenerValues()
{
alListenerfv(AL_POSITION, ListenerPos);
alListenerfv(AL_VELOCITY, ListenerVel);
alListenerfv(AL_ORIENTATION,
ListenerOri);
}
Listener
özelliklerini set etmek için bu fonksiyonu yarattık.
void KillALData()
{
alDeleteBuffers(1,
&Buffer);
alDeleteSources(1,
&Source);
alutExit();
}
Bu,
bizim kapanış prosedürümüz olacak.
Programımızın, kullandığı tüm hafıza ve
ses aygıtlarını serbest bırakmak için bu çağrı
gereklidir.
int main(int argc, char *argv[])
{
// OpenAL’ı
ilkle ve hata bitini resetle.
alutInit(&argc, argv);
alGetError();
'alutInit'
Fonksiyonu, bizim için yapmada Alc ‘nin gerek duyduğu her
şeyi kuracak. Basitçe Alut, Alc aracılığıyla
bir OpenAL context’ini yaratır ve onu aktif geçerli olarak
set eder. Windows platformunda, DirectSound'u ilkler. Sonra hata bitini
resetlemek üzere hata fonksiyonuna ilk çağrıyı yaparız.
Yani hata durumunu 'AL_NO_ERROR' 'e getirmek için 'alGetError'
çağrısını yaparız.
// wav datasını
yükle.
if (LoadALData() ==
AL_FALSE)
return -1;
SetListenerValues();
// bir
çıkış prosedürü kur.
atexit(KillALData);
wav
dosyalarının doğru şekilde
yüklülüğünü anlamaya
çalışacağız. Aksi durumda programı
sonlamalıyız. Sonra, listener değerlerini set eder Ve en sonda
çıkış prosedürümüzü set ederiz.
ALubyte c = ' ';
while (c != 'q')
{
c =
getche();
switch (c)
{
// 'p' ’e basılma çalmayı başlatacak.
case 'p': alSourcePlay(Source); break;
// 's' ’e basılması çalmayı bitirecek.
case 's':
alSourceStop(Source); break;
// 'h'’e basılması çalmayı duraklatacak.
case 'h': alSourcePause(Source);
break;
};
}
return 0;
}
Bu,
dersin ilginç kısmıdır. Ses dosyasının
çalınmasını kontrol etmemize imkan veren oldukça
basit bir döngüdür. 'p' ’e basılma
çalmayı tekrarlatacak, 's' ’e basılma
çalmayı bitirecek ve 'h' ’e basılma çalmayı
duraklatacaktır. 'q' ’e basılma programdan
çıkaracaktır.
Eee durum
böyle. OpenAL'ı ilk keşfiniz. Sizin
için yeterince kolay olduğunu umuyorum. 1337 h4X0r için
biraz fazla basit olmuş olabilir ama hepimiz bir yerden
başladık. İlerledikçe daha gelişilecek.
Dev-C++
proje ve kaynak dosyalarını yükle
Visual C++ 6.0 proje ve kaynak dosyalarını yükle - (TheCell tarafından port edildi)
Java kaynak kodlarını yükle - (Athomas Goldberg tarafından port edildi)
Bu dersin Linux’e portunu yükleyin - (Lee Trager tarafından port edildi)
Bu dersin MacOS’e portunu yükleyin - (Joshua Schrier tarafından port edildi)
Visual C++ 6.0 proje ve kaynak dosyalarını yükle - (TheCell tarafından port edildi)
Java kaynak kodlarını yükle - (Athomas Goldberg tarafından port edildi)
Bu dersin Linux’e portunu yükleyin - (Lee Trager tarafından port edildi)
Bu dersin MacOS’e portunu yükleyin - (Joshua Schrier tarafından port edildi)
*Bu dersin
Java versiyonu için Java Bindings for OpenAL
sayfasına bakın (Athomas Goldberg tarafından adapte edildi)
Dersin Orjinali : http://www.devmaster.net/articles/openal-tutorials/lesson1.php
Dersin Orjinali : http://www.devmaster.net/articles/openal-tutorials/lesson1.php