mirror of
https://github.com/UberGames/ioef.git
synced 2024-11-24 05:01:40 +00:00
Make OpenAL buffer management work on OS X
Don't assume we have unlimited OpenAL buffers. Detach buffers from sources by setting AL_BUFFER to 0. Cannot delete buffers on OS X immediately after alSourceUnqueueBuffers. Free unprocessed stream and music buffers. Free unused sfx buffers when sound file exists and fails loading into OpenAL (though I haven't seen it fail).
This commit is contained in:
parent
d526eacd10
commit
5795be68f6
1 changed files with 105 additions and 32 deletions
|
@ -312,6 +312,44 @@ static qboolean S_AL_BufferEvict( void )
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
S_AL_GenBuffers
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static qboolean S_AL_GenBuffers(ALsizei numBuffers, ALuint *buffers, const char *name)
|
||||||
|
{
|
||||||
|
ALenum error;
|
||||||
|
|
||||||
|
S_AL_ClearError( qfalse );
|
||||||
|
qalGenBuffers( numBuffers, buffers );
|
||||||
|
error = qalGetError();
|
||||||
|
|
||||||
|
// If we ran out of buffers, start evicting the least recently used sounds
|
||||||
|
while( error == AL_INVALID_VALUE )
|
||||||
|
{
|
||||||
|
if( !S_AL_BufferEvict( ) )
|
||||||
|
{
|
||||||
|
Com_Printf( S_COLOR_RED "ERROR: Out of audio buffers\n");
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try again
|
||||||
|
S_AL_ClearError( qfalse );
|
||||||
|
qalGenBuffers( numBuffers, buffers );
|
||||||
|
error = qalGetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( error != AL_NO_ERROR )
|
||||||
|
{
|
||||||
|
Com_Printf( S_COLOR_RED "ERROR: Can't create a sound buffer for %s - %s\n",
|
||||||
|
name, S_AL_ErrorMsg(error));
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
S_AL_BufferLoad
|
S_AL_BufferLoad
|
||||||
|
@ -354,14 +392,10 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache)
|
||||||
format = S_AL_Format(info.width, info.channels);
|
format = S_AL_Format(info.width, info.channels);
|
||||||
|
|
||||||
// Create a buffer
|
// Create a buffer
|
||||||
S_AL_ClearError( qfalse );
|
if (!S_AL_GenBuffers(1, &curSfx->buffer, curSfx->filename))
|
||||||
qalGenBuffers(1, &curSfx->buffer);
|
|
||||||
if((error = qalGetError()) != AL_NO_ERROR)
|
|
||||||
{
|
{
|
||||||
S_AL_BufferUseDefault(sfx);
|
S_AL_BufferUseDefault(sfx);
|
||||||
Hunk_FreeTempMemory(data);
|
Hunk_FreeTempMemory(data);
|
||||||
Com_Printf( S_COLOR_RED "ERROR: Can't create a sound buffer for %s - %s\n",
|
|
||||||
curSfx->filename, S_AL_ErrorMsg(error));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,6 +417,7 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache)
|
||||||
{
|
{
|
||||||
if( !S_AL_BufferEvict( ) )
|
if( !S_AL_BufferEvict( ) )
|
||||||
{
|
{
|
||||||
|
qalDeleteBuffers(1, &curSfx->buffer);
|
||||||
S_AL_BufferUseDefault(sfx);
|
S_AL_BufferUseDefault(sfx);
|
||||||
Hunk_FreeTempMemory(data);
|
Hunk_FreeTempMemory(data);
|
||||||
Com_Printf( S_COLOR_RED "ERROR: Out of memory loading %s\n", curSfx->filename);
|
Com_Printf( S_COLOR_RED "ERROR: Out of memory loading %s\n", curSfx->filename);
|
||||||
|
@ -397,6 +432,7 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache)
|
||||||
// Some other error condition
|
// Some other error condition
|
||||||
if(error != AL_NO_ERROR)
|
if(error != AL_NO_ERROR)
|
||||||
{
|
{
|
||||||
|
qalDeleteBuffers(1, &curSfx->buffer);
|
||||||
S_AL_BufferUseDefault(sfx);
|
S_AL_BufferUseDefault(sfx);
|
||||||
Hunk_FreeTempMemory(data);
|
Hunk_FreeTempMemory(data);
|
||||||
Com_Printf( S_COLOR_RED "ERROR: Can't fill sound buffer for %s - %s\n",
|
Com_Printf( S_COLOR_RED "ERROR: Can't fill sound buffer for %s - %s\n",
|
||||||
|
@ -964,7 +1000,7 @@ static void S_AL_SrcKill(srcHandle_t src)
|
||||||
curSource->isPlaying = qfalse;
|
curSource->isPlaying = qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the buffer
|
// Detach any buffers
|
||||||
qalSourcei(curSource->alSource, AL_BUFFER, 0);
|
qalSourcei(curSource->alSource, AL_BUFFER, 0);
|
||||||
|
|
||||||
curSource->sfx = 0;
|
curSource->sfx = 0;
|
||||||
|
@ -1623,9 +1659,15 @@ ALuint S_AL_SrcGet(srcHandle_t src)
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
|
// Q3A cinematics use up to 12 buffers at once
|
||||||
|
#define MAX_STREAM_BUFFERS 20
|
||||||
|
|
||||||
static srcHandle_t streamSourceHandles[MAX_RAW_STREAMS];
|
static srcHandle_t streamSourceHandles[MAX_RAW_STREAMS];
|
||||||
static qboolean streamPlaying[MAX_RAW_STREAMS];
|
static qboolean streamPlaying[MAX_RAW_STREAMS];
|
||||||
static ALuint streamSources[MAX_RAW_STREAMS];
|
static ALuint streamSources[MAX_RAW_STREAMS];
|
||||||
|
static ALuint streamBuffers[MAX_RAW_STREAMS][MAX_STREAM_BUFFERS];
|
||||||
|
static int streamNumBuffers[MAX_RAW_STREAMS];
|
||||||
|
static int streamBufIndex[MAX_RAW_STREAMS];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
|
@ -1683,6 +1725,9 @@ static void S_AL_AllocateStreamChannel(int stream, int entityNum)
|
||||||
|
|
||||||
streamSourceHandles[stream] = cursrc;
|
streamSourceHandles[stream] = cursrc;
|
||||||
streamSources[stream] = alsrc;
|
streamSources[stream] = alsrc;
|
||||||
|
|
||||||
|
streamNumBuffers[stream] = 0;
|
||||||
|
streamBufIndex[stream] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1695,6 +1740,15 @@ static void S_AL_FreeStreamChannel( int stream )
|
||||||
if ((stream < 0) || (stream >= MAX_RAW_STREAMS))
|
if ((stream < 0) || (stream >= MAX_RAW_STREAMS))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Detach any buffers
|
||||||
|
qalSourcei(streamSources[stream], AL_BUFFER, 0);
|
||||||
|
|
||||||
|
// Delete the buffers
|
||||||
|
if (streamNumBuffers[stream] > 0) {
|
||||||
|
qalDeleteBuffers(streamNumBuffers[stream], streamBuffers[stream]);
|
||||||
|
streamNumBuffers[stream] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Release the output streamSource
|
// Release the output streamSource
|
||||||
S_AL_SrcUnlock(streamSourceHandles[stream]);
|
S_AL_SrcUnlock(streamSourceHandles[stream]);
|
||||||
S_AL_SrcKill(streamSourceHandles[stream]);
|
S_AL_SrcKill(streamSourceHandles[stream]);
|
||||||
|
@ -1710,6 +1764,7 @@ S_AL_RawSamples
|
||||||
static
|
static
|
||||||
void S_AL_RawSamples(int stream, int samples, int rate, int width, int channels, const byte *data, float volume, int entityNum)
|
void S_AL_RawSamples(int stream, int samples, int rate, int width, int channels, const byte *data, float volume, int entityNum)
|
||||||
{
|
{
|
||||||
|
int numBuffers;
|
||||||
ALuint buffer;
|
ALuint buffer;
|
||||||
ALuint format;
|
ALuint format;
|
||||||
|
|
||||||
|
@ -1731,8 +1786,40 @@ void S_AL_RawSamples(int stream, int samples, int rate, int width, int channels,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a buffer, and stuff the data into it
|
qalGetSourcei(streamSources[stream], AL_BUFFERS_QUEUED, &numBuffers);
|
||||||
qalGenBuffers(1, &buffer);
|
|
||||||
|
if (numBuffers == MAX_STREAM_BUFFERS)
|
||||||
|
{
|
||||||
|
Com_DPrintf(S_COLOR_RED"WARNING: Steam dropping raw samples, reached MAX_STREAM_BUFFERS\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a new AL buffer if needed
|
||||||
|
if (numBuffers == streamNumBuffers[stream])
|
||||||
|
{
|
||||||
|
ALuint oldBuffers[MAX_STREAM_BUFFERS];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!S_AL_GenBuffers(1, &buffer, "stream"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Com_Memcpy(oldBuffers, &streamBuffers[stream], sizeof (oldBuffers));
|
||||||
|
|
||||||
|
// Reorder buffer array in order of oldest to newest
|
||||||
|
for ( i = 0; i < streamNumBuffers[stream]; ++i )
|
||||||
|
streamBuffers[stream][i] = oldBuffers[(streamBufIndex[stream] + i) % streamNumBuffers[stream]];
|
||||||
|
|
||||||
|
// Add the new buffer to end
|
||||||
|
streamBuffers[stream][streamNumBuffers[stream]] = buffer;
|
||||||
|
streamBufIndex[stream] = streamNumBuffers[stream];
|
||||||
|
streamNumBuffers[stream]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select next buffer in loop
|
||||||
|
buffer = streamBuffers[stream][ streamBufIndex[stream] ];
|
||||||
|
streamBufIndex[stream] = (streamBufIndex[stream] + 1) % streamNumBuffers[stream];
|
||||||
|
|
||||||
|
// Fill buffer
|
||||||
qalBufferData(buffer, format, (ALvoid *)data, (samples * width * channels), rate);
|
qalBufferData(buffer, format, (ALvoid *)data, (samples * width * channels), rate);
|
||||||
|
|
||||||
// Shove the data onto the streamSource
|
// Shove the data onto the streamSource
|
||||||
|
@ -1762,13 +1849,12 @@ void S_AL_StreamUpdate( int stream )
|
||||||
if(streamSourceHandles[stream] == -1)
|
if(streamSourceHandles[stream] == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Un-queue any buffers, and delete them
|
// Un-queue any buffers
|
||||||
qalGetSourcei( streamSources[stream], AL_BUFFERS_PROCESSED, &numBuffers );
|
qalGetSourcei( streamSources[stream], AL_BUFFERS_PROCESSED, &numBuffers );
|
||||||
while( numBuffers-- )
|
while( numBuffers-- )
|
||||||
{
|
{
|
||||||
ALuint buffer;
|
ALuint buffer;
|
||||||
qalSourceUnqueueBuffers(streamSources[stream], 1, &buffer);
|
qalSourceUnqueueBuffers(streamSources[stream], 1, &buffer);
|
||||||
qalDeleteBuffers(1, &buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the streamSource playing if necessary
|
// Start the streamSource playing if necessary
|
||||||
|
@ -1799,8 +1885,6 @@ S_AL_StreamDie
|
||||||
static
|
static
|
||||||
void S_AL_StreamDie( int stream )
|
void S_AL_StreamDie( int stream )
|
||||||
{
|
{
|
||||||
int numBuffers;
|
|
||||||
|
|
||||||
if ((stream < 0) || (stream >= MAX_RAW_STREAMS))
|
if ((stream < 0) || (stream >= MAX_RAW_STREAMS))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1810,15 +1894,6 @@ void S_AL_StreamDie( int stream )
|
||||||
streamPlaying[stream] = qfalse;
|
streamPlaying[stream] = qfalse;
|
||||||
qalSourceStop(streamSources[stream]);
|
qalSourceStop(streamSources[stream]);
|
||||||
|
|
||||||
// Un-queue any buffers, and delete them
|
|
||||||
qalGetSourcei( streamSources[stream], AL_BUFFERS_PROCESSED, &numBuffers );
|
|
||||||
while( numBuffers-- )
|
|
||||||
{
|
|
||||||
ALuint buffer;
|
|
||||||
qalSourceUnqueueBuffers(streamSources[stream], 1, &buffer);
|
|
||||||
qalDeleteBuffers(1, &buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
S_AL_FreeStreamChannel(stream);
|
S_AL_FreeStreamChannel(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1910,22 +1985,17 @@ S_AL_StopBackgroundTrack
|
||||||
static
|
static
|
||||||
void S_AL_StopBackgroundTrack( void )
|
void S_AL_StopBackgroundTrack( void )
|
||||||
{
|
{
|
||||||
int numBuffers;
|
|
||||||
|
|
||||||
if(!musicPlaying)
|
if(!musicPlaying)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Stop playing
|
// Stop playing
|
||||||
qalSourceStop(musicSource);
|
qalSourceStop(musicSource);
|
||||||
|
|
||||||
// Un-queue any buffers, and delete them
|
// Detach any buffers
|
||||||
qalGetSourcei( musicSource, AL_BUFFERS_PROCESSED, &numBuffers );
|
qalSourcei(musicSource, AL_BUFFER, 0);
|
||||||
while( numBuffers-- )
|
|
||||||
{
|
// Delete the buffers
|
||||||
ALuint buffer;
|
qalDeleteBuffers(NUM_MUSIC_BUFFERS, musicBuffers);
|
||||||
qalSourceUnqueueBuffers(musicSource, 1, &buffer);
|
|
||||||
qalDeleteBuffers(1, &buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free the musicSource
|
// Free the musicSource
|
||||||
S_AL_MusicSourceFree();
|
S_AL_MusicSourceFree();
|
||||||
|
@ -2058,7 +2128,8 @@ void S_AL_StartBackgroundTrack( const char *intro, const char *loop )
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the musicBuffers
|
// Generate the musicBuffers
|
||||||
qalGenBuffers(NUM_MUSIC_BUFFERS, musicBuffers);
|
if (!S_AL_GenBuffers(NUM_MUSIC_BUFFERS, musicBuffers, "music"))
|
||||||
|
return;
|
||||||
|
|
||||||
// Queue the musicBuffers up
|
// Queue the musicBuffers up
|
||||||
for(i = 0; i < NUM_MUSIC_BUFFERS; i++)
|
for(i = 0; i < NUM_MUSIC_BUFFERS; i++)
|
||||||
|
@ -2419,6 +2490,8 @@ qboolean S_AL_Init( soundInterface_t *si )
|
||||||
streamSourceHandles[i] = -1;
|
streamSourceHandles[i] = -1;
|
||||||
streamPlaying[i] = qfalse;
|
streamPlaying[i] = qfalse;
|
||||||
streamSources[i] = 0;
|
streamSources[i] = 0;
|
||||||
|
streamNumBuffers[i] = 0;
|
||||||
|
streamBufIndex[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// New console variables
|
// New console variables
|
||||||
|
|
Loading…
Reference in a new issue