Como devo desassociar e excluir os buffers OpenAL?

12

Estou usando o OpenAL para reproduzir sons. Estou tentando implementar uma função de acionar e esquecer que usa um ID de buffer e o atribui a uma fonte de um pool que eu aloquei anteriormente e o executa. No entanto, há um problema com a vida útil do objeto.

No OpenGL, as funções de exclusão desvinculam automaticamente as coisas (por exemplo, texturas) ou excluem automaticamente as coisas quando eventualmente não são acopladas (por exemplo, shaders) e, portanto, geralmente é fácil gerenciar a exclusão. No entanto, alDeleteBufferssimplesmente falha com AL_INVALID_OPERATIONse o buffer ainda estiver vinculado a uma fonte.

Existe uma maneira idiomática de "excluir" os buffers OpenAL que lhes permitam terminar a reprodução e depois desassociar automaticamente e realmente eles? Preciso vincular o gerenciamento de buffer mais profundamente ao pool de origem (por exemplo, excluir um buffer requer a verificação de todas as fontes alocadas também)?

Da mesma forma, existe uma maneira idiomática de desvincular (mas não excluir) os buffers quando eles terminam de tocar? Seria bom se, quando eu estava procurando uma fonte livre, eu só precisasse ver se um buffer estava conectado e não me incomodar em verificar o estado da fonte.

(Estou usando C ++, embora as abordagens para C também sejam boas. Abordagens que pressupõem uma linguagem GCd e que usam finalizadores provavelmente não são aplicáveis.)


fonte
Se você ainda precisa de uma resposta, eu usei um método de coleta de lixo no motor de Gorgon: sf.net/p/gorgon-ge
Cem Kalyoncu

Respostas:

8

Antes de excluir um buffer, você deve desvinculá-lo de cada fonte que o usa (por exemplo: alSourcei(mSourceId, AL_BUFFER, NULL);ou excluir todas as fontes que estão vinculadas ao buffer.

Você precisa acompanhar a duração de cada um dos seus sons para liberá-los após a conclusão. Você pode fazer isso usando uma estrutura para cada fonte para manter a duração do som e o tempo jogado (atualize cada tick de jogo). Ex:

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

Se você usar um sistema baseado em componentes, poderá verificar periodicamente todas as fontes em execução para concluir e excluir a desatação / origem.

Se você não acompanhar as alterações de reprodução / pausa no seu código, também desejará verificar se as fontes estão sendo reproduzidas antes de aumentar o tempo de reprodução.

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

Se você deseja acompanhar as fontes ligadas a um buffer, você pode usar uma estrutura com o ID do seu buffer e um vetor vinculando-se às estruturas de origem dessa maneira. Você pode até interromper todas as fontes vinculadas a um buffer. ASSIM QUE POSSÍVEL. Ex:

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

Isso deve ser suficiente para levá-lo ao caminho certo. Não posso fornecer um código mais detalhado dos meus projetos, pois eles dependem muito de macros e mecanismos de RTTI feitos à mão.

Coiote
fonte