Use a separate structure for the active effect slot properties
This commit is contained in:
@@ -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
|
||||
|
||||
+36
-36
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-47
@@ -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)
|
||||
};
|
||||
|
||||
+4
-2
@@ -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);
|
||||
|
||||
+8
-8
@@ -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);
|
||||
|
||||
+5
-4
@@ -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;
|
||||
|
||||
+55
-59
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
+5
-3
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;)
|
||||
{
|
||||
|
||||
@@ -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()};
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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*/)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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};
|
||||
}
|
||||
@@ -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 */
|
||||
+5
-4
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user