OpenAL arabelleklerini nasıl açmalı ve silmeliyim?


12

Sesleri çalmak için OpenAL kullanıyorum. Bir arabellek kimliği alır ve daha önce ayırdığınız bir havuzdan bir kaynağa atar ve çalış bir ateşle ve unut oyun işlevini uygulamaya çalışıyorum. Bununla birlikte, nesne yaşamlarında bir sorun vardır.

OpenGL'de silme işlevleri ya şeyleri otomatik olarak çözer (örn. Dokular) ya da sonunda bağlanmamış olduğunda (örneğin gölgelendiriciler) otomatik olarak siler ve bu nedenle silme işlemini yönetmek kolaydır. Ancak , tampon hala bir kaynağa bağlıysa alDeleteBuffersbunun yerine başarısız olur AL_INVALID_OPERATION.

OpenAL arabelleklerini "silmenin" oynatmayı bitirmesine izin veren, sonra da otomatik olarak bağları gerçekten söker ve gerçekten onları çözer mi? Arabellek yönetimini kaynak havuzuna daha derinden bağlamam gerekiyor mu (örn. Bir tamponun silinmesi, tahsis edilen tüm kaynakları da kontrol etmeyi gerektirir)?

Benzer şekilde, arabellekleri oynatmayı bitirdiklerinde ayırmanın (ama silmemenin) deyimsel bir yolu var mı? Ücretsiz bir kaynak ararken, sadece bir tamponun takılı olup olmadığını görmek ve kaynak durumunu kontrol etmekten rahatsız olmamak güzel olurdu.

(C için yaklaşımlar da iyi olsa da, C ++ kullanıyorum. GCd dili varsayımı ve sonlandırıcıları kullanma yaklaşımları muhtemelen geçerli değildir.)

openal 

Hala bir cevaba ihtiyacınız varsa, Gorgon motorunda bir çöp toplama yöntemi kullandım: sf.net/p/gorgon-ge
Cem Kalyoncu

Yanıtlar:


8

Bir arabelleği silmeden önce, arabelleği kullanan her kaynaktan ayırmalısınız (ör: alSourcei(mSourceId, AL_BUFFER, NULL);arabelleğe bağlı tüm kaynakları silmelisiniz).

Tamamlandıktan sonra yayınlamak için seslerinizin her birinin uzunluğunu izlemeniz gerekir. Bunu, ses uzunluğunu ve çalınan zamanı korumak için her kaynak için bir yapı kullanarak yapabilirsiniz (her oyun işaretini güncelleyin). Ör:

struct AudioVoice
{
    ALuint          mSourceId;
    ALuint          mMsDuration;
    ALuint          mMsPlayed;
};

Bileşen tabanlı bir sistem kullanıyorsanız, çalışan tüm kaynakları periyodik olarak tamamlanma bakımından kontrol edebilir ve bağlantıyı kaldırma / kaynak silme işlemini orada yapabilirsiniz.

Kodunuzdaki oynat / duraklat değişikliklerini takip etmezseniz, oynatılan süreyi uzatmadan önce kaynakların oynatılıp oynatılmadığını da kontrol etmek istersiniz.

ALint sourceState;
alGetSourcei(mSourceId, AL_SOURCE_STATE, &sourceState);
if (sourceState == AL_PLAYING) { /* increase played time */  }

Bir tampona bağlı kaynakları takip etmek istiyorsanız, tamponunuzun kimliğine sahip bir yapı ve kaynak yapılara bağlanan bir vektör kullanarak bu şekilde bırakmanız gereken bir tampona bağlı tüm kaynakları bile kesebilirsiniz. EN KISA SÜREDE. Ör:

struct AudioData
{
    RKuint                      mMsDuration;
    ALuint                      mSourceId;
    std::vector<AudioVoice*>    mVoices;
};

Bu sizi doğru yola sokmak için yeterli olmalıdır. Büyük ölçüde makrolara ve el yapımı RTTI mekanizmalarına bağlı oldukları için projelerimden daha ayrıntılı kod veremem.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.