我应该如何取消绑定和删除OpenAL缓冲区?


12

我正在使用OpenAL播放声音。我正在尝试实现即弃即用播放功能,该功能采用缓冲区ID并将其分配给我先前已分配的池中的源,并进行播放。但是,对象生存期存在问题。

在OpenGL中,删除功能可以自动解除绑定(例如纹理),或者在最终解除绑定时自动删除(例如着色器),因此通常易于管理删除。但是alDeleteBuffersAL_INVALID_OPERATION如果缓冲区仍绑定到源,则会简单地失败。

是否有一种惯用的方式来“删除” OpenAL缓冲区,使它们可以完成播放,然后自动解除绑定,从而真正解除绑定?我是否需要将缓冲区管理更深入地绑定到源池中(例如,删除缓冲区还需要检查所有分配的源)?

同样,在结束播放时,是否有一种惯用的方式来解除绑定(但不删除)缓冲区?如果当我在寻找免费资源时,只需要查看是否附加了缓冲区,而不必费心检查源状态,那将是很好的。

(尽管使用C的方法也不错,但我使用的是C ++。假设使用GCd语言并使用终结器的方法可能不适用。)

openal 

如果您仍然需要答案,我在Gorgon引擎中使用了垃圾回收方法:sf.net/p/gorgon-ge
Cem Kalyoncu

Answers:


8

删除缓冲区之前,必须将其与使用它的每个源解除绑定(例如:alSourcei(mSourceId, AL_BUFFER, NULL);或删除绑定到缓冲区的所有源。

您需要跟踪每种声音的长度,以在完成时释放它们。您可以使用每个音源的结构来做到这一点,以保持声音的长度和播放的时间(每个游戏滴答声都更新)。例如:

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

如果您使用的是基于组件的系统,则可以定期检查所有正在运行的源代码是否完整,并在那里进行取消绑定/源代码删除。

如果您不跟踪代码中的播放/暂停更改,则还需要在增加播放时间之前检查源是否正在播放。

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

如果要跟踪绑定到缓冲区的源,则可以使用带有缓冲区ID的结构以及以这种方式链接到源结构的向量,您甚至可以中断所有需要释放的绑定到缓冲区的源尽快。例如:

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

这应该足以使您走上正确的道路。我无法从我的项目中提供更详细的代码,因为它们严重依赖宏和手工RTTI机制。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.