aboutsummaryrefslogtreecommitdiffstats
path: root/al/effect.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'al/effect.cpp')
-rw-r--r--al/effect.cpp288
1 files changed, 161 insertions, 127 deletions
diff --git a/al/effect.cpp b/al/effect.cpp
index 3e48e91b..071b32c6 100644
--- a/al/effect.cpp
+++ b/al/effect.cpp
@@ -58,7 +58,7 @@
#include "eax/exception.h"
#endif // ALSOFT_EAX
-const EffectList gEffectList[16]{
+const std::array<EffectList,16> gEffectList{{
{ "eaxreverb", EAXREVERB_EFFECT, AL_EFFECT_EAXREVERB },
{ "reverb", REVERB_EFFECT, AL_EFFECT_REVERB },
{ "autowah", AUTOWAH_EFFECT, AL_EFFECT_AUTOWAH },
@@ -75,9 +75,7 @@ const EffectList gEffectList[16]{
{ "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT },
{ "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_DIALOGUE },
{ "convolution", CONVOLUTION_EFFECT, AL_EFFECT_CONVOLUTION_SOFT },
-};
-
-bool DisabledEffects[MAX_EFFECTS];
+}};
effect_exception::effect_exception(ALenum code, const char *msg, ...) : mErrorCode{code}
@@ -91,72 +89,36 @@ effect_exception::~effect_exception() = default;
namespace {
-struct EffectPropsItem {
- ALenum Type;
- const EffectProps &DefaultProps;
- const EffectVtable &Vtable;
-};
-constexpr EffectPropsItem EffectPropsList[] = {
- { AL_EFFECT_NULL, NullEffectProps, NullEffectVtable },
- { AL_EFFECT_EAXREVERB, ReverbEffectProps, ReverbEffectVtable },
- { AL_EFFECT_REVERB, StdReverbEffectProps, StdReverbEffectVtable },
- { AL_EFFECT_AUTOWAH, AutowahEffectProps, AutowahEffectVtable },
- { AL_EFFECT_CHORUS, ChorusEffectProps, ChorusEffectVtable },
- { AL_EFFECT_COMPRESSOR, CompressorEffectProps, CompressorEffectVtable },
- { AL_EFFECT_DISTORTION, DistortionEffectProps, DistortionEffectVtable },
- { AL_EFFECT_ECHO, EchoEffectProps, EchoEffectVtable },
- { AL_EFFECT_EQUALIZER, EqualizerEffectProps, EqualizerEffectVtable },
- { AL_EFFECT_FLANGER, FlangerEffectProps, FlangerEffectVtable },
- { AL_EFFECT_FREQUENCY_SHIFTER, FshifterEffectProps, FshifterEffectVtable },
- { AL_EFFECT_RING_MODULATOR, ModulatorEffectProps, ModulatorEffectVtable },
- { AL_EFFECT_PITCH_SHIFTER, PshifterEffectProps, PshifterEffectVtable },
- { AL_EFFECT_VOCAL_MORPHER, VmorpherEffectProps, VmorpherEffectVtable },
- { AL_EFFECT_DEDICATED_DIALOGUE, DedicatedEffectProps, DedicatedEffectVtable },
- { AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, DedicatedEffectProps, DedicatedEffectVtable },
- { AL_EFFECT_CONVOLUTION_SOFT, ConvolutionEffectProps, ConvolutionEffectVtable },
-};
-
-
-void ALeffect_setParami(ALeffect *effect, ALenum param, int value)
-{ effect->vtab->setParami(&effect->Props, param, value); }
-void ALeffect_setParamiv(ALeffect *effect, ALenum param, const int *values)
-{ effect->vtab->setParamiv(&effect->Props, param, values); }
-void ALeffect_setParamf(ALeffect *effect, ALenum param, float value)
-{ effect->vtab->setParamf(&effect->Props, param, value); }
-void ALeffect_setParamfv(ALeffect *effect, ALenum param, const float *values)
-{ effect->vtab->setParamfv(&effect->Props, param, values); }
+using SubListAllocator = typename al::allocator<std::array<ALeffect,64>>;
-void ALeffect_getParami(const ALeffect *effect, ALenum param, int *value)
-{ effect->vtab->getParami(&effect->Props, param, value); }
-void ALeffect_getParamiv(const ALeffect *effect, ALenum param, int *values)
-{ effect->vtab->getParamiv(&effect->Props, param, values); }
-void ALeffect_getParamf(const ALeffect *effect, ALenum param, float *value)
-{ effect->vtab->getParamf(&effect->Props, param, value); }
-void ALeffect_getParamfv(const ALeffect *effect, ALenum param, float *values)
-{ effect->vtab->getParamfv(&effect->Props, param, values); }
-
-
-const EffectPropsItem *getEffectPropsItemByType(ALenum type)
+auto GetDefaultProps(ALenum type) -> const EffectProps&
{
- auto iter = std::find_if(std::begin(EffectPropsList), std::end(EffectPropsList),
- [type](const EffectPropsItem &item) noexcept -> bool
- { return item.Type == type; });
- return (iter != std::end(EffectPropsList)) ? al::to_address(iter) : nullptr;
+ switch(type)
+ {
+ case AL_EFFECT_NULL: return NullEffectProps;
+ case AL_EFFECT_EAXREVERB: return ReverbEffectProps;
+ case AL_EFFECT_REVERB: return StdReverbEffectProps;
+ case AL_EFFECT_AUTOWAH: return AutowahEffectProps;
+ case AL_EFFECT_CHORUS: return ChorusEffectProps;
+ case AL_EFFECT_COMPRESSOR: return CompressorEffectProps;
+ case AL_EFFECT_DISTORTION: return DistortionEffectProps;
+ case AL_EFFECT_ECHO: return EchoEffectProps;
+ case AL_EFFECT_EQUALIZER: return EqualizerEffectProps;
+ case AL_EFFECT_FLANGER: return FlangerEffectProps;
+ case AL_EFFECT_FREQUENCY_SHIFTER: return FshifterEffectProps;
+ case AL_EFFECT_RING_MODULATOR: return ModulatorEffectProps;
+ case AL_EFFECT_PITCH_SHIFTER: return PshifterEffectProps;
+ case AL_EFFECT_VOCAL_MORPHER: return VmorpherEffectProps;
+ case AL_EFFECT_DEDICATED_DIALOGUE: return DedicatedDialogEffectProps;
+ case AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT: return DedicatedLfeEffectProps;
+ case AL_EFFECT_CONVOLUTION_SOFT: return ConvolutionEffectProps;
+ }
+ return NullEffectProps;
}
void InitEffectParams(ALeffect *effect, ALenum type)
{
- const EffectPropsItem *item{getEffectPropsItemByType(type)};
- if(item)
- {
- effect->Props = item->DefaultProps;
- effect->vtab = &item->Vtable;
- }
- else
- {
- effect->Props = EffectProps{};
- effect->vtab = &NullEffectVtable;
- }
+ effect->Props = GetDefaultProps(type);
effect->type = type;
}
@@ -166,21 +128,21 @@ bool EnsureEffects(ALCdevice *device, size_t needed)
[](size_t cur, const EffectSubList &sublist) noexcept -> size_t
{ return cur + static_cast<ALuint>(al::popcount(sublist.FreeMask)); })};
- while(needed > count)
- {
- if(device->EffectList.size() >= 1<<25) UNLIKELY
- return false;
-
- device->EffectList.emplace_back();
- auto sublist = device->EffectList.end() - 1;
- sublist->FreeMask = ~0_u64;
- sublist->Effects = static_cast<ALeffect*>(al_calloc(alignof(ALeffect), sizeof(ALeffect)*64));
- if(!sublist->Effects) UNLIKELY
+ try {
+ while(needed > count)
{
- device->EffectList.pop_back();
- return false;
+ if(device->EffectList.size() >= 1<<25) UNLIKELY
+ return false;
+
+ EffectSubList sublist{};
+ sublist.FreeMask = ~0_u64;
+ sublist.Effects = SubListAllocator{}.allocate(1);
+ device->EffectList.emplace_back(std::move(sublist));
+ count += 64;
}
- count += 64;
+ }
+ catch(...) {
+ return false;
}
return true;
}
@@ -194,7 +156,7 @@ ALeffect *AllocEffect(ALCdevice *device)
auto slidx = static_cast<ALuint>(al::countr_zero(sublist->FreeMask));
ASSUME(slidx < 64);
- ALeffect *effect{al::construct_at(sublist->Effects + slidx)};
+ ALeffect *effect{al::construct_at(al::to_address(sublist->Effects->begin() + slidx))};
InitEffectParams(effect, AL_EFFECT_NULL);
/* Add 1 to avoid effect ID 0. */
@@ -228,7 +190,7 @@ inline ALeffect *LookupEffect(ALCdevice *device, ALuint id)
EffectSubList &sublist = device->EffectList[lidx];
if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY
return nullptr;
- return sublist.Effects + slidx;
+ return al::to_address(sublist.Effects->begin() + slidx);
}
} // namespace
@@ -328,7 +290,7 @@ FORCE_ALIGN void AL_APIENTRY alEffectiDirect(ALCcontext *context, ALuint effect,
{
for(const EffectList &effectitem : gEffectList)
{
- if(value == effectitem.val && !DisabledEffects[effectitem.type])
+ if(value == effectitem.val && !DisabledEffects.test(effectitem.type))
{
isOk = true;
break;
@@ -344,7 +306,16 @@ FORCE_ALIGN void AL_APIENTRY alEffectiDirect(ALCcontext *context, ALuint effect,
else try
{
/* Call the appropriate handler */
- ALeffect_setParami(aleffect, param, value);
+ std::visit([aleffect,param,value](auto &arg)
+ {
+ using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
+ if constexpr(std::is_same_v<Type,ReverbProps>)
+ {
+ if(aleffect->type == AL_EFFECT_REVERB)
+ return EffectHandler::StdReverbSetParami(arg, param, value);
+ }
+ return EffectHandler::SetParami(arg, param, value);
+ }, aleffect->Props);
}
catch(effect_exception &e) {
context->setError(e.errorCode(), "%s", e.what());
@@ -371,7 +342,16 @@ FORCE_ALIGN void AL_APIENTRY alEffectivDirect(ALCcontext *context, ALuint effect
else try
{
/* Call the appropriate handler */
- ALeffect_setParamiv(aleffect, param, values);
+ std::visit([aleffect,param,values](auto &arg)
+ {
+ using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
+ if constexpr(std::is_same_v<Type,ReverbProps>)
+ {
+ if(aleffect->type == AL_EFFECT_REVERB)
+ return EffectHandler::StdReverbSetParamiv(arg, param, values);
+ }
+ return EffectHandler::SetParamiv(arg, param, values);
+ }, aleffect->Props);
}
catch(effect_exception &e) {
context->setError(e.errorCode(), "%s", e.what());
@@ -391,7 +371,16 @@ FORCE_ALIGN void AL_APIENTRY alEffectfDirect(ALCcontext *context, ALuint effect,
else try
{
/* Call the appropriate handler */
- ALeffect_setParamf(aleffect, param, value);
+ std::visit([aleffect,param,value](auto &arg)
+ {
+ using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
+ if constexpr(std::is_same_v<Type,ReverbProps>)
+ {
+ if(aleffect->type == AL_EFFECT_REVERB)
+ return EffectHandler::StdReverbSetParamf(arg, param, value);
+ }
+ return EffectHandler::SetParamf(arg, param, value);
+ }, aleffect->Props);
}
catch(effect_exception &e) {
context->setError(e.errorCode(), "%s", e.what());
@@ -411,7 +400,16 @@ FORCE_ALIGN void AL_APIENTRY alEffectfvDirect(ALCcontext *context, ALuint effect
else try
{
/* Call the appropriate handler */
- ALeffect_setParamfv(aleffect, param, values);
+ std::visit([aleffect,param,values](auto &arg)
+ {
+ using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
+ if constexpr(std::is_same_v<Type,ReverbProps>)
+ {
+ if(aleffect->type == AL_EFFECT_REVERB)
+ return EffectHandler::StdReverbSetParamfv(arg, param, values);
+ }
+ return EffectHandler::SetParamfv(arg, param, values);
+ }, aleffect->Props);
}
catch(effect_exception &e) {
context->setError(e.errorCode(), "%s", e.what());
@@ -433,7 +431,16 @@ FORCE_ALIGN void AL_APIENTRY alGetEffectiDirect(ALCcontext *context, ALuint effe
else try
{
/* Call the appropriate handler */
- ALeffect_getParami(aleffect, param, value);
+ std::visit([aleffect,param,value](auto &arg)
+ {
+ using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
+ if constexpr(std::is_same_v<Type,ReverbProps>)
+ {
+ if(aleffect->type == AL_EFFECT_REVERB)
+ return EffectHandler::StdReverbGetParami(arg, param, value);
+ }
+ return EffectHandler::GetParami(arg, param, value);
+ }, aleffect->Props);
}
catch(effect_exception &e) {
context->setError(e.errorCode(), "%s", e.what());
@@ -460,7 +467,16 @@ FORCE_ALIGN void AL_APIENTRY alGetEffectivDirect(ALCcontext *context, ALuint eff
else try
{
/* Call the appropriate handler */
- ALeffect_getParamiv(aleffect, param, values);
+ std::visit([aleffect,param,values](auto &arg)
+ {
+ using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
+ if constexpr(std::is_same_v<Type,ReverbProps>)
+ {
+ if(aleffect->type == AL_EFFECT_REVERB)
+ return EffectHandler::StdReverbGetParamiv(arg, param, values);
+ }
+ return EffectHandler::GetParamiv(arg, param, values);
+ }, aleffect->Props);
}
catch(effect_exception &e) {
context->setError(e.errorCode(), "%s", e.what());
@@ -480,7 +496,16 @@ FORCE_ALIGN void AL_APIENTRY alGetEffectfDirect(ALCcontext *context, ALuint effe
else try
{
/* Call the appropriate handler */
- ALeffect_getParamf(aleffect, param, value);
+ std::visit([aleffect,param,value](auto &arg)
+ {
+ using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
+ if constexpr(std::is_same_v<Type,ReverbProps>)
+ {
+ if(aleffect->type == AL_EFFECT_REVERB)
+ return EffectHandler::StdReverbGetParamf(arg, param, value);
+ }
+ return EffectHandler::GetParamf(arg, param, value);
+ }, aleffect->Props);
}
catch(effect_exception &e) {
context->setError(e.errorCode(), "%s", e.what());
@@ -500,7 +525,16 @@ FORCE_ALIGN void AL_APIENTRY alGetEffectfvDirect(ALCcontext *context, ALuint eff
else try
{
/* Call the appropriate handler */
- ALeffect_getParamfv(aleffect, param, values);
+ std::visit([aleffect,param,values](auto &arg)
+ {
+ using Type = std::remove_cv_t<std::remove_reference_t<decltype(arg)>>;
+ if constexpr(std::is_same_v<Type,ReverbProps>)
+ {
+ if(aleffect->type == AL_EFFECT_REVERB)
+ return EffectHandler::StdReverbGetParamfv(arg, param, values);
+ }
+ return EffectHandler::GetParamfv(arg, param, values);
+ }, aleffect->Props);
}
catch(effect_exception &e) {
context->setError(e.errorCode(), "%s", e.what());
@@ -535,20 +569,21 @@ EffectSubList::~EffectSubList()
while(usemask)
{
const int idx{al::countr_zero(usemask)};
- std::destroy_at(Effects+idx);
+ std::destroy_at(al::to_address(Effects->begin()+idx));
usemask &= ~(1_u64 << idx);
}
FreeMask = ~usemask;
- al_free(Effects);
+ SubListAllocator{}.deallocate(Effects, 1);
Effects = nullptr;
}
-#define DECL(x) { #x, EFX_REVERB_PRESET_##x }
-static const struct {
- const char name[32];
+struct EffectPreset {
+ const char name[32]; /* NOLINT(*-avoid-c-arrays) */
EFXEAXREVERBPROPERTIES props;
-} reverblist[] = {
+};
+#define DECL(x) EffectPreset{#x, EFX_REVERB_PRESET_##x}
+static constexpr std::array reverblist{
DECL(GENERIC),
DECL(PADDEDCELL),
DECL(ROOM),
@@ -687,48 +722,47 @@ void LoadReverbPreset(const char *name, ALeffect *effect)
return;
}
- if(!DisabledEffects[EAXREVERB_EFFECT])
+ if(!DisabledEffects.test(EAXREVERB_EFFECT))
InitEffectParams(effect, AL_EFFECT_EAXREVERB);
- else if(!DisabledEffects[REVERB_EFFECT])
+ else if(!DisabledEffects.test(REVERB_EFFECT))
InitEffectParams(effect, AL_EFFECT_REVERB);
else
InitEffectParams(effect, AL_EFFECT_NULL);
for(const auto &reverbitem : reverblist)
{
- const EFXEAXREVERBPROPERTIES *props;
-
if(al::strcasecmp(name, reverbitem.name) != 0)
continue;
TRACE("Loading reverb '%s'\n", reverbitem.name);
- props = &reverbitem.props;
- effect->Props.Reverb.Density = props->flDensity;
- effect->Props.Reverb.Diffusion = props->flDiffusion;
- effect->Props.Reverb.Gain = props->flGain;
- effect->Props.Reverb.GainHF = props->flGainHF;
- effect->Props.Reverb.GainLF = props->flGainLF;
- effect->Props.Reverb.DecayTime = props->flDecayTime;
- effect->Props.Reverb.DecayHFRatio = props->flDecayHFRatio;
- effect->Props.Reverb.DecayLFRatio = props->flDecayLFRatio;
- effect->Props.Reverb.ReflectionsGain = props->flReflectionsGain;
- effect->Props.Reverb.ReflectionsDelay = props->flReflectionsDelay;
- effect->Props.Reverb.ReflectionsPan[0] = props->flReflectionsPan[0];
- effect->Props.Reverb.ReflectionsPan[1] = props->flReflectionsPan[1];
- effect->Props.Reverb.ReflectionsPan[2] = props->flReflectionsPan[2];
- effect->Props.Reverb.LateReverbGain = props->flLateReverbGain;
- effect->Props.Reverb.LateReverbDelay = props->flLateReverbDelay;
- effect->Props.Reverb.LateReverbPan[0] = props->flLateReverbPan[0];
- effect->Props.Reverb.LateReverbPan[1] = props->flLateReverbPan[1];
- effect->Props.Reverb.LateReverbPan[2] = props->flLateReverbPan[2];
- effect->Props.Reverb.EchoTime = props->flEchoTime;
- effect->Props.Reverb.EchoDepth = props->flEchoDepth;
- effect->Props.Reverb.ModulationTime = props->flModulationTime;
- effect->Props.Reverb.ModulationDepth = props->flModulationDepth;
- effect->Props.Reverb.AirAbsorptionGainHF = props->flAirAbsorptionGainHF;
- effect->Props.Reverb.HFReference = props->flHFReference;
- effect->Props.Reverb.LFReference = props->flLFReference;
- effect->Props.Reverb.RoomRolloffFactor = props->flRoomRolloffFactor;
- effect->Props.Reverb.DecayHFLimit = props->iDecayHFLimit ? AL_TRUE : AL_FALSE;
+ const auto &props = reverbitem.props;
+ auto &dst = std::get<ReverbProps>(effect->Props);
+ dst.Density = props.flDensity;
+ dst.Diffusion = props.flDiffusion;
+ dst.Gain = props.flGain;
+ dst.GainHF = props.flGainHF;
+ dst.GainLF = props.flGainLF;
+ dst.DecayTime = props.flDecayTime;
+ dst.DecayHFRatio = props.flDecayHFRatio;
+ dst.DecayLFRatio = props.flDecayLFRatio;
+ dst.ReflectionsGain = props.flReflectionsGain;
+ dst.ReflectionsDelay = props.flReflectionsDelay;
+ dst.ReflectionsPan[0] = props.flReflectionsPan[0];
+ dst.ReflectionsPan[1] = props.flReflectionsPan[1];
+ dst.ReflectionsPan[2] = props.flReflectionsPan[2];
+ dst.LateReverbGain = props.flLateReverbGain;
+ dst.LateReverbDelay = props.flLateReverbDelay;
+ dst.LateReverbPan[0] = props.flLateReverbPan[0];
+ dst.LateReverbPan[1] = props.flLateReverbPan[1];
+ dst.LateReverbPan[2] = props.flLateReverbPan[2];
+ dst.EchoTime = props.flEchoTime;
+ dst.EchoDepth = props.flEchoDepth;
+ dst.ModulationTime = props.flModulationTime;
+ dst.ModulationDepth = props.flModulationDepth;
+ dst.AirAbsorptionGainHF = props.flAirAbsorptionGainHF;
+ dst.HFReference = props.flHFReference;
+ dst.LFReference = props.flLFReference;
+ dst.RoomRolloffFactor = props.flRoomRolloffFactor;
+ dst.DecayHFLimit = props.iDecayHFLimit ? AL_TRUE : AL_FALSE;
return;
}
@@ -742,7 +776,7 @@ bool IsValidEffectType(ALenum type) noexcept
for(const auto &effect_item : gEffectList)
{
- if(type == effect_item.val && !DisabledEffects[effect_item.type])
+ if(type == effect_item.val && !DisabledEffects.test(effect_item.type))
return true;
}
return false;