aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/ALc.c
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/ALc.c')
-rw-r--r--Alc/ALc.c99
1 files changed, 90 insertions, 9 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 69e37540..1028321e 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -1769,6 +1769,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
ALCcontext *context;
enum HrtfRequestMode hrtf_appreq = Hrtf_Default;
enum HrtfRequestMode hrtf_userreq = Hrtf_Default;
+ ALsizei old_sends = device->NumAuxSends;
enum DevFmtChannels oldChans;
enum DevFmtType oldType;
ALCuint oldFreq;
@@ -2183,7 +2184,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
{
ALsizei pos;
- ReadLock(&context->PropLock);
+ WriteLock(&context->PropLock);
LockUIntMapRead(&context->EffectSlotMap);
for(pos = 0;pos < context->EffectSlotMap.size;pos++)
{
@@ -2208,8 +2209,10 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
for(pos = 0;pos < context->SourceMap.size;pos++)
{
ALsource *source = context->SourceMap.values[pos];
- ALuint s = device->NumAuxSends;
- while(s < MAX_SENDS)
+ struct ALsourceProps *props;
+ ALsizei s;
+
+ for(s = device->NumAuxSends;s < MAX_SENDS;s++)
{
if(source->Send[s].Slot)
DecrementRef(&source->Send[s].Slot->ref);
@@ -2219,14 +2222,32 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
source->Send[s].HFReference = LOWPASSFREQREF;
source->Send[s].GainLF = 1.0f;
source->Send[s].LFReference = HIGHPASSFREQREF;
- s++;
}
+
source->NeedsUpdate = AL_TRUE;
+
+ /* Clear any pre-existing source property structs, in case the
+ * number of auxiliary sends changed. Playing (or paused) sources
+ * will have updates specified.
+ */
+ props = ATOMIC_EXCHANGE_SEQ(struct ALsourceProps*, &source->Update, NULL);
+ al_free(props);
+
+ props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->FreeList, NULL,
+ almemory_order_relaxed);
+ while(props)
+ {
+ struct ALsourceProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
+ al_free(props);
+ props = next;
+ }
}
+ AllocateVoices(context, context->MaxVoices, old_sends);
UnlockUIntMapRead(&context->SourceMap);
UpdateListenerProps(context);
- ReadUnlock(&context->PropLock);
+ UpdateAllSourceProps(context);
+ WriteUnlock(&context->PropLock);
context = context->next;
}
@@ -2595,6 +2616,65 @@ ALCcontext *GetContextRef(void)
}
+void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
+{
+ ALCdevice *device = context->Device;
+ ALsizei num_sends = device->NumAuxSends;
+ struct ALsourceProps *props;
+ size_t sizeof_props;
+ ALvoice *voices;
+ 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.
+ */
+ sizeof_props = RoundUp(offsetof(struct ALsourceProps, Send[num_sends]), 16);
+ size = sizeof(*voices) + sizeof_props;
+
+ voices = al_calloc(16, size * num_voices);
+ props = (struct ALsourceProps*)(voices + num_voices);
+
+ if(context->Voices)
+ {
+ ALsizei v_count = mini(context->VoiceCount, num_voices);
+ for(;v < v_count;v++)
+ {
+ ALsizei s_count = mini(old_sends, num_sends);
+ ALsizei i;
+
+ /* Copy the old voice data and source property set to the new
+ * storage.
+ */
+ voices[v] = context->Voices[v];
+ *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;
+ props = (struct ALsourceProps*)((char*)props + sizeof_props);
+ }
+ }
+ /* Finish setting the voices' property set pointers. */
+ for(;v < num_voices;v++)
+ {
+ voices[v].Props = props;
+ props = (struct ALsourceProps*)((char*)props + sizeof_props);
+ }
+
+ al_free(context->Voices);
+ context->Voices = voices;
+ context->MaxVoices = num_voices;
+ context->VoiceCount = mini(context->VoiceCount, num_voices);
+}
+
+
/************************************************
* Standard ALC functions
************************************************/
@@ -3267,11 +3347,13 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
InitRef(&ALContext->ref, 1);
ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
+ ALContext->Device = device;
ATOMIC_INIT(&ALContext->ActiveAuxSlotList, NULL);
+ ALContext->Voices = NULL;
+ ALContext->MaxVoices = 0;
ALContext->VoiceCount = 0;
- ALContext->MaxVoices = 256;
- ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0]));
+ AllocateVoices(ALContext, 256, device->NumAuxSends);
}
if(!ALContext || !ALContext->Voices)
{
@@ -3312,8 +3394,7 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
return NULL;
}
- ALContext->Device = device;
- ALCdevice_IncRef(device);
+ ALCdevice_IncRef(ALContext->Device);
InitContext(ALContext);
if(ConfigValueFloat(al_string_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf))