Come devo separare ed eliminare i buffer OpenAL?


12

Sto usando OpenAL per riprodurre suoni. Sto cercando di implementare una funzione di riproduzione attiva e dimentica che accetta un ID buffer e lo assegna a una sorgente da un pool che ho precedentemente allocato e lo riproduce. Tuttavia, c'è un problema con la durata degli oggetti.

In OpenGL, le funzioni di eliminazione separano automaticamente le cose (ad esempio le trame) o eliminano automaticamente la cosa quando alla fine non sono legate (ad es. Shader) e quindi di solito è facile gestire la cancellazione. Tuttavia alDeleteBuffersinvece fallisce semplicemente AL_INVALID_OPERATIONse il buffer è ancora associato a una sorgente.

Esiste un modo idiomatico di "eliminare" i buffer OpenAL che consente loro di terminare la riproduzione e quindi di sciogliersi automaticamente e davvero? Devo collegare in modo più approfondito la gestione del buffer nel pool di origini (ad esempio, l'eliminazione di un buffer richiede anche il controllo di tutte le fonti allocate)?

Allo stesso modo, c'è un modo idiomatico per separare (ma non eliminare) i buffer quando hanno finito di giocare? Sarebbe bello se, quando stavo cercando una fonte libera, avessi solo bisogno di vedere se un buffer era collegato e non preoccuparmi di controllare lo stato della fonte.

(Sto usando C ++, anche se gli approcci per C vanno bene. Gli approcci che presuppongono un linguaggio GCd e che usano i finalizzatori probabilmente non sono applicabili.)

openal 

Se hai ancora bisogno di una risposta, ho usato un metodo di garbage collection nel motore Gorgon: sf.net/p/gorgon-ge
Cem Kalyoncu,

Risposte:


8

Prima di eliminare un buffer, è necessario separarlo da ogni sorgente che lo utilizza (es: alSourcei(mSourceId, AL_BUFFER, NULL);o eliminare tutte le fonti associate al buffer.

Devi tenere traccia della lunghezza di ciascuno dei tuoi suoni per rilasciarli al completamento. Puoi farlo usando una struttura per ogni sorgente per mantenere la lunghezza del suono e il tempo giocato (aggiornato ogni segno di spunta del gioco). Ex:

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

Se si utilizza un sistema basato su componenti, è possibile controllare periodicamente il completamento di tutte le origini in esecuzione ed eliminare in questo modo il unbind / source.

Se non tieni traccia delle modifiche di riproduzione / pausa nel tuo codice, dovrai anche verificare se le fonti sono in riproduzione prima di aumentare il tempo di riproduzione.

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

Se si desidera tenere traccia delle origini associate a un buffer, è possibile utilizzare una struttura con l'id del buffer e un vettore che si collega alle strutture di origine in questo modo, è anche possibile interrompere tutte le origini associate a un buffer che è necessario rilasciare AL PIÙ PRESTO. Ex:

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

Questo dovrebbe essere sufficiente per portarti sulla strada giusta. Non posso darvi codice più dettagliato dai miei progetti in quanto si basano fortemente su macro e meccanismi RTTI fatti a mano.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.