Arama Motoru

OggVorbis Dosyalarının Bellekten Yüklenmesi

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’lerov_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/