Use an array of active sources when mixing

Prevents iterating over all allocated sources during mixing updates
This commit is contained in:
Chris Robinson 2010-06-06 00:17:50 -07:00
parent ed58571079
commit 7f6df7695c
4 changed files with 82 additions and 14 deletions

View File

@ -892,6 +892,7 @@ static ALvoid InitContext(ALCcontext *pContext)
//Validate pContext
pContext->LastError = AL_NO_ERROR;
pContext->Suspended = AL_FALSE;
pContext->ActiveSourceCount = 0;
InitUIntMap(&pContext->SourceMap);
//Set globals
@ -1613,8 +1614,15 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
device->Contexts = temp;
ALContext = calloc(1, sizeof(ALCcontext));
if(!ALContext)
if(ALContext)
{
ALContext->MaxActiveSources = 256;
ALContext->ActiveSources = malloc(sizeof(*ALContext->ActiveSources) *
ALContext->MaxActiveSources);
}
if(!ALContext || !ALContext->ActiveSources)
{
free(ALContext);
alcSetError(device, ALC_OUT_OF_MEMORY);
ProcessContext(NULL);
return NULL;
@ -1693,6 +1701,11 @@ ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
}
ResetUIntMap(&context->EffectSlotMap);
free(context->ActiveSources);
context->ActiveSources = NULL;
context->MaxActiveSources = 0;
context->ActiveSourceCount = 0;
list = &g_pContextList;
while(*list != context)
list = &(*list)->next;

View File

@ -939,23 +939,27 @@ static void MixSomeSources(ALCcontext *ALContext, float (*DryBuffer)[OUTPUTCHANN
ALenum State;
ALsizei pos;
if(ALContext->SourceMap.size <= 0)
return;
DuplicateStereo = ALContext->Device->DuplicateStereo;
DeviceFreq = ALContext->Device->Frequency;
rampLength = DeviceFreq * MIN_RAMP_LENGTH / 1000;
rampLength = max(rampLength, SamplesToDo);
pos = ALContext->SourceMap.size;
pos = 0;
next_source:
do {
if(pos-- <= 0)
return;
ALSource = ALContext->SourceMap.array[pos].value;
} while(ALSource->state != AL_PLAYING);
j = 0;
while(ALContext->ActiveSourceCount > pos)
{
ALsizei end;
ALSource = ALContext->ActiveSources[pos];
if(ALSource->state == AL_PLAYING)
break;
end = --(ALContext->ActiveSourceCount);
ALContext->ActiveSources[pos] = ALContext->ActiveSources[end];
}
if(pos >= ALContext->ActiveSourceCount)
return;
/* Find buffer format */
Frequency = 0;
@ -1028,8 +1032,8 @@ next_source:
for(i = 0;i < BuffersPlayed && BufferListItem;i++)
BufferListItem = BufferListItem->next;
while(State == AL_PLAYING && j < SamplesToDo)
{
j = 0;
do {
ALfloat *Data = NULL;
ALuint LoopStart = 0;
ALuint LoopEnd = 0;
@ -1397,7 +1401,7 @@ next_source:
DataPosFrac = 0;
}
}
}
} while(State == AL_PLAYING && j < SamplesToDo);
/* Update source info */
ALSource->state = State;
@ -1413,6 +1417,8 @@ next_source:
ALSource->FirstStart = AL_FALSE;
if(ALSource->state == AL_PLAYING)
pos++;
goto next_source;
}

View File

@ -433,6 +433,10 @@ struct ALCcontext_struct
ALfloat DopplerVelocity;
ALfloat flSpeedOfSound;
struct ALsource **ActiveSources;
ALsizei ActiveSourceCount;
ALsizei MaxActiveSources;
ALCdevice *Device;
const ALCchar *ExtensionList;

View File

@ -145,6 +145,16 @@ AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
// Recheck that the Source is valid, because there could be duplicated Source names
if((Source=LookupSource(Context->SourceMap, sources[i])) != NULL)
{
for(j = 0;j < Context->ActiveSourceCount;j++)
{
if(Context->ActiveSources[j] == Source)
{
ALsizei end = --(Context->ActiveSourceCount);
Context->ActiveSources[j] = Context->ActiveSources[end];
break;
}
}
// For each buffer in the source's queue, decrement its reference counter and remove it
while(Source->queue != NULL)
{
@ -1310,6 +1320,31 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
}
}
if(Context->ActiveSourceCount+n < n)
{
alSetError(Context, AL_OUT_OF_MEMORY);
goto done;
}
while(Context->MaxActiveSources < Context->ActiveSourceCount+n)
{
void *temp = NULL;
ALsizei newcount;
newcount = Context->MaxActiveSources << 1;
if(newcount > 0)
temp = realloc(Context->ActiveSources,
sizeof(*Context->ActiveSources) * newcount);
if(!temp)
{
alSetError(Context, AL_OUT_OF_MEMORY);
goto done;
}
Context->ActiveSources = temp;
Context->MaxActiveSources = newcount;
}
for(i = 0;i < n;i++)
{
Source = (ALsource*)ALTHUNK_LOOKUPENTRY(sources[i]);
@ -1364,6 +1399,16 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
Source->position = 0;
Source->position_fraction = 0;
}
else
{
for(j = 0;j < Context->ActiveSourceCount;j++)
{
if(Context->ActiveSources[j] == Source)
break;
}
if(j == Context->ActiveSourceCount)
Context->ActiveSources[Context->ActiveSourceCount++] = Source;
}
}
done: