05/02/2004
09/05/2010
Giriş
Bu ders, Jesse Maurais’nin OpenAL
Ders
8: OggVorbis Streamleme
- Source Kuyruğunu Kullanma dersinin
doğrudan devamı olarak
tasarlanmıştır. Bu sebeple kullanılan
kod tabanı o derste kullanılanla hemen hemen
aynıdır, tek değişiklik
dosyanın nasıl yüklendiği ile ilgilidir. Diğer her şey tamamen aynıdır. OggVorbis
kütüphanelerinin gerçek
kuvvetlerinden biride, her ne şekilde isterseniz .ogg
dosyasını yükleyebilmenizdir, ve tüm diğer çağrılar tamamen aynı şekilde kullanılır. Görüp
göreceğinle böyle.
Dosyayı
Belleğe Alma
Vorbis
kütüphanelerini kullanmaya başlanmadan önce OggVorbis dosyası belleğe yüklenmeye
ihtiyaç duyulur. Örnek
programda
kullanılan metot, açıkça söylemek gerekirse, tam bir bomba. Normal
olarak, dosya, belki bir sıkıştırılmış dosyadan veya
benzerinden onu çıkarırken, yükleme zamanında hafızaya ön yüklü olmuş olurdu. Bu dersin hatrına, sadece ana belleğe onu nasıl aldığımı
görmezlikten gel.
Bellekten
Okumaya Hazırlık
Vorbis
kütüphaneleri fiilen bellekten dosyaların
yüklenmesi için herhangi bir desteğe sahip değil, Onlar, bunu sana bırakır, Sadece sorarlar ihtiyaçları
olduklarında
döndürdüğün müsait data var mı diye (Bu oldukça güzel , herhangi yerinden ve gelişi güzel .ogg
dosyasını okuyabileceğin anlamındadır). Bunun çalışması için, dört callback
fonksiyonu
lazım (Eğer bir callback
fonksiyonunun ne olduğunu bilmiyorsan, C programlama
kitabı oku ;) )
Callback’ler, ov_callbacks yapısı
kullanılarak
geçilir , onlar:
Fonksiyon İsmi
|
Fonksiyon Tanımı
|
read_func
|
Bellekten datayı
okuyan fonksiyon
|
close_func
|
Bellekte dosyayı kapatan fonksiyon
|
seek_func
|
Bellekte dosyanın belirli kısmını aratan
fonksiyon
|
tell_func
|
Şuana kadar ne kadar okuma yaptığımızı söyleyen
fonksiyon
|
Bu fonksiyonlardan Standart C
IO fonksiyonları (fread(...), ftell(...) vesaire) ile tamamen aynı tarzda çalışması beklenir
,
Ve aslında aynı girdi ve aynı dönüş değerlerine sahiptirler.
Callback
fonksiyonlarımızı deklare ettiğimiz andan
itibaren, ov_callback
yapısının içinde onları depolarız
vorbisCallbacks.read_func = VorbisRead;
vorbisCallbacks.close_func = VorbisClose;
vorbisCallbacks.seek_func = VorbisSeek;
vorbisCallbacks.tell_func = VorbisTell;
Vorbis librarylerine
datada
tüm farklı IO hareketlerini
nasıl gerçekleyeceğimizi söylediğimiz düşünülürse, bilfiil datamızı yükleyecek fonksiyonu göstermemiz
gerekir. Bunu yapmak için, tüm farklı IO
hareketlerini
yapmamıza izin verilmesinde gereksindiğimiz gibi kendi yapımızı tanımlamaya ihtiyaç
duyarız.
Yapı, şöyle:
struct SOggFile
{
char* dataPtr;
// bellekteki dataya
pointer
int dataSize;
// datanın boyutu
int dataRead;
// şuana kadar
okunmuş data miktarı
};
SOggFile oggMemoryFile;
Yapıyı
sahipsek ilkleyeceğiz. Oldukça basit. dataPtr'e data
pointer'ını, dataSize'e datanın boyutunu, Ve dataRead'e 0 koyarız (henüz herhangi okuma yapmadığımız
anlamında).
Artık sadece direksiyonda yön vermeye gerek var.
ov_open_callbacks(&oggMemoryFile,
&oggStream, NULL, 0, vorbisCallbacks)
Bu fonksiyon, kütüphanelere bir
.off
dosyası açmayı istediğimizi bilgilendirir, ama bir DOSYAYI kullanmak yerine, veride kendimiz okuma
yapacağız.
Burada
bir şeyde daha önce oggStream'ı görmedik. Bu sadece,
dosyayı okunacak kıvama bizim için
getirecek olan OggVorbis_File 'ye bir göstergedir.
Bellekteki
Datadan Okuma
Şimdi
yapılması kalan tek şey bilfiil hafızadan
veriyi okumaktır. Bu tamamen,
daha önce tanımladığımız callback
fonksiyonlarının içinde yapılır. Sırayla göz
atalım...
VorbisRead
size_t VorbisRead(void *ptr,
// vorbis dosyası
datasına pointer
size_t byteSize,
//
bir byte nekadar
büyüktür
size_t sizeToRead,
//
ne kadar okuyabiliriz
void *datasource)
/*
ov_open_callbacklerine
geçtiğimiz dataya
bir pointer’dır
bu (SOggFile yapımız)*/
{
...
}
Bu
fonksiyon, hafızadan verinin okunup ptr
değişkenine yerleştirilmesinde gerekli (byteSize*sizeToRead boyutlu). Burada
yapmaya ihtiyaç
duyduğumuz tek şey hafızadan ptr'e verimizi
almak
için memcopy (...) 'i kullanmaktır, Bellekteki verimizin
sınırları aşılmadığından emin olunmalı.
0 'ın dönmesinin anlamı dosyanın
sonuna ulaşıldı, okunacak veri artık
yok demek
olmalı.
Aksi takdirde okuduğumuz veri miktarını döndürmeliyiz.
VorbisSeek
int VorbisSeek(void *datasource, // bu, ov_open_callback’lerine
geçtiğimiz
dataya pointer’dır (SOggFile
yapımız)
ogg_int64_t offset,
// aramayı
başlatmayı istediğimiz noktanın offseti
int whence)
// nereyi
aramayı istiyoruz
{
...
}
Bu fonksiyon, fseek(...)
ile aynı şekilde çalışır.
Benzer şekilde aranacak olan bir nokta (SEEK_SET, SEEK_CUR, SEEK_END), Ve data pointer'ımızı
set etmeliyiz (Bir daha bir daha emin olunmalı data sınırı ötesine geçmediğimizden).
-1
dönmesinin anlamı, Bu dosya, aranabilir
değildir
(mesela, pointer’ı hareket ettiremezsin, ve
bu
tarzda, dosyada yeni ayarlama yapılamaz). Bu, eğer örneği döngülemeyi
istemiyorsak
sorun
yok,
Ama
eğer döngülüyorsak pointer'ı dosyanın başına geri
götürmeye ihtiyaç duyarız. 0 dönüşü, başarılı bir çağrı
demektir.
VorbisClose
int VorbisClose(void *datasource) // bu, ov_open_callback’lerine
geçtiğimiz dataya pointer’dır
(SOggFile yapımız)
{
...
}
Bu
fonksiyon, kodumuzun içinde ov_close(...)'u çağırdığımız zaman
çağrılır.
Bu
fonksiyonun
ana amacı, dosyanın açıldığı esnada yapılmış herhangi tahsisatı temizlemektir (az veya
hiçte
olabilir). Eğer
istersen
bellekten
dosyayı temizlebilirdin, Ama ben
belleğin başka bir yerde temizlenecek
olduğunu farz ediyorum Ve bundan dolayı bu fonksiyon boş kalır.
Dönüş
değeri önemsizdir. Bu
fonksiyonun her zaman
başarılı
çalıştırıldığı farz ediliyor.
VorbisTell
long VorbisTell(void *datasource) // bu, ov_open_callback’lerine
geçtiğimiz dataya pointer’dır
(SOggFile yapımız)
{
...
}
Bu, kütüphanelere dosyadan şimdiye kadar ne
kadar okuduğumuzun bilgisi için
kullanılır. Oldukça basit ,
tam olarak
okuduğumuz miktar döndürülür. -1 ’in dönmesi bir hatayı gösterir, ama
bunun
olabileceğini düşünmüyorum!
Sonuç
Şimdi sahip olduklarımız. Birkaç basit
fonksiyon
ve dosyanın bellekten yüklenmesidir. Yapılması kalan tek şey ilk yerde hafızaya yüklediğimiz dosyayı hafızadan temizlemektir, Ama o,
programın ömrü
boyunca orada olmasına ihtiyaç duyulur (döngüleniyor , yeniden çalınacak) .
Muhtemel çakacağın üzere bellekte
olmadığında Callback'leri kullanarak herhangi bir
yerde dosyayı yükleyebiliriz. Geliştiricilere datanın nasıl ve ne zaman okunacağını kontrol etmenin bir yolunu vererek,
dilediğimiz gibi sesle oynaşmamıza imkan verir, aktüel kaynak örneğini değiştirmek zorunda olmadan basit efektler yaratmaya imkan verir!
Bu ders dahilindeki
teorinin pratiğini gösteren örnek bir program için
aşağıdaki linke bak. Bu dersin oralarda bir yerde bazılarına faydalı olduğunu umuyorum, böyle
olsa iyi olur ki yatak odası
kodlamalarım israf olmasın;) Herhangi soru veya sorunlarınızı mail
veya forumlarla
yollayacağınıza eminim.
Bu
dersin
Linux’e portunu
yükle - (Lee Trager tarafından port
edilmiştir)
Dersin Orjinali : http://www.devmaster.net/articles/openal-ogg-file/