Comment dois-je dissocier et supprimer les tampons OpenAL?

12

J'utilise OpenAL pour jouer des sons. J'essaie d'implémenter une fonction de jeu de tir et d'oublier qui prend un ID de tampon et l'affecte à une source à partir d'un pool que j'ai précédemment alloué, et le joue. Cependant, il y a un problème avec les durées de vie des objets.

Dans OpenGL, les fonctions de suppression délient automatiquement les éléments (par exemple les textures) ou suppriment automatiquement l'élément lorsqu'il est finalement non lié (par exemple les shaders) et il est donc généralement facile de gérer la suppression. Cependant, alDeleteBufferséchoue simplement avec AL_INVALID_OPERATIONsi le tampon est toujours lié à une source.

Existe-t-il un moyen idiomatique de «supprimer» les tampons OpenAL qui leur permet de terminer la lecture, puis de les délier automatiquement et vraiment eux? Dois-je lier plus profondément la gestion des tampons au pool source (par exemple, la suppression d'un tampon nécessite également de vérifier toutes les sources allouées)?

De même, existe-t-il un moyen idiomatique de dissocier (mais pas de supprimer) les tampons lorsqu'ils ont fini de jouer? Ce serait bien si, lorsque je cherchais une source gratuite, je n'avais besoin que de voir si un tampon était attaché du tout et pas pris la peine de vérifier l'état de la source.

(J'utilise C ++, bien que les approches pour C soient également correctes. Les approches supposant un langage GCd et utilisant des finaliseurs ne sont probablement pas applicables.)


la source
Si vous avez toujours besoin d'une réponse, j'ai utilisé une méthode de collecte des ordures dans le moteur Gorgon: sf.net/p/gorgon-ge
Cem Kalyoncu

Réponses:

8

Avant de supprimer un tampon, vous devez le dissocier de chaque source qui l'utilise (ex: alSourcei(mSourceId, AL_BUFFER, NULL);ou supprimer toutes les sources liées au tampon.

Vous devez garder une trace de la longueur de chacun de vos sons pour les libérer à la fin. Vous pouvez le faire en utilisant une structure pour chaque source pour conserver la durée du son et le temps joué (mis à jour à chaque tick du jeu). Ex:

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

Si vous utilisez un système basé sur des composants, vous pouvez vérifier périodiquement toutes les sources en cours d'exécution et y supprimer la liaison / source.

Si vous ne suivez pas les changements de lecture / pause dans votre code, vous voudrez également vérifier si les sources sont en cours de lecture avant d'augmenter la durée de lecture.

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

Si vous souhaitez garder une trace des sources liées à un tampon, vous pouvez utiliser une structure avec l'id de votre tampon et un vecteur reliant aux structures de source de cette façon, vous pouvez même interrompre toutes les sources liées à un tampon que vous devez libérer AU PLUS VITE. Ex:

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

Cela devrait suffire à vous mettre sur la bonne voie. Je ne peux pas vous donner de code plus détaillé de mes projets car ils reposent fortement sur des macros et des mécanismes RTTI faits à la main.

Coyote
la source