aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
Diffstat (limited to 'Alc')
-rw-r--r--Alc/ALc.c99
-rw-r--r--Alc/ALu.c22
-rw-r--r--Alc/helpers.c1
3 files changed, 102 insertions, 20 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))
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 31dd6271..3cb02f84 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -807,14 +807,6 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *pro
ALint NumSends;
ALint i;
- DryGainHF = 1.0f;
- DryGainLF = 1.0f;
- for(i = 0;i < MAX_SENDS;i++)
- {
- WetGainHF[i] = 1.0f;
- WetGainLF[i] = 1.0f;
- }
-
/* Get context/device properties */
DopplerFactor = Listener->Params.DopplerFactor;
SpeedOfSound = Listener->Params.SpeedOfSound;
@@ -989,8 +981,14 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *pro
/* Source Gain + Attenuation */
DryGain = SourceVolume * Attenuation;
+ DryGainHF = 1.0f;
+ DryGainLF = 1.0f;
for(i = 0;i < NumSends;i++)
+ {
WetGain[i] = SourceVolume * RoomAttenuation[i];
+ WetGainHF[i] = 1.0f;
+ WetGainLF[i] = 1.0f;
+ }
/* Distance-based air absorption */
if(AirAbsorptionFactor > 0.0f && ClampedDist > MinDist)
@@ -1284,7 +1282,9 @@ static void CalcSourceParams(ALvoice *voice, ALCcontext *context, ALboolean forc
if(props)
{
- voice->Props = *props;
+ memcpy(voice->Props, props,
+ offsetof(struct ALsourceProps, Send[context->Device->NumAuxSends])
+ );
ATOMIC_REPLACE_HEAD(struct ALsourceProps*, &source->FreeList, props);
}
@@ -1296,9 +1296,9 @@ static void CalcSourceParams(ALvoice *voice, ALCcontext *context, ALboolean forc
if((buffer=BufferListItem->buffer) != NULL)
{
if(buffer->FmtChannels == FmtMono)
- CalcAttnSourceParams(voice, &voice->Props, buffer, context);
+ CalcAttnSourceParams(voice, voice->Props, buffer, context);
else
- CalcNonAttnSourceParams(voice, &voice->Props, buffer, context);
+ CalcNonAttnSourceParams(voice, voice->Props, buffer, context);
break;
}
BufferListItem = BufferListItem->next;
diff --git a/Alc/helpers.c b/Alc/helpers.c
index eac3811d..1ce567b2 100644
--- a/Alc/helpers.c
+++ b/Alc/helpers.c
@@ -112,6 +112,7 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x
extern inline ALuint NextPowerOf2(ALuint value);
+extern inline size_t RoundUp(size_t value, size_t r);
extern inline ALint fastf2i(ALfloat f);
extern inline ALuint fastf2u(ALfloat f);