aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c56
-rw-r--r--Alc/ALu.c103
-rw-r--r--Alc/effects/autowah.c13
-rw-r--r--Alc/effects/chorus.c17
-rw-r--r--Alc/effects/compressor.c7
-rw-r--r--Alc/effects/dedicated.c9
-rw-r--r--Alc/effects/distortion.c15
-rw-r--r--Alc/effects/echo.c13
-rw-r--r--Alc/effects/equalizer.c29
-rw-r--r--Alc/effects/flanger.c17
-rw-r--r--Alc/effects/modulator.c15
-rw-r--r--Alc/effects/null.c6
-rw-r--r--Alc/effects/reverb.c9
-rw-r--r--OpenAL32/Include/alAuxEffectSlot.h44
-rw-r--r--OpenAL32/alAuxEffectSlot.c166
15 files changed, 332 insertions, 187 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 058dd242..b3d7eb38 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -1570,12 +1570,6 @@ void ALCcontext_DeferUpdates(ALCcontext *context)
/* Make sure all pending updates are performed */
UpdateContextSources(context);
-#define UPDATE_SLOT(iter) do { \
- if(ATOMIC_EXCHANGE(ALenum, &(*iter)->NeedsUpdate, AL_FALSE)) \
- V((*iter)->EffectState,update)(device, *iter); \
-} while(0)
- VECTOR_FOR_EACH(ALeffectslot*, context->ActiveAuxSlots, UPDATE_SLOT);
-#undef UPDATE_SLOT
}
V0(device->Backend,unlock)();
@@ -2059,6 +2053,22 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
SetMixerFPUMode(&oldMode);
V0(device->Backend,lock)();
+ if(device->DefaultSlot)
+ {
+ ALeffectslot *slot = device->DefaultSlot;
+ ALeffectState *state = slot->Params.EffectState;
+
+ state->OutBuffer = device->Dry.Buffer;
+ state->OutChannels = device->Dry.NumChannels;
+ if(V(state,deviceUpdate)(device) == AL_FALSE)
+ {
+ V0(device->Backend,unlock)();
+ RestoreFPUMode(&oldMode);
+ return ALC_INVALID_DEVICE;
+ }
+ UpdateEffectSlotProps(slot);
+ }
+
context = ATOMIC_LOAD(&device->ContextList);
while(context)
{
@@ -2069,17 +2079,16 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
{
ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
- slot->EffectState->OutBuffer = device->Dry.Buffer;
- slot->EffectState->OutChannels = device->Dry.NumChannels;
- if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
+ slot->Params.EffectState->OutBuffer = device->Dry.Buffer;
+ slot->Params.EffectState->OutChannels = device->Dry.NumChannels;
+ if(V(slot->Params.EffectState,deviceUpdate)(device) == AL_FALSE)
{
UnlockUIntMapRead(&context->EffectSlotMap);
V0(device->Backend,unlock)();
RestoreFPUMode(&oldMode);
return ALC_INVALID_DEVICE;
}
- ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
- V(slot->EffectState,update)(device, slot);
+ UpdateEffectSlotProps(slot);
}
UnlockUIntMapRead(&context->EffectSlotMap);
@@ -2126,22 +2135,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
context = context->next;
}
- if(device->DefaultSlot)
- {
- ALeffectslot *slot = device->DefaultSlot;
- ALeffectState *state = slot->EffectState;
-
- state->OutBuffer = device->Dry.Buffer;
- state->OutChannels = device->Dry.NumChannels;
- if(V(state,deviceUpdate)(device) == AL_FALSE)
- {
- V0(device->Backend,unlock)();
- RestoreFPUMode(&oldMode);
- return ALC_INVALID_DEVICE;
- }
- ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
- V(slot->EffectState,update)(device, slot);
- }
V0(device->Backend,unlock)();
RestoreFPUMode(&oldMode);
@@ -2170,9 +2163,8 @@ static ALCvoid FreeDevice(ALCdevice *device)
if(device->DefaultSlot)
{
- ALeffectState *state = device->DefaultSlot->EffectState;
+ DeinitEffectSlot(device->DefaultSlot);
device->DefaultSlot = NULL;
- DELETE_OBJ(state);
}
if(device->BufferMap.size > 0)
@@ -3497,13 +3489,15 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
}
else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
{
- ALeffectState *state = device->DefaultSlot->EffectState;
+ DeinitEffectSlot(device->DefaultSlot);
device->DefaultSlot = NULL;
- DELETE_OBJ(state);
ERR("Failed to initialize the default effect\n");
}
else
+ {
aluInitEffectPanning(device->DefaultSlot);
+ UpdateEffectSlotProps(device->DefaultSlot);
+ }
}
{
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 82553cc7..3b873aa5 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -330,6 +330,55 @@ static ALboolean CalcListenerParams(ALCcontext *Context)
return AL_TRUE;
}
+static ALboolean CalcEffectSlotParams(ALeffectslot *slot, ALCdevice *device)
+{
+ struct ALeffectslotProps *first;
+ struct ALeffectslotProps *props;
+
+ props = ATOMIC_EXCHANGE(struct ALeffectslotProps*, &slot->Update, NULL, almemory_order_acq_rel);
+ if(!props) return AL_FALSE;
+
+ slot->Params.Gain = ATOMIC_LOAD(&props->Gain, almemory_order_relaxed);
+ slot->Params.AuxSendAuto = ATOMIC_LOAD(&props->AuxSendAuto, almemory_order_relaxed);
+ slot->Params.EffectType = ATOMIC_LOAD(&props->Type, almemory_order_relaxed);
+ memcpy(&slot->Params.EffectProps, &props->Props, sizeof(props->Props));
+ /* If the existing state object is different from the one being set,
+ * exchange it so it remains in the freelist and isn't leaked.
+ */
+ if(slot->Params.EffectState == ATOMIC_LOAD(&props->State, almemory_order_relaxed))
+ slot->Params.EffectState = NULL;
+ slot->Params.EffectState = ATOMIC_EXCHANGE(ALeffectState*,
+ &props->State, slot->Params.EffectState, almemory_order_relaxed
+ );
+ if(IsReverbEffect(slot->Params.EffectType))
+ {
+ slot->Params.RoomRolloff = slot->Params.EffectProps.Reverb.RoomRolloffFactor;
+ slot->Params.DecayTime = slot->Params.EffectProps.Reverb.DecayTime;
+ slot->Params.AirAbsorptionGainHF = slot->Params.EffectProps.Reverb.AirAbsorptionGainHF;
+ }
+ else
+ {
+ slot->Params.RoomRolloff = 0.0f;
+ slot->Params.DecayTime = 0.0f;
+ slot->Params.AirAbsorptionGainHF = 1.0f;
+ }
+
+ V(slot->Params.EffectState,update)(device, slot);
+
+ /* WARNING: A livelock is theoretically possible if another thread keeps
+ * changing the freelist head without giving this a chance to actually swap
+ * in the old container (practically impossible with this little code,
+ * but...).
+ */
+ first = ATOMIC_LOAD(&slot->FreeList);
+ do {
+ ATOMIC_STORE(&props->next, first, almemory_order_relaxed);
+ } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*,
+ &slot->FreeList, &first, props) == 0);
+
+ return AL_TRUE;
+}
+
ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const ALbuffer *ALBuffer, const ALCcontext *ALContext)
{
static const struct ChanMap MonoMap[1] = {
@@ -415,7 +464,7 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
SendSlots[i] = ALSource->Send[i].Slot;
if(!SendSlots[i] && i == 0)
SendSlots[i] = Device->DefaultSlot;
- if(!SendSlots[i] || SendSlots[i]->EffectType == AL_EFFECT_NULL)
+ if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL)
{
SendSlots[i] = NULL;
voice->Send[i].OutBuffer = NULL;
@@ -847,7 +896,7 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALbuffer
if(!SendSlots[i] && i == 0)
SendSlots[i] = Device->DefaultSlot;
- if(!SendSlots[i] || SendSlots[i]->EffectType == AL_EFFECT_NULL)
+ if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL)
{
SendSlots[i] = NULL;
RoomRolloff[i] = 0.0f;
@@ -856,19 +905,10 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALbuffer
}
else if(SendSlots[i]->AuxSendAuto)
{
- RoomRolloff[i] = RoomRolloffBase;
- if(IsReverbEffect(SendSlots[i]->EffectType))
- {
- RoomRolloff[i] += SendSlots[i]->EffectProps.Reverb.RoomRolloffFactor;
- DecayDistance[i] = SendSlots[i]->EffectProps.Reverb.DecayTime *
- SPEEDOFSOUNDMETRESPERSEC;
- RoomAirAbsorption[i] = SendSlots[i]->EffectProps.Reverb.AirAbsorptionGainHF;
- }
- else
- {
- DecayDistance[i] = 0.0f;
- RoomAirAbsorption[i] = 1.0f;
- }
+ RoomRolloff[i] = SendSlots[i]->Params.RoomRolloff + RoomRolloffBase;
+ DecayDistance[i] = SendSlots[i]->Params.DecayTime *
+ SPEEDOFSOUNDMETRESPERSEC;
+ RoomAirAbsorption[i] = SendSlots[i]->Params.AirAbsorptionGainHF;
}
else
{
@@ -1245,9 +1285,18 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALbuffer
void UpdateContextSources(ALCcontext *ctx)
{
ALvoice *voice, *voice_end;
+ ALboolean fullupdate;
ALsource *source;
- if(CalcListenerParams(ctx))
+ fullupdate = CalcListenerParams(ctx);
+#define UPDATE_SLOT(iter) do { \
+ if(CalcEffectSlotParams(*iter, ctx->Device)) \
+ fullupdate = AL_TRUE; \
+} while(0)
+ VECTOR_FOR_EACH(ALeffectslot*, ctx->ActiveAuxSlots, UPDATE_SLOT);
+#undef UPDATE_SLOT
+
+ if(fullupdate)
{
voice = ctx->Voices;
voice_end = voice + ctx->VoiceCount;
@@ -1388,8 +1437,7 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
if((slot=device->DefaultSlot) != NULL)
{
- if(ATOMIC_EXCHANGE(ALenum, &slot->NeedsUpdate, AL_FALSE))
- V(slot->EffectState,update)(device, slot);
+ CalcEffectSlotParams(device->DefaultSlot, device);
for(i = 0;i < slot->NumChannels;i++)
memset(slot->WetBuffer[i], 0, SamplesToDo*sizeof(ALfloat));
}
@@ -1398,26 +1446,13 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
while(ctx)
{
if(!ctx->DeferUpdates)
- {
UpdateContextSources(ctx);
-#define UPDATE_SLOT(iter) do { \
- if(ATOMIC_EXCHANGE(ALenum, &(*iter)->NeedsUpdate, AL_FALSE)) \
- V((*iter)->EffectState,update)(device, *iter); \
- for(i = 0;i < (*iter)->NumChannels;i++) \
- memset((*iter)->WetBuffer[i], 0, SamplesToDo*sizeof(ALfloat)); \
-} while(0)
- VECTOR_FOR_EACH(ALeffectslot*, ctx->ActiveAuxSlots, UPDATE_SLOT);
-#undef UPDATE_SLOT
- }
- else
- {
#define CLEAR_WET_BUFFER(iter) do { \
for(i = 0;i < (*iter)->NumChannels;i++) \
memset((*iter)->WetBuffer[i], 0, SamplesToDo*sizeof(ALfloat)); \
} while(0)
- VECTOR_FOR_EACH(ALeffectslot*, ctx->ActiveAuxSlots, CLEAR_WET_BUFFER);
+ VECTOR_FOR_EACH(ALeffectslot*, ctx->ActiveAuxSlots, CLEAR_WET_BUFFER);
#undef CLEAR_WET_BUFFER
- }
/* source processing */
voice = ctx->Voices;
@@ -1434,7 +1469,7 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
for(i = 0;i < c;i++)
{
const ALeffectslot *slot = VECTOR_ELEM(ctx->ActiveAuxSlots, i);
- ALeffectState *state = slot->EffectState;
+ ALeffectState *state = slot->Params.EffectState;
V(state,process)(SamplesToDo, slot->WetBuffer, state->OutBuffer,
state->OutChannels);
}
@@ -1445,7 +1480,7 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
if(device->DefaultSlot != NULL)
{
const ALeffectslot *slot = device->DefaultSlot;
- ALeffectState *state = slot->EffectState;
+ ALeffectState *state = slot->Params.EffectState;
V(state,process)(SamplesToDo, slot->WetBuffer, state->OutBuffer,
state->OutChannels);
}
diff --git a/Alc/effects/autowah.c b/Alc/effects/autowah.c
index 7c5abfb1..1e7a8e29 100644
--- a/Alc/effects/autowah.c
+++ b/Alc/effects/autowah.c
@@ -53,8 +53,9 @@ typedef struct ALautowahState {
ALfilterState LowPass;
} ALautowahState;
-static ALvoid ALautowahState_Destruct(ALautowahState *UNUSED(state))
+static ALvoid ALautowahState_Destruct(ALautowahState *state)
{
+ ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
}
static ALboolean ALautowahState_deviceUpdate(ALautowahState *state, ALCdevice *device)
@@ -67,15 +68,15 @@ static ALvoid ALautowahState_update(ALautowahState *state, const ALCdevice *devi
{
ALfloat attackTime, releaseTime;
- attackTime = slot->EffectProps.Autowah.AttackTime * state->Frequency;
- releaseTime = slot->EffectProps.Autowah.ReleaseTime * state->Frequency;
+ attackTime = slot->Params.EffectProps.Autowah.AttackTime * state->Frequency;
+ releaseTime = slot->Params.EffectProps.Autowah.ReleaseTime * state->Frequency;
state->AttackRate = powf(1.0f/GAIN_SILENCE_THRESHOLD, 1.0f/attackTime);
state->ReleaseRate = powf(GAIN_SILENCE_THRESHOLD/1.0f, 1.0f/releaseTime);
- state->PeakGain = slot->EffectProps.Autowah.PeakGain;
- state->Resonance = slot->EffectProps.Autowah.Resonance;
+ state->PeakGain = slot->Params.EffectProps.Autowah.PeakGain;
+ state->Resonance = slot->Params.EffectProps.Autowah.Resonance;
- ComputeAmbientGains(device->Dry, slot->Gain, state->Gain);
+ ComputeAmbientGains(device->Dry, slot->Params.Gain, state->Gain);
}
static ALvoid ALautowahState_process(ALautowahState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)
diff --git a/Alc/effects/chorus.c b/Alc/effects/chorus.c
index 9deb2a1f..3eff95a4 100644
--- a/Alc/effects/chorus.c
+++ b/Alc/effects/chorus.c
@@ -60,6 +60,7 @@ static ALvoid ALchorusState_Destruct(ALchorusState *state)
free(state->SampleBuffer[0]);
state->SampleBuffer[0] = NULL;
state->SampleBuffer[1] = NULL;
+ ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
}
static ALboolean ALchorusState_deviceUpdate(ALchorusState *state, ALCdevice *Device)
@@ -98,7 +99,7 @@ static ALvoid ALchorusState_update(ALchorusState *state, const ALCdevice *Device
ALfloat rate;
ALint phase;
- switch(Slot->EffectProps.Chorus.Waveform)
+ switch(Slot->Params.EffectProps.Chorus.Waveform)
{
case AL_CHORUS_WAVEFORM_TRIANGLE:
state->waveform = CWF_Triangle;
@@ -107,18 +108,18 @@ static ALvoid ALchorusState_update(ALchorusState *state, const ALCdevice *Device
state->waveform = CWF_Sinusoid;
break;
}
- state->depth = Slot->EffectProps.Chorus.Depth;
- state->feedback = Slot->EffectProps.Chorus.Feedback;
- state->delay = fastf2i(Slot->EffectProps.Chorus.Delay * frequency);
+ state->depth = Slot->Params.EffectProps.Chorus.Depth;
+ state->feedback = Slot->Params.EffectProps.Chorus.Feedback;
+ state->delay = fastf2i(Slot->Params.EffectProps.Chorus.Delay * frequency);
/* Gains for left and right sides */
CalcXYZCoeffs(-1.0f, 0.0f, 0.0f, 0.0f, coeffs);
- ComputePanningGains(Device->Dry, coeffs, Slot->Gain, state->Gain[0]);
+ ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[0]);
CalcXYZCoeffs( 1.0f, 0.0f, 0.0f, 0.0f, coeffs);
- ComputePanningGains(Device->Dry, coeffs, Slot->Gain, state->Gain[1]);
+ ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[1]);
- phase = Slot->EffectProps.Chorus.Phase;
- rate = Slot->EffectProps.Chorus.Rate;
+ phase = Slot->Params.EffectProps.Chorus.Phase;
+ rate = Slot->Params.EffectProps.Chorus.Rate;
if(!(rate > 0.0f))
{
state->lfo_scale = 0.0f;
diff --git a/Alc/effects/compressor.c b/Alc/effects/compressor.c
index bc4955b9..c501b3ba 100644
--- a/Alc/effects/compressor.c
+++ b/Alc/effects/compressor.c
@@ -40,8 +40,9 @@ typedef struct ALcompressorState {
ALfloat GainCtrl;
} ALcompressorState;
-static ALvoid ALcompressorState_Destruct(ALcompressorState *UNUSED(state))
+static ALvoid ALcompressorState_Destruct(ALcompressorState *state)
{
+ ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
}
static ALboolean ALcompressorState_deviceUpdate(ALcompressorState *state, ALCdevice *device)
@@ -60,7 +61,7 @@ static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCdevice
aluMatrixf matrix;
ALuint i;
- state->Enabled = slot->EffectProps.Compressor.OnOff;
+ state->Enabled = slot->Params.EffectProps.Compressor.OnOff;
aluMatrixfSet(&matrix,
1.0f, 0.0f, 0.0f, 0.0f,
@@ -72,7 +73,7 @@ static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCdevice
STATIC_CAST(ALeffectState,state)->OutBuffer = device->FOAOut.Buffer;
STATIC_CAST(ALeffectState,state)->OutChannels = device->FOAOut.NumChannels;
for(i = 0;i < 4;i++)
- ComputeFirstOrderGains(device->FOAOut, matrix.m[i], slot->Gain,
+ ComputeFirstOrderGains(device->FOAOut, matrix.m[i], slot->Params.Gain,
state->Gain[i]);
}
diff --git a/Alc/effects/dedicated.c b/Alc/effects/dedicated.c
index f510e8fe..34e5ed80 100644
--- a/Alc/effects/dedicated.c
+++ b/Alc/effects/dedicated.c
@@ -36,8 +36,9 @@ typedef struct ALdedicatedState {
} ALdedicatedState;
-static ALvoid ALdedicatedState_Destruct(ALdedicatedState *UNUSED(state))
+static ALvoid ALdedicatedState_Destruct(ALdedicatedState *state)
{
+ ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
}
static ALboolean ALdedicatedState_deviceUpdate(ALdedicatedState *UNUSED(state), ALCdevice *UNUSED(device))
@@ -53,8 +54,8 @@ static ALvoid ALdedicatedState_update(ALdedicatedState *state, const ALCdevice *
for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
state->gains[i] = 0.0f;
- Gain = Slot->Gain * Slot->EffectProps.Dedicated.Gain;
- if(Slot->EffectType == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
+ Gain = Slot->Params.Gain * Slot->Params.EffectProps.Dedicated.Gain;
+ if(Slot->Params.EffectType == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
{
int idx;
if((idx=GetChannelIdxByName(device->RealOut, LFE)) != -1)
@@ -64,7 +65,7 @@ static ALvoid ALdedicatedState_update(ALdedicatedState *state, const ALCdevice *
state->gains[idx] = Gain;
}
}
- else if(Slot->EffectType == AL_EFFECT_DEDICATED_DIALOGUE)
+ else if(Slot->Params.EffectType == AL_EFFECT_DEDICATED_DIALOGUE)
{
int idx;
/* Dialog goes to the front-center speaker if it exists, otherwise it
diff --git a/Alc/effects/distortion.c b/Alc/effects/distortion.c
index 7a4c2f62..534a817c 100644
--- a/Alc/effects/distortion.c
+++ b/Alc/effects/distortion.c
@@ -43,8 +43,9 @@ typedef struct ALdistortionState {
ALfloat edge_coeff;
} ALdistortionState;
-static ALvoid ALdistortionState_Destruct(ALdistortionState *UNUSED(state))
+static ALvoid ALdistortionState_Destruct(ALdistortionState *state)
{
+ ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
}
static ALboolean ALdistortionState_deviceUpdate(ALdistortionState *UNUSED(state), ALCdevice *UNUSED(device))
@@ -60,15 +61,15 @@ static ALvoid ALdistortionState_update(ALdistortionState *state, const ALCdevice
ALfloat edge;
/* Store distorted signal attenuation settings */
- state->attenuation = Slot->EffectProps.Distortion.Gain;
+ state->attenuation = Slot->Params.EffectProps.Distortion.Gain;
/* Store waveshaper edge settings */
- edge = sinf(Slot->EffectProps.Distortion.Edge * (F_PI_2));
+ edge = sinf(Slot->Params.EffectProps.Distortion.Edge * (F_PI_2));
edge = minf(edge, 0.99f);
state->edge_coeff = 2.0f * edge / (1.0f-edge);
/* Lowpass filter */
- cutoff = Slot->EffectProps.Distortion.LowpassCutoff;
+ cutoff = Slot->Params.EffectProps.Distortion.LowpassCutoff;
/* Bandwidth value is constant in octaves */
bandwidth = (cutoff / 2.0f) / (cutoff * 0.67f);
ALfilterState_setParams(&state->lowpass, ALfilterType_LowPass, 1.0f,
@@ -76,14 +77,14 @@ static ALvoid ALdistortionState_update(ALdistortionState *state, const ALCdevice
);
/* Bandpass filter */
- cutoff = Slot->EffectProps.Distortion.EQCenter;
+ cutoff = Slot->Params.EffectProps.Distortion.EQCenter;
/* Convert bandwidth in Hz to octaves */
- bandwidth = Slot->EffectProps.Distortion.EQBandwidth / (cutoff * 0.67f);
+ bandwidth = Slot->Params.EffectProps.Distortion.EQBandwidth / (cutoff * 0.67f);
ALfilterState_setParams(&state->bandpass, ALfilterType_BandPass, 1.0f,
cutoff / (frequency*4.0f), calc_rcpQ_from_bandwidth(cutoff / (frequency*4.0f), bandwidth)
);
- ComputeAmbientGains(Device->Dry, Slot->Gain, state->Gain);
+ ComputeAmbientGains(Device->Dry, Slot->Params.Gain, state->Gain);
}
static ALvoid ALdistortionState_process(ALdistortionState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)
diff --git a/Alc/effects/echo.c b/Alc/effects/echo.c
index 8600db70..eea86f15 100644
--- a/Alc/effects/echo.c
+++ b/Alc/effects/echo.c
@@ -54,6 +54,7 @@ static ALvoid ALechoState_Destruct(ALechoState *state)
{
free(state->SampleBuffer);
state->SampleBuffer = NULL;
+ ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
}
static ALboolean ALechoState_deviceUpdate(ALechoState *state, ALCdevice *Device)
@@ -87,11 +88,11 @@ static ALvoid ALechoState_update(ALechoState *state, const ALCdevice *Device, co
ALfloat coeffs[MAX_AMBI_COEFFS];
ALfloat gain, lrpan, spread;
- state->Tap[0].delay = fastf2u(Slot->EffectProps.Echo.Delay * frequency) + 1;
- state->Tap[1].delay = fastf2u(Slot->EffectProps.Echo.LRDelay * frequency);
+ state->Tap[0].delay = fastf2u(Slot->Params.EffectProps.Echo.Delay * frequency) + 1;
+ state->Tap[1].delay = fastf2u(Slot->Params.EffectProps.Echo.LRDelay * frequency);
state->Tap[1].delay += state->Tap[0].delay;
- spread = Slot->EffectProps.Echo.Spread;
+ spread = Slot->Params.EffectProps.Echo.Spread;
if(spread < 0.0f) lrpan = -1.0f;
else lrpan = 1.0f;
/* Convert echo spread (where 0 = omni, +/-1 = directional) to coverage
@@ -99,14 +100,14 @@ static ALvoid ALechoState_update(ALechoState *state, const ALCdevice *Device, co
*/
spread = asinf(1.0f - fabsf(spread))*4.0f;
- state->FeedGain = Slot->EffectProps.Echo.Feedback;
+ state->FeedGain = Slot->Params.EffectProps.Echo.Feedback;
- gain = minf(1.0f - Slot->EffectProps.Echo.Damping, 0.01f);
+ gain = minf(1.0f - Slot->Params.EffectProps.Echo.Damping, 0.01f);
ALfilterState_setParams(&state->Filter, ALfilterType_HighShelf,
gain, LOWPASSFREQREF/frequency,
calc_rcpQ_from_slope(gain, 0.75f));
- gain = Slot->Gain;
+ gain = Slot->Params.Gain;
/* First tap panning */
CalcXYZCoeffs(-lrpan, 0.0f, 0.0f, spread, coeffs);
diff --git a/Alc/effects/equalizer.c b/Alc/effects/equalizer.c
index e0fa010e..94ee1853 100644
--- a/Alc/effects/equalizer.c
+++ b/Alc/effects/equalizer.c
@@ -87,8 +87,9 @@ typedef struct ALequalizerState {
ALfloat SampleBuffer[4][MAX_EFFECT_CHANNELS][MAX_UPDATE_SAMPLES];
} ALequalizerState;
-static ALvoid ALequalizerState_Destruct(ALequalizerState *UNUSED(state))
+static ALvoid ALequalizerState_Destruct(ALequalizerState *state)
{
+ ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
}
static ALboolean ALequalizerState_deviceUpdate(ALequalizerState *UNUSED(state), ALCdevice *UNUSED(device))
@@ -113,15 +114,15 @@ static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice *
STATIC_CAST(ALeffectState,state)->OutBuffer = device->FOAOut.Buffer;
STATIC_CAST(ALeffectState,state)->OutChannels = device->FOAOut.NumChannels;
for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
- ComputeFirstOrderGains(device->FOAOut, matrix.m[i], slot->Gain,
+ ComputeFirstOrderGains(device->FOAOut, matrix.m[i], slot->Params.Gain,
state->Gain[i]);
/* Calculate coefficients for the each type of filter. Note that the shelf
* filters' gain is for the reference frequency, which is the centerpoint
* of the transition band.
*/
- gain = sqrtf(slot->EffectProps.Equalizer.LowGain);
- freq_mult = slot->EffectProps.Equalizer.LowCutoff/frequency;
+ gain = sqrtf(slot->Params.EffectProps.Equalizer.LowGain);
+ freq_mult = slot->Params.EffectProps.Equalizer.LowCutoff/frequency;
ALfilterState_setParams(&state->filter[0][0], ALfilterType_LowShelf,
gain, freq_mult, calc_rcpQ_from_slope(gain, 0.75f)
);
@@ -136,10 +137,12 @@ static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice *
state->filter[0][i].process = state->filter[0][0].process;
}
- gain = slot->EffectProps.Equalizer.Mid1Gain;
- freq_mult = slot->EffectProps.Equalizer.Mid1Center/frequency;
+ gain = slot->Params.EffectProps.Equalizer.Mid1Gain;
+ freq_mult = slot->Params.EffectProps.Equalizer.Mid1Center/frequency;
ALfilterState_setParams(&state->filter[1][0], ALfilterType_Peaking,
- gain, freq_mult, calc_rcpQ_from_bandwidth(freq_mult, slot->EffectProps.Equalizer.Mid1Width)
+ gain, freq_mult, calc_rcpQ_from_bandwidth(
+ freq_mult, slot->Params.EffectProps.Equalizer.Mid1Width
+ )
);
for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
{
@@ -151,10 +154,12 @@ static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice *
state->filter[1][i].process = state->filter[1][0].process;
}
- gain = slot->EffectProps.Equalizer.Mid2Gain;
- freq_mult = slot->EffectProps.Equalizer.Mid2Center/frequency;
+ gain = slot->Params.EffectProps.Equalizer.Mid2Gain;
+ freq_mult = slot->Params.EffectProps.Equalizer.Mid2Center/frequency;
ALfilterState_setParams(&state->filter[2][0], ALfilterType_Peaking,
- gain, freq_mult, calc_rcpQ_from_bandwidth(freq_mult, slot->EffectProps.Equalizer.Mid2Width)
+ gain, freq_mult, calc_rcpQ_from_bandwidth(
+ freq_mult, slot->Params.EffectProps.Equalizer.Mid2Width
+ )
);
for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
{
@@ -166,8 +171,8 @@ static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice *
state->filter[2][i].process = state->filter[2][0].process;
}
- gain = sqrtf(slot->EffectProps.Equalizer.HighGain);
- freq_mult = slot->EffectProps.Equalizer.HighCutoff/frequency;
+ gain = sqrtf(slot->Params.EffectProps.Equalizer.HighGain);
+ freq_mult = slot->Params.EffectProps.Equalizer.HighCutoff/frequency;
ALfilterState_setParams(&state->filter[3][0], ALfilterType_HighShelf,
gain, freq_mult, calc_rcpQ_from_slope(gain, 0.75f)
);
diff --git a/Alc/effects/flanger.c b/Alc/effects/flanger.c
index a71eb9c2..966622e6 100644
--- a/Alc/effects/flanger.c
+++ b/Alc/effects/flanger.c
@@ -60,6 +60,7 @@ static ALvoid ALflangerState_Destruct(ALflangerState *state)
free(state->SampleBuffer[0]);
state->SampleBuffer[0] = NULL;
state->SampleBuffer[1] = NULL;
+ ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
}
static ALboolean ALflangerState_deviceUpdate(ALflangerState *state, ALCdevice *Device)
@@ -98,7 +99,7 @@ static ALvoid ALflangerState_update(ALflangerState *state, const ALCdevice *Devi
ALfloat rate;
ALint phase;
- switch(Slot->EffectProps.Flanger.Waveform)
+ switch(Slot->Params.EffectProps.Flanger.Waveform)
{
case AL_FLANGER_WAVEFORM_TRIANGLE:
state->waveform = FWF_Triangle;
@@ -107,18 +108,18 @@ static ALvoid ALflangerState_update(ALflangerState *state, const ALCdevice *Devi
state->waveform = FWF_Sinusoid;
break;
}
- state->depth = Slot->EffectProps.Flanger.Depth;
- state->feedback = Slot->EffectProps.Flanger.Feedback;
- state->delay = fastf2i(Slot->EffectProps.Flanger.Delay * frequency);
+ state->depth = Slot->Params.EffectProps.Flanger.Depth;
+ state->feedback = Slot->Params.EffectProps.Flanger.Feedback;
+ state->delay = fastf2i(Slot->Params.EffectProps.Flanger.Delay * frequency);
/* Gains for left and right sides */
CalcXYZCoeffs(-1.0f, 0.0f, 0.0f, 0.0f, coeffs);
- ComputePanningGains(Device->Dry, coeffs, Slot->Gain, state->Gain[0]);
+ ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[0]);
CalcXYZCoeffs( 1.0f, 0.0f, 0.0f, 0.0f, coeffs);
- ComputePanningGains(Device->Dry, coeffs, Slot->Gain, state->Gain[1]);
+ ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[1]);
- phase = Slot->EffectProps.Flanger.Phase;
- rate = Slot->EffectProps.Flanger.Rate;
+ phase = Slot->Params.EffectProps.Flanger.Phase;
+ rate = Slot->Params.EffectProps.Flanger.Rate;
if(!(rate > 0.0f))
{
state->lfo_scale = 0.0f;
diff --git a/Alc/effects/modulator.c b/Alc/effects/modulator.c
index fb75043a..5a96bb9d 100644
--- a/Alc/effects/modulator.c
+++ b/Alc/effects/modulator.c
@@ -82,8 +82,9 @@ DECL_TEMPLATE(Square)
#undef DECL_TEMPLATE
-static ALvoid ALmodulatorState_Destruct(ALmodulatorState *UNUSED(state))
+static ALvoid ALmodulatorState_Destruct(ALmodulatorState *state)
{
+ ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
}
static ALboolean ALmodulatorState_deviceUpdate(ALmodulatorState *UNUSED(state), ALCdevice *UNUSED(device))
@@ -97,19 +98,19 @@ static ALvoid ALmodulatorState_update(ALmodulatorState *state, const ALCdevice *
ALfloat cw, a;
ALuint i;
- if(Slot->EffectProps.Modulator.Waveform == AL_RING_MODULATOR_SINUSOID)
+ if(Slot->Params.EffectProps.Modulator.Waveform == AL_RING_MODULATOR_SINUSOID)
state->Process = ModulateSin;
- else if(Slot->EffectProps.Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH)
+ else if(Slot->Params.EffectProps.Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH)
state->Process = ModulateSaw;
- else /*if(Slot->EffectProps.Modulator.Waveform == AL_RING_MODULATOR_SQUARE)*/
+ else /*if(Slot->Params.EffectProps.Modulator.Waveform == AL_RING_MODULATOR_SQUARE)*/
state->Process = ModulateSquare;
- state->step = fastf2u(Slot->EffectProps.Modulator.Frequency*WAVEFORM_FRACONE /
+ state->step = fastf2u(Slot->Params.EffectProps.Modulator.Frequency*WAVEFORM_FRACONE /
Device->Frequency);
if(state->step == 0) state->step = 1;
/* Custom filter coeffs, which match the old version instead of a low-shelf. */
- cw = cosf(F_TAU * Slot->EffectProps.Modulator.HighPassCutoff / Device->Frequency);
+ cw = cosf(F_TAU * Slot->Params.EffectProps.Modulator.HighPassCutoff / Device->Frequency);
a = (2.0f-cw) - sqrtf(powf(2.0f-cw, 2.0f) - 1.0f);
for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
@@ -132,7 +133,7 @@ static ALvoid ALmodulatorState_update(ALmodulatorState *state, const ALCdevice *
STATIC_CAST(ALeffectState,state)->OutBuffer = Device->FOAOut.Buffer;
STATIC_CAST(ALeffectState,state)->OutChannels = Device->FOAOut.NumChannels;
for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
- ComputeFirstOrderGains(Device->FOAOut, matrix.m[i], Slot->Gain,
+ ComputeFirstOrderGains(Device->FOAOut, matrix.m[i], Slot->Params.Gain,
state->Gain[i]);
}
diff --git a/Alc/effects/null.c b/Alc/effects/null.c
index 0600703d..b90f75c9 100644
--- a/Alc/effects/null.c
+++ b/Alc/effects/null.c
@@ -15,10 +15,12 @@ typedef struct ALnullState {
/* This destructs (not free!) the effect state. It's called only when the
- * effect slot is no longer used.
+ * effect slot is no longer used. Make sure to call the parent Destruct
+ * function before returning!
*/
-static ALvoid ALnullState_Destruct(ALnullState* UNUSED(state))
+static ALvoid ALnullState_Destruct(ALnullState *state)
{
+ ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
}
/* This updates the device-dependant effect state. This is called on
diff --git a/Alc/effects/reverb.c b/Alc/effects/reverb.c
index ef3ab6c3..bd5637e9 100644
--- a/Alc/effects/reverb.c
+++ b/Alc/effects/reverb.c
@@ -169,6 +169,7 @@ static ALvoid ALreverbState_Destruct(ALreverbState *State)
{
free(State->SampleBuffer);
State->SampleBuffer = NULL;
+ ALeffectState_Destruct(STATIC_CAST(ALeffectState,State));
}
static ALboolean ALreverbState_deviceUpdate(ALreverbState *State, ALCdevice *Device);
@@ -894,15 +895,15 @@ static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *Reflection
static ALvoid ALreverbState_update(ALreverbState *State, const ALCdevice *Device, const ALeffectslot *Slot)
{
- const ALeffectProps *props = &Slot->EffectProps;
+ const ALeffectProps *props = &Slot->Params.EffectProps;
ALuint frequency = Device->Frequency;
ALfloat lfscale, hfscale, hfRatio;
ALfloat gain, gainlf, gainhf;
ALfloat cw, x, y;
- if(Slot->EffectType == AL_EFFECT_EAXREVERB && !EmulateEAXReverb)
+ if(Slot->Params.EffectType == AL_EFFECT_EAXREVERB && !EmulateEAXReverb)
State->IsEax = AL_TRUE;
- else if(Slot->EffectType == AL_EFFECT_REVERB || EmulateEAXReverb)
+ else if(Slot->Params.EffectType == AL_EFFECT_REVERB || EmulateEAXReverb)
State->IsEax = AL_FALSE;
// Calculate the master filters
@@ -952,7 +953,7 @@ static ALvoid ALreverbState_update(ALreverbState *State, const ALCdevice *Device
props->Reverb.Diffusion, props->Reverb.EchoDepth,
hfRatio, cw, frequency, State);
- gain = props->Reverb.Gain * Slot->Gain * ReverbBoost;
+ gain = props->Reverb.Gain * Slot->Params.Gain * ReverbBoost;
// Update early and late 3D panning.
if(Device->Hrtf || Device->Uhj_Encoder)
UpdateMixedPanning(Device, props->Reverb.ReflectionsPan,
diff --git a/OpenAL32/Include/alAuxEffectSlot.h b/OpenAL32/Include/alAuxEffectSlot.h
index e521ff82..7f670a95 100644
--- a/OpenAL32/Include/alAuxEffectSlot.h
+++ b/OpenAL32/Include/alAuxEffectSlot.h
@@ -20,6 +20,8 @@ typedef struct ALeffectState {
ALuint OutChannels;
} ALeffectState;
+void ALeffectState_Destruct(ALeffectState *state);
+
struct ALeffectStateVtable {
void (*const Destruct)(ALeffectState *state);
@@ -70,18 +72,48 @@ static const struct ALeffectStateFactoryVtable T##_ALeffectStateFactory_vtable =
#define MAX_EFFECT_CHANNELS (4)
-typedef struct ALeffectslot {
- ALenum EffectType;
- ALeffectProps EffectProps;
+struct ALeffectslotProps {
+ ATOMIC(ALfloat) Gain;
+ ATOMIC(ALboolean) AuxSendAuto;
+
+ ATOMIC(ALenum) Type;
+ ALeffectProps Props;
+
+ ATOMIC(ALeffectState*) State;
+
+ ATOMIC(struct ALeffectslotProps*) next;
+};
+
+typedef struct ALeffectslot {
volatile ALfloat Gain;
volatile ALboolean AuxSendAuto;
- ATOMIC(ALenum) NeedsUpdate;
- ALeffectState *EffectState;
+ struct {
+ ALenum Type;
+ ALeffectProps Props;
+
+ ALeffectState *State;
+ } Effect;
RefCount ref;
+ ATOMIC(struct ALeffectslotProps*) Update;
+ ATOMIC(struct ALeffectslotProps*) FreeList;
+
+ struct {
+ ALfloat Gain;
+ ALboolean AuxSendAuto;
+
+ ALenum EffectType;
+ ALeffectProps EffectProps;
+ ALeffectState *EffectState;
+
+ ALfloat RoomRolloff; /* Added to the source's room rolloff, not multiplied. */
+ ALfloat DecayTime;
+ ALfloat AirAbsorptionGainHF;
+ } Params;
+
/* Self ID */
ALuint id;
@@ -106,6 +138,8 @@ inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id)
{ return (struct ALeffectslot*)RemoveUIntMapKey(&context->EffectSlotMap, id); }
ALenum InitEffectSlot(ALeffectslot *slot);
+void DeinitEffectSlot(ALeffectslot *slot);
+void UpdateEffectSlotProps(ALeffectslot *slot);
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context);
diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c
index 7f570ef8..1407e1b1 100644
--- a/OpenAL32/alAuxEffectSlot.c
+++ b/OpenAL32/alAuxEffectSlot.c
@@ -86,7 +86,7 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
if(err != AL_NO_ERROR)
{
FreeThunkEntry(slot->id);
- DELETE_OBJ(slot->EffectState);
+ DELETE_OBJ(slot->Params.EffectState);
al_free(slot);
alDeleteAuxiliaryEffectSlots(cur, effectslots);
@@ -139,7 +139,7 @@ AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *
FreeThunkEntry(slot->id);
RemoveEffectSlotArray(context, slot);
- DELETE_OBJ(slot->EffectState);
+ DeinitEffectSlot(slot);
memset(slot, 0, sizeof(*slot));
al_free(slot);
@@ -175,12 +175,13 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param
context = GetContextRef();
if(!context) return;
- device = context->Device;
+ WriteLock(&context->PropLock);
if((slot=LookupEffectSlot(context, effectslot)) == NULL)
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
switch(param)
{
case AL_EFFECTSLOT_EFFECT:
+ device = context->Device;
effect = (value ? LookupEffect(device, value) : NULL);
if(!(value == 0 || effect != NULL))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
@@ -193,19 +194,16 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
if(!(value == AL_TRUE || value == AL_FALSE))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
slot->AuxSendAuto = value;
break;
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
- /* HACK: Force sources to update by doing a listener update */
- ReadLock(&context->PropLock);
- UpdateListenerProps(context);
- ReadUnlock(&context->PropLock);
+ UpdateEffectSlotProps(slot);
done:
+ WriteUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
@@ -244,6 +242,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param
context = GetContextRef();
if(!context) return;
+ WriteLock(&context->PropLock);
if((slot=LookupEffectSlot(context, effectslot)) == NULL)
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
switch(param)
@@ -251,16 +250,16 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param
case AL_EFFECTSLOT_GAIN:
if(!(value >= 0.0f && value <= 1.0f))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
slot->Gain = value;
- ATOMIC_STORE(&slot->NeedsUpdate, AL_TRUE);
break;
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
+ UpdateEffectSlotProps(slot);
done:
+ WriteUnlock(&context->PropLock);
ALCcontext_DecRef(context);
}
@@ -451,7 +450,7 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
ALeffectStateFactory *factory;
- if(newtype != EffectSlot->EffectType)
+ if(newtype != EffectSlot->Effect.Type)
{
ALeffectState *State;
FPUCtl oldMode;
@@ -467,7 +466,9 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
return AL_OUT_OF_MEMORY;
SetMixerFPUMode(&oldMode);
-
+ /* FIXME: This just needs to prevent the device from being reset during
+ * the state's device update, so the list lock in ALc.c should do here.
+ */
ALCdevice_Lock(Device);
State->OutBuffer = Device->Dry.Buffer;
State->OutChannels = Device->Dry.NumChannels;
@@ -478,70 +479,135 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
DELETE_OBJ(State);
return AL_OUT_OF_MEMORY;
}
-
- State = ExchangePtr((XchgPtr*)&EffectSlot->EffectState, State);
- if(!effect)
- {
- memset(&EffectSlot->EffectProps, 0, sizeof(EffectSlot->EffectProps));
- EffectSlot->EffectType = AL_EFFECT_NULL;
- }
- else
- {
- memcpy(&EffectSlot->EffectProps, &effect->Props, sizeof(effect->Props));
- EffectSlot->EffectType = effect->type;
- }
-
- /* FIXME: This should be done asynchronously, but since the EffectState
- * object was changed, it needs an update before its Process method can
- * be called. */
- ATOMIC_STORE(&EffectSlot->NeedsUpdate, AL_FALSE);
- V(EffectSlot->EffectState,update)(Device, EffectSlot);
ALCdevice_Unlock(Device);
-
RestoreFPUMode(&oldMode);
- DELETE_OBJ(State);
- State = NULL;
+ EffectSlot->Effect.State = State;
+ }
+
+ if(!effect)
+ {
+ EffectSlot->Effect.Type = AL_EFFECT_NULL;
+ memset(&EffectSlot->Effect.Props, 0, sizeof(EffectSlot->Effect.Props));
}
else
{
- if(effect)
- {
- ALCdevice_Lock(Device);
- memcpy(&EffectSlot->EffectProps, &effect->Props, sizeof(effect->Props));
- ALCdevice_Unlock(Device);
- ATOMIC_STORE(&EffectSlot->NeedsUpdate, AL_TRUE);
- }
+ EffectSlot->Effect.Type = effect->type;
+ memcpy(&EffectSlot->Effect.Props, &effect->Props, sizeof(EffectSlot->Effect.Props));
}
return AL_NO_ERROR;
}
+void ALeffectState_Destruct(ALeffectState *UNUSED(state))
+{
+}
+
+
ALenum InitEffectSlot(ALeffectslot *slot)
{
ALeffectStateFactory *factory;
- ALuint i, c;
- slot->EffectType = AL_EFFECT_NULL;
+ slot->Effect.Type = AL_EFFECT_NULL;
factory = getFactoryByType(AL_EFFECT_NULL);
- if(!(slot->EffectState=V0(factory,create)()))
+ if(!(slot->Effect.State=V0(factory,create)()))
return AL_OUT_OF_MEMORY;
slot->Gain = 1.0;
slot->AuxSendAuto = AL_TRUE;
- ATOMIC_INIT(&slot->NeedsUpdate, AL_FALSE);
- for(c = 0;c < 1;c++)
- {
- for(i = 0;i < BUFFERSIZE;i++)
- slot->WetBuffer[c][i] = 0.0f;
- }
InitRef(&slot->ref, 0);
+ ATOMIC_INIT(&slot->Update, NULL);
+ ATOMIC_INIT(&slot->FreeList, NULL);
+
+ slot->Params.Gain = 1.0f;
+ slot->Params.AuxSendAuto = AL_TRUE;
+ slot->Params.EffectState = slot->Effect.State;
+ slot->Params.RoomRolloff = 0.0f;
+ slot->Params.DecayTime = 0.0f;
+ slot->Params.AirAbsorptionGainHF = 1.0f;
+
return AL_NO_ERROR;
}
+void DeinitEffectSlot(ALeffectslot *slot)
+{
+ struct ALeffectslotProps *props;
+ size_t count = 0;
+
+ props = ATOMIC_LOAD(&slot->Update);
+ if(props)
+ {
+ DELETE_OBJ(props->State);
+ TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", props);
+ al_free(props);
+ }
+ props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed);
+ while(props)
+ {
+ struct ALeffectslotProps *next;
+ next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
+ DELETE_OBJ(props->State);
+ al_free(props);
+ props = next;
+ ++count;
+ }
+ TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
+
+ DELETE_OBJ(slot->Params.EffectState);
+}
+
+void UpdateEffectSlotProps(ALeffectslot *slot)
+{
+ struct ALeffectslotProps *props;
+ ALeffectState *oldstate;
+
+ /* Get an unused property container, or allocate a new one as needed. */
+ props = ATOMIC_LOAD(&slot->FreeList, almemory_order_acquire);
+ if(!props)
+ props = al_calloc(16, sizeof(*props));
+ else
+ {
+ struct ALeffectslotProps *next;
+ do {
+ next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
+ } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*,
+ &slot->FreeList, &props, next, almemory_order_seq_cst,
+ almemory_order_consume) == 0);
+ }
+
+ /* Copy in current property values. */
+ ATOMIC_STORE(&props->Gain, slot->Gain, almemory_order_relaxed);
+ ATOMIC_STORE(&props->AuxSendAuto, slot->AuxSendAuto, almemory_order_relaxed);
+
+ ATOMIC_STORE(&props->Type, slot->Effect.Type, almemory_order_relaxed);
+ memcpy(&props->Props, &slot->Effect.Props, sizeof(props->Props));
+ /* Swap out any stale effect state object there may be in the container, to
+ * delete it.
+ */
+ oldstate = ATOMIC_EXCHANGE(ALeffectState*, &props->State, slot->Effect.State,
+ almemory_order_relaxed);
+
+ /* Set the new container for updating internal parameters. */
+ props = ATOMIC_EXCHANGE(struct ALeffectslotProps*, &slot->Update, props,
+ almemory_order_acq_rel);
+ if(props)
+ {
+ /* If there was an unused update container, put it back in the
+ * freelist.
+ */
+ struct ALeffectslotProps *first = ATOMIC_LOAD(&slot->FreeList);
+ do {
+ ATOMIC_STORE(&props->next, first, almemory_order_relaxed);
+ } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*,
+ &slot->FreeList, &first, props) == 0);
+ }
+
+ DELETE_OBJ(oldstate);
+}
+
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
{
ALsizei pos;
@@ -550,7 +616,7 @@ ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
ALeffectslot *temp = Context->EffectSlotMap.array[pos].value;
Context->EffectSlotMap.array[pos].value = NULL;
- DELETE_OBJ(temp->EffectState);
+ DeinitEffectSlot(temp);
FreeThunkEntry(temp->id);
memset(temp, 0, sizeof(ALeffectslot));