Make the voices' Send[] array dynamically sized

The voices are still all allocated in one chunk to avoid memory fragmentation.
But they're accessed as an array of pointers since the size isn't static.
This commit is contained in:
Chris Robinson
2017-02-21 11:17:47 -08:00
parent e0e6efbfea
commit cd24e42b3f
5 changed files with 49 additions and 33 deletions
+28 -12
View File
@@ -2607,21 +2607,26 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
ALsizei num_sends = device->NumAuxSends;
struct ALsourceProps *props;
size_t sizeof_props;
ALvoice *voices;
size_t sizeof_voice;
ALvoice **voices;
ALvoice *voice;
ALsizei v = 0;
size_t size;
if(num_voices == context->MaxVoices && num_sends == old_sends)
return;
/* Allocate the voices, and the voices' stored source property set
* (including the dynamically-sized Send[] array) in one chunk.
/* Allocate the voice pointers, voices, and the voices' stored source
* property set (including the dynamically-sized Send[] array) in one
* chunk.
*/
sizeof_props = RoundUp(offsetof(struct ALsourceProps, Send[num_sends]), 16);
size = sizeof(*voices) + sizeof_props;
sizeof_voice = RoundUp(offsetof(ALvoice, Send[num_sends]), 16);
size = sizeof(ALvoice*) + sizeof_voice + sizeof_props;
voices = al_calloc(16, size * num_voices);
props = (struct ALsourceProps*)(voices + num_voices);
voices = al_calloc(16, RoundUp(size*num_voices, 16));
voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16));
props = (struct ALsourceProps*)((char*)voice + num_voices*sizeof_voice);
if(context->Voices)
{
@@ -2634,23 +2639,34 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
/* Copy the old voice data and source property set to the new
* storage.
*/
voices[v] = context->Voices[v];
*props = *(context->Voices[v].Props);
*voice = *(context->Voices[v]);
for(i = 0;i < s_count;i++)
props->Send[i] = context->Voices[v].Props->Send[i];
voice->Send[i] = context->Voices[v]->Send[i];
*props = *(context->Voices[v]->Props);
for(i = 0;i < s_count;i++)
props->Send[i] = context->Voices[v]->Props->Send[i];
/* Set this voice's property set pointer and increment 'props' to
* the next property storage space.
*/
voices[v].Props = props;
voice->Props = props;
props = (struct ALsourceProps*)((char*)props + sizeof_props);
/* Set this voice's reference and increment 'voice' to the next
* voice storage space.
*/
voices[v] = voice;
voice = (ALvoice*)((char*)voice + sizeof_voice);
}
}
/* Finish setting the voices' property set pointers. */
/* Finish setting the voices' property set pointers and references. */
for(;v < num_voices;v++)
{
voices[v].Props = props;
voice->Props = props;
props = (struct ALsourceProps*)((char*)props + sizeof_props);
voices[v] = voice;
voice = (ALvoice*)((char*)voice + sizeof_voice);
}
al_free(context->Voices);
+11 -11
View File
@@ -1313,7 +1313,7 @@ static void CalcSourceParams(ALvoice *voice, ALCcontext *context, ALboolean forc
static void UpdateContextSources(ALCcontext *ctx, ALeffectslot *slot)
{
ALvoice *voice, *voice_end;
ALvoice **voice, **voice_end;
ALsource *source;
IncrementRef(&ctx->UpdateCount);
@@ -1330,11 +1330,11 @@ static void UpdateContextSources(ALCcontext *ctx, ALeffectslot *slot)
voice_end = voice + ctx->VoiceCount;
for(;voice != voice_end;++voice)
{
if(!(source=voice->Source)) continue;
if(!(source=(*voice)->Source)) continue;
if(!IsPlayingOrPaused(source))
voice->Source = NULL;
(*voice)->Source = NULL;
else
CalcSourceParams(voice, ctx, force);
CalcSourceParams(*voice, ctx, force);
}
}
IncrementRef(&ctx->UpdateCount);
@@ -1424,7 +1424,7 @@ DECL_TEMPLATE(ALbyte, aluF2B)
void aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
{
ALsizei SamplesToDo;
ALvoice *voice, *voice_end;
ALvoice **voice, **voice_end;
ALeffectslot *slot;
ALsource *source;
ALCcontext *ctx;
@@ -1475,11 +1475,11 @@ void aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
voice_end = voice + ctx->VoiceCount;
for(;voice != voice_end;++voice)
{
ALboolean IsVoiceInit = (voice->Step > 0);
source = voice->Source;
ALboolean IsVoiceInit = ((*voice)->Step > 0);
source = (*voice)->Source;
if(IsVoiceInit && source &&
ATOMIC_LOAD(&source->state, almemory_order_relaxed) == AL_PLAYING)
MixSource(voice, source, device, SamplesToDo);
MixSource(*voice, source, device, SamplesToDo);
}
/* effect slot processing */
@@ -1637,15 +1637,15 @@ void aluHandleDisconnect(ALCdevice *device)
Context = ATOMIC_LOAD_SEQ(&device->ContextList);
while(Context)
{
ALvoice *voice, *voice_end;
ALvoice **voice, **voice_end;
voice = Context->Voices;
voice_end = voice + Context->VoiceCount;
while(voice != voice_end)
{
ALenum playing = AL_PLAYING;
ALsource *source = voice->Source;
voice->Source = NULL;
ALsource *source = (*voice)->Source;
(*voice)->Source = NULL;
if(source &&
ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALenum, &source->state, &playing, AL_STOPPED))
+1 -1
View File
@@ -812,7 +812,7 @@ struct ALCcontext_struct {
ALfloat GainBoost;
struct ALvoice *Voices;
struct ALvoice **Voices;
ALsizei VoiceCount;
ALsizei MaxVoices;
+1 -1
View File
@@ -106,7 +106,7 @@ typedef struct ALvoice {
ALfloat (*Buffer)[BUFFERSIZE];
ALsizei Channels;
} Send[MAX_SENDS];
} Send[];
} ALvoice;
+8 -8
View File
@@ -128,12 +128,12 @@ static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp
static inline ALvoice *GetSourceVoice(const ALsource *source, const ALCcontext *context)
{
ALvoice *voice = context->Voices;
ALvoice *voice_end = voice + context->VoiceCount;
ALvoice **voice = context->Voices;
ALvoice **voice_end = voice + context->VoiceCount;
while(voice != voice_end)
{
if(voice->Source == source)
return voice;
if((*voice)->Source == source)
return *voice;
++voice;
}
return NULL;
@@ -2915,7 +2915,7 @@ void UpdateAllSourceProps(ALCcontext *context)
for(pos = 0;pos < context->VoiceCount;pos++)
{
ALvoice *voice = &context->Voices[pos];
ALvoice *voice = context->Voices[pos];
ALsource *source = voice->Source;
if(source != NULL && source->NeedsUpdate && IsPlayingOrPaused(source))
{
@@ -2982,16 +2982,16 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
{
for(i = 0;i < Context->VoiceCount;i++)
{
if(Context->Voices[i].Source == NULL)
if(Context->Voices[i]->Source == NULL)
{
voice = &Context->Voices[i];
voice = Context->Voices[i];
voice->Source = Source;
break;
}
}
if(voice == NULL)
{
voice = &Context->Voices[Context->VoiceCount++];
voice = Context->Voices[Context->VoiceCount++];
voice->Source = Source;
}
discontinuity = AL_TRUE;