diff options
author | Chris Robinson <[email protected]> | 2020-11-02 04:24:36 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2020-11-02 04:24:36 -0800 |
commit | 52d58a40234b8829801f0a587375eca91694c30f (patch) | |
tree | caa8d283de74feeb4f23eab39ea57b3835c3bffc /alc | |
parent | 6e05adf955bdd81c82a1feabb25f6f27d7bc56e0 (diff) |
Store the wet buffers in the context
This is rather ugly, but we need the wet buffers to remain allocated after its
effect slot is deleted, because a voice can still use it for its final fade-out
mix.
Diffstat (limited to 'alc')
-rw-r--r-- | alc/alc.cpp | 34 | ||||
-rw-r--r-- | alc/alcmain.h | 1 | ||||
-rw-r--r-- | alc/alcontext.h | 14 | ||||
-rw-r--r-- | alc/alu.cpp | 2 | ||||
-rw-r--r-- | alc/alu.h | 3 | ||||
-rw-r--r-- | alc/panning.cpp | 27 |
6 files changed, 68 insertions, 13 deletions
diff --git a/alc/alc.cpp b/alc/alc.cpp index c4fdad95..b3da9209 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2100,9 +2100,35 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) FPUCtl mixer_mode{}; for(ALCcontext *context : *device->mContexts.load()) { + std::unique_lock<std::mutex> proplock{context->mPropLock}; + std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock}; + /* HACK: Clear the effect slots' wet buffer references, and clear the wet + * buffer array so they're reallocated (with potentially a new channel + * count) when reinitialized. + */ + if(ALeffectslot *slot{context->mDefaultSlot.get()}) + { + slot->mWetBuffer = nullptr; + slot->Wet.Buffer = {}; + } + for(auto &sublist : context->mEffectSlotList) + { + uint64_t usemask{~sublist.FreeMask}; + while(usemask) + { + const ALsizei idx{CountTrailingZeros(usemask)}; + ALeffectslot *slot{sublist.EffectSlots + idx}; + usemask &= ~(1_u64 << idx); + + slot->mWetBuffer = nullptr; + slot->Wet.Buffer = {}; + } + } + decltype(context->mWetBuffers){}.swap(context->mWetBuffers); + if(ALeffectslot *slot{context->mDefaultSlot.get()}) { - aluInitEffectPanning(slot, device); + aluInitEffectPanning(slot, context); EffectState *state{slot->Effect.State.get()}; state->mOutTarget = device->Dry.Buffer; @@ -2112,8 +2138,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) slot->updateProps(context); } - std::unique_lock<std::mutex> proplock{context->mPropLock}; - std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock}; if(ALeffectslotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)}) std::fill_n(curarray->end(), curarray->size(), nullptr); for(auto &sublist : context->mEffectSlotList) @@ -2125,7 +2149,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) ALeffectslot *slot{sublist.EffectSlots + idx}; usemask &= ~(1_u64 << idx); - aluInitEffectPanning(slot, device); + aluInitEffectPanning(slot, context); EffectState *state{slot->Effect.State.get()}; state->mOutTarget = device->Dry.Buffer; @@ -2439,7 +2463,7 @@ void ALCcontext::init() { mDefaultSlot = std::unique_ptr<ALeffectslot>{new ALeffectslot{}}; if(mDefaultSlot->init() == AL_NO_ERROR) - aluInitEffectPanning(mDefaultSlot.get(), mDevice.get()); + aluInitEffectPanning(mDefaultSlot.get(), this); else { mDefaultSlot = nullptr; diff --git a/alc/alcmain.h b/alc/alcmain.h index 7a6c952f..abeb0201 100644 --- a/alc/alcmain.h +++ b/alc/alcmain.h @@ -148,6 +148,7 @@ public: al::span<DistData,MAX_OUTPUT_CHANNELS> as_span() { return mChannels; } }; + struct BFChannelConfig { float Scale; ALuint Index; diff --git a/alc/alcontext.h b/alc/alcontext.h index 59775849..20e48253 100644 --- a/alc/alcontext.h +++ b/alc/alcontext.h @@ -42,6 +42,17 @@ enum class DistanceModel { }; +struct WetBuffer { + bool mInUse; + al::FlexArray<FloatBufferLine, 16> mBuffer; + + WetBuffer(size_t count) : mBuffer{count} { } + + DEF_FAM_NEWDEL(WetBuffer, mBuffer) +}; +using WetBufferPtr = std::unique_ptr<WetBuffer>; + + struct ALcontextProps { float DopplerFactor; float DopplerVelocity; @@ -178,6 +189,9 @@ 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}; diff --git a/alc/alu.cpp b/alc/alu.cpp index 5bc1f6bf..262986e4 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -1739,7 +1739,7 @@ void ProcessContexts(ALCdevice *device, const ALuint SamplesToDo) /* Clear auxiliary effect slot mixing buffers. */ for(ALeffectslot *slot : auxslots) { - for(auto &buffer : slot->MixBuffer) + for(auto &buffer : slot->Wet.Buffer) buffer.fill(0.0f); } @@ -11,6 +11,7 @@ #include "alcmain.h" #include "alspan.h" +struct ALCcontext; struct ALbufferlistitem; struct ALeffectslot; @@ -73,7 +74,7 @@ void aluInitMixer(void); void aluInitRenderer(ALCdevice *device, int hrtf_id, HrtfRequestMode hrtf_appreq, HrtfRequestMode hrtf_userreq); -void aluInitEffectPanning(ALeffectslot *slot, ALCdevice *device); +void aluInitEffectPanning(ALeffectslot *slot, ALCcontext *context); /** * Calculates ambisonic encoder coefficients using the X, Y, and Z direction diff --git a/alc/panning.cpp b/alc/panning.cpp index 15a05136..ee7f39eb 100644 --- a/alc/panning.cpp +++ b/alc/panning.cpp @@ -40,6 +40,7 @@ #include "al/auxeffectslot.h" #include "alcmain.h" #include "alconfig.h" +#include "alcontext.h" #include "almalloc.h" #include "alnumeric.h" #include "aloptional.h" @@ -1034,19 +1035,33 @@ no_hrtf: } -void aluInitEffectPanning(ALeffectslot *slot, ALCdevice *device) +void aluInitEffectPanning(ALeffectslot *slot, ALCcontext *context) { + ALCdevice *device{context->mDevice.get()}; const size_t count{AmbiChannelsFromOrder(device->mAmbiOrder)}; - slot->MixBuffer.resize(count); - slot->MixBuffer.shrink_to_fit(); + + ALuint idx{0}; + for(auto &wetbuffer : context->mWetBuffers) + { + if(!wetbuffer->mInUse) + break; + ++idx; + } + if(idx == context->mWetBuffers.size()) + { + auto newbuffer = WetBufferPtr{new(FamCount(count)) WetBuffer{count}}; + context->mWetBuffers.emplace_back(std::move(newbuffer)); + } + auto *wetbuffer = context->mWetBuffers[idx].get(); + slot->mWetBuffer = wetbuffer; + wetbuffer->mInUse = true; auto acnmap_end = AmbiIndex::FromACN.begin() + count; auto iter = std::transform(AmbiIndex::FromACN.begin(), acnmap_end, slot->Wet.AmbiMap.begin(), [](const uint8_t &acn) noexcept -> BFChannelConfig - { return BFChannelConfig{1.0f, acn}; } - ); + { return BFChannelConfig{1.0f, acn}; }); std::fill(iter, slot->Wet.AmbiMap.end(), BFChannelConfig{}); - slot->Wet.Buffer = {slot->MixBuffer.data(), slot->MixBuffer.size()}; + slot->Wet.Buffer = {wetbuffer->mBuffer.data(), count}; } |