diff options
Diffstat (limited to 'al/effect.cpp')
-rw-r--r-- | al/effect.cpp | 288 |
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; |