diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | al/auxeffectslot.cpp | 72 | ||||
-rw-r--r-- | al/auxeffectslot.h | 49 | ||||
-rw-r--r-- | al/source.cpp | 6 | ||||
-rw-r--r-- | alc/alc.cpp | 16 | ||||
-rw-r--r-- | alc/alcontext.h | 9 | ||||
-rw-r--r-- | alc/alu.cpp | 114 | ||||
-rw-r--r-- | alc/effects/autowah.cpp | 14 | ||||
-rw-r--r-- | alc/effects/base.h | 8 | ||||
-rw-r--r-- | alc/effects/chorus.cpp | 13 | ||||
-rw-r--r-- | alc/effects/compressor.cpp | 14 | ||||
-rw-r--r-- | alc/effects/convolution.cpp | 10 | ||||
-rw-r--r-- | alc/effects/dedicated.cpp | 15 | ||||
-rw-r--r-- | alc/effects/distortion.cpp | 11 | ||||
-rw-r--r-- | alc/effects/echo.cpp | 13 | ||||
-rw-r--r-- | alc/effects/equalizer.cpp | 11 | ||||
-rw-r--r-- | alc/effects/fshifter.cpp | 13 | ||||
-rw-r--r-- | alc/effects/modulator.cpp | 11 | ||||
-rw-r--r-- | alc/effects/null.cpp | 8 | ||||
-rw-r--r-- | alc/effects/pshifter.cpp | 11 | ||||
-rw-r--r-- | alc/effects/reverb.cpp | 11 | ||||
-rw-r--r-- | alc/effects/vmorpher.cpp | 11 | ||||
-rw-r--r-- | alc/effectslot.cpp | 18 | ||||
-rw-r--r-- | alc/effectslot.h | 63 | ||||
-rw-r--r-- | alc/panning.cpp | 9 | ||||
-rw-r--r-- | alc/voice.h | 3 |
26 files changed, 309 insertions, 226 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f811f31f..06dc5f9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -638,6 +638,8 @@ set(ALC_OBJS alc/cpu_caps.cpp alc/cpu_caps.h alc/devformat.h + alc/effectslot.cpp + alc/effectslot.h alc/effects/base.h alc/effects/autowah.cpp alc/effects/chorus.cpp diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index df04f430..8271f988 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -94,16 +94,16 @@ inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) noexcept void AddActiveEffectSlots(const al::span<const ALuint> slotids, ALCcontext *context) { if(slotids.empty()) return; - ALeffectslotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_acquire)}; + EffectSlotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_acquire)}; size_t newcount{curarray->size() + slotids.size()}; /* Insert the new effect slots into the head of the array, followed by the * existing ones. */ - ALeffectslotArray *newarray = ALeffectslot::CreatePtrArray(newcount); + EffectSlotArray *newarray = EffectSlot::CreatePtrArray(newcount); auto slotiter = std::transform(slotids.begin(), slotids.end(), newarray->begin(), - [context](ALuint id) noexcept -> ALeffectslot* - { return LookupEffectSlot(context, id); }); + [context](ALuint id) noexcept -> EffectSlot* + { return &LookupEffectSlot(context, id)->mSlot; }); std::copy(curarray->begin(), curarray->end(), slotiter); /* Remove any duplicates (first instance of each will be kept). */ @@ -122,7 +122,7 @@ void AddActiveEffectSlots(const al::span<const ALuint> slotids, ALCcontext *cont if UNLIKELY(newcount < newarray->size()) { curarray = newarray; - newarray = ALeffectslot::CreatePtrArray(newcount); + newarray = EffectSlot::CreatePtrArray(newcount); std::copy_n(curarray->begin(), newcount, newarray->begin()); delete curarray; curarray = nullptr; @@ -139,24 +139,31 @@ void AddActiveEffectSlots(const al::span<const ALuint> slotids, ALCcontext *cont void RemoveActiveEffectSlots(const al::span<const ALuint> slotids, ALCcontext *context) { if(slotids.empty()) return; - ALeffectslotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_acquire)}; + EffectSlotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_acquire)}; /* Don't shrink the allocated array size since we don't know how many (if * any) of the effect slots to remove are in the array. */ - ALeffectslotArray *newarray = ALeffectslot::CreatePtrArray(curarray->size()); + EffectSlotArray *newarray = EffectSlot::CreatePtrArray(curarray->size()); - /* Copy each element in curarray to newarray whose ID is not in slotids. */ - auto slotiter = std::copy_if(curarray->begin(), curarray->end(), newarray->begin(), - [slotids](const ALeffectslot *slot) -> bool - { return std::find(slotids.begin(), slotids.end(), slot->id) == slotids.end(); }); + auto new_end = std::copy(curarray->begin(), curarray->end(), newarray->begin()); + /* Remove elements from newarray that match any ID in slotids. */ + for(const ALuint id : slotids) + { + if(ALeffectslot *auxslot{LookupEffectSlot(context, id)}) + { + auto proc_match = [auxslot](EffectSlot *slot) noexcept -> bool + { return (slot == &auxslot->mSlot); }; + new_end = std::remove_if(newarray->begin(), new_end, proc_match); + } + } /* Reallocate with the new size. */ - auto newsize = static_cast<size_t>(std::distance(newarray->begin(), slotiter)); + auto newsize = static_cast<size_t>(std::distance(newarray->begin(), new_end)); if LIKELY(newsize != newarray->size()) { curarray = newarray; - newarray = ALeffectslot::CreatePtrArray(newsize); + newarray = EffectSlot::CreatePtrArray(newsize); std::copy_n(curarray->begin(), newsize, newarray->begin()); delete curarray; @@ -250,15 +257,6 @@ void FreeEffectSlot(ALCcontext *context, ALeffectslot *slot) } // namespace -ALeffectslotArray *ALeffectslot::CreatePtrArray(size_t count) noexcept -{ - /* Allocate space for twice as many pointers, so the mixer has scratch - * space to store a sorted list during mixing. - */ - void *ptr{al_calloc(alignof(ALeffectslotArray), ALeffectslotArray::Sizeof(count*2))}; - return new (ptr) ALeffectslotArray{count}; -} - AL_API void AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) START_API_FUNC @@ -814,7 +812,7 @@ ALeffectslot::~ALeffectslot() DecrementRef(Buffer->ref); Buffer = nullptr; - ALeffectslotProps *props{Params.Update.load()}; + EffectSlotProps *props{mSlot.Update.exchange(nullptr)}; if(props) { TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", @@ -824,8 +822,8 @@ ALeffectslot::~ALeffectslot() if(mWetBuffer) mWetBuffer->mInUse = false; - if(Params.mEffectState) - Params.mEffectState->release(); + if(mSlot.mEffectState) + mSlot.mEffectState->release(); } ALenum ALeffectslot::init() @@ -837,7 +835,7 @@ ALenum ALeffectslot::init() if(!Effect.State) return AL_OUT_OF_MEMORY; Effect.State->add_ref(); - Params.mEffectState = Effect.State.get(); + mSlot.mEffectState = Effect.State.get(); return AL_NO_ERROR; } @@ -882,7 +880,7 @@ ALenum ALeffectslot::initEffect(ALeffect *effect, ALCcontext *context) Effect.Props = effect->Props; /* Remove state references from old effect slot property updates. */ - ALeffectslotProps *props{context->mFreeEffectslotProps.load()}; + EffectSlotProps *props{context->mFreeEffectslotProps.load()}; while(props) { props->State = nullptr; @@ -895,12 +893,12 @@ ALenum ALeffectslot::initEffect(ALeffect *effect, ALCcontext *context) void ALeffectslot::updateProps(ALCcontext *context) { /* Get an unused property container, or allocate a new one as needed. */ - ALeffectslotProps *props{context->mFreeEffectslotProps.load(std::memory_order_relaxed)}; + EffectSlotProps *props{context->mFreeEffectslotProps.load(std::memory_order_relaxed)}; if(!props) - props = new ALeffectslotProps{}; + props = new EffectSlotProps{}; else { - ALeffectslotProps *next; + EffectSlotProps *next; do { next = props->next.load(std::memory_order_relaxed); } while(context->mFreeEffectslotProps.compare_exchange_weak(props, next, @@ -910,14 +908,14 @@ void ALeffectslot::updateProps(ALCcontext *context) /* Copy in current property values. */ props->Gain = Gain; props->AuxSendAuto = AuxSendAuto; - props->Target = Target; + props->Target = Target ? &Target->mSlot : nullptr; props->Type = Effect.Type; props->Props = Effect.Props; props->State = Effect.State; /* Set the new container for updating internal parameters. */ - props = Params.Update.exchange(props, std::memory_order_acq_rel); + props = mSlot.Update.exchange(props, std::memory_order_acq_rel); if(props) { /* If there was an unused update container, put it back in the @@ -931,11 +929,13 @@ void ALeffectslot::updateProps(ALCcontext *context) void UpdateAllEffectSlotProps(ALCcontext *context) { std::lock_guard<std::mutex> _{context->mEffectSlotLock}; - ALeffectslotArray *auxslots{context->mActiveAuxSlots.load(std::memory_order_acquire)}; - for(ALeffectslot *slot : *auxslots) + EffectSlotArray *slots{context->mActiveAuxSlots.load(std::memory_order_acquire)}; + for(EffectSlot *slot : *slots) { - if(!slot->PropsClean.test_and_set(std::memory_order_acq_rel)) - slot->updateProps(context); + ALeffectslot *auxslot{reinterpret_cast<ALeffectslot*>( + reinterpret_cast<al::byte*>(slot) - offsetof(ALeffectslot,mSlot))}; + if(!auxslot->PropsClean.test_and_set(std::memory_order_acq_rel)) + auxslot->updateProps(context); } } diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 03ba034a..c2967c93 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -11,35 +11,16 @@ #include "alcmain.h" #include "almalloc.h" #include "atomic.h" +#include "effectslot.h" #include "effects/base.h" #include "intrusive_ptr.h" #include "vector.h" struct ALbuffer; struct ALeffect; -struct ALeffectslot; struct WetBuffer; -using ALeffectslotArray = al::FlexArray<ALeffectslot*>; - - -struct ALeffectslotProps { - float Gain; - bool AuxSendAuto; - ALeffectslot *Target; - - ALenum Type; - EffectProps Props; - - al::intrusive_ptr<EffectState> State; - - std::atomic<ALeffectslotProps*> next; - - DEF_NEWDEL(ALeffectslotProps) -}; - - enum class SlotState : ALenum { Initial = AL_INITIAL, Playing = AL_PLAYING, @@ -65,24 +46,7 @@ struct ALeffectslot { RefCount ref{0u}; - struct { - std::atomic<ALeffectslotProps*> Update{nullptr}; - - float Gain{1.0f}; - bool AuxSendAuto{true}; - ALeffectslot *Target{nullptr}; - - ALenum EffectType{AL_EFFECT_NULL}; - EffectProps mEffectProps{}; - EffectState *mEffectState{nullptr}; - - float RoomRolloff{0.0f}; /* Added to the source's room rolloff, not multiplied. */ - float DecayTime{0.0f}; - float DecayLFRatio{0.0f}; - float DecayHFRatio{0.0f}; - bool DecayHFLimit{false}; - float AirAbsorptionGainHF{1.0f}; - } Params; + EffectSlot mSlot; /* Self ID */ ALuint id{}; @@ -90,13 +54,6 @@ struct ALeffectslot { /* Mixing buffer used by the Wet mix. */ WetBuffer *mWetBuffer{nullptr}; - /* Wet buffer configuration is ACN channel order with N3D scaling. - * Consequently, effects that only want to work with mono input can use - * channel 0 by itself. Effects that want multichannel can process the - * ambisonics signal and make a B-Format source pan. - */ - MixParams Wet; - ALeffectslot() { PropsClean.test_and_set(std::memory_order_relaxed); } ALeffectslot(const ALeffectslot&) = delete; ALeffectslot& operator=(const ALeffectslot&) = delete; @@ -106,8 +63,6 @@ struct ALeffectslot { ALenum initEffect(ALeffect *effect, ALCcontext *context); void updateProps(ALCcontext *context); - static ALeffectslotArray *CreatePtrArray(size_t count) noexcept; - /* This can be new'd for the context's default effect slot. */ DEF_NEWDEL(ALeffectslot) }; diff --git a/al/source.cpp b/al/source.cpp index 64a7afc1..d089f24c 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -149,8 +149,8 @@ void UpdateSourceProps(const ALsource *source, Voice *voice, ALCcontext *context auto copy_send = [](const ALsource::SendData &srcsend) noexcept -> VoiceProps::SendData { - VoiceProps::SendData ret; - ret.Slot = srcsend.Slot; + VoiceProps::SendData ret{}; + ret.Slot = srcsend.Slot ? &srcsend.Slot->mSlot : nullptr; ret.Gain = srcsend.Gain; ret.GainHF = srcsend.GainHF; ret.HFReference = srcsend.HFReference; @@ -159,6 +159,8 @@ void UpdateSourceProps(const ALsource *source, Voice *voice, ALCcontext *context return ret; }; std::transform(source->Send.cbegin(), source->Send.cend(), props->Send, copy_send); + if(!props->Send[0].Slot && context->mDefaultSlot) + props->Send[0].Slot = &context->mDefaultSlot->mSlot; /* Set the new container for updating internal parameters. */ props = voice->mUpdate.exchange(props, std::memory_order_acq_rel); diff --git a/alc/alc.cpp b/alc/alc.cpp index c94a9d53..08bb4c2f 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2122,7 +2122,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) slot->updateProps(context); } - if(ALeffectslotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)}) + if(EffectSlotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)}) std::fill_n(curarray->end(), curarray->size(), nullptr); for(auto &sublist : context->mEffectSlotList) { @@ -2366,17 +2366,17 @@ ALCcontext::~ALCcontext() mNumSources = 0; count = 0; - ALeffectslotProps *eprops{mFreeEffectslotProps.exchange(nullptr, std::memory_order_acquire)}; + EffectSlotProps *eprops{mFreeEffectslotProps.exchange(nullptr, std::memory_order_acquire)}; while(eprops) { - ALeffectslotProps *next{eprops->next.load(std::memory_order_relaxed)}; + EffectSlotProps *next{eprops->next.load(std::memory_order_relaxed)}; delete eprops; eprops = next; ++count; } TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s"); - if(ALeffectslotArray *curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)}) + if(EffectSlotArray *curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)}) { al::destroy_n(curarray->end(), curarray->size()); delete curarray; @@ -2455,13 +2455,13 @@ void ALCcontext::init() } } - ALeffectslotArray *auxslots; + EffectSlotArray *auxslots; if(!mDefaultSlot) - auxslots = ALeffectslot::CreatePtrArray(0); + auxslots = EffectSlot::CreatePtrArray(0); else { - auxslots = ALeffectslot::CreatePtrArray(1); - (*auxslots)[0] = mDefaultSlot.get(); + auxslots = EffectSlot::CreatePtrArray(1); + (*auxslots)[0] = &mDefaultSlot->mSlot; mDefaultSlot->mState = SlotState::Playing; } mActiveAuxSlots.store(auxslots, std::memory_order_relaxed); diff --git a/alc/alcontext.h b/alc/alcontext.h index 20e48253..3699b244 100644 --- a/alc/alcontext.h +++ b/alc/alcontext.h @@ -24,8 +24,9 @@ #include "voice.h" struct ALeffectslot; -struct ALeffectslotProps; struct ALsource; +struct EffectSlot; +struct EffectSlotProps; struct RingBuffer; @@ -148,7 +149,7 @@ struct ALCcontext : public al::intrusive_ref<ALCcontext> { std::atomic<ALcontextProps*> mFreeContextProps{nullptr}; std::atomic<ALlistenerProps*> mFreeListenerProps{nullptr}; std::atomic<VoicePropsItem*> mFreeVoiceProps{nullptr}; - std::atomic<ALeffectslotProps*> mFreeEffectslotProps{nullptr}; + std::atomic<EffectSlotProps*> mFreeEffectslotProps{nullptr}; /* Asynchronous voice change actions are processed as a linked list of * VoiceChange objects by the mixer, which is atomically appended to. @@ -192,8 +193,8 @@ struct ALCcontext : public al::intrusive_ref<ALCcontext> { /* Wet buffers used by effect slots. */ al::vector<WetBufferPtr> mWetBuffers; - using ALeffectslotArray = al::FlexArray<ALeffectslot*>; - std::atomic<ALeffectslotArray*> mActiveAuxSlots{nullptr}; + using EffectSlotArray = al::FlexArray<EffectSlot*>; + std::atomic<EffectSlotArray*> mActiveAuxSlots{nullptr}; std::thread mEventThread; al::semaphore mEventSem; diff --git a/alc/alu.cpp b/alc/alu.cpp index 1073a160..8964a515 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -442,43 +442,43 @@ bool CalcListenerParams(ALCcontext *Context) return true; } -bool CalcEffectSlotParams(ALeffectslot *slot, ALeffectslot **sorted_slots, ALCcontext *context) +bool CalcEffectSlotParams(EffectSlot *slot, EffectSlot **sorted_slots, ALCcontext *context) { - ALeffectslotProps *props{slot->Params.Update.exchange(nullptr, std::memory_order_acq_rel)}; + EffectSlotProps *props{slot->Update.exchange(nullptr, std::memory_order_acq_rel)}; if(!props) return false; /* If the effect slot target changed, clear the first sorted entry to force * a re-sort. */ - if(slot->Params.Target != props->Target) + if(slot->Target != props->Target) *sorted_slots = nullptr; - slot->Params.Gain = props->Gain; - slot->Params.AuxSendAuto = props->AuxSendAuto; - slot->Params.Target = props->Target; - slot->Params.EffectType = props->Type; - slot->Params.mEffectProps = props->Props; + slot->Gain = props->Gain; + slot->AuxSendAuto = props->AuxSendAuto; + slot->Target = props->Target; + slot->EffectType = props->Type; + slot->mEffectProps = props->Props; if(IsReverbEffect(props->Type)) { - slot->Params.RoomRolloff = props->Props.Reverb.RoomRolloffFactor; - slot->Params.DecayTime = props->Props.Reverb.DecayTime; - slot->Params.DecayLFRatio = props->Props.Reverb.DecayLFRatio; - slot->Params.DecayHFRatio = props->Props.Reverb.DecayHFRatio; - slot->Params.DecayHFLimit = props->Props.Reverb.DecayHFLimit; - slot->Params.AirAbsorptionGainHF = props->Props.Reverb.AirAbsorptionGainHF; + slot->RoomRolloff = props->Props.Reverb.RoomRolloffFactor; + slot->DecayTime = props->Props.Reverb.DecayTime; + slot->DecayLFRatio = props->Props.Reverb.DecayLFRatio; + slot->DecayHFRatio = props->Props.Reverb.DecayHFRatio; + slot->DecayHFLimit = props->Props.Reverb.DecayHFLimit; + slot->AirAbsorptionGainHF = props->Props.Reverb.AirAbsorptionGainHF; } else { - slot->Params.RoomRolloff = 0.0f; - slot->Params.DecayTime = 0.0f; - slot->Params.DecayLFRatio = 0.0f; - slot->Params.DecayHFRatio = 0.0f; - slot->Params.DecayHFLimit = false; - slot->Params.AirAbsorptionGainHF = 1.0f; + slot->RoomRolloff = 0.0f; + slot->DecayTime = 0.0f; + slot->DecayLFRatio = 0.0f; + slot->DecayHFRatio = 0.0f; + slot->DecayHFLimit = false; + slot->AirAbsorptionGainHF = 1.0f; } EffectState *state{props->State.release()}; - EffectState *oldstate{slot->Params.mEffectState}; - slot->Params.mEffectState = state; + EffectState *oldstate{slot->mEffectState}; + slot->mEffectState = state; /* Only release the old state if it won't get deleted, since we can't be * deleting/freeing anything in the mixer. @@ -508,14 +508,14 @@ bool CalcEffectSlotParams(ALeffectslot *slot, ALeffectslot **sorted_slots, ALCco AtomicReplaceHead(context->mFreeEffectslotProps, props); EffectTarget output; - if(ALeffectslot *target{slot->Params.Target}) + if(EffectSlot *target{slot->Target}) output = EffectTarget{&target->Wet, nullptr}; else { ALCdevice *device{context->mDevice.get()}; output = EffectTarget{&device->Dry, &device->RealOut}; } - state->update(context, slot, &slot->Params.mEffectProps, output); + state->update(context, slot, &slot->mEffectProps, output); return true; } @@ -701,7 +701,7 @@ struct GainTriplet { float Base, HF, LF; }; void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, const float zpos, const float Distance, const float Spread, const GainTriplet &DryGain, - const al::span<const GainTriplet,MAX_SENDS> WetGain, ALeffectslot *(&SendSlots)[MAX_SENDS], + const al::span<const GainTriplet,MAX_SENDS> WetGain, EffectSlot *(&SendSlots)[MAX_SENDS], const VoiceProps *props, const ALlistener &Listener, const ALCdevice *Device) { static const ChanMap MonoMap[1]{ @@ -884,7 +884,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con voice->mChans[0].mDryParams.Gains.Target); for(ALuint i{0};i < NumSends;i++) { - if(const ALeffectslot *Slot{SendSlots[i]}) + if(const EffectSlot *Slot{SendSlots[i]}) ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base*scales[0], voice->mChans[0].mWetParams[i].Gains.Target); } @@ -946,7 +946,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con for(ALuint i{0};i < NumSends;i++) { - if(const ALeffectslot *Slot{SendSlots[i]}) + if(const EffectSlot *Slot{SendSlots[i]}) ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, voice->mChans[c].mWetParams[i].Gains.Target); } @@ -991,7 +991,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con for(ALuint i{0};i < NumSends;i++) { - if(const ALeffectslot *Slot{SendSlots[i]}) + if(const EffectSlot *Slot{SendSlots[i]}) ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, voice->mChans[c].mWetParams[i].Gains.Target); } @@ -1037,7 +1037,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con continue; for(ALuint i{0};i < NumSends;i++) { - if(const ALeffectslot *Slot{SendSlots[i]}) + if(const EffectSlot *Slot{SendSlots[i]}) ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base * downmix_gain, voice->mChans[c].mWetParams[i].Gains.Target); } @@ -1069,7 +1069,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con for(ALuint i{0};i < NumSends;i++) { - if(const ALeffectslot *Slot{SendSlots[i]}) + if(const EffectSlot *Slot{SendSlots[i]}) ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, voice->mChans[c].mWetParams[i].Gains.Target); } @@ -1131,7 +1131,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con voice->mChans[c].mDryParams.Gains.Target); for(ALuint i{0};i < NumSends;i++) { - if(const ALeffectslot *Slot{SendSlots[i]}) + if(const EffectSlot *Slot{SendSlots[i]}) ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base * downmix_gain, voice->mChans[c].mWetParams[i].Gains.Target); } @@ -1173,7 +1173,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con voice->mChans[c].mDryParams.Gains.Target); for(ALuint i{0};i < NumSends;i++) { - if(const ALeffectslot *Slot{SendSlots[i]}) + if(const EffectSlot *Slot{SendSlots[i]}) ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, voice->mChans[c].mWetParams[i].Gains.Target); } @@ -1223,15 +1223,13 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con void CalcNonAttnSourceParams(Voice *voice, const VoiceProps *props, const ALCcontext *ALContext) { const ALCdevice *Device{ALContext->mDevice.get()}; - ALeffectslot *SendSlots[MAX_SENDS]; + EffectSlot *SendSlots[MAX_SENDS]; voice->mDirect.Buffer = Device->Dry.Buffer; for(ALuint i{0};i < Device->NumAuxSends;i++) { SendSlots[i] = props->Send[i].Slot; - if(!SendSlots[i] && i == 0) - SendSlots[i] = ALContext->mDefaultSlot.get(); - if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL) + if(!SendSlots[i] || SendSlots[i]->EffectType == AL_EFFECT_NULL) { SendSlots[i] = nullptr; voice->mSend[i].Buffer = {}; @@ -1277,15 +1275,13 @@ void CalcAttnSourceParams(Voice *voice, const VoiceProps *props, const ALCcontex /* Set mixing buffers and get send parameters. */ voice->mDirect.Buffer = Device->Dry.Buffer; - ALeffectslot *SendSlots[MAX_SENDS]; + EffectSlot *SendSlots[MAX_SENDS]; float RoomRolloff[MAX_SENDS]; GainTriplet DecayDistance[MAX_SENDS]; for(ALuint i{0};i < NumSends;i++) { SendSlots[i] = props->Send[i].Slot; - if(!SendSlots[i] && i == 0) - SendSlots[i] = ALContext->mDefaultSlot.get(); - if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL) + if(!SendSlots[i] || SendSlots[i]->EffectType == AL_EFFECT_NULL) { SendSlots[i] = nullptr; RoomRolloff[i] = 0.0f; @@ -1293,18 +1289,18 @@ void CalcAttnSourceParams(Voice *voice, const VoiceProps *props, const ALCcontex DecayDistance[i].LF = 0.0f; DecayDistance[i].HF = 0.0f; } - else if(SendSlots[i]->Params.AuxSendAuto) + else if(SendSlots[i]->AuxSendAuto) { - RoomRolloff[i] = SendSlots[i]->Params.RoomRolloff + props->RoomRolloffFactor; + RoomRolloff[i] = SendSlots[i]->RoomRolloff + props->RoomRolloffFactor; /* Calculate the distances to where this effect's decay reaches * -60dB. */ - DecayDistance[i].Base = SendSlots[i]->Params.DecayTime * SpeedOfSoundMetersPerSec; - DecayDistance[i].LF = DecayDistance[i].Base * SendSlots[i]->Params.DecayLFRatio; - DecayDistance[i].HF = DecayDistance[i].Base * SendSlots[i]->Params.DecayHFRatio; - if(SendSlots[i]->Params.DecayHFLimit) + DecayDistance[i].Base = SendSlots[i]->DecayTime * SpeedOfSoundMetersPerSec; + DecayDistance[i].LF = DecayDistance[i].Base * SendSlots[i]->DecayLFRatio; + DecayDistance[i].HF = DecayDistance[i].Base * SendSlots[i]->DecayHFRatio; + if(SendSlots[i]->DecayHFLimit) { - const float airAbsorption{SendSlots[i]->Params.AirAbsorptionGainHF}; + const float airAbsorption{SendSlots[i]->AirAbsorptionGainHF}; if(airAbsorption < 1.0f) { /* Calculate the distance to where this effect's air @@ -1700,7 +1696,7 @@ void ProcessVoiceChanges(ALCcontext *ctx) ctx->mCurrentVoiceChange.store(cur, std::memory_order_release); } -void ProcessParamUpdates(ALCcontext *ctx, const ALeffectslotArray &slots, +void ProcessParamUpdates(ALCcontext *ctx, const EffectSlotArray &slots, const al::span<Voice*> voices) { ProcessVoiceChanges(ctx); @@ -1710,8 +1706,8 @@ void ProcessParamUpdates(ALCcontext *ctx, const ALeffectslotArray &slots, { bool force{CalcContextParams(ctx)}; force |= CalcListenerParams(ctx); - auto sorted_slots = const_cast<ALeffectslot**>(slots.data() + slots.size()); - for(ALeffectslot *slot : slots) + auto sorted_slots = const_cast<EffectSlot**>(slots.data() + slots.size()); + for(EffectSlot *slot : slots) force |= CalcEffectSlotParams(slot, sorted_slots, ctx); for(Voice *voice : voices) @@ -1730,14 +1726,14 @@ void ProcessContexts(ALCdevice *device, const ALuint SamplesToDo) for(ALCcontext *ctx : *device->mContexts.load(std::memory_order_acquire)) { - const ALeffectslotArray &auxslots = *ctx->mActiveAuxSlots.load(std::memory_order_acquire); + const EffectSlotArray &auxslots = *ctx->mActiveAuxSlots.load(std::memory_order_acquire); const al::span<Voice*> voices{ctx->getVoicesSpanAcquired()}; /* Process pending propery updates for objects on the context. */ ProcessParamUpdates(ctx, auxslots, voices); /* Clear auxiliary effect slot mixing buffers. */ - for(ALeffectslot *slot : auxslots) + for(EffectSlot *slot : auxslots) { for(auto &buffer : slot->Wet.Buffer) buffer.fill(0.0f); @@ -1760,7 +1756,7 @@ void ProcessContexts(ALCdevice *device, const ALuint SamplesToDo) /* Sort the slots into extra storage, so that effect slots come * before their effect slot target (or their targets' target). */ - const al::span<ALeffectslot*> sorted_slots{const_cast<ALeffectslot**>(slots_end), + const al::span<EffectSlot*> sorted_slots{const_cast<EffectSlot**>(slots_end), num_slots}; /* Skip sorting if it has already been done. */ if(!sorted_slots[0]) @@ -1771,8 +1767,8 @@ void ProcessContexts(ALCdevice *device, const ALuint SamplesToDo) */ std::copy(slots, slots_end, sorted_slots.begin()); auto split_point = std::partition(sorted_slots.begin(), sorted_slots.end(), - [](const ALeffectslot *slot) noexcept -> bool - { return slot->Params.Target != nullptr; }); + [](const EffectSlot *slot) noexcept -> bool + { return slot->Target != nullptr; }); /* There must be at least one slot without a slot target. */ assert(split_point != sorted_slots.end()); @@ -1801,15 +1797,15 @@ void ProcessContexts(ALCdevice *device, const ALuint SamplesToDo) --next_target; split_point = std::partition(sorted_slots.begin(), split_point, - [next_target](const ALeffectslot *slot) noexcept -> bool - { return slot->Params.Target != *next_target; }); + [next_target](const EffectSlot *slot) noexcept -> bool + { return slot->Target != *next_target; }); } while(split_point - sorted_slots.begin() > 1); } } - for(const ALeffectslot *slot : sorted_slots) + for(const EffectSlot *slot : sorted_slots) { - EffectState *state{slot->Params.mEffectState}; + EffectState *state{slot->mEffectState}; state->process(SamplesToDo, slot->Wet.Buffer, state->mOutTarget); } } diff --git a/alc/effects/autowah.cpp b/alc/effects/autowah.cpp index 3ebb1544..423d1b54 100644 --- a/alc/effects/autowah.cpp +++ b/alc/effects/autowah.cpp @@ -70,8 +70,10 @@ struct AutowahState final : public EffectState { void deviceUpdate(const ALCdevice *device) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; DEF_NEWDEL(AutowahState) }; @@ -102,7 +104,8 @@ void AutowahState::deviceUpdate(const ALCdevice*) } } -void AutowahState::update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) +void AutowahState::update(const ALCcontext *context, const EffectSlot *slot, + const EffectProps *props, const EffectTarget target) { const ALCdevice *device{context->mDevice.get()}; const auto frequency = static_cast<float>(device->Frequency); @@ -119,11 +122,12 @@ void AutowahState::update(const ALCcontext *context, const ALeffectslot *slot, c mOutTarget = target.Main->Buffer; auto set_gains = [slot,target](auto &chan, al::span<const float,MAX_AMBI_CHANNELS> coeffs) - { ComputePanGains(target.Main, coeffs.data(), slot->Params.Gain, chan.TargetGains); }; + { ComputePanGains(target.Main, coeffs.data(), slot->Gain, chan.TargetGains); }; SetAmbiPanIdentity(std::begin(mChans), slot->Wet.Buffer.size(), set_gains); } -void AutowahState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) +void AutowahState::process(const size_t samplesToDo, + const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) { const float attack_rate{mAttackRate}; const float release_rate{mReleaseRate}; diff --git a/alc/effects/base.h b/alc/effects/base.h index db38fc49..0efd5599 100644 --- a/alc/effects/base.h +++ b/alc/effects/base.h @@ -10,7 +10,7 @@ #include "atomic.h" #include "intrusive_ptr.h" -struct ALeffectslot; +struct EffectSlot; struct BufferStorage; @@ -168,8 +168,10 @@ struct EffectState : public al::intrusive_ref<EffectState> { virtual void deviceUpdate(const ALCdevice *device) = 0; virtual void setBuffer(const ALCdevice* /*device*/, const BufferStorage* /*buffer*/) { } - virtual void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) = 0; - virtual void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) = 0; + virtual void update(const ALCcontext *context, const EffectSlot *slot, + const EffectProps *props, const EffectTarget target) = 0; + virtual void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) = 0; }; diff --git a/alc/effects/chorus.cpp b/alc/effects/chorus.cpp index 7e68508d..a531c5e1 100644 --- a/alc/effects/chorus.cpp +++ b/alc/effects/chorus.cpp @@ -81,8 +81,10 @@ struct ChorusState final : public EffectState { void getSinusoidDelays(ALuint (*delays)[MAX_UPDATE_SAMPLES], const size_t todo); void deviceUpdate(const ALCdevice *device) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; DEF_NEWDEL(ChorusState) }; @@ -104,7 +106,8 @@ void ChorusState::deviceUpdate(const ALCdevice *Device) } } -void ChorusState::update(const ALCcontext *Context, const ALeffectslot *Slot, const EffectProps *props, const EffectTarget target) +void ChorusState::update(const ALCcontext *Context, const EffectSlot *Slot, + const EffectProps *props, const EffectTarget target) { constexpr ALsizei mindelay{(MAX_RESAMPLER_PADDING>>1) << MixerFracBits}; @@ -135,8 +138,8 @@ void ChorusState::update(const ALCcontext *Context, const ALeffectslot *Slot, co const auto rcoeffs = CalcDirectionCoeffs({ 1.0f, 0.0f, 0.0f}, 0.0f); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, lcoeffs.data(), Slot->Params.Gain, mGains[0].Target); - ComputePanGains(target.Main, rcoeffs.data(), Slot->Params.Gain, mGains[1].Target); + ComputePanGains(target.Main, lcoeffs.data(), Slot->Gain, mGains[0].Target); + ComputePanGains(target.Main, rcoeffs.data(), Slot->Gain, mGains[1].Target); float rate{props->Chorus.Rate}; if(!(rate > 0.0f)) diff --git a/alc/effects/compressor.cpp b/alc/effects/compressor.cpp index e02dec3b..9d92fdc7 100644 --- a/alc/effects/compressor.cpp +++ b/alc/effects/compressor.cpp @@ -50,8 +50,10 @@ struct CompressorState final : public EffectState { void deviceUpdate(const ALCdevice *device) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; DEF_NEWDEL(CompressorState) }; @@ -71,17 +73,19 @@ void CompressorState::deviceUpdate(const ALCdevice *device) mReleaseMult = std::pow(AMP_ENVELOPE_MIN/AMP_ENVELOPE_MAX, 1.0f/releaseCount); } -void CompressorState::update(const ALCcontext*, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) +void CompressorState::update(const ALCcontext*, const EffectSlot *slot, + const EffectProps *props, const EffectTarget target) { mEnabled = props->Compressor.OnOff; mOutTarget = target.Main->Buffer; auto set_gains = [slot,target](auto &gains, al::span<const float,MAX_AMBI_CHANNELS> coeffs) - { ComputePanGains(target.Main, coeffs.data(), slot->Params.Gain, gains); }; + { ComputePanGains(target.Main, coeffs.data(), slot->Gain, gains); }; SetAmbiPanIdentity(std::begin(mGain), slot->Wet.Buffer.size(), set_gains); } -void CompressorState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) +void CompressorState::process(const size_t samplesToDo, + const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) { for(size_t base{0u};base < samplesToDo;) { diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index ffd2f0c7..c4bc41dc 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -177,8 +177,10 @@ struct ConvolutionState final : public EffectState { void deviceUpdate(const ALCdevice *device) override; void setBuffer(const ALCdevice *device, const BufferStorage *buffer) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; DEF_NEWDEL(ConvolutionState) }; @@ -304,7 +306,7 @@ void ConvolutionState::setBuffer(const ALCdevice *device, const BufferStorage *b } -void ConvolutionState::update(const ALCcontext *context, const ALeffectslot *slot, +void ConvolutionState::update(const ALCcontext *context, const EffectSlot *slot, const EffectProps* /*props*/, const EffectTarget target) { /* NOTE: Stereo and Rear are slightly different from normal mixing (as @@ -361,7 +363,7 @@ void ConvolutionState::update(const ALCcontext *context, const ALeffectslot *slo for(auto &chan : *mChans) std::fill(std::begin(chan.Target), std::end(chan.Target), 0.0f); - const float gain{slot->Params.Gain}; + const float gain{slot->Gain}; if(mChannels == FmtBFormat3D || mChannels == FmtBFormat2D) { ALCdevice *device{context->mDevice.get()}; diff --git a/alc/effects/dedicated.cpp b/alc/effects/dedicated.cpp index 2f985412..283d009a 100644 --- a/alc/effects/dedicated.cpp +++ b/alc/effects/dedicated.cpp @@ -38,8 +38,10 @@ struct DedicatedState final : public EffectState { void deviceUpdate(const ALCdevice *device) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; DEF_NEWDEL(DedicatedState) }; @@ -49,13 +51,14 @@ void DedicatedState::deviceUpdate(const ALCdevice*) std::fill(std::begin(mCurrentGains), std::end(mCurrentGains), 0.0f); } -void DedicatedState::update(const ALCcontext*, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) +void DedicatedState::update(const ALCcontext*, const EffectSlot *slot, + const EffectProps *props, const EffectTarget target) { std::fill(std::begin(mTargetGains), std::end(mTargetGains), 0.0f); - const float Gain{slot->Params.Gain * props->Dedicated.Gain}; + const float Gain{slot->Gain * props->Dedicated.Gain}; - if(slot->Params.EffectType == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT) + if(slot->EffectType == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT) { const ALuint idx{!target.RealOut ? INVALID_CHANNEL_INDEX : GetChannelIdxByName(*target.RealOut, LFE)}; @@ -65,7 +68,7 @@ void DedicatedState::update(const ALCcontext*, const ALeffectslot *slot, const E mTargetGains[idx] = Gain; } } - else if(slot->Params.EffectType == AL_EFFECT_DEDICATED_DIALOGUE) + else if(slot->EffectType == AL_EFFECT_DEDICATED_DIALOGUE) { /* Dialog goes to the front-center speaker if it exists, otherwise it * plays from the front-center location. */ diff --git a/alc/effects/distortion.cpp b/alc/effects/distortion.cpp index be787b78..a199952f 100644 --- a/alc/effects/distortion.cpp +++ b/alc/effects/distortion.cpp @@ -47,8 +47,10 @@ struct DistortionState final : public EffectState { void deviceUpdate(const ALCdevice *device) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; DEF_NEWDEL(DistortionState) }; @@ -59,7 +61,8 @@ void DistortionState::deviceUpdate(const ALCdevice*) mBandpass.clear(); } -void DistortionState::update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) +void DistortionState::update(const ALCcontext *context, const EffectSlot *slot, + const EffectProps *props, const EffectTarget target) { const ALCdevice *device{context->mDevice.get()}; @@ -85,7 +88,7 @@ void DistortionState::update(const ALCcontext *context, const ALeffectslot *slot const auto coeffs = CalcDirectionCoeffs({0.0f, 0.0f, -1.0f}, 0.0f); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, coeffs.data(), slot->Params.Gain*props->Distortion.Gain, mGain); + ComputePanGains(target.Main, coeffs.data(), slot->Gain*props->Distortion.Gain, mGain); } void DistortionState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) diff --git a/alc/effects/echo.cpp b/alc/effects/echo.cpp index b53f4f30..93305cdb 100644 --- a/alc/effects/echo.cpp +++ b/alc/effects/echo.cpp @@ -58,8 +58,10 @@ struct EchoState final : public EffectState { alignas(16) float mTempBuffer[2][BUFFERSIZE]; void deviceUpdate(const ALCdevice *device) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; DEF_NEWDEL(EchoState) }; @@ -83,7 +85,8 @@ void EchoState::deviceUpdate(const ALCdevice *Device) } } -void EchoState::update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) +void EchoState::update(const ALCcontext *context, const EffectSlot *slot, + const EffectProps *props, const EffectTarget target) { const ALCdevice *device{context->mDevice.get()}; const auto frequency = static_cast<float>(device->Frequency); @@ -103,8 +106,8 @@ void EchoState::update(const ALCcontext *context, const ALeffectslot *slot, cons const auto coeffs1 = CalcAngleCoeffs( angle, 0.0f, 0.0f); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, coeffs0.data(), slot->Params.Gain, mGains[0].Target); - ComputePanGains(target.Main, coeffs1.data(), slot->Params.Gain, mGains[1].Target); + ComputePanGains(target.Main, coeffs0.data(), slot->Gain, mGains[0].Target); + ComputePanGains(target.Main, coeffs1.data(), slot->Gain, mGains[1].Target); } void EchoState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) diff --git a/alc/effects/equalizer.cpp b/alc/effects/equalizer.cpp index 8f002f8c..2f02182c 100644 --- a/alc/effects/equalizer.cpp +++ b/alc/effects/equalizer.cpp @@ -92,8 +92,10 @@ struct EqualizerState final : public EffectState { void deviceUpdate(const ALCdevice *device) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; DEF_NEWDEL(EqualizerState) }; @@ -107,7 +109,8 @@ void EqualizerState::deviceUpdate(const ALCdevice*) } } -void EqualizerState::update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) +void EqualizerState::update(const ALCcontext *context, const EffectSlot *slot, + const EffectProps *props, const EffectTarget target) { const ALCdevice *device{context->mDevice.get()}; auto frequency = static_cast<float>(device->Frequency); @@ -148,7 +151,7 @@ void EqualizerState::update(const ALCcontext *context, const ALeffectslot *slot, mOutTarget = target.Main->Buffer; auto set_gains = [slot,target](auto &chan, al::span<const float,MAX_AMBI_CHANNELS> coeffs) - { ComputePanGains(target.Main, coeffs.data(), slot->Params.Gain, chan.TargetGains); }; + { ComputePanGains(target.Main, coeffs.data(), slot->Gain, chan.TargetGains); }; SetAmbiPanIdentity(std::begin(mChans), slot->Wet.Buffer.size(), set_gains); } diff --git a/alc/effects/fshifter.cpp b/alc/effects/fshifter.cpp index f3f409e0..3eb4bb79 100644 --- a/alc/effects/fshifter.cpp +++ b/alc/effects/fshifter.cpp @@ -83,8 +83,10 @@ struct FshifterState final : public EffectState { void deviceUpdate(const ALCdevice *device) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; DEF_NEWDEL(FshifterState) }; @@ -109,7 +111,8 @@ void FshifterState::deviceUpdate(const ALCdevice*) } } -void FshifterState::update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) +void FshifterState::update(const ALCcontext *context, const EffectSlot *slot, + const EffectProps *props, const EffectTarget target) { const ALCdevice *device{context->mDevice.get()}; @@ -152,8 +155,8 @@ void FshifterState::update(const ALCcontext *context, const ALeffectslot *slot, const auto rcoeffs = CalcDirectionCoeffs({ 1.0f, 0.0f, 0.0f}, 0.0f); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, lcoeffs.data(), slot->Params.Gain, mGains[0].Target); - ComputePanGains(target.Main, rcoeffs.data(), slot->Params.Gain, mGains[1].Target); + ComputePanGains(target.Main, lcoeffs.data(), slot->Gain, mGains[0].Target); + ComputePanGains(target.Main, rcoeffs.data(), slot->Gain, mGains[1].Target); } void FshifterState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) diff --git a/alc/effects/modulator.cpp b/alc/effects/modulator.cpp index f75e4dc6..cd48f91e 100644 --- a/alc/effects/modulator.cpp +++ b/alc/effects/modulator.cpp @@ -83,8 +83,10 @@ struct ModulatorState final : public EffectState { void deviceUpdate(const ALCdevice *device) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; DEF_NEWDEL(ModulatorState) }; @@ -98,7 +100,8 @@ void ModulatorState::deviceUpdate(const ALCdevice*) } } -void ModulatorState::update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) +void ModulatorState::update(const ALCcontext *context, const EffectSlot *slot, + const EffectProps *props, const EffectTarget target) { const ALCdevice *device{context->mDevice.get()}; @@ -123,7 +126,7 @@ void ModulatorState::update(const ALCcontext *context, const ALeffectslot *slot, mOutTarget = target.Main->Buffer; auto set_gains = [slot,target](auto &chan, al::span<const float,MAX_AMBI_CHANNELS> coeffs) - { ComputePanGains(target.Main, coeffs.data(), slot->Params.Gain, chan.TargetGains); }; + { ComputePanGains(target.Main, coeffs.data(), slot->Gain, chan.TargetGains); }; SetAmbiPanIdentity(std::begin(mChans), slot->Wet.Buffer.size(), set_gains); } diff --git a/alc/effects/null.cpp b/alc/effects/null.cpp index 5bef1827..2f676d4d 100644 --- a/alc/effects/null.cpp +++ b/alc/effects/null.cpp @@ -19,8 +19,10 @@ struct NullState final : public EffectState { ~NullState() override; void deviceUpdate(const ALCdevice *device) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; DEF_NEWDEL(NullState) }; @@ -47,7 +49,7 @@ void NullState::deviceUpdate(const ALCdevice* /*device*/) /* This updates the effect state with new properties. This is called any time * the effect is (re)loaded into a slot. */ -void NullState::update(const ALCcontext* /*context*/, const ALeffectslot* /*slot*/, +void NullState::update(const ALCcontext* /*context*/, const EffectSlot* /*slot*/, const EffectProps* /*props*/, const EffectTarget /*target*/) { } diff --git a/alc/effects/pshifter.cpp b/alc/effects/pshifter.cpp index 44ddc694..4326c929 100644 --- a/alc/effects/pshifter.cpp +++ b/alc/effects/pshifter.cpp @@ -97,8 +97,10 @@ struct PshifterState final : public EffectState { void deviceUpdate(const ALCdevice *device) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; DEF_NEWDEL(PshifterState) }; @@ -123,7 +125,8 @@ void PshifterState::deviceUpdate(const ALCdevice *device) std::fill(std::begin(mTargetGains), std::end(mTargetGains), 0.0f); } -void PshifterState::update(const ALCcontext*, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) +void PshifterState::update(const ALCcontext*, const EffectSlot *slot, + const EffectProps *props, const EffectTarget target) { const int tune{props->Pshifter.CoarseTune*100 + props->Pshifter.FineTune}; const float pitch{std::pow(2.0f, static_cast<float>(tune) / 1200.0f)}; @@ -133,7 +136,7 @@ void PshifterState::update(const ALCcontext*, const ALeffectslot *slot, const Ef const auto coeffs = CalcDirectionCoeffs({0.0f, 0.0f, -1.0f}, 0.0f); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, coeffs.data(), slot->Params.Gain, mTargetGains); + ComputePanGains(target.Main, coeffs.data(), slot->Gain, mTargetGains); } void PshifterState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index 3fa0b271..45464193 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -529,8 +529,10 @@ struct ReverbState final : public EffectState { const float fadeStep); void deviceUpdate(const ALCdevice *device) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; DEF_NEWDEL(ReverbState) }; @@ -984,7 +986,8 @@ void ReverbState::update3DPanning(const float *ReflectionsPan, const float *Late } } -void ReverbState::update(const ALCcontext *Context, const ALeffectslot *Slot, const EffectProps *props, const EffectTarget target) +void ReverbState::update(const ALCcontext *Context, const EffectSlot *Slot, + const EffectProps *props, const EffectTarget target) { const ALCdevice *Device{Context->mDevice.get()}; const auto frequency = static_cast<float>(Device->Frequency); @@ -1036,7 +1039,7 @@ void ReverbState::update(const ALCcontext *Context, const ALeffectslot *Slot, co props->Reverb.DecayTime, hfDecayTime, lf0norm, hf0norm, frequency); /* Update early and late 3D panning. */ - const float gain{props->Reverb.Gain * Slot->Params.Gain * ReverbBoost}; + const float gain{props->Reverb.Gain * Slot->Gain * ReverbBoost}; update3DPanning(props->Reverb.ReflectionsPan, props->Reverb.LateReverbPan, props->Reverb.ReflectionsGain*gain, props->Reverb.LateReverbGain*gain, target); diff --git a/alc/effects/vmorpher.cpp b/alc/effects/vmorpher.cpp index 0ffe23e6..8e945396 100644 --- a/alc/effects/vmorpher.cpp +++ b/alc/effects/vmorpher.cpp @@ -137,8 +137,10 @@ struct VmorpherState final : public EffectState { alignas(16) float mLfo[MAX_UPDATE_SAMPLES]{}; void deviceUpdate(const ALCdevice *device) override; - void update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut) override; + void update(const ALCcontext *context, const EffectSlot *slot, const EffectProps *props, + const EffectTarget target) override; + void process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, + const al::span<FloatBufferLine> samplesOut) override; static std::array<FormantFilter,4> getFiltersByPhoneme(ALenum phoneme, float frequency, float pitch); @@ -206,7 +208,8 @@ void VmorpherState::deviceUpdate(const ALCdevice* /*device*/) } } -void VmorpherState::update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) +void VmorpherState::update(const ALCcontext *context, const EffectSlot *slot, + const EffectProps *props, const EffectTarget target) { const ALCdevice *device{context->mDevice.get()}; const float frequency{static_cast<float>(device->Frequency)}; @@ -239,7 +242,7 @@ void VmorpherState::update(const ALCcontext *context, const ALeffectslot *slot, mOutTarget = target.Main->Buffer; auto set_gains = [slot,target](auto &chan, al::span<const float,MAX_AMBI_CHANNELS> coeffs) - { ComputePanGains(target.Main, coeffs.data(), slot->Params.Gain, chan.TargetGains); }; + { ComputePanGains(target.Main, coeffs.data(), slot->Gain, chan.TargetGains); }; SetAmbiPanIdentity(std::begin(mChans), slot->Wet.Buffer.size(), set_gains); } diff --git a/alc/effectslot.cpp b/alc/effectslot.cpp new file mode 100644 index 00000000..f3324858 --- /dev/null +++ b/alc/effectslot.cpp @@ -0,0 +1,18 @@ + +#include "config.h" + +#include "effectslot.h" + +#include <stddef.h> + +#include "almalloc.h" + + +EffectSlotArray *EffectSlot::CreatePtrArray(size_t count) noexcept +{ + /* Allocate space for twice as many pointers, so the mixer has scratch + * space to store a sorted list during mixing. + */ + void *ptr{al_calloc(alignof(EffectSlotArray), EffectSlotArray::Sizeof(count*2))}; + return new(ptr) EffectSlotArray{count}; +} diff --git a/alc/effectslot.h b/alc/effectslot.h new file mode 100644 index 00000000..2bef5477 --- /dev/null +++ b/alc/effectslot.h @@ -0,0 +1,63 @@ +#ifndef EFFECTSLOT_H +#define EFFECTSLOT_H + +#include <atomic.h> + +#include "almalloc.h" +#include "alcmain.h" +#include "effects/base.h" +#include "intrusive_ptr.h" + + +struct EffectSlot; + +using EffectSlotArray = al::FlexArray<EffectSlot*>; + + +struct EffectSlotProps { + float Gain; + bool AuxSendAuto; + EffectSlot *Target; + + ALenum Type; + EffectProps Props; + + al::intrusive_ptr<EffectState> State; + + std::atomic<EffectSlotProps*> next; + + DEF_NEWDEL(EffectSlotProps) +}; + + +struct EffectSlot { + std::atomic<EffectSlotProps*> Update{nullptr}; + + /* Wet buffer configuration is ACN channel order with N3D scaling. + * Consequently, effects that only want to work with mono input can use + * channel 0 by itself. Effects that want multichannel can process the + * ambisonics signal and make a B-Format source pan. + */ + MixParams Wet; + + float Gain{1.0f}; + bool AuxSendAuto{true}; + EffectSlot *Target{nullptr}; + + ALenum EffectType{}; + EffectProps mEffectProps{}; + EffectState *mEffectState{nullptr}; + + float RoomRolloff{0.0f}; /* Added to the source's room rolloff, not multiplied. */ + float DecayTime{0.0f}; + float DecayLFRatio{0.0f}; + float DecayHFRatio{0.0f}; + bool DecayHFLimit{false}; + float AirAbsorptionGainHF{1.0f}; + + static EffectSlotArray *CreatePtrArray(size_t count) noexcept; + + DISABLE_ALLOC() +}; + +#endif /* EFFECTSLOT_H */ diff --git a/alc/panning.cpp b/alc/panning.cpp index 47d916d4..eadf6f12 100644 --- a/alc/panning.cpp +++ b/alc/panning.cpp @@ -1052,7 +1052,7 @@ void aluInitEffectPanning(ALeffectslot *slot, ALCcontext *context) if(wetbuffer_iter->get() == slot->mWetBuffer) { slot->mWetBuffer = nullptr; - slot->Wet.Buffer = {}; + slot->mSlot.Wet.Buffer = {}; *wetbuffer_iter = WetBufferPtr{new(FamCount(count)) WetBuffer{count}}; @@ -1080,11 +1080,12 @@ void aluInitEffectPanning(ALeffectslot *slot, ALCcontext *context) wetbuffer->mInUse = true; auto acnmap_end = AmbiIndex::FromACN.begin() + count; - auto iter = std::transform(AmbiIndex::FromACN.begin(), acnmap_end, slot->Wet.AmbiMap.begin(), + auto iter = std::transform(AmbiIndex::FromACN.begin(), acnmap_end, + slot->mSlot.Wet.AmbiMap.begin(), [](const uint8_t &acn) noexcept -> BFChannelConfig { return BFChannelConfig{1.0f, acn}; }); - std::fill(iter, slot->Wet.AmbiMap.end(), BFChannelConfig{}); - slot->Wet.Buffer = wetbuffer->mBuffer; + std::fill(iter, slot->mSlot.Wet.AmbiMap.end(), BFChannelConfig{}); + slot->mSlot.Wet.Buffer = wetbuffer->mBuffer; } diff --git a/alc/voice.h b/alc/voice.h index a9774fd3..7822ea39 100644 --- a/alc/voice.h +++ b/alc/voice.h @@ -17,6 +17,7 @@ #include "filters/splitter.h" #include "hrtf.h" +struct EffectSlot; enum class DistanceModel; @@ -160,7 +161,7 @@ struct VoiceProps { float LFReference; } Direct; struct SendData { - ALeffectslot *Slot; + EffectSlot *Slot; float Gain; float GainHF; float HFReference; |