Memory leak in streaming audio
by Richard McKinney · in Torque Game Builder · 11/01/2006 (4:42 pm) · 7 replies
I have posted a fix for this bug below and replicated the fix in the report bugs forums. Check the last post here for the fixes to get rid of the streaming ogg memory leak.
Starting and stopping streaming audio causes a memory leak. I've tried many different versions of openal32.dll/wrap_oal.dll and they all have it. It looks like the memory is being allocated by openal, so you can't see it as a leak in Torque.
I can open up a console and just keep doing:
$musicHandle = alxPlay (musicProfile);
alxStop ($musicHandle);
over and over again and memory will jump about 500k each time. If you're only starting and stopping music a couple of times in a game you won't notice it much, but when you're changing music at rapid intervals it becomes a problem quickly.
Currently, to get around the memory being leaked I'm picking a central point in our game and reinitializing the openAL driver entirely calling:
OpenALShutdownDriver();
OpenALInitDriver();
This frees up the memory that was leaked, but this is not an ideal solution (although I think I'm going to have to ship with it). I am watching this with perfmon, not just task manager. It looks like memory's just not getting freed correctly from the alDeleteBuffers() call.
There is no problem with audio profiles whose descriptions do not have isStreaming=true set, but that adds 70-90 megs from music alone to our runtime memory requirement so it's a pretty bad solution.
I tried using alxCreateSource() and playing those instead of the profiles, but when using streaming audio, that fails as soon as you stop the audio with "alxStop: handle in inactive list" because the stream was created with AUDIOHANDLE_INACTIVE_BIT, but isn't placed in the inactive list. Maybe I'm just using that wrong, or maybe I need to play with the source more.
If I can find a better solution to this, I'll update, but until then has anyone else fixed/circumvented this leak? I have a few more things to try still, but I'm almost out of time.
Thanks for any information!
Starting and stopping streaming audio causes a memory leak. I've tried many different versions of openal32.dll/wrap_oal.dll and they all have it. It looks like the memory is being allocated by openal, so you can't see it as a leak in Torque.
I can open up a console and just keep doing:
$musicHandle = alxPlay (musicProfile);
alxStop ($musicHandle);
over and over again and memory will jump about 500k each time. If you're only starting and stopping music a couple of times in a game you won't notice it much, but when you're changing music at rapid intervals it becomes a problem quickly.
Currently, to get around the memory being leaked I'm picking a central point in our game and reinitializing the openAL driver entirely calling:
OpenALShutdownDriver();
OpenALInitDriver();
This frees up the memory that was leaked, but this is not an ideal solution (although I think I'm going to have to ship with it). I am watching this with perfmon, not just task manager. It looks like memory's just not getting freed correctly from the alDeleteBuffers() call.
There is no problem with audio profiles whose descriptions do not have isStreaming=true set, but that adds 70-90 megs from music alone to our runtime memory requirement so it's a pretty bad solution.
I tried using alxCreateSource() and playing those instead of the profiles, but when using streaming audio, that fails as soon as you stop the audio with "alxStop: handle in inactive list" because the stream was created with AUDIOHANDLE_INACTIVE_BIT, but isn't placed in the inactive list. Maybe I'm just using that wrong, or maybe I need to play with the source more.
If I can find a better solution to this, I'll update, but until then has anyone else fixed/circumvented this leak? I have a few more things to try still, but I'm almost out of time.
Thanks for any information!
About the author
#2
In audio/VorbisStreamSource.h, add the following line in the private section (just above clearBuffers() is fine):
in VorbisStreamSource::Clear() change
If you're lazy you could just add that call to alSourceUnqueueBuffers() to both freeStream() and clear() instead of calling deleteBuffers().
11/02/2006 (9:31 am)
I have identified the source of this problem. The buffers in openAL are reference counted and they're never being reduced to zero, so the one time VorbisStreamSource calls alDeleteBuffers() it just skips over them. Here is a fix to this issue. I will replicate this fix in the report bugs forum.In audio/VorbisStreamSource.h, add the following line in the private section (just above clearBuffers() is fine):
void deleteBuffers();In audio/VorbisStreamSource.cc:
in VorbisStreamSource::Clear() change
if(mBufferList[0] != 0)
alDeleteBuffers(NUMBUFFERS, mBufferList);
for(int i = 0; i < NUMBUFFERS; i++)
mBufferList[i] = 0;todeleteBuffers();in VorbisStreamSource::freeStream() change
if(mBufferList[0] != 0)
alDeleteBuffers(NUMBUFFERS, mBufferList);
for(int i = 0; i < NUMBUFFERS; i++)
mBufferList[i] = 0;todeleteBuffers();and finally add the deleteBuffers method just below VorbisStreamSource::freeStream():
void VorbisStreamSource::deleteBuffers()
{
// Ensure that the refCount on the buffers is zero:
alSourceUnqueueBuffers (mSource, NUMBUFFERS, mBufferList);
if(mBufferList[0] != 0)
alDeleteBuffers(NUMBUFFERS, mBufferList);
for(int i = 0; i < NUMBUFFERS; i++)
mBufferList[i] = 0;
}If you're lazy you could just add that call to alSourceUnqueueBuffers() to both freeStream() and clear() instead of calling deleteBuffers().
#3
02/10/2010 (12:52 pm)
Great fix, works perfect on TGE :)
#4
02/10/2010 (11:15 pm)
Has this made it into the latest TGB or are we still having to manually edit the source to fix this? The original post was from 2006 lol...
#5
02/07/2011 (7:18 am)
It is not added to TGB 1.7.5
#7
01/22/2012 (1:59 pm)
Bumping this 2006 thread, since this fix does not seem to be in 1.76 either.
Torque 3D Owner Richard McKinney
Default Studio Name
alxPlay:
Total allocated: 667,648k
alxStop:
Total deallocated: 135,168.
Total missing: 532,480 bytes. That's exactly the size alloc'd by alBufferData() + 16k.