diff options
-rw-r--r-- | Alc/ALc.c | 56 | ||||
-rw-r--r-- | Alc/ALu.c | 103 | ||||
-rw-r--r-- | Alc/effects/autowah.c | 13 | ||||
-rw-r--r-- | Alc/effects/chorus.c | 17 | ||||
-rw-r--r-- | Alc/effects/compressor.c | 7 | ||||
-rw-r--r-- | Alc/effects/dedicated.c | 9 | ||||
-rw-r--r-- | Alc/effects/distortion.c | 15 | ||||
-rw-r--r-- | Alc/effects/echo.c | 13 | ||||
-rw-r--r-- | Alc/effects/equalizer.c | 29 | ||||
-rw-r--r-- | Alc/effects/flanger.c | 17 | ||||
-rw-r--r-- | Alc/effects/modulator.c | 15 | ||||
-rw-r--r-- | Alc/effects/null.c | 6 | ||||
-rw-r--r-- | Alc/effects/reverb.c | 9 | ||||
-rw-r--r-- | OpenAL32/Include/alAuxEffectSlot.h | 44 | ||||
-rw-r--r-- | OpenAL32/alAuxEffectSlot.c | 166 |
15 files changed, 332 insertions, 187 deletions
@@ -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); + } } { @@ -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)); |