aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c99
-rw-r--r--Alc/ALu.c22
-rw-r--r--Alc/helpers.c1
-rw-r--r--OpenAL32/Include/alMain.h9
-rw-r--r--OpenAL32/Include/alSource.h8
-rw-r--r--OpenAL32/alSource.c21
6 files changed, 121 insertions, 39 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);
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 2573c836..947a16ba 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -356,6 +356,13 @@ inline ALuint NextPowerOf2(ALuint value)
return value+1;
}
+/** Round up a value to the next multiple. */
+inline size_t RoundUp(size_t value, size_t r)
+{
+ value += r-1;
+ return value - (value%r);
+}
+
/* Fast float-to-int conversion. Assumes the FPU is already in round-to-zero
* mode. */
inline ALint fastf2i(ALfloat f)
@@ -813,6 +820,8 @@ ALCcontext *GetContextRef(void);
void ALCcontext_IncRef(ALCcontext *context);
void ALCcontext_DecRef(ALCcontext *context);
+void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends);
+
void AppendAllDevicesList(const ALCchar *name);
void AppendCaptureDeviceList(const ALCchar *name);
diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h
index d45e5d9c..cc9dd763 100644
--- a/OpenAL32/Include/alSource.h
+++ b/OpenAL32/Include/alSource.h
@@ -23,6 +23,8 @@ typedef struct ALbufferlistitem {
struct ALsourceProps {
+ ATOMIC(struct ALsourceProps*) next;
+
ATOMIC(ALfloat) Pitch;
ATOMIC(ALfloat) Gain;
ATOMIC(ALfloat) OuterGain;
@@ -69,14 +71,12 @@ struct ALsourceProps {
ATOMIC(ALfloat) HFReference;
ATOMIC(ALfloat) GainLF;
ATOMIC(ALfloat) LFReference;
- } Send[MAX_SENDS];
-
- ATOMIC(struct ALsourceProps*) next;
+ } Send[];
};
typedef struct ALvoice {
- struct ALsourceProps Props;
+ struct ALsourceProps *Props;
struct ALsource *Source;
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
index 036b7542..56d2b415 100644
--- a/OpenAL32/alSource.c
+++ b/OpenAL32/alSource.c
@@ -2306,23 +2306,13 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
ALCdevice_Lock(context->Device);
while(n > context->MaxVoices-context->VoiceCount)
{
- ALvoice *temp = NULL;
- ALsizei newcount;
-
- newcount = context->MaxVoices << 1;
- if(newcount > 0)
- temp = al_malloc(16, newcount * sizeof(context->Voices[0]));
- if(!temp)
+ ALsizei newcount = context->MaxVoices << 1;
+ if(context->MaxVoices >= newcount)
{
ALCdevice_Unlock(context->Device);
SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
}
- memcpy(temp, context->Voices, context->MaxVoices * sizeof(temp[0]));
- memset(&temp[context->MaxVoices], 0, (newcount-context->MaxVoices) * sizeof(temp[0]));
-
- al_free(context->Voices);
- context->Voices = temp;
- context->MaxVoices = newcount;
+ AllocateVoices(context, newcount, context->Device->NumAuxSends);
}
if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire) == DeferAll)
@@ -2757,6 +2747,7 @@ static void InitSourceParams(ALsource *Source)
Source->Direct.LFReference = HIGHPASSFREQREF;
for(i = 0;i < MAX_SENDS;i++)
{
+ Source->Send[i].Slot = NULL;
Source->Send[i].Gain = 1.0f;
Source->Send[i].GainHF = 1.0f;
Source->Send[i].HFReference = LOWPASSFREQREF;
@@ -2819,7 +2810,7 @@ static void DeinitSource(ALsource *source)
BufferList = next;
}
- for(i = 0;i < MAX_SENDS;++i)
+ for(i = 0;i < MAX_SENDS;i++)
{
if(source->Send[i].Slot)
DecrementRef(&source->Send[i].Slot->ref);
@@ -2835,7 +2826,7 @@ static void UpdateSourceProps(ALsource *source, ALuint num_sends)
/* Get an unused property container, or allocate a new one as needed. */
props = ATOMIC_LOAD(&source->FreeList, almemory_order_acquire);
if(!props)
- props = al_calloc(16, sizeof(*props));
+ props = al_calloc(16, offsetof(struct ALsourceProps, Send[num_sends]));
else
{
struct ALsourceProps *next;