aboutsummaryrefslogtreecommitdiffstats
path: root/alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2020-11-02 04:24:36 -0800
committerChris Robinson <[email protected]>2020-11-02 04:24:36 -0800
commit52d58a40234b8829801f0a587375eca91694c30f (patch)
treecaa8d283de74feeb4f23eab39ea57b3835c3bffc /alc
parent6e05adf955bdd81c82a1feabb25f6f27d7bc56e0 (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.cpp34
-rw-r--r--alc/alcmain.h1
-rw-r--r--alc/alcontext.h14
-rw-r--r--alc/alu.cpp2
-rw-r--r--alc/alu.h3
-rw-r--r--alc/panning.cpp27
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);
}
diff --git a/alc/alu.h b/alc/alu.h
index 37210ce1..f87da792 100644
--- a/alc/alu.h
+++ b/alc/alu.h
@@ -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};
}