¿Cómo debo desvincular y eliminar los búferes OpenAL?


12

Estoy usando OpenAL para reproducir sonidos. Estoy tratando de implementar una función de reproducción de disparar y olvidar que toma una ID de búfer y la asigna a una fuente de un grupo que he asignado previamente, y la reproduce. Sin embargo, hay un problema con las vidas de los objetos.

En OpenGL, las funciones de eliminación desvinculan automáticamente las cosas (p. Ej. Texturas) o eliminan automáticamente la cosa cuando eventualmente se desvincula (p. Ej. Sombreadores) y, por lo tanto, es fácil administrar la eliminación. Sin embargo, alDeleteBufferssimplemente falla AL_INVALID_OPERATIONsi el búfer todavía está vinculado a una fuente.

¿Hay alguna forma idiomática de "eliminar" los búferes OpenAL que les permite terminar de jugar y luego se desenlaza automáticamente y realmente los elimina? ¿Necesito vincular la administración del búfer más profundamente en el grupo de origen (por ejemplo, eliminar un búfer requiere verificar también todas las fuentes asignadas)?

Del mismo modo, ¿hay una forma idiomática de desvincular (pero no eliminar) los buffers cuando terminen de jugar? Sería bueno si, cuando buscara una fuente gratuita, solo necesitara ver si un búfer estaba conectado y no molestarme en verificar el estado de la fuente.

(Estoy usando C ++, aunque los enfoques para C también están bien. Los enfoques que suponen un lenguaje GCd y el uso de finalizadores probablemente no sean aplicables).

openal 

Si todavía necesita una respuesta, utilicé un método de recolección de basura en el motor Gorgon: sf.net/p/gorgon-ge
Cem Kalyoncu

Respuestas:


8

Antes de eliminar un búfer, debe desvincularlo de cada fuente que lo use (por ejemplo, alSourcei(mSourceId, AL_BUFFER, NULL);o eliminar todas las fuentes que están vinculadas al búfer.

Debe realizar un seguimiento de la duración de cada uno de sus sonidos para liberarlos al finalizar. Puede hacerlo utilizando una estructura para cada fuente para mantener la duración del sonido y el tiempo jugado (actualizado cada tic del juego). Ex:

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

Si utiliza un sistema basado en componentes, puede verificar periódicamente la finalización de todas las fuentes en ejecución y eliminar el enlace / fuente allí.

Si no realiza un seguimiento de los cambios de reproducción / pausa en su código, también querrá verificar si las fuentes se están reproduciendo antes de aumentar el tiempo de reproducción.

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

Si desea realizar un seguimiento de las fuentes vinculadas a un búfer, puede usar una estructura con la identificación de su búfer y un vector que se vincule a las estructuras de origen de esta manera, incluso puede interrumpir todas las fuentes que están unidas a un búfer que necesita liberar Lo antes posible. Ex:

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

Esto debería ser suficiente para llevarte por el camino correcto. No puedo darle un código más detallado de mis proyectos, ya que dependen en gran medida de macros y mecanismos RTTI hechos a mano.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.