1
0
forked from 0ad/0ad

Fix audio leak that resulted in openAL errors after a while.

Sound items were only deleted after 'last play' when stopped, but they
could also be left in 'paused' or 'initial' states, and were then not
cleared until the game exits (effectively a memory leak). This affected
particularly music & ambient sounds, which also used the most
buffers(/memory).
On MacOS (at least), this resulted in OpenAL errors & sound failures
after a while playing the game, because MacOS has a max "in flight
buffers" of 1024.

Also clean up some control flow in CStreamItem

Reported by: Eszett
Thanks langbart for the consistent repro'.

Fixes #5265

Differential Revision: https://code.wildfiregames.com/D3445
This was SVN commit r24762.
This commit is contained in:
wraitii 2021-01-22 12:50:05 +00:00
parent 9ae6f904ad
commit ce74c41297
3 changed files with 43 additions and 45 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2019 Wildfire Games.
/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -79,8 +79,8 @@ bool CBufferItem::IdleTask()
int proc_state;
alGetSourcei(m_ALSource, AL_SOURCE_STATE, &proc_state);
AL_CHECK;
m_ShouldBePlaying = (proc_state != AL_STOPPED);
return (proc_state != AL_STOPPED);
m_ShouldBePlaying = (proc_state != AL_STOPPED && proc_state != AL_INITIAL && proc_state != AL_PAUSED);
return m_ShouldBePlaying;
}
if (GetLooping())

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2019 Wildfire Games.
/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -57,8 +57,8 @@ bool CSoundItem::IdleTask()
int proc_state;
alGetSourcei(m_ALSource, AL_SOURCE_STATE, &proc_state);
AL_CHECK;
m_ShouldBePlaying = (proc_state != AL_STOPPED);
return (proc_state != AL_STOPPED);
m_ShouldBePlaying = (proc_state != AL_STOPPED && proc_state != AL_INITIAL && proc_state != AL_PAUSED);
return m_ShouldBePlaying;
}
return true;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2015 Wildfire Games.
/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -67,50 +67,48 @@ bool CStreamItem::IdleTask()
HandleFade();
AL_CHECK;
if (m_ALSource != 0)
if (m_ALSource == 0)
return true;
int proc_state;
alGetSourcei(m_ALSource, AL_SOURCE_STATE, &proc_state);
AL_CHECK;
if (proc_state == AL_STOPPED || proc_state == AL_PAUSED)
return !m_LastPlay;
if (m_SoundData == nullptr)
return true;
COggData* theData = (COggData*)m_SoundData;
if (!theData->IsFileFinished())
{
int proc_state;
alGetSourcei(m_ALSource, AL_SOURCE_STATE, &proc_state);
int num_processed;
alGetSourcei(m_ALSource, AL_BUFFERS_PROCESSED, &num_processed);
AL_CHECK;
if (proc_state == AL_STOPPED)
if (num_processed > 0)
{
if (m_LastPlay)
return (proc_state != AL_STOPPED);
}
else if (m_SoundData != NULL)
{
COggData* theData = (COggData*)m_SoundData;
if (! theData->IsFileFinished())
{
int num_processed;
alGetSourcei(m_ALSource, AL_BUFFERS_PROCESSED, &num_processed);
AL_CHECK;
if (num_processed > 0)
{
ALuint* al_buf = new ALuint[num_processed];
alSourceUnqueueBuffers(m_ALSource, num_processed, al_buf);
AL_CHECK;
int didWrite = theData->FetchDataIntoBuffer(num_processed, al_buf);
alSourceQueueBuffers(m_ALSource, didWrite, al_buf);
AL_CHECK;
delete[] al_buf;
}
}
else if (GetLooping())
{
theData->ResetFile();
}
else
{
int num_processed;
alGetSourcei(m_ALSource, AL_BUFFERS_QUEUED, &num_processed);
m_ShouldBePlaying = ( num_processed == 0 );
}
ALuint* al_buf = new ALuint[num_processed];
alSourceUnqueueBuffers(m_ALSource, num_processed, al_buf);
AL_CHECK;
int didWrite = theData->FetchDataIntoBuffer(num_processed, al_buf);
alSourceQueueBuffers(m_ALSource, didWrite, al_buf);
AL_CHECK;
delete[] al_buf;
}
}
else if (GetLooping())
{
theData->ResetFile();
}
else
{
int num_processed;
alGetSourcei(m_ALSource, AL_BUFFERS_QUEUED, &num_processed);
m_ShouldBePlaying = ( num_processed == 0 );
}
AL_CHECK;
return true;
}