From c52bf8c401aaf78bbcfa99b33fdaf4838999d547 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 5 Sep 2020 20:48:56 -0700 Subject: Rework effect slot buffer setting Rather than creating an effect-specific buffer that gets passed along as a property, the buffer is set the effect state when the effect state is created, the device is updated, or the buffer is changed. The buffer can only be set while the effect slot isn't playing, so it won't be changed or updated while the mixer is processing the effect state. --- alc/alc.cpp | 10 ++-------- alc/alu.cpp | 18 ------------------ alc/effects/base.h | 12 +----------- alc/effects/convolution.cpp | 29 +++++++++++++---------------- 4 files changed, 16 insertions(+), 53 deletions(-) (limited to 'alc') diff --git a/alc/alc.cpp b/alc/alc.cpp index a8ec407f..8a89e8c2 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2102,10 +2102,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) state->mOutTarget = device->Dry.Buffer; state->deviceUpdate(device); if(ALbuffer *buffer{slot->Buffer}) - { - slot->Effect.Buffer = nullptr; - slot->Effect.Buffer.reset(state->createBuffer(device, buffer->mBuffer)); - } + state->setBuffer(device, &buffer->mBuffer); slot->updateProps(context); } @@ -2128,10 +2125,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) state->mOutTarget = device->Dry.Buffer; state->deviceUpdate(device); if(ALbuffer *buffer{slot->Buffer}) - { - slot->Effect.Buffer = nullptr; - slot->Effect.Buffer.reset(state->createBuffer(device, buffer->mBuffer)); - } + state->setBuffer(device, &buffer->mBuffer); slot->updateProps(context); } } diff --git a/alc/alu.cpp b/alc/alu.cpp index 978f6d62..bda8b08d 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -505,24 +505,6 @@ bool CalcEffectSlotParams(ALeffectslot *slot, ALeffectslot **sorted_slots, ALCco } } - EffectBufferBase *buffer{props->Buffer.release()}; - EffectBufferBase *oldbuffer{slot->Params.mEffectBuffer}; - slot->Params.mEffectBuffer = buffer; - - if(oldbuffer && !oldbuffer->releaseIfNoDelete()) - { - RingBuffer *ring{context->mAsyncEvents.get()}; - auto evt_vec = ring->getWriteVector(); - if LIKELY(evt_vec.first.len > 0) - { - AsyncEvent *evt{::new(evt_vec.first.buf) AsyncEvent{EventType_ReleaseEffectBuffer}}; - evt->u.mEffectBuffer = oldbuffer; - ring->writeAdvance(1); - } - else - props->Buffer.reset(oldbuffer); - } - AtomicReplaceHead(context->mFreeEffectslotProps, props); EffectTarget output; diff --git a/alc/effects/base.h b/alc/effects/base.h index a6b7e98a..db38fc49 100644 --- a/alc/effects/base.h +++ b/alc/effects/base.h @@ -155,10 +155,6 @@ const EffectVtable T##_vtable = { \ } -struct EffectBufferBase : public al::intrusive_ref { - virtual ~EffectBufferBase() = default; -}; - struct EffectTarget { MixParams *Main; RealMixParams *RealOut; @@ -171,13 +167,7 @@ struct EffectState : public al::intrusive_ref { virtual ~EffectState() = default; virtual void deviceUpdate(const ALCdevice *device) = 0; - /* Implementations are currently required to copy the buffer data if they - * wish to hold on to it, as there's no guarantee the buffer won't be - * deleted or altered during a mix. - */ - virtual EffectBufferBase *createBuffer(const ALCdevice* /*device*/, - const BufferStorage& /*buffer*/) - { return nullptr; } + 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 samplesIn, const al::span samplesOut) = 0; }; diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index 1ce3bae2..2ba0bde8 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -97,7 +97,7 @@ using complex_d = std::complex; constexpr size_t ConvolveUpdateSize{1024}; constexpr size_t ConvolveUpdateSamples{ConvolveUpdateSize / 2}; -struct ConvolutionFilter final : public EffectBufferBase { +struct ConvolutionFilter { FmtChannels mChannels{}; AmbiLayout mAmbiLayout{}; AmbiScaling mAmbiScaling{}; @@ -385,13 +385,13 @@ void ConvolutionFilter::process(const size_t samplesToDo, struct ConvolutionState final : public EffectState { - ConvolutionFilter *mFilter{}; + std::unique_ptr mFilter; ConvolutionState() = default; ~ConvolutionState() override = default; void deviceUpdate(const ALCdevice *device) override; - EffectBufferBase *createBuffer(const ALCdevice *device, const BufferStorage &buffer) 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 samplesIn, const al::span samplesOut) override; @@ -402,29 +402,26 @@ void ConvolutionState::deviceUpdate(const ALCdevice* /*device*/) { } -EffectBufferBase *ConvolutionState::createBuffer(const ALCdevice *device, - const BufferStorage &buffer) +void ConvolutionState::setBuffer(const ALCdevice *device, const BufferStorage *buffer) { + mFilter = nullptr; /* An empty buffer doesn't need a convolution filter. */ - if(buffer.mSampleLen < 1) return nullptr; + if(!buffer || buffer->mSampleLen < 1) return; - auto numChannels = ChannelsFromFmt(buffer.mChannels, - minu(buffer.mAmbiOrder, device->mAmbiOrder)); + auto numChannels = ChannelsFromFmt(buffer->mChannels, + minu(buffer->mAmbiOrder, device->mAmbiOrder)); - al::intrusive_ptr filter{new ConvolutionFilter{numChannels}}; - if LIKELY(filter->init(device, buffer)) - return filter.release(); - return nullptr; + mFilter.reset(new ConvolutionFilter{numChannels}); + if(!mFilter->init(device, *buffer)) + mFilter = nullptr; } void ConvolutionState::update(const ALCcontext *context, const ALeffectslot *slot, const EffectProps *props, const EffectTarget target) { - mFilter = static_cast(slot->Params.mEffectBuffer); - if(!mFilter) return; - - mFilter->update(mOutTarget, context, slot, props, target); + if(mFilter) + mFilter->update(mOutTarget, context, slot, props, target); } void ConvolutionState::process(const size_t samplesToDo, -- cgit v1.2.3