From 32b9a46b39e3bfb3ccf1e05c520ce40232efa5d9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 25 Nov 2020 13:55:29 -0800 Subject: Move AL EffectProp handling to separate sources --- al/effects/distortion.cpp | 114 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 al/effects/distortion.cpp (limited to 'al/effects/distortion.cpp') diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp new file mode 100644 index 00000000..8961a4d9 --- /dev/null +++ b/al/effects/distortion.cpp @@ -0,0 +1,114 @@ + +#include "config.h" + +#include "AL/al.h" +#include "AL/efx.h" + +#include "effects.h" +#include "effects/base.h" + + +namespace { + +void Distortion_setParami(EffectProps*, ALenum param, int) +{ throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer property 0x%04x", param}; } +void Distortion_setParamiv(EffectProps*, ALenum param, const int*) +{ + throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer-vector property 0x%04x", + param}; +} +void Distortion_setParamf(EffectProps *props, ALenum param, float val) +{ + switch(param) + { + case AL_DISTORTION_EDGE: + if(!(val >= AL_DISTORTION_MIN_EDGE && val <= AL_DISTORTION_MAX_EDGE)) + throw effect_exception{AL_INVALID_VALUE, "Distortion edge out of range"}; + props->Distortion.Edge = val; + break; + + case AL_DISTORTION_GAIN: + if(!(val >= AL_DISTORTION_MIN_GAIN && val <= AL_DISTORTION_MAX_GAIN)) + throw effect_exception{AL_INVALID_VALUE, "Distortion gain out of range"}; + props->Distortion.Gain = val; + break; + + case AL_DISTORTION_LOWPASS_CUTOFF: + if(!(val >= AL_DISTORTION_MIN_LOWPASS_CUTOFF && val <= AL_DISTORTION_MAX_LOWPASS_CUTOFF)) + throw effect_exception{AL_INVALID_VALUE, "Distortion low-pass cutoff out of range"}; + props->Distortion.LowpassCutoff = val; + break; + + case AL_DISTORTION_EQCENTER: + if(!(val >= AL_DISTORTION_MIN_EQCENTER && val <= AL_DISTORTION_MAX_EQCENTER)) + throw effect_exception{AL_INVALID_VALUE, "Distortion EQ center out of range"}; + props->Distortion.EQCenter = val; + break; + + case AL_DISTORTION_EQBANDWIDTH: + if(!(val >= AL_DISTORTION_MIN_EQBANDWIDTH && val <= AL_DISTORTION_MAX_EQBANDWIDTH)) + throw effect_exception{AL_INVALID_VALUE, "Distortion EQ bandwidth out of range"}; + props->Distortion.EQBandwidth = val; + break; + + default: + throw effect_exception{AL_INVALID_ENUM, "Invalid distortion float property 0x%04x", param}; + } +} +void Distortion_setParamfv(EffectProps *props, ALenum param, const float *vals) +{ Distortion_setParamf(props, param, vals[0]); } + +void Distortion_getParami(const EffectProps*, ALenum param, int*) +{ throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer property 0x%04x", param}; } +void Distortion_getParamiv(const EffectProps*, ALenum param, int*) +{ + throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer-vector property 0x%04x", + param}; +} +void Distortion_getParamf(const EffectProps *props, ALenum param, float *val) +{ + switch(param) + { + case AL_DISTORTION_EDGE: + *val = props->Distortion.Edge; + break; + + case AL_DISTORTION_GAIN: + *val = props->Distortion.Gain; + break; + + case AL_DISTORTION_LOWPASS_CUTOFF: + *val = props->Distortion.LowpassCutoff; + break; + + case AL_DISTORTION_EQCENTER: + *val = props->Distortion.EQCenter; + break; + + case AL_DISTORTION_EQBANDWIDTH: + *val = props->Distortion.EQBandwidth; + break; + + default: + throw effect_exception{AL_INVALID_ENUM, "Invalid distortion float property 0x%04x", param}; + } +} +void Distortion_getParamfv(const EffectProps *props, ALenum param, float *vals) +{ Distortion_getParamf(props, param, vals); } + +EffectProps genDefaultProps() noexcept +{ + EffectProps props{}; + props.Distortion.Edge = AL_DISTORTION_DEFAULT_EDGE; + props.Distortion.Gain = AL_DISTORTION_DEFAULT_GAIN; + props.Distortion.LowpassCutoff = AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF; + props.Distortion.EQCenter = AL_DISTORTION_DEFAULT_EQCENTER; + props.Distortion.EQBandwidth = AL_DISTORTION_DEFAULT_EQBANDWIDTH; + return props; +} + +} // namespace + +DEFINE_ALEFFECT_VTABLE(Distortion); + +const EffectProps DistortionEffectProps{genDefaultProps()}; -- cgit v1.2.3 From 061148072f6bbcda20d57a4512e414c833129479 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 27 Apr 2021 16:04:54 -0700 Subject: Update include headers Don't add alc/ to the include paths. --- CMakeLists.txt | 1 - al/auxeffectslot.cpp | 8 ++++---- al/auxeffectslot.h | 6 +++--- al/buffer.cpp | 6 +++--- al/buffer.h | 2 +- al/effect.cpp | 6 +++--- al/effects/autowah.cpp | 2 +- al/effects/chorus.cpp | 2 +- al/effects/compressor.cpp | 2 +- al/effects/convolution.cpp | 4 ++-- al/effects/dedicated.cpp | 4 ++-- al/effects/distortion.cpp | 2 +- al/effects/echo.cpp | 2 +- al/effects/equalizer.cpp | 2 +- al/effects/fshifter.cpp | 2 +- al/effects/modulator.cpp | 2 +- al/effects/null.cpp | 2 +- al/effects/pshifter.cpp | 2 +- al/effects/reverb.cpp | 2 +- al/effects/vmorpher.cpp | 2 +- al/error.cpp | 2 +- al/event.cpp | 6 +++--- al/extension.cpp | 2 +- al/filter.cpp | 4 ++-- al/listener.cpp | 2 +- al/source.cpp | 10 +++++----- al/source.h | 4 ++-- al/state.cpp | 8 ++++---- alc/backends/alsa.cpp | 7 +++---- alc/backends/alsa.h | 2 +- alc/backends/coreaudio.cpp | 13 ++++++------- alc/backends/coreaudio.h | 2 +- alc/backends/dsound.cpp | 8 ++++---- alc/backends/dsound.h | 2 +- alc/backends/jack.cpp | 8 ++++---- alc/backends/jack.h | 2 +- alc/backends/loopback.cpp | 9 ++++----- alc/backends/loopback.h | 2 +- alc/backends/null.cpp | 5 ++--- alc/backends/null.h | 2 +- alc/backends/oboe.h | 2 +- alc/backends/opensl.cpp | 6 +++--- alc/backends/opensl.h | 2 +- alc/backends/oss.cpp | 7 +++---- alc/backends/oss.h | 2 +- alc/backends/portaudio.cpp | 8 ++++---- alc/backends/portaudio.h | 2 +- alc/backends/pulseaudio.cpp | 4 ++-- alc/backends/pulseaudio.h | 2 +- alc/backends/sndio.cpp | 6 +++--- alc/backends/sndio.h | 2 +- alc/backends/wasapi.cpp | 6 +++--- alc/backends/wasapi.h | 2 +- alc/backends/wave.cpp | 7 +++---- alc/backends/wave.h | 2 +- alc/backends/winmm.cpp | 6 +++--- alc/backends/winmm.h | 2 +- alc/effects/autowah.cpp | 4 ++-- alc/effects/base.h | 9 ++++++--- alc/effects/chorus.cpp | 4 ++-- alc/effects/compressor.cpp | 4 ++-- alc/effects/convolution.cpp | 4 ++-- alc/effects/dedicated.cpp | 4 ++-- alc/effects/distortion.cpp | 4 ++-- alc/effects/echo.cpp | 4 ++-- alc/effects/equalizer.cpp | 4 ++-- alc/effects/fshifter.cpp | 4 ++-- alc/effects/modulator.cpp | 4 ++-- alc/effects/null.cpp | 2 +- alc/effects/pshifter.cpp | 4 ++-- alc/effects/reverb.cpp | 4 ++-- alc/effects/vmorpher.cpp | 4 ++-- alc/effectslot.h | 5 ++--- core/helpers.cpp | 5 +++-- 74 files changed, 149 insertions(+), 153 deletions(-) (limited to 'al/effects/distortion.cpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index 11c3975b..8b286781 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1345,7 +1345,6 @@ target_include_directories(${IMPL_TARGET} ${INC_PATHS} ${OpenAL_BINARY_DIR} ${OpenAL_SOURCE_DIR} - ${OpenAL_SOURCE_DIR}/alc ${OpenAL_SOURCE_DIR}/common ) diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 3ee0a46e..eee274b1 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -36,18 +36,18 @@ #include "AL/efx.h" #include "albit.h" -#include "alcmain.h" -#include "alcontext.h" +#include "alc/alcmain.h" +#include "alc/alcontext.h" +#include "alc/alu.h" +#include "alc/inprogext.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" -#include "alu.h" #include "buffer.h" #include "core/except.h" #include "core/fpu_ctrl.h" #include "core/logging.h" #include "effect.h" -#include "inprogext.h" #include "opthelpers.h" diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 8d7e396b..ca73c757 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -8,11 +8,11 @@ #include "AL/alc.h" #include "AL/efx.h" -#include "alcmain.h" +#include "alc/alcmain.h" +#include "alc/effectslot.h" +#include "alc/effects/base.h" #include "almalloc.h" #include "atomic.h" -#include "effectslot.h" -#include "effects/base.h" #include "intrusive_ptr.h" #include "vector.h" diff --git a/al/buffer.cpp b/al/buffer.cpp index 21f46fc8..aaffddf1 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -43,8 +43,9 @@ #include "albit.h" #include "albyte.h" -#include "alcmain.h" -#include "alcontext.h" +#include "alc/alcmain.h" +#include "alc/alcontext.h" +#include "alc/inprogext.h" #include "almalloc.h" #include "alnumeric.h" #include "aloptional.h" @@ -52,7 +53,6 @@ #include "core/except.h" #include "core/logging.h" #include "core/voice.h" -#include "inprogext.h" #include "opthelpers.h" diff --git a/al/buffer.h b/al/buffer.h index fe37b0af..a78c65c6 100644 --- a/al/buffer.h +++ b/al/buffer.h @@ -6,10 +6,10 @@ #include "AL/al.h" #include "albyte.h" +#include "alc/inprogext.h" #include "almalloc.h" #include "atomic.h" #include "core/buffer_storage.h" -#include "inprogext.h" #include "vector.h" diff --git a/al/effect.cpp b/al/effect.cpp index 645e41df..2c39394f 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -39,14 +39,14 @@ #include "AL/efx.h" #include "albit.h" -#include "alcmain.h" -#include "alcontext.h" +#include "alc/alcmain.h" +#include "alc/alcontext.h" +#include "alc/effects/base.h" #include "almalloc.h" #include "alnumeric.h" #include "alstring.h" #include "core/except.h" #include "core/logging.h" -#include "effects/base.h" #include "opthelpers.h" #include "vector.h" diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 65d4b702..9abef1f7 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -8,7 +8,7 @@ #include "AL/efx.h" -#include "effects/base.h" +#include "alc/effects/base.h" #include "effects.h" namespace { diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index 60152755..704d7230 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -4,10 +4,10 @@ #include "AL/al.h" #include "AL/efx.h" +#include "alc/effects/base.h" #include "aloptional.h" #include "core/logging.h" #include "effects.h" -#include "effects/base.h" namespace { diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp index 94e07431..f5db2a6f 100644 --- a/al/effects/compressor.cpp +++ b/al/effects/compressor.cpp @@ -4,8 +4,8 @@ #include "AL/al.h" #include "AL/efx.h" +#include "alc/effects/base.h" #include "effects.h" -#include "effects/base.h" namespace { diff --git a/al/effects/convolution.cpp b/al/effects/convolution.cpp index 4d87b1c4..8e850fd3 100644 --- a/al/effects/convolution.cpp +++ b/al/effects/convolution.cpp @@ -2,10 +2,10 @@ #include "config.h" #include "AL/al.h" -#include "inprogext.h" +#include "alc/inprogext.h" +#include "alc/effects/base.h" #include "effects.h" -#include "effects/base.h" namespace { diff --git a/al/effects/dedicated.cpp b/al/effects/dedicated.cpp index 334d9e56..db57003c 100644 --- a/al/effects/dedicated.cpp +++ b/al/effects/dedicated.cpp @@ -4,10 +4,10 @@ #include #include "AL/al.h" -#include "AL/efx.h" +#include "AL/alext.h" +#include "alc/effects/base.h" #include "effects.h" -#include "effects/base.h" namespace { diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index 8961a4d9..f5d64a9a 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -4,8 +4,8 @@ #include "AL/al.h" #include "AL/efx.h" +#include "alc/effects/base.h" #include "effects.h" -#include "effects/base.h" namespace { diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index 79a60521..65f691c6 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -4,8 +4,8 @@ #include "AL/al.h" #include "AL/efx.h" +#include "alc/effects/base.h" #include "effects.h" -#include "effects/base.h" namespace { diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index 3a7c0a8f..3c039688 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -4,8 +4,8 @@ #include "AL/al.h" #include "AL/efx.h" +#include "alc/effects/base.h" #include "effects.h" -#include "effects/base.h" namespace { diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index 444b0260..63621aa6 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -4,9 +4,9 @@ #include "AL/al.h" #include "AL/efx.h" +#include "alc/effects/base.h" #include "aloptional.h" #include "effects.h" -#include "effects/base.h" namespace { diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index 89dcc209..4c4ee485 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -4,9 +4,9 @@ #include "AL/al.h" #include "AL/efx.h" +#include "alc/effects/base.h" #include "aloptional.h" #include "effects.h" -#include "effects/base.h" namespace { diff --git a/al/effects/null.cpp b/al/effects/null.cpp index 0ac5278f..516446db 100644 --- a/al/effects/null.cpp +++ b/al/effects/null.cpp @@ -4,8 +4,8 @@ #include "AL/al.h" #include "AL/efx.h" +#include "alc/effects/base.h" #include "effects.h" -#include "effects/base.h" namespace { diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp index e6b0b3b0..56059a3c 100644 --- a/al/effects/pshifter.cpp +++ b/al/effects/pshifter.cpp @@ -4,8 +4,8 @@ #include "AL/al.h" #include "AL/efx.h" +#include "alc/effects/base.h" #include "effects.h" -#include "effects/base.h" namespace { diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index caa0c81e..3f234b93 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -6,8 +6,8 @@ #include "AL/al.h" #include "AL/efx.h" +#include "alc/effects/base.h" #include "effects.h" -#include "effects/base.h" namespace { diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index 03eb2c62..076776a9 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -4,9 +4,9 @@ #include "AL/al.h" #include "AL/efx.h" +#include "alc/effects/base.h" #include "aloptional.h" #include "effects.h" -#include "effects/base.h" namespace { diff --git a/al/error.cpp b/al/error.cpp index 444b55aa..b6489a86 100644 --- a/al/error.cpp +++ b/al/error.cpp @@ -35,7 +35,7 @@ #include "AL/al.h" #include "AL/alc.h" -#include "alcontext.h" +#include "alc/alcontext.h" #include "almalloc.h" #include "core/except.h" #include "core/logging.h" diff --git a/al/event.cpp b/al/event.cpp index 843a90e1..5b6c1976 100644 --- a/al/event.cpp +++ b/al/event.cpp @@ -18,14 +18,14 @@ #include "AL/alc.h" #include "albyte.h" -#include "alcontext.h" +#include "alc/alcontext.h" +#include "alc/effects/base.h" +#include "alc/inprogext.h" #include "almalloc.h" #include "core/async_event.h" #include "core/except.h" #include "core/logging.h" #include "core/voice_change.h" -#include "effects/base.h" -#include "inprogext.h" #include "opthelpers.h" #include "ringbuffer.h" #include "threads.h" diff --git a/al/extension.cpp b/al/extension.cpp index 7346a5c6..bd903a6f 100644 --- a/al/extension.cpp +++ b/al/extension.cpp @@ -27,7 +27,7 @@ #include "AL/al.h" #include "AL/alc.h" -#include "alcontext.h" +#include "alc/alcontext.h" #include "alstring.h" #include "core/except.h" #include "opthelpers.h" diff --git a/al/filter.cpp b/al/filter.cpp index c3391193..09249c81 100644 --- a/al/filter.cpp +++ b/al/filter.cpp @@ -37,8 +37,8 @@ #include "AL/efx.h" #include "albit.h" -#include "alcmain.h" -#include "alcontext.h" +#include "alc/alcmain.h" +#include "alc/alcontext.h" #include "almalloc.h" #include "alnumeric.h" #include "core/except.h" diff --git a/al/listener.cpp b/al/listener.cpp index edc1ed06..00626a20 100644 --- a/al/listener.cpp +++ b/al/listener.cpp @@ -29,7 +29,7 @@ #include "AL/alc.h" #include "AL/efx.h" -#include "alcontext.h" +#include "alc/alcontext.h" #include "almalloc.h" #include "atomic.h" #include "core/except.h" diff --git a/al/source.cpp b/al/source.cpp index ca234a05..25d84f9f 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -46,16 +46,17 @@ #include "AL/efx.h" #include "albit.h" -#include "alcmain.h" -#include "alcontext.h" +#include "alc/alcmain.h" +#include "alc/alcontext.h" +#include "alc/alu.h" +#include "alc/backends/base.h" +#include "alc/inprogext.h" #include "almalloc.h" #include "alnumeric.h" #include "aloptional.h" #include "alspan.h" -#include "alu.h" #include "atomic.h" #include "auxeffectslot.h" -#include "backends/base.h" #include "buffer.h" #include "core/ambidefs.h" #include "core/bformatdec.h" @@ -66,7 +67,6 @@ #include "core/voice_change.h" #include "event.h" #include "filter.h" -#include "inprogext.h" #include "math_defs.h" #include "opthelpers.h" #include "ringbuffer.h" diff --git a/al/source.h b/al/source.h index 2063068a..dd3f56a7 100644 --- a/al/source.h +++ b/al/source.h @@ -11,11 +11,11 @@ #include "AL/al.h" #include "AL/alc.h" -#include "alcontext.h" +#include "alc/alcontext.h" +#include "alc/alu.h" #include "aldeque.h" #include "almalloc.h" #include "alnumeric.h" -#include "alu.h" #include "atomic.h" #include "core/voice.h" #include "math_defs.h" diff --git a/al/state.cpp b/al/state.cpp index 950d64fc..b0b05972 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -32,17 +32,17 @@ #include "AL/alc.h" #include "AL/alext.h" -#include "alcmain.h" -#include "alcontext.h" +#include "alc/alcmain.h" +#include "alc/alcontext.h" +#include "alc/alu.h" +#include "alc/inprogext.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" -#include "alu.h" #include "atomic.h" #include "core/except.h" #include "core/voice.h" #include "event.h" -#include "inprogext.h" #include "opthelpers.h" #include "strutils.h" diff --git a/alc/backends/alsa.cpp b/alc/backends/alsa.cpp index a6c7e178..f6f318eb 100644 --- a/alc/backends/alsa.cpp +++ b/alc/backends/alsa.cpp @@ -20,7 +20,7 @@ #include "config.h" -#include "backends/alsa.h" +#include "alsa.h" #include #include @@ -36,12 +36,11 @@ #include #include "albyte.h" -#include "alcmain.h" -#include "alconfig.h" +#include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" #include "aloptional.h" -#include "alu.h" +#include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "dynload.h" diff --git a/alc/backends/alsa.h b/alc/backends/alsa.h index 1a28e6b9..b256dcf5 100644 --- a/alc/backends/alsa.h +++ b/alc/backends/alsa.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_ALSA_H #define BACKENDS_ALSA_H -#include "backends/base.h" +#include "base.h" struct AlsaBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index 45c814bf..81ce32bc 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -20,23 +20,22 @@ #include "config.h" -#include "backends/coreaudio.h" +#include "coreaudio.h" -#include +#include #include #include #include +#include #include -#include "alcmain.h" -#include "alu.h" -#include "ringbuffer.h" +#include "alnumeric.h" #include "core/converter.h" +#include "core/device.h" #include "core/logging.h" -#include "backends/base.h" +#include "ringbuffer.h" -#include #include #include diff --git a/alc/backends/coreaudio.h b/alc/backends/coreaudio.h index 19e50eab..1252edde 100644 --- a/alc/backends/coreaudio.h +++ b/alc/backends/coreaudio.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_COREAUDIO_H #define BACKENDS_COREAUDIO_H -#include "backends/base.h" +#include "base.h" struct CoreAudioBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp index 928ff507..401f8165 100644 --- a/alc/backends/dsound.cpp +++ b/alc/backends/dsound.cpp @@ -20,7 +20,7 @@ #include "config.h" -#include "backends/dsound.h" +#include "dsound.h" #define WIN32_LEAN_AND_MEAN #include @@ -44,9 +44,9 @@ #include #include -#include "alcmain.h" -#include "alu.h" +#include "alnumeric.h" #include "comptr.h" +#include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "dynload.h" @@ -175,7 +175,7 @@ struct DSoundPlayback final : public BackendBase { int mixerProc(); - void open(const ALCchar *name) override; + void open(const char *name) override; bool reset() override; void start() override; void stop() override; diff --git a/alc/backends/dsound.h b/alc/backends/dsound.h index 3b5b344b..787f227a 100644 --- a/alc/backends/dsound.h +++ b/alc/backends/dsound.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_DSOUND_H #define BACKENDS_DSOUND_H -#include "backends/base.h" +#include "base.h" struct DSoundBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/jack.cpp b/alc/backends/jack.cpp index b7b35217..54bd19e6 100644 --- a/alc/backends/jack.cpp +++ b/alc/backends/jack.cpp @@ -20,7 +20,7 @@ #include "config.h" -#include "backends/jack.h" +#include "jack.h" #include #include @@ -31,9 +31,9 @@ #include #include -#include "alcmain.h" -#include "alu.h" -#include "alconfig.h" +#include "alc/alconfig.h" +#include "alnumeric.h" +#include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "dynload.h" diff --git a/alc/backends/jack.h b/alc/backends/jack.h index 6f81a209..b83f24dd 100644 --- a/alc/backends/jack.h +++ b/alc/backends/jack.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_JACK_H #define BACKENDS_JACK_H -#include "backends/base.h" +#include "base.h" struct JackBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/loopback.cpp b/alc/backends/loopback.cpp index bafe8cc8..bf4ab246 100644 --- a/alc/backends/loopback.cpp +++ b/alc/backends/loopback.cpp @@ -20,10 +20,9 @@ #include "config.h" -#include "backends/loopback.h" +#include "loopback.h" -#include "alcmain.h" -#include "alu.h" +#include "core/device.h" namespace { @@ -31,7 +30,7 @@ namespace { struct LoopbackBackend final : public BackendBase { LoopbackBackend(DeviceBase *device) noexcept : BackendBase{device} { } - void open(const ALCchar *name) override; + void open(const char *name) override; bool reset() override; void start() override; void stop() override; @@ -40,7 +39,7 @@ struct LoopbackBackend final : public BackendBase { }; -void LoopbackBackend::open(const ALCchar *name) +void LoopbackBackend::open(const char *name) { mDevice->DeviceName = name; } diff --git a/alc/backends/loopback.h b/alc/backends/loopback.h index 1a031a1f..cb42b3c8 100644 --- a/alc/backends/loopback.h +++ b/alc/backends/loopback.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_LOOPBACK_H #define BACKENDS_LOOPBACK_H -#include "backends/base.h" +#include "base.h" struct LoopbackBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/null.cpp b/alc/backends/null.cpp index 763d4d2e..5a8fc255 100644 --- a/alc/backends/null.cpp +++ b/alc/backends/null.cpp @@ -20,7 +20,7 @@ #include "config.h" -#include "backends/null.h" +#include "null.h" #include #include @@ -30,9 +30,8 @@ #include #include -#include "alcmain.h" +#include "core/device.h" #include "almalloc.h" -#include "alu.h" #include "core/helpers.h" #include "threads.h" diff --git a/alc/backends/null.h b/alc/backends/null.h index c9d1b3b3..7048cad6 100644 --- a/alc/backends/null.h +++ b/alc/backends/null.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_NULL_H #define BACKENDS_NULL_H -#include "backends/base.h" +#include "base.h" struct NullBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/oboe.h b/alc/backends/oboe.h index 228ec807..a39c2445 100644 --- a/alc/backends/oboe.h +++ b/alc/backends/oboe.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_OBOE_H #define BACKENDS_OBOE_H -#include "backends/base.h" +#include "base.h" struct OboeBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/opensl.cpp b/alc/backends/opensl.cpp index af656470..7be7f031 100644 --- a/alc/backends/opensl.cpp +++ b/alc/backends/opensl.cpp @@ -21,7 +21,7 @@ #include "config.h" -#include "backends/opensl.h" +#include "opensl.h" #include #include @@ -33,8 +33,8 @@ #include #include "albit.h" -#include "alcmain.h" -#include "alu.h" +#include "alnumeric.h" +#include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "opthelpers.h" diff --git a/alc/backends/opensl.h b/alc/backends/opensl.h index 36586bbb..b8162447 100644 --- a/alc/backends/opensl.h +++ b/alc/backends/opensl.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_OSL_H #define BACKENDS_OSL_H -#include "backends/base.h" +#include "base.h" struct OSLBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/oss.cpp b/alc/backends/oss.cpp index d769a1eb..6d4fa261 100644 --- a/alc/backends/oss.cpp +++ b/alc/backends/oss.cpp @@ -20,7 +20,7 @@ #include "config.h" -#include "backends/oss.h" +#include "oss.h" #include #include @@ -41,13 +41,12 @@ #include #include -#include "alcmain.h" -#include "alconfig.h" #include "albyte.h" +#include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" #include "aloptional.h" -#include "alu.h" +#include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "ringbuffer.h" diff --git a/alc/backends/oss.h b/alc/backends/oss.h index 798da456..4f2c00b9 100644 --- a/alc/backends/oss.h +++ b/alc/backends/oss.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_OSS_H #define BACKENDS_OSS_H -#include "backends/base.h" +#include "base.h" struct OSSBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/portaudio.cpp b/alc/backends/portaudio.cpp index 8f41b12a..2d5cd36d 100644 --- a/alc/backends/portaudio.cpp +++ b/alc/backends/portaudio.cpp @@ -20,15 +20,15 @@ #include "config.h" -#include "backends/portaudio.h" +#include "portaudio.h" #include #include #include -#include "alcmain.h" -#include "alu.h" -#include "alconfig.h" +#include "alc/alconfig.h" +#include "alnumeric.h" +#include "core/device.h" #include "core/logging.h" #include "dynload.h" #include "ringbuffer.h" diff --git a/alc/backends/portaudio.h b/alc/backends/portaudio.h index 34bb8d1b..c35ccff2 100644 --- a/alc/backends/portaudio.h +++ b/alc/backends/portaudio.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_PORTAUDIO_H #define BACKENDS_PORTAUDIO_H -#include "backends/base.h" +#include "base.h" struct PortBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp index da1ffcb0..23bcecad 100644 --- a/alc/backends/pulseaudio.cpp +++ b/alc/backends/pulseaudio.cpp @@ -21,7 +21,7 @@ #include "config.h" -#include "backends/pulseaudio.h" +#include "pulseaudio.h" #include #include @@ -43,7 +43,7 @@ #include #include "albyte.h" -#include "alconfig.h" +#include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" #include "aloptional.h" diff --git a/alc/backends/pulseaudio.h b/alc/backends/pulseaudio.h index 60ebbc36..6690fe8a 100644 --- a/alc/backends/pulseaudio.h +++ b/alc/backends/pulseaudio.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_PULSEAUDIO_H #define BACKENDS_PULSEAUDIO_H -#include "backends/base.h" +#include "base.h" class PulseBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/sndio.cpp b/alc/backends/sndio.cpp index c7c42210..2d8b424c 100644 --- a/alc/backends/sndio.cpp +++ b/alc/backends/sndio.cpp @@ -20,7 +20,7 @@ #include "config.h" -#include "backends/sndio.h" +#include "sndio.h" #include #include @@ -29,8 +29,8 @@ #include #include -#include "alcmain.h" -#include "alu.h" +#include "alnumeric.h" +#include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "ringbuffer.h" diff --git a/alc/backends/sndio.h b/alc/backends/sndio.h index 9b93199f..d9433191 100644 --- a/alc/backends/sndio.h +++ b/alc/backends/sndio.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_SNDIO_H #define BACKENDS_SNDIO_H -#include "backends/base.h" +#include "base.h" struct SndIOBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 114c69e0..d38fc25d 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -20,7 +20,7 @@ #include "config.h" -#include "backends/wasapi.h" +#include "wasapi.h" #define WIN32_LEAN_AND_MEAN #include @@ -56,10 +56,10 @@ #include #include "albit.h" -#include "alcmain.h" -#include "alu.h" +#include "alnumeric.h" #include "comptr.h" #include "core/converter.h" +#include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "ringbuffer.h" diff --git a/alc/backends/wasapi.h b/alc/backends/wasapi.h index fa4b811e..bb2671ee 100644 --- a/alc/backends/wasapi.h +++ b/alc/backends/wasapi.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_WASAPI_H #define BACKENDS_WASAPI_H -#include "backends/base.h" +#include "base.h" struct WasapiBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/wave.cpp b/alc/backends/wave.cpp index 434a5fb1..259cbc62 100644 --- a/alc/backends/wave.cpp +++ b/alc/backends/wave.cpp @@ -20,7 +20,7 @@ #include "config.h" -#include "backends/wave.h" +#include "wave.h" #include #include @@ -35,11 +35,10 @@ #include "albit.h" #include "albyte.h" -#include "alcmain.h" -#include "alconfig.h" +#include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" -#include "alu.h" +#include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "opthelpers.h" diff --git a/alc/backends/wave.h b/alc/backends/wave.h index 926e2198..e768d336 100644 --- a/alc/backends/wave.h +++ b/alc/backends/wave.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_WAVE_H #define BACKENDS_WAVE_H -#include "backends/base.h" +#include "base.h" struct WaveBackendFactory final : public BackendFactory { public: diff --git a/alc/backends/winmm.cpp b/alc/backends/winmm.cpp index c346a828..42aee313 100644 --- a/alc/backends/winmm.cpp +++ b/alc/backends/winmm.cpp @@ -20,7 +20,7 @@ #include "config.h" -#include "backends/winmm.h" +#include "winmm.h" #include #include @@ -38,8 +38,8 @@ #include #include -#include "alcmain.h" -#include "alu.h" +#include "alnumeric.h" +#include "core/device.h" #include "core/helpers.h" #include "core/logging.h" #include "ringbuffer.h" diff --git a/alc/backends/winmm.h b/alc/backends/winmm.h index a376b8a4..45a706aa 100644 --- a/alc/backends/winmm.h +++ b/alc/backends/winmm.h @@ -1,7 +1,7 @@ #ifndef BACKENDS_WINMM_H #define BACKENDS_WINMM_H -#include "backends/base.h" +#include "base.h" struct WinMMBackendFactory final : public BackendFactory { public: diff --git a/alc/effects/autowah.cpp b/alc/effects/autowah.cpp index 6016b8ab..9c2ec335 100644 --- a/alc/effects/autowah.cpp +++ b/alc/effects/autowah.cpp @@ -26,6 +26,8 @@ #include #include +#include "alc/effects/base.h" +#include "alc/effectslot.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -35,8 +37,6 @@ #include "core/devformat.h" #include "core/device.h" #include "core/mixer.h" -#include "effects/base.h" -#include "effectslot.h" #include "intrusive_ptr.h" #include "math_defs.h" diff --git a/alc/effects/base.h b/alc/effects/base.h index 6c31ae0c..1fb339aa 100644 --- a/alc/effects/base.h +++ b/alc/effects/base.h @@ -1,18 +1,21 @@ #ifndef EFFECTS_BASE_H #define EFFECTS_BASE_H -#include +#include #include "albyte.h" -#include "alcmain.h" #include "almalloc.h" #include "alspan.h" #include "atomic.h" +#include "core/bufferline.h" #include "intrusive_ptr.h" +struct BufferStorage; struct ContextBase; +struct DeviceBase; struct EffectSlot; -struct BufferStorage; +struct MixParams; +struct RealMixParams; /** Target gain for the reverb decay feedback reaching the decay time. */ diff --git a/alc/effects/chorus.cpp b/alc/effects/chorus.cpp index 50cf1e40..3a1b9ae4 100644 --- a/alc/effects/chorus.cpp +++ b/alc/effects/chorus.cpp @@ -26,6 +26,8 @@ #include #include +#include "alc/effects/base.h" +#include "alc/effectslot.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -36,8 +38,6 @@ #include "core/mixer.h" #include "core/mixer/defs.h" #include "core/resampler_limits.h" -#include "effects/base.h" -#include "effectslot.h" #include "intrusive_ptr.h" #include "math_defs.h" #include "opthelpers.h" diff --git a/alc/effects/compressor.cpp b/alc/effects/compressor.cpp index 9a6f9b5d..030bfe08 100644 --- a/alc/effects/compressor.cpp +++ b/alc/effects/compressor.cpp @@ -37,6 +37,8 @@ #include #include +#include "alc/effects/base.h" +#include "alc/effectslot.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -46,8 +48,6 @@ #include "core/device.h" #include "core/mixer.h" #include "core/mixer/defs.h" -#include "effects/base.h" -#include "effectslot.h" #include "intrusive_ptr.h" struct ContextBase; diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp index fd68ea41..ca5a7321 100644 --- a/alc/effects/convolution.cpp +++ b/alc/effects/convolution.cpp @@ -19,9 +19,11 @@ #include "albyte.h" #include "alcomplex.h" +#include "alc/effectslot.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" +#include "base.h" #include "core/ambidefs.h" #include "core/bufferline.h" #include "core/buffer_storage.h" @@ -31,8 +33,6 @@ #include "core/filters/splitter.h" #include "core/fmt_traits.h" #include "core/mixer.h" -#include "effects/base.h" -#include "effectslot.h" #include "intrusive_ptr.h" #include "math_defs.h" #include "polyphase_resampler.h" diff --git a/alc/effects/dedicated.cpp b/alc/effects/dedicated.cpp index 6afd7baa..e7ea89e0 100644 --- a/alc/effects/dedicated.cpp +++ b/alc/effects/dedicated.cpp @@ -25,14 +25,14 @@ #include #include +#include "alc/effects/base.h" +#include "alc/effectslot.h" #include "almalloc.h" #include "alspan.h" #include "core/bufferline.h" #include "core/devformat.h" #include "core/device.h" #include "core/mixer.h" -#include "effects/base.h" -#include "effectslot.h" #include "intrusive_ptr.h" struct ContextBase; diff --git a/alc/effects/distortion.cpp b/alc/effects/distortion.cpp index a3f287c0..26b4df8e 100644 --- a/alc/effects/distortion.cpp +++ b/alc/effects/distortion.cpp @@ -25,6 +25,8 @@ #include #include +#include "alc/effects/base.h" +#include "alc/effectslot.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -35,8 +37,6 @@ #include "core/filters/biquad.h" #include "core/mixer.h" #include "core/mixer/defs.h" -#include "effects/base.h" -#include "effectslot.h" #include "intrusive_ptr.h" #include "math_defs.h" diff --git a/alc/effects/echo.cpp b/alc/effects/echo.cpp index 4fccabfe..4cdef37c 100644 --- a/alc/effects/echo.cpp +++ b/alc/effects/echo.cpp @@ -26,6 +26,8 @@ #include #include +#include "alc/effects/base.h" +#include "alc/effectslot.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -35,8 +37,6 @@ #include "core/device.h" #include "core/filters/biquad.h" #include "core/mixer.h" -#include "effects/base.h" -#include "effectslot.h" #include "intrusive_ptr.h" #include "opthelpers.h" #include "vector.h" diff --git a/alc/effects/equalizer.cpp b/alc/effects/equalizer.cpp index aedf537e..800330a3 100644 --- a/alc/effects/equalizer.cpp +++ b/alc/effects/equalizer.cpp @@ -27,6 +27,8 @@ #include #include +#include "alc/effects/base.h" +#include "alc/effectslot.h" #include "almalloc.h" #include "alspan.h" #include "core/ambidefs.h" @@ -36,8 +38,6 @@ #include "core/device.h" #include "core/filters/biquad.h" #include "core/mixer.h" -#include "effects/base.h" -#include "effectslot.h" #include "intrusive_ptr.h" diff --git a/alc/effects/fshifter.cpp b/alc/effects/fshifter.cpp index e19809bb..c25aab82 100644 --- a/alc/effects/fshifter.cpp +++ b/alc/effects/fshifter.cpp @@ -27,6 +27,8 @@ #include #include +#include "alc/effects/base.h" +#include "alc/effectslot.h" #include "alcomplex.h" #include "almalloc.h" #include "alnumeric.h" @@ -37,8 +39,6 @@ #include "core/device.h" #include "core/mixer.h" #include "core/mixer/defs.h" -#include "effects/base.h" -#include "effectslot.h" #include "intrusive_ptr.h" #include "math_defs.h" diff --git a/alc/effects/modulator.cpp b/alc/effects/modulator.cpp index ded35805..a518ff63 100644 --- a/alc/effects/modulator.cpp +++ b/alc/effects/modulator.cpp @@ -25,6 +25,8 @@ #include #include +#include "alc/effects/base.h" +#include "alc/effectslot.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -35,8 +37,6 @@ #include "core/device.h" #include "core/filters/biquad.h" #include "core/mixer.h" -#include "effects/base.h" -#include "effectslot.h" #include "intrusive_ptr.h" #include "math_defs.h" diff --git a/alc/effects/null.cpp b/alc/effects/null.cpp index 1413909f..cda1420e 100644 --- a/alc/effects/null.cpp +++ b/alc/effects/null.cpp @@ -5,8 +5,8 @@ #include "almalloc.h" #include "alspan.h" +#include "base.h" #include "core/bufferline.h" -#include "effects/base.h" #include "intrusive_ptr.h" struct ContextBase; diff --git a/alc/effects/pshifter.cpp b/alc/effects/pshifter.cpp index 5bf813e5..26115605 100644 --- a/alc/effects/pshifter.cpp +++ b/alc/effects/pshifter.cpp @@ -27,6 +27,8 @@ #include #include +#include "alc/effects/base.h" +#include "alc/effectslot.h" #include "alcomplex.h" #include "almalloc.h" #include "alnumeric.h" @@ -36,8 +38,6 @@ #include "core/device.h" #include "core/mixer.h" #include "core/mixer/defs.h" -#include "effects/base.h" -#include "effectslot.h" #include "intrusive_ptr.h" #include "math_defs.h" diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp index 0db27210..d6f1dbbf 100644 --- a/alc/effects/reverb.cpp +++ b/alc/effects/reverb.cpp @@ -28,6 +28,8 @@ #include #include +#include "alc/effects/base.h" +#include "alc/effectslot.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -40,8 +42,6 @@ #include "core/filters/splitter.h" #include "core/mixer.h" #include "core/mixer/defs.h" -#include "effects/base.h" -#include "effectslot.h" #include "intrusive_ptr.h" #include "math_defs.h" #include "opthelpers.h" diff --git a/alc/effects/vmorpher.cpp b/alc/effects/vmorpher.cpp index c3790e30..6c419ba2 100644 --- a/alc/effects/vmorpher.cpp +++ b/alc/effects/vmorpher.cpp @@ -38,6 +38,8 @@ #include #include +#include "alc/effects/base.h" +#include "alc/effectslot.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" @@ -47,8 +49,6 @@ #include "core/devformat.h" #include "core/device.h" #include "core/mixer.h" -#include "effects/base.h" -#include "effectslot.h" #include "intrusive_ptr.h" #include "math_defs.h" diff --git a/alc/effectslot.h b/alc/effectslot.h index c1eb1cc3..cbb1a2f5 100644 --- a/alc/effectslot.h +++ b/alc/effectslot.h @@ -1,14 +1,13 @@ #ifndef EFFECTSLOT_H #define EFFECTSLOT_H -#include +#include #include "almalloc.h" -#include "alcmain.h" +#include "core/device.h" #include "effects/base.h" #include "intrusive_ptr.h" - struct EffectSlot; struct WetBuffer; diff --git a/core/helpers.cpp b/core/helpers.cpp index a2f1a6c9..94219544 100644 --- a/core/helpers.cpp +++ b/core/helpers.cpp @@ -10,9 +10,9 @@ #include #include #include +#include #include -#include "alcmain.h" #include "almalloc.h" #include "alfstream.h" #include "aloptional.h" @@ -199,7 +199,8 @@ void SetRTPriority(void) #include #include -#include "core/rtkit.h" +#include "dbus_wrap.h" +#include "rtkit.h" #ifndef RLIMIT_RTTIME #define RLIMIT_RTTIME 15 #endif -- cgit v1.2.3 From 19ed994dc30ed84ea7cbbb5152577669fc25caf6 Mon Sep 17 00:00:00 2001 From: "Boris I. Bendovsky" Date: Sun, 30 Jan 2022 14:47:32 +0200 Subject: Add EAX extensions (EAX 2.0-5.0, X-RAM) (#632) * Add EAX extensions (EAX 2.0-5.0, X-RAM) * Comment out C++17 leftovers * Remove everything related to patching * Update alsoftrc.sample * Rewrite integration * Fix GCC compilation under Linux * Always reset EAX effect properties when loading it into FX slot --- CMakeLists.txt | 30 + al/auxeffectslot.cpp | 834 +++++++++++++++ al/auxeffectslot.h | 221 ++++ al/buffer.cpp | 292 ++++++ al/buffer.h | 9 + al/eax_api.cpp | 1151 +++++++++++++++++++++ al/eax_api.h | 1542 ++++++++++++++++++++++++++++ al/eax_eax_call.cpp | 370 +++++++ al/eax_eax_call.h | 128 +++ al/eax_effect.cpp | 1 + al/eax_effect.h | 28 + al/eax_exception.cpp | 61 ++ al/eax_exception.h | 25 + al/eax_fx_slot_index.cpp | 164 +++ al/eax_fx_slot_index.h | 69 ++ al/eax_fx_slots.cpp | 81 ++ al/eax_fx_slots.h | 46 + al/eax_globals.cpp | 18 + al/eax_globals.h | 22 + al/eax_utils.cpp | 35 + al/eax_utils.h | 164 +++ al/eax_x_ram.cpp | 1 + al/eax_x_ram.h | 38 + al/effect.cpp | 143 +++ al/effect.h | 53 + al/effects/autowah.cpp | 471 +++++++++ al/effects/chorus.cpp | 1240 ++++++++++++++++++++++ al/effects/compressor.cpp | 272 +++++ al/effects/distortion.cpp | 536 ++++++++++ al/effects/echo.cpp | 534 ++++++++++ al/effects/effects.cpp | 106 ++ al/effects/effects.h | 11 + al/effects/equalizer.cpp | 866 ++++++++++++++++ al/effects/fshifter.cpp | 414 ++++++++ al/effects/modulator.cpp | 411 ++++++++ al/effects/null.cpp | 57 ++ al/effects/pshifter.cpp | 338 ++++++ al/effects/reverb.cpp | 1922 ++++++++++++++++++++++++++++++++++ al/effects/vmorpher.cpp | 624 ++++++++++++ al/extension.cpp | 117 +++ al/filter.cpp | 81 ++ al/filter.h | 40 + al/listener.cpp | 22 + al/listener.h | 7 + al/source.cpp | 2488 +++++++++++++++++++++++++++++++++++++++++++++ al/source.h | 689 +++++++++++++ al/state.cpp | 42 + alc/alc.cpp | 44 + alc/context.cpp | 1228 ++++++++++++++++++++++ alc/context.h | 386 +++++++ alc/device.h | 8 + alsoftrc.sample | 8 + common/alnumeric.h | 45 + 53 files changed, 18533 insertions(+) create mode 100644 al/eax_api.cpp create mode 100644 al/eax_api.h create mode 100644 al/eax_eax_call.cpp create mode 100644 al/eax_eax_call.h create mode 100644 al/eax_effect.cpp create mode 100644 al/eax_effect.h create mode 100644 al/eax_exception.cpp create mode 100644 al/eax_exception.h create mode 100644 al/eax_fx_slot_index.cpp create mode 100644 al/eax_fx_slot_index.h create mode 100644 al/eax_fx_slots.cpp create mode 100644 al/eax_fx_slots.h create mode 100644 al/eax_globals.cpp create mode 100644 al/eax_globals.h create mode 100644 al/eax_utils.cpp create mode 100644 al/eax_utils.h create mode 100644 al/eax_x_ram.cpp create mode 100644 al/eax_x_ram.h create mode 100644 al/effects/effects.cpp (limited to 'al/effects/distortion.cpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index 93f2c7ec..9480910b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,8 @@ option(ALSOFT_INSTALL_EXAMPLES "Install example programs (alplay, alstream, ...) option(ALSOFT_INSTALL_UTILS "Install utility programs (openal-info, alsoft-config, ...)" ON) option(ALSOFT_UPDATE_BUILD_VERSION "Update git build version info" ON) +option(ALSOFT_EAX "Enable EAX extensions." ON) + if(DEFINED SHARE_INSTALL_DIR) message(WARNING "SHARE_INSTALL_DIR is deprecated. Use the variables provided by the GNUInstallDirs module instead") set(CMAKE_INSTALL_DATADIR "${SHARE_INSTALL_DIR}") @@ -764,6 +766,7 @@ set(OPENAL_OBJS al/effects/dedicated.cpp al/effects/distortion.cpp al/effects/echo.cpp + al/effects/effects.cpp al/effects/effects.h al/effects/equalizer.cpp al/effects/fshifter.cpp @@ -813,6 +816,30 @@ set(ALC_OBJS alc/inprogext.h alc/panning.cpp) +if (ALSOFT_EAX) + set(OPENAL_OBJS + ${OPENAL_OBJS} + al/eax_api.cpp + al/eax_api.h + al/eax_eax_call.cpp + al/eax_eax_call.h + al/eax_effect.cpp + al/eax_effect.h + al/eax_exception.cpp + al/eax_exception.h + al/eax_fx_slot_index.cpp + al/eax_fx_slot_index.h + al/eax_fx_slots.cpp + al/eax_fx_slots.h + al/eax_globals.cpp + al/eax_globals.h + al/eax_utils.cpp + al/eax_utils.h + al/eax_x_ram.cpp + al/eax_x_ram.h +) +endif () + # Include SIMD mixers set(CPU_EXTS "Default") if(HAVE_SSE) @@ -1289,6 +1316,7 @@ target_include_directories(common PRIVATE ${OpenAL_BINARY_DIR} ${OpenAL_SOURCE_D target_compile_definitions(common PRIVATE ${CPP_DEFS}) target_compile_options(common PRIVATE ${C_FLAGS}) set_target_properties(common PROPERTIES POSITION_INDEPENDENT_CODE TRUE) +target_compile_definitions(common PRIVATE "ALSOFT_EAX=$") unset(HAS_ROUTER) @@ -1299,6 +1327,7 @@ if(LIBTYPE STREQUAL "STATIC") add_library(${IMPL_TARGET} STATIC ${COMMON_OBJS} ${OPENAL_OBJS} ${ALC_OBJS} ${CORE_OBJS}) target_compile_definitions(${IMPL_TARGET} PUBLIC AL_LIBTYPE_STATIC) target_link_libraries(${IMPL_TARGET} PRIVATE ${LINKER_FLAGS} ${EXTRA_LIBS} ${MATH_LIB}) + if(WIN32) # This option is for static linking OpenAL Soft into another project # that already defines the IDs. It is up to that project to ensure all @@ -1409,6 +1438,7 @@ set_target_properties(${IMPL_TARGET} PROPERTIES OUTPUT_NAME ${LIBNAME} target_compile_definitions(${IMPL_TARGET} PRIVATE AL_BUILD_LIBRARY AL_ALEXT_PROTOTYPES "ALC_API=${EXPORT_DECL}" "AL_API=${EXPORT_DECL}" ${CPP_DEFS}) +target_compile_definitions(${IMPL_TARGET} PRIVATE "ALSOFT_EAX=$") target_compile_options(${IMPL_TARGET} PRIVATE ${C_FLAGS}) if(TARGET build_version) diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 16e4cbea..40949aa3 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -50,6 +50,10 @@ #include "effect.h" #include "opthelpers.h" +#if ALSOFT_EAX +#include "eax_exception.h" +#include "eax_utils.h" +#endif // ALSOFT_EAX namespace { @@ -1042,3 +1046,833 @@ EffectSlotSubList::~EffectSlotSubList() al_free(EffectSlots); EffectSlots = nullptr; } + +#if ALSOFT_EAX +namespace +{ + + +class EaxFxSlotException : + public EaxException +{ +public: + explicit EaxFxSlotException( + const char* message) + : + EaxException{"EAX_FX_SLOT", message} + { + } +}; // EaxFxSlotException + + +} // namespace + + +void ALeffectslot::eax_initialize( + ALCcontext& al_context, + EaxFxSlotIndexValue index) +{ + eax_al_context_ = &al_context; + + if (index >= EAX_MAX_FXSLOTS) + { + eax_fail("Index out of range."); + } + + eax_fx_slot_index_ = index; + + eax_initialize_eax(); + eax_initialize_effects(); + eax_set_default_slots_defaults(); +} + +void ALeffectslot::eax_uninitialize() noexcept +{ + eax_al_effect_ = nullptr; +} + +const EAX50FXSLOTPROPERTIES& ALeffectslot::eax_get_eax_fx_slot() const noexcept +{ + return eax_eax_fx_slot_; +} + +void ALeffectslot::eax_validate_fx_slot_effect( + const GUID& eax_effect_id) +{ + if (eax_effect_id != EAX_NULL_GUID && + eax_effect_id != EAX_REVERB_EFFECT) + { + eax_fail("Unsupported EAX effect GUID."); + } +} + +void ALeffectslot::eax_validate_fx_slot_volume( + long eax_volume) +{ + eax_validate_range( + "Volume", + eax_volume, + EAXFXSLOT_MINVOLUME, + EAXFXSLOT_MAXVOLUME); +} + +void ALeffectslot::eax_validate_fx_slot_lock( + long eax_lock) +{ + eax_validate_range( + "Lock", + eax_lock, + EAXFXSLOT_MINLOCK, + EAXFXSLOT_MAXLOCK); +} + +void ALeffectslot::eax_validate_fx_slot_lock_state( + long eax_lock, + const GUID& eax_effect_id) +{ + if (eax_lock == EAXFXSLOT_LOCKED && eax_effect_id != eax_eax_fx_slot_.guidLoadEffect) + { + eax_fail("Loading an effect in a locked slot."); + } +} + +void ALeffectslot::eax_validate_fx_slot_flags( + unsigned long eax_flags, + int eax_version) +{ + eax_validate_range( + "Flags", + eax_flags, + 0UL, + ~(eax_version == 4 ? EAX40FXSLOTFLAGS_RESERVED : EAX50FXSLOTFLAGS_RESERVED)); +} + +void ALeffectslot::eax_validate_fx_slot_occlusion( + long eax_occlusion) +{ + eax_validate_range( + "Occlusion", + eax_occlusion, + EAXFXSLOT_MINOCCLUSION, + EAXFXSLOT_MAXOCCLUSION); +} + +void ALeffectslot::eax_validate_fx_slot_occlusion_lf_ratio( + float eax_occlusion_lf_ratio) +{ + eax_validate_range( + "Occlusion LF Ratio", + eax_occlusion_lf_ratio, + EAXFXSLOT_MINOCCLUSIONLFRATIO, + EAXFXSLOT_MAXOCCLUSIONLFRATIO); +} + +void ALeffectslot::eax_validate_fx_slot_all( + const EAX40FXSLOTPROPERTIES& fx_slot, + int eax_version) +{ + eax_validate_fx_slot_effect(fx_slot.guidLoadEffect); + eax_validate_fx_slot_volume(fx_slot.lVolume); + eax_validate_fx_slot_lock(fx_slot.lLock); + eax_validate_fx_slot_flags(fx_slot.ulFlags, eax_version); +} + +void ALeffectslot::eax_validate_fx_slot_all( + const EAX50FXSLOTPROPERTIES& fx_slot, + int eax_version) +{ + eax_validate_fx_slot_all(static_cast(fx_slot), eax_version); + + eax_validate_fx_slot_occlusion(fx_slot.lOcclusion); + eax_validate_fx_slot_occlusion_lf_ratio(fx_slot.flOcclusionLFRatio); +} + +void ALeffectslot::eax_set_fx_slot_effect( + const GUID& eax_effect_id) +{ + if (eax_eax_fx_slot_.guidLoadEffect == eax_effect_id) + { + return; + } + + eax_eax_fx_slot_.guidLoadEffect = eax_effect_id; + + eax_set_fx_slot_effect(); +} + +void ALeffectslot::eax_set_fx_slot_volume( + long eax_volume) +{ + if (eax_eax_fx_slot_.lVolume == eax_volume) + { + return; + } + + eax_eax_fx_slot_.lVolume = eax_volume; + + eax_set_fx_slot_volume(); +} + +void ALeffectslot::eax_set_fx_slot_lock( + long eax_lock) +{ + if (eax_eax_fx_slot_.lLock == eax_lock) + { + return; + } + + eax_eax_fx_slot_.lLock = eax_lock; +} + +void ALeffectslot::eax_set_fx_slot_flags( + unsigned long eax_flags) +{ + if (eax_eax_fx_slot_.ulFlags == eax_flags) + { + return; + } + + eax_eax_fx_slot_.ulFlags = eax_flags; + + eax_set_fx_slot_flags(); +} + +// [[nodiscard]] +bool ALeffectslot::eax_set_fx_slot_occlusion( + long eax_occlusion) +{ + if (eax_eax_fx_slot_.lOcclusion == eax_occlusion) + { + return false; + } + + eax_eax_fx_slot_.lOcclusion = eax_occlusion; + + return true; +} + +// [[nodiscard]] +bool ALeffectslot::eax_set_fx_slot_occlusion_lf_ratio( + float eax_occlusion_lf_ratio) +{ + if (eax_eax_fx_slot_.flOcclusionLFRatio == eax_occlusion_lf_ratio) + { + return false; + } + + eax_eax_fx_slot_.flOcclusionLFRatio = eax_occlusion_lf_ratio; + + return true; +} + +void ALeffectslot::eax_set_fx_slot_all( + const EAX40FXSLOTPROPERTIES& eax_fx_slot) +{ + eax_set_fx_slot_effect(eax_fx_slot.guidLoadEffect); + eax_set_fx_slot_volume(eax_fx_slot.lVolume); + eax_set_fx_slot_lock(eax_fx_slot.lLock); + eax_set_fx_slot_flags(eax_fx_slot.ulFlags); +} + +// [[nodiscard]] +bool ALeffectslot::eax_set_fx_slot_all( + const EAX50FXSLOTPROPERTIES& eax_fx_slot) +{ + eax_set_fx_slot_all(static_cast(eax_fx_slot)); + + const auto is_occlusion_modified = eax_set_fx_slot_occlusion(eax_fx_slot.lOcclusion); + const auto is_occlusion_lf_ratio_modified = eax_set_fx_slot_occlusion_lf_ratio(eax_fx_slot.flOcclusionLFRatio); + + return is_occlusion_modified || is_occlusion_lf_ratio_modified; +} + +// [[nodiscard]] +bool ALeffectslot::eax_dispatch( + const EaxEaxCall& eax_call) +{ + return eax_call.is_get() ? eax_get(eax_call) : eax_set(eax_call); +} + +[[noreturn]] +void ALeffectslot::eax_fail( + const char* message) +{ + throw EaxFxSlotException{message}; +} + +void ALeffectslot::eax_set_eax_fx_slot_defaults() +{ + eax_eax_fx_slot_.guidLoadEffect = EAX_NULL_GUID; + eax_eax_fx_slot_.lVolume = EAXFXSLOT_DEFAULTVOLUME; + eax_eax_fx_slot_.lLock = EAXFXSLOT_UNLOCKED; + eax_eax_fx_slot_.ulFlags = EAX50FXSLOT_DEFAULTFLAGS; + eax_eax_fx_slot_.lOcclusion = EAXFXSLOT_DEFAULTOCCLUSION; + eax_eax_fx_slot_.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO; +} + +void ALeffectslot::eax_initialize_eax() +{ + eax_set_eax_fx_slot_defaults(); +} + +void ALeffectslot::eax_initialize_effects() +{ + eax_set_fx_slot_effect(); +} + +void ALeffectslot::eax_set_default_slot_0_defaults() +{ + eax_set_fx_slot_effect(EAX_REVERB_EFFECT); +} + +void ALeffectslot::eax_set_default_slot_1_defaults() +{ + eax_set_fx_slot_effect(EAX_CHORUS_EFFECT); +} + +void ALeffectslot::eax_set_default_slots_defaults() +{ + switch (eax_fx_slot_index_) + { + case 0: + eax_set_default_slot_0_defaults(); + break; + + case 1: + eax_set_default_slot_1_defaults(); + break; + + case 2: + case 3: + break; + + default: + eax_fail("FX slot index out of range."); + } +} + +void ALeffectslot::eax_get_fx_slot_all( + const EaxEaxCall& eax_call) const +{ + switch (eax_call.get_version()) + { + case 4: + eax_call.set_value(eax_eax_fx_slot_); + break; + + case 5: + eax_call.set_value(eax_eax_fx_slot_); + break; + + default: + eax_fail("Unsupported EAX version."); + } +} + +void ALeffectslot::eax_get_fx_slot( + const EaxEaxCall& eax_call) const +{ + switch (eax_call.get_property_id()) + { + case EAXFXSLOT_ALLPARAMETERS: + eax_get_fx_slot_all(eax_call); + break; + + case EAXFXSLOT_LOADEFFECT: + eax_call.set_value(eax_eax_fx_slot_.guidLoadEffect); + break; + + case EAXFXSLOT_VOLUME: + eax_call.set_value(eax_eax_fx_slot_.lVolume); + break; + + case EAXFXSLOT_LOCK: + eax_call.set_value(eax_eax_fx_slot_.lLock); + break; + + case EAXFXSLOT_FLAGS: + eax_call.set_value(eax_eax_fx_slot_.ulFlags); + break; + + case EAXFXSLOT_OCCLUSION: + eax_call.set_value(eax_eax_fx_slot_.lOcclusion); + break; + + case EAXFXSLOT_OCCLUSIONLFRATIO: + eax_call.set_value(eax_eax_fx_slot_.flOcclusionLFRatio); + break; + + default: + eax_fail("Unsupported FX slot property id."); + } +} + +// [[nodiscard]] +bool ALeffectslot::eax_get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_set_id()) + { + case EaxEaxCallPropertySetId::fx_slot: + eax_get_fx_slot(eax_call); + break; + + case EaxEaxCallPropertySetId::fx_slot_effect: + eax_dispatch_effect(eax_call); + break; + + default: + eax_fail("Unsupported property id."); + } + + return false; +} + +void ALeffectslot::eax_set_fx_slot_effect( + ALenum al_effect_type) +{ + if (!eax_al_effect_) + { + eax_al_effect_ = eax_create_al_effect(*eax_al_context_, al_effect_type); + } + else + { + auto& device = eax_al_context_->mALDevice; + std::lock_guard effect_lock{device->EffectLock}; + + eax_al_effect_->eax_al_set_effect(al_effect_type); + } + + eax_al_effect_->eax_initialize(); + + eax_set_effect_slot_effect(*eax_al_effect_); +} + +void ALeffectslot::eax_set_fx_slot_effect() +{ + auto al_effect_type = ALenum{}; + + if (false) + { + } + else if (eax_eax_fx_slot_.guidLoadEffect == EAX_NULL_GUID) + { + al_effect_type = AL_EFFECT_NULL; + } + else if (eax_eax_fx_slot_.guidLoadEffect == EAX_AUTOWAH_EFFECT) + { + al_effect_type = AL_EFFECT_AUTOWAH; + } + else if (eax_eax_fx_slot_.guidLoadEffect == EAX_CHORUS_EFFECT) + { + al_effect_type = AL_EFFECT_CHORUS; + } + else if (eax_eax_fx_slot_.guidLoadEffect == EAX_AGCCOMPRESSOR_EFFECT) + { + al_effect_type = AL_EFFECT_COMPRESSOR; + } + else if (eax_eax_fx_slot_.guidLoadEffect == EAX_DISTORTION_EFFECT) + { + al_effect_type = AL_EFFECT_DISTORTION; + } + else if (eax_eax_fx_slot_.guidLoadEffect == EAX_REVERB_EFFECT) + { + al_effect_type = AL_EFFECT_EAXREVERB; + } + else if (eax_eax_fx_slot_.guidLoadEffect == EAX_ECHO_EFFECT) + { + al_effect_type = AL_EFFECT_ECHO; + } + else if (eax_eax_fx_slot_.guidLoadEffect == EAX_EQUALIZER_EFFECT) + { + al_effect_type = AL_EFFECT_EQUALIZER; + } + else if (eax_eax_fx_slot_.guidLoadEffect == EAX_FLANGER_EFFECT) + { + al_effect_type = AL_EFFECT_FLANGER; + } + else if (eax_eax_fx_slot_.guidLoadEffect == EAX_FREQUENCYSHIFTER_EFFECT) + { + al_effect_type = AL_EFFECT_FREQUENCY_SHIFTER; + } + else if (eax_eax_fx_slot_.guidLoadEffect == EAX_PITCHSHIFTER_EFFECT) + { + al_effect_type = AL_EFFECT_PITCH_SHIFTER; + } + else if (eax_eax_fx_slot_.guidLoadEffect == EAX_RINGMODULATOR_EFFECT) + { + al_effect_type = AL_EFFECT_RING_MODULATOR; + } + else if (eax_eax_fx_slot_.guidLoadEffect == EAX_VOCALMORPHER_EFFECT) + { + al_effect_type = AL_EFFECT_VOCAL_MORPHER; + } + else + { + eax_fail("Unsupported effect."); + } + + eax_set_fx_slot_effect(al_effect_type); +} + +void ALeffectslot::eax_set_efx_effect_slot_gain() +{ + const auto gain = level_mb_to_gain( + static_cast(clamp( + eax_eax_fx_slot_.lVolume, + EAXFXSLOT_MINVOLUME, + EAXFXSLOT_MAXVOLUME))); + + eax_set_effect_slot_gain(gain); +} + +void ALeffectslot::eax_set_fx_slot_volume() +{ + eax_set_efx_effect_slot_gain(); +} + +void ALeffectslot::eax_set_effect_slot_send_auto() +{ + eax_set_effect_slot_send_auto((eax_eax_fx_slot_.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0); +} + +void ALeffectslot::eax_set_fx_slot_flags() +{ + eax_set_effect_slot_send_auto(); +} + +void ALeffectslot::eax_set_fx_slot_effect( + const EaxEaxCall& eax_call) +{ + const auto& eax_effect_id = + eax_call.get_value(); + + eax_validate_fx_slot_effect(eax_effect_id); + eax_validate_fx_slot_lock_state(eax_eax_fx_slot_.lLock, eax_effect_id); + + eax_set_fx_slot_effect(eax_effect_id); +} + +void ALeffectslot::eax_set_fx_slot_volume( + const EaxEaxCall& eax_call) +{ + const auto& eax_volume = + eax_call.get_value(); + + eax_validate_fx_slot_volume(eax_volume); + eax_set_fx_slot_volume(eax_volume); +} + +void ALeffectslot::eax_set_fx_slot_lock( + const EaxEaxCall& eax_call) +{ + const auto& eax_lock = + eax_call.get_value(); + + eax_validate_fx_slot_lock(eax_lock); + eax_set_fx_slot_lock(eax_lock); +} + +void ALeffectslot::eax_set_fx_slot_flags( + const EaxEaxCall& eax_call) +{ + const auto& eax_flags = + eax_call.get_value(); + + eax_validate_fx_slot_flags(eax_flags, eax_call.get_version()); + eax_set_fx_slot_flags(eax_flags); +} + +// [[nodiscard]] +bool ALeffectslot::eax_set_fx_slot_occlusion( + const EaxEaxCall& eax_call) +{ + const auto& eax_occlusion = + eax_call.get_value(); + + eax_validate_fx_slot_occlusion(eax_occlusion); + + return eax_set_fx_slot_occlusion(eax_occlusion); +} + +// [[nodiscard]] +bool ALeffectslot::eax_set_fx_slot_occlusion_lf_ratio( + const EaxEaxCall& eax_call) +{ + const auto& eax_occlusion_lf_ratio = + eax_call.get_value(); + + eax_validate_fx_slot_occlusion_lf_ratio(eax_occlusion_lf_ratio); + + return eax_set_fx_slot_occlusion_lf_ratio(eax_occlusion_lf_ratio); +} + +// [[nodiscard]] +bool ALeffectslot::eax_set_fx_slot_all( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_version()) + { + case 4: + { + const auto& eax_all = + eax_call.get_value(); + + eax_validate_fx_slot_all(eax_all, eax_call.get_version()); + eax_set_fx_slot_all(eax_all); + + return false; + } + + case 5: + { + const auto& eax_all = + eax_call.get_value(); + + eax_validate_fx_slot_all(eax_all, eax_call.get_version()); + return eax_set_fx_slot_all(eax_all); + } + + default: + eax_fail("Unsupported EAX version."); + } +} + +bool ALeffectslot::eax_set_fx_slot( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXFXSLOT_NONE: + return false; + + case EAXFXSLOT_ALLPARAMETERS: + return eax_set_fx_slot_all(eax_call); + + case EAXFXSLOT_LOADEFFECT: + eax_set_fx_slot_effect(eax_call); + return false; + + case EAXFXSLOT_VOLUME: + eax_set_fx_slot_volume(eax_call); + return false; + + case EAXFXSLOT_LOCK: + eax_set_fx_slot_lock(eax_call); + return false; + + case EAXFXSLOT_FLAGS: + eax_set_fx_slot_flags(eax_call); + return false; + + case EAXFXSLOT_OCCLUSION: + return eax_set_fx_slot_occlusion(eax_call); + + case EAXFXSLOT_OCCLUSIONLFRATIO: + return eax_set_fx_slot_occlusion_lf_ratio(eax_call); + + + default: + eax_fail("Unsupported FX slot property id."); + } +} + +// [[nodiscard]] +bool ALeffectslot::eax_set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_set_id()) + { + case EaxEaxCallPropertySetId::fx_slot: + return eax_set_fx_slot(eax_call); + + case EaxEaxCallPropertySetId::fx_slot_effect: + eax_dispatch_effect(eax_call); + return false; + + default: + eax_fail("Unsupported property id."); + } +} + +void ALeffectslot::eax_dispatch_effect( + const EaxEaxCall& eax_call) +{ + auto is_changed = false; + + { + std::lock_guard effect_lock{eax_al_context_->mALDevice->EffectLock}; + + if (!eax_al_effect_->eax_effect) + { + return; + } + + is_changed = eax_al_effect_->eax_effect->dispatch(eax_call); + } + + if (is_changed) + { + eax_set_effect_slot_effect(*eax_al_effect_); + } +} + +void ALeffectslot::eax_set_effect_slot_effect( + ALeffect& effect) +{ +#define EAX_PREFIX "[EAX_SET_EFFECT_SLOT_EFFECT] " + + auto& device = *eax_al_context_->mALDevice; + + std::lock_guard effect_slot_lock{eax_al_context_->mEffectSlotLock}; + std::lock_guard effect_lock{device.EffectLock}; + + const auto error = initEffect(&effect, eax_al_context_); + + if (error != AL_NO_ERROR) + { + ERR(EAX_PREFIX "%s\n", "Failed to initialize an effect."); + return; + } + + if (mState == SlotState::Initial) + { + mPropsDirty.test_and_clear(std::memory_order_acq_rel); + updateProps(eax_al_context_); + + auto effect_slot_ptr = this; + + AddActiveEffectSlots({&effect_slot_ptr, 1}, eax_al_context_); + mState = SlotState::Playing; + + return; + } + + { + auto context = EaxAlContextWrapper{*eax_al_context_}; + auto slot = this; + + DO_UPDATEPROPS(); + } + +#undef EAX_PREFIX +} + +void ALeffectslot::eax_set_effect_slot_send_auto( + bool is_send_auto) +{ + std::lock_guard effect_slot_lock{eax_al_context_->mEffectSlotLock}; + + const auto is_changed = (AuxSendAuto != is_send_auto); + + AuxSendAuto = is_send_auto; + + if (is_changed) + { + auto context = EaxAlContextWrapper{*eax_al_context_}; + auto slot = this; + + DO_UPDATEPROPS(); + } +} + +void ALeffectslot::eax_set_effect_slot_gain( + ALfloat gain) +{ +#define EAX_PREFIX "[EAX_SET_EFFECT_SLOT_GAIN] " + + if (gain < 0.0F || gain > 1.0F) + { + ERR(EAX_PREFIX "%s\n", "Gain out of range."); + return; + } + + std::lock_guard effect_slot_lock{eax_al_context_->mEffectSlotLock}; + + const auto is_changed = (Gain != gain); + + Gain = gain; + + if (is_changed) + { + auto context = EaxAlContextWrapper{*eax_al_context_}; + auto slot = this; + + DO_UPDATEPROPS(); + } + +#undef EAX_PREFIX +} + + +EaxAlEffectSlotDeleter::EaxAlEffectSlotDeleter( + ALCcontext& context) noexcept + : + context_{&context} +{ +} + +void EaxAlEffectSlotDeleter::operator()( + ALeffectslot* effect_slot) +{ + assert(effect_slot); + eax_delete_al_effect_slot(*context_, *effect_slot); +} + + +EaxAlEffectSlotUPtr eax_create_al_effect_slot( + ALCcontext& context) +{ +#define EAX_PREFIX "[EAX_MAKE_EFFECT_SLOT] " + + std::unique_lock effect_slot_lock{context.mEffectSlotLock}; + + auto& device = *context.mALDevice; + + if (context.mNumEffectSlots == device.AuxiliaryEffectSlotMax) + { + ERR(EAX_PREFIX "%s\n", "Out of memory."); + return nullptr; + } + + if (!EnsureEffectSlots(&context, 1)) + { + ERR(EAX_PREFIX "%s\n", "Failed to ensure."); + return nullptr; + } + + auto effect_slot = EaxAlEffectSlotUPtr{AllocEffectSlot(&context), EaxAlEffectSlotDeleter{context}}; + + if (!effect_slot) + { + ERR(EAX_PREFIX "%s\n", "Failed to allocate."); + return nullptr; + } + + return effect_slot; + +#undef EAX_PREFIX +} + +void eax_delete_al_effect_slot( + ALCcontext& context, + ALeffectslot& effect_slot) +{ +#define EAX_PREFIX "[EAX_DELETE_EFFECT_SLOT] " + + std::lock_guard effect_slot_lock{context.mEffectSlotLock}; + + if (ReadRef(effect_slot.ref) != 0) + { + ERR(EAX_PREFIX "Deleting in-use effect slot %u.\n", effect_slot.id); + return; + } + + auto effect_slot_ptr = &effect_slot; + + RemoveActiveEffectSlots({&effect_slot_ptr, 1}, &context); + FreeEffectSlot(&context, &effect_slot); + +#undef EAX_PREFIX +} +#endif // ALSOFT_EAX diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 4de1df7a..54f1987d 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -16,6 +16,15 @@ #include "intrusive_ptr.h" #include "vector.h" +#if ALSOFT_EAX +#include + +#include "al/effect.h" + +#include "eax_eax_call.h" +#include "eax_fx_slot_index.h" +#endif // ALSOFT_EAX + struct ALbuffer; struct ALeffect; struct WetBuffer; @@ -61,8 +70,220 @@ struct ALeffectslot { /* This can be new'd for the context's default effect slot. */ DEF_NEWDEL(ALeffectslot) + + +#if ALSOFT_EAX +public: + void eax_initialize( + ALCcontext& al_context, + EaxFxSlotIndexValue index); + + void eax_uninitialize() noexcept; + + + const EAX50FXSLOTPROPERTIES& eax_get_eax_fx_slot() const noexcept; + + + // [[nodiscard]] + bool eax_dispatch( + const EaxEaxCall& eax_call); + + +private: + ALCcontext* eax_al_context_{}; + + EaxFxSlotIndexValue eax_fx_slot_index_{}; + + EAX50FXSLOTPROPERTIES eax_eax_fx_slot_{}; + + EaxAlEffectUPtr eax_al_effect_{}; + + + [[noreturn]] + static void eax_fail( + const char* message); + + + void eax_set_eax_fx_slot_defaults(); + + void eax_initialize_eax(); + + + void eax_initialize_effects(); + + + void eax_set_default_slot_0_defaults(); + + void eax_set_default_slot_1_defaults(); + + void eax_set_default_slots_defaults(); + + + void eax_get_fx_slot_all( + const EaxEaxCall& eax_call) const; + + void eax_get_fx_slot( + const EaxEaxCall& eax_call) const; + + // [[nodiscard]] + bool eax_get( + const EaxEaxCall& eax_call); + + + void eax_set_fx_slot_effect( + ALenum effect_type); + + void eax_set_fx_slot_effect(); + + + void eax_set_efx_effect_slot_gain(); + + void eax_set_fx_slot_volume(); + + + void eax_set_effect_slot_send_auto(); + + void eax_set_fx_slot_flags(); + + + void eax_validate_fx_slot_effect( + const GUID& eax_effect_id); + + void eax_validate_fx_slot_volume( + long eax_volume); + + void eax_validate_fx_slot_lock( + long eax_lock); + + void eax_validate_fx_slot_lock_state( + long eax_lock, + const GUID& eax_effect_id); + + void eax_validate_fx_slot_flags( + unsigned long eax_flags, + int eax_version); + + void eax_validate_fx_slot_occlusion( + long eax_occlusion); + + void eax_validate_fx_slot_occlusion_lf_ratio( + float eax_occlusion_lf_ratio); + + void eax_validate_fx_slot_all( + const EAX40FXSLOTPROPERTIES& fx_slot, + int eax_version); + + void eax_validate_fx_slot_all( + const EAX50FXSLOTPROPERTIES& fx_slot, + int eax_version); + + + void eax_set_fx_slot_effect( + const GUID& eax_effect_id); + + void eax_set_fx_slot_volume( + long eax_volume); + + void eax_set_fx_slot_lock( + long eax_lock); + + void eax_set_fx_slot_flags( + unsigned long eax_flags); + + // [[nodiscard]] + bool eax_set_fx_slot_occlusion( + long eax_occlusion); + + // [[nodiscard]] + bool eax_set_fx_slot_occlusion_lf_ratio( + float eax_occlusion_lf_ratio); + + void eax_set_fx_slot_all( + const EAX40FXSLOTPROPERTIES& eax_fx_slot); + + // [[nodiscard]] + bool eax_set_fx_slot_all( + const EAX50FXSLOTPROPERTIES& eax_fx_slot); + + + void eax_set_fx_slot_effect( + const EaxEaxCall& eax_call); + + void eax_set_fx_slot_volume( + const EaxEaxCall& eax_call); + + void eax_set_fx_slot_lock( + const EaxEaxCall& eax_call); + + void eax_set_fx_slot_flags( + const EaxEaxCall& eax_call); + + // [[nodiscard]] + bool eax_set_fx_slot_occlusion( + const EaxEaxCall& eax_call); + + // [[nodiscard]] + bool eax_set_fx_slot_occlusion_lf_ratio( + const EaxEaxCall& eax_call); + + // [[nodiscard]] + bool eax_set_fx_slot_all( + const EaxEaxCall& eax_call); + + bool eax_set_fx_slot( + const EaxEaxCall& eax_call); + + // [[nodiscard]] + bool eax_set( + const EaxEaxCall& eax_call); + + + void eax_dispatch_effect( + const EaxEaxCall& eax_call); + + + // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)` + void eax_set_effect_slot_effect( + ALeffect& effect); + + // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, value)` + void eax_set_effect_slot_send_auto( + bool is_send_auto); + + // `alAuxiliaryEffectSlotf(effect_slot, AL_EFFECTSLOT_GAIN, gain)` + void eax_set_effect_slot_gain( + ALfloat gain); +#endif // ALSOFT_EAX }; void UpdateAllEffectSlotProps(ALCcontext *context); +#if ALSOFT_EAX +class EaxAlEffectSlotDeleter +{ +public: + EaxAlEffectSlotDeleter() noexcept = default; + + EaxAlEffectSlotDeleter( + ALCcontext& context) noexcept; + + void operator()( + ALeffectslot* effect_slot); + + +private: + ALCcontext* context_{}; +}; // EaxAlEffectSlotDeleter + +using EaxAlEffectSlotUPtr = std::unique_ptr; + + +EaxAlEffectSlotUPtr eax_create_al_effect_slot( + ALCcontext& context); + +void eax_delete_al_effect_slot( + ALCcontext& context, + ALeffectslot& effect_slot); +#endif // ALSOFT_EAX + #endif diff --git a/al/buffer.cpp b/al/buffer.cpp index a473c3f9..a4967223 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -56,6 +56,11 @@ #include "core/voice.h" #include "opthelpers.h" +#if ALSOFT_EAX +#include "eax_globals.h" +#include "eax_x_ram.h" +#endif // ALSOFT_EAX + namespace { @@ -412,6 +417,15 @@ ALbuffer *AllocBuffer(ALCdevice *device) void FreeBuffer(ALCdevice *device, ALbuffer *buffer) { +#if ALSOFT_EAX + if (buffer->eax_x_ram_is_hardware) + { + const auto buffer_size = static_cast(buffer->OriginalSize); + assert((device->eax_x_ram_free_size + buffer_size) <= eax_x_ram_max_size); + device->eax_x_ram_free_size += buffer_size; + } +#endif // ALSOFT_EAX + const ALuint id{buffer->id - 1}; const size_t lidx{id >> 6}; const ALuint slidx{id & 0x3f}; @@ -485,6 +499,102 @@ const ALchar *NameFromUserFmtType(UserFmtType type) return ""; } +#if ALSOFT_EAX +bool eax_x_ram_validate_buffer( + ALCdevice& al_device, + ALbuffer& al_buffer) +{ + switch (al_buffer.eax_x_ram_mode) + { + case AL_STORAGE_HARDWARE: + if (al_buffer.OriginalSize > static_cast(al_device.eax_x_ram_free_size)) + { + return false; + } + + break; + + case AL_STORAGE_AUTOMATIC: + case AL_STORAGE_ACCESSIBLE: + break; + + default: + assert(false && "Unsupported X-RAM mode."); + return false; + } + + return true; +} + +void eax_x_ram_update_buffer( + ALCdevice& al_device, + ALbuffer& al_buffer) +{ + const auto buffer_size = static_cast(al_buffer.OriginalSize); + + auto is_hardware = al_buffer.eax_x_ram_is_hardware; + auto size_delta = ALsizei{}; + + switch (al_buffer.eax_x_ram_mode) + { + case AL_STORAGE_AUTOMATIC: + if (!al_buffer.eax_x_ram_is_dirty) + { + // First usage. + + if (buffer_size <= al_device.eax_x_ram_free_size) + { + // Have enough X-RAM memory. + + is_hardware = true; + size_delta = -buffer_size; + } + } + else + { + // Used at least once. + // From now on, use only system memory. + + is_hardware = false; + + if (al_buffer.eax_x_ram_is_hardware) + { + // First allocation was in X-RAM. + // Free that block. + + size_delta = buffer_size; + } + } + + break; + + case AL_STORAGE_HARDWARE: + is_hardware = true; + size_delta = buffer_size; + + break; + + case AL_STORAGE_ACCESSIBLE: + // Always use system memory. + is_hardware = false; + break; + + default: + break; + } + + al_buffer.eax_x_ram_is_hardware = is_hardware; + al_buffer.eax_x_ram_is_dirty = true; + + assert( + (al_device.eax_x_ram_free_size + size_delta) >= eax_x_ram_min_size && + (al_device.eax_x_ram_free_size + size_delta) <= eax_x_ram_max_size + ); + + al_device.eax_x_ram_free_size += size_delta; +} +#endif // ALSOFT_EAX + /** Loads the specified data into the buffer, using the specified format. */ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size, UserFmtChannels SrcChannels, UserFmtType SrcType, const al::byte *SrcData, @@ -620,6 +730,13 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size, ALBuf->mSampleLen = frames; ALBuf->mLoopStart = 0; ALBuf->mLoopEnd = ALBuf->mSampleLen; + +#if ALSOFT_EAX + if (eax_g_is_enabled) + { + eax_x_ram_update_buffer(*context->mALDevice, *ALBuf); + } +#endif // ALSOFT_EAX } /** Prepares the buffer to use the specified callback, using the specified format. */ @@ -889,8 +1006,24 @@ START_API_FUNC if UNLIKELY(!usrfmt) context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format); else +#if ALSOFT_EAX + { + if (eax_g_is_enabled) + { + const auto is_buffer_valid = eax_x_ram_validate_buffer(*device, *albuf); + + if (!is_buffer_valid) + { + context->setError(AL_OUT_OF_MEMORY, "Out of X-RAM memory."); + return; + } + } +#endif // ALSOFT_EAX LoadData(context.get(), albuf, freq, static_cast(size), usrfmt->channels, usrfmt->type, static_cast(data), flags); +#if ALSOFT_EAX + } +#endif // ALSOFT_EAX } } END_API_FUNC @@ -1642,3 +1775,162 @@ BufferSubList::~BufferSubList() al_free(Buffers); Buffers = nullptr; } + + +#if ALSOFT_EAX +ALboolean AL_APIENTRY EAXSetBufferMode( + ALsizei n, + const ALuint* buffers, + ALint value) +START_API_FUNC +{ +#define EAX_PREFIX "[EAXSetBufferMode] " + + if (n == 0) + { + return ALC_TRUE; + } + + if (n < 0) + { + ERR(EAX_PREFIX "Buffer count %d out of range.\n", n); + return ALC_FALSE; + } + + if (!buffers) + { + ERR(EAX_PREFIX "%s\n", "Null AL buffers."); + return ALC_FALSE; + } + + switch (value) + { + case AL_STORAGE_AUTOMATIC: + case AL_STORAGE_HARDWARE: + case AL_STORAGE_ACCESSIBLE: + break; + + default: + ERR(EAX_PREFIX "Unsupported X-RAM mode %d.\n", value); + return ALC_FALSE; + } + + const auto context = ContextRef{GetContextRef()}; + + if (!context) + { + ERR(EAX_PREFIX "%s\n", "No current context."); + return ALC_FALSE; + } + + if (!eax_g_is_enabled) + { + ERR(EAX_PREFIX "%s\n", "EAX not enabled."); + return ALC_FALSE; + } + + auto device = context->mALDevice.get(); + std::lock_guard device_lock{device->BufferLock}; + + // Validate the buffers. + // + for (auto i = 0; i < n; ++i) + { + const auto buffer = buffers[i]; + + if (buffer == AL_NONE) + { + continue; + } + + const auto al_buffer = LookupBuffer(device, buffer); + + if (!al_buffer) + { + ERR(EAX_PREFIX "Invalid buffer ID %u.\n", buffer); + return ALC_FALSE; + } + + if (al_buffer->eax_x_ram_is_dirty) + { + ERR(EAX_PREFIX "Buffer %u has audio data.\n", buffer); + return ALC_FALSE; + } + } + + // Update the mode. + // + for (auto i = 0; i < n; ++i) + { + const auto buffer = buffers[i]; + + if (buffer == AL_NONE) + { + continue; + } + + const auto al_buffer = LookupBuffer(device, buffer); + assert(al_buffer); + assert(!al_buffer->eax_x_ram_is_dirty); + + al_buffer->eax_x_ram_mode = value; + } + + return AL_TRUE; + +#undef EAX_PREFIX +} +END_API_FUNC + +ALenum AL_APIENTRY EAXGetBufferMode( + ALuint buffer, + ALint* pReserved) +START_API_FUNC +{ +#define EAX_PREFIX "[EAXGetBufferMode] " + + if (buffer == AL_NONE) + { + ERR(EAX_PREFIX "%s\n", "Null AL buffer."); + return AL_NONE; + } + + if (pReserved) + { + ERR(EAX_PREFIX "%s\n", "Non-null reserved parameter."); + return AL_NONE; + } + + const auto context = ContextRef{GetContextRef()}; + + if (!context) + { + ERR(EAX_PREFIX "%s\n", "No current context."); + return AL_NONE; + } + + if (!eax_g_is_enabled) + { + ERR(EAX_PREFIX "%s\n", "EAX not enabled."); + return AL_NONE; + } + + auto device = context->mALDevice.get(); + std::lock_guard device_lock{device->BufferLock}; + + const auto al_buffer = LookupBuffer(device, buffer); + + if (!al_buffer) + { + ERR(EAX_PREFIX "Invalid buffer ID %u.\n", buffer); + return AL_NONE; + } + + return al_buffer->eax_x_ram_mode; + +#undef EAX_PREFIX +} +END_API_FUNC + + +#endif // ALSOFT_EAX diff --git a/al/buffer.h b/al/buffer.h index a78c65c6..0514d984 100644 --- a/al/buffer.h +++ b/al/buffer.h @@ -12,6 +12,9 @@ #include "core/buffer_storage.h" #include "vector.h" +#if ALSOFT_EAX +#include "eax_x_ram.h" +#endif // ALSOFT_EAX /* User formats */ enum UserFmtType : unsigned char { @@ -68,6 +71,12 @@ struct ALbuffer : public BufferStorage { ALuint id{0}; DISABLE_ALLOC() + +#if ALSOFT_EAX + ALenum eax_x_ram_mode{AL_STORAGE_AUTOMATIC}; + bool eax_x_ram_is_hardware{}; + bool eax_x_ram_is_dirty{}; +#endif // ALSOFT_EAX }; #endif diff --git a/al/eax_api.cpp b/al/eax_api.cpp new file mode 100644 index 00000000..9907dd4d --- /dev/null +++ b/al/eax_api.cpp @@ -0,0 +1,1151 @@ +// +// EAX API. +// +// Based on headers `eax[2-5].h` included in Doom 3 source code: +// https://github.com/id-Software/DOOM-3/tree/master/neo/openal/include +// + + +#include + +#include "al/eax_api.h" + + +const GUID DSPROPSETID_EAX20_ListenerProperties = +{ + 0x306A6A8, + 0xB224, + 0x11D2, + {0x99, 0xE5, 0x00, 0x00, 0xE8, 0xD8, 0xC7, 0x22} +}; + +const GUID DSPROPSETID_EAX20_BufferProperties = +{ + 0x306A6A7, + 0xB224, + 0x11D2, + {0x99, 0xE5, 0x00, 0x00, 0xE8, 0xD8, 0xC7, 0x22} +}; + +const GUID DSPROPSETID_EAX30_ListenerProperties = +{ + 0xA8FA6882, + 0xB476, + 0x11D3, + {0xBD, 0xB9, 0x00, 0xC0, 0xF0, 0x2D, 0xDF, 0x87} +}; + +const GUID DSPROPSETID_EAX30_BufferProperties = +{ + 0xA8FA6881, + 0xB476, + 0x11D3, + {0xBD, 0xB9, 0x00, 0xC0, 0xF0, 0x2D, 0xDF, 0x87} +}; + +const GUID EAX_NULL_GUID = +{ + 0x00000000, + 0x0000, + 0x0000, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; + +const GUID EAX_PrimaryFXSlotID = +{ + 0xF317866D, + 0x924C, + 0x450C, + {0x86, 0x1B, 0xE6, 0xDA, 0xA2, 0x5E, 0x7C, 0x20} +}; + +const GUID EAXPROPERTYID_EAX40_Context = +{ + 0x1D4870AD, + 0xDEF, + 0x43C0, + {0xA4, 0xC, 0x52, 0x36, 0x32, 0x29, 0x63, 0x42} +}; + +const GUID EAXPROPERTYID_EAX50_Context = +{ + 0x57E13437, + 0xB932, + 0x4AB2, + {0xB8, 0xBD, 0x52, 0x66, 0xC1, 0xA8, 0x87, 0xEE} +}; + +const GUID EAXPROPERTYID_EAX40_FXSlot0 = +{ + 0xC4D79F1E, + 0xF1AC, + 0x436B, + {0xA8, 0x1D, 0xA7, 0x38, 0xE7, 0x04, 0x54, 0x69} +}; + +const GUID EAXPROPERTYID_EAX50_FXSlot0 = +{ + 0x91F9590F, + 0xC388, + 0x407A, + {0x84, 0xB0, 0x1B, 0xAE, 0xE, 0xF7, 0x1A, 0xBC} +}; + +const GUID EAXPROPERTYID_EAX40_FXSlot1 = +{ + 0x8C00E96, + 0x74BE, + 0x4491, + {0x93, 0xAA, 0xE8, 0xAD, 0x35, 0xA4, 0x91, 0x17} +}; + +const GUID EAXPROPERTYID_EAX50_FXSlot1 = +{ + 0x8F5F7ACA, + 0x9608, + 0x4965, + {0x81, 0x37, 0x82, 0x13, 0xC7, 0xB9, 0xD9, 0xDE} +}; + +const GUID EAXPROPERTYID_EAX40_FXSlot2 = +{ + 0x1D433B88, + 0xF0F6, + 0x4637, + {0x91, 0x9F, 0x60, 0xE7, 0xE0, 0x6B, 0x5E, 0xDD} +}; + +const GUID EAXPROPERTYID_EAX50_FXSlot2 = +{ + 0x3C0F5252, + 0x9834, + 0x46F0, + {0xA1, 0xD8, 0x5B, 0x95, 0xC4, 0xA0, 0xA, 0x30} +}; + +const GUID EAXPROPERTYID_EAX40_FXSlot3 = +{ + 0xEFFF08EA, + 0xC7D8, + 0x44AB, + {0x93, 0xAD, 0x6D, 0xBD, 0x5F, 0x91, 0x00, 0x64} +}; + +const GUID EAXPROPERTYID_EAX50_FXSlot3 = +{ + 0xE2EB0EAA, + 0xE806, + 0x45E7, + {0x9F, 0x86, 0x06, 0xC1, 0x57, 0x1A, 0x6F, 0xA3} +}; + +const GUID EAXPROPERTYID_EAX40_Source = +{ + 0x1B86B823, + 0x22DF, + 0x4EAE, + {0x8B, 0x3C, 0x12, 0x78, 0xCE, 0x54, 0x42, 0x27} +}; + +const GUID EAXPROPERTYID_EAX50_Source = +{ + 0x5EDF82F0, + 0x24A7, + 0x4F38, + {0x8E, 0x64, 0x2F, 0x09, 0xCA, 0x05, 0xDE, 0xE1} +}; + +const GUID EAX_REVERB_EFFECT = +{ + 0xCF95C8F, + 0xA3CC, + 0x4849, + {0xB0, 0xB6, 0x83, 0x2E, 0xCC, 0x18, 0x22, 0xDF} +}; + +const GUID EAX_AGCCOMPRESSOR_EFFECT = +{ + 0xBFB7A01E, + 0x7825, + 0x4039, + {0x92, 0x7F, 0x03, 0xAA, 0xBD, 0xA0, 0xC5, 0x60} +}; + +const GUID EAX_AUTOWAH_EFFECT = +{ + 0xEC3130C0, + 0xAC7A, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_CHORUS_EFFECT = +{ + 0xDE6D6FE0, + 0xAC79, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_DISTORTION_EFFECT = +{ + 0x975A4CE0, + 0xAC7E, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_ECHO_EFFECT = +{ + 0xE9F1BC0, + 0xAC82, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_EQUALIZER_EFFECT = +{ + 0x65F94CE0, + 0x9793, + 0x11D3, + {0x93, 0x9D, 0x00, 0xC0, 0xF0, 0x2D, 0xD6, 0xF0} +}; + +const GUID EAX_FLANGER_EFFECT = +{ + 0xA70007C0, + 0x7D2, + 0x11D3, + {0x9B, 0x1E, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_FREQUENCYSHIFTER_EFFECT = +{ + 0xDC3E1880, + 0x9212, + 0x11D3, + {0x93, 0x9D, 0x00, 0xC0, 0xF0, 0x2D, 0xD6, 0xF0} +}; + +const GUID EAX_VOCALMORPHER_EFFECT = +{ + 0xE41CF10C, + 0x3383, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_PITCHSHIFTER_EFFECT = +{ + 0xE7905100, + 0xAFB2, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_RINGMODULATOR_EFFECT = +{ + 0xB89FE60, + 0xAFB5, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + + +bool operator==( + const EAXVECTOR& lhs, + const EAXVECTOR& rhs) noexcept +{ + return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z; +} + +bool operator!=( + const EAXVECTOR& lhs, + const EAXVECTOR& rhs) noexcept +{ + return !(lhs == rhs); +} + + +bool operator==( + const EAX40CONTEXTPROPERTIES& lhs, + const EAX40CONTEXTPROPERTIES& rhs) noexcept +{ + return + lhs.guidPrimaryFXSlotID == rhs.guidPrimaryFXSlotID && + lhs.flDistanceFactor == rhs.flDistanceFactor && + lhs.flAirAbsorptionHF == rhs.flAirAbsorptionHF && + lhs.flHFReference == rhs.flHFReference; +} + +bool operator==( + const EAX50CONTEXTPROPERTIES& lhs, + const EAX50CONTEXTPROPERTIES& rhs) noexcept +{ + return + static_cast(lhs) == static_cast(rhs) && + lhs.flMacroFXFactor == rhs.flMacroFXFactor; +} + + +const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX40_FXSlot0; + +bool operator==( + const EAX40FXSLOTPROPERTIES& lhs, + const EAX40FXSLOTPROPERTIES& rhs) noexcept +{ + return + lhs.guidLoadEffect == rhs.guidLoadEffect && + lhs.lVolume == rhs.lVolume && + lhs.lLock == rhs.lLock && + lhs.ulFlags == rhs.ulFlags; +} + +bool operator==( + const EAX50FXSLOTPROPERTIES& lhs, + const EAX50FXSLOTPROPERTIES& rhs) noexcept +{ + return + static_cast(lhs) == static_cast(rhs) && + lhs.lOcclusion == rhs.lOcclusion && + lhs.flOcclusionLFRatio == rhs.flOcclusionLFRatio; +} + +const EAX50ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS +{{ + EAX_NULL_GUID, + EAXPROPERTYID_EAX40_FXSlot0, +}}; + +bool operator==( + const EAX50ACTIVEFXSLOTS& lhs, + const EAX50ACTIVEFXSLOTS& rhs) noexcept +{ + return std::equal( + std::cbegin(lhs.guidActiveFXSlots), + std::cend(lhs.guidActiveFXSlots), + std::begin(rhs.guidActiveFXSlots)); +} + +bool operator!=( + const EAX50ACTIVEFXSLOTS& lhs, + const EAX50ACTIVEFXSLOTS& rhs) noexcept +{ + return !(lhs == rhs); +} + + +const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS +{{ + EAX_NULL_GUID, + EAX_PrimaryFXSlotID, + EAX_NULL_GUID, + EAX_NULL_GUID, +}}; + + +const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS +{{ + EAX_NULL_GUID, + EAX_NULL_GUID, + EAX_NULL_GUID, + EAX_NULL_GUID, +}}; + +bool operator==( + const EAXREVERBPROPERTIES& lhs, + const EAXREVERBPROPERTIES& rhs) noexcept +{ + return + lhs.ulEnvironment == rhs.ulEnvironment && + lhs.flEnvironmentSize == rhs.flEnvironmentSize && + lhs.flEnvironmentDiffusion == rhs.flEnvironmentDiffusion && + lhs.lRoom == rhs.lRoom && + lhs.lRoomHF == rhs.lRoomHF && + lhs.lRoomLF == rhs.lRoomLF && + lhs.flDecayTime == rhs.flDecayTime && + lhs.flDecayHFRatio == rhs.flDecayHFRatio && + lhs.flDecayLFRatio == rhs.flDecayLFRatio && + lhs.lReflections == rhs.lReflections && + lhs.flReflectionsDelay == rhs.flReflectionsDelay && + lhs.vReflectionsPan == rhs.vReflectionsPan && + lhs.lReverb == rhs.lReverb && + lhs.flReverbDelay == rhs.flReverbDelay && + lhs.vReverbPan == rhs.vReverbPan && + lhs.flEchoTime == rhs.flEchoTime && + lhs.flEchoDepth == rhs.flEchoDepth && + lhs.flModulationTime == rhs.flModulationTime && + lhs.flModulationDepth == rhs.flModulationDepth && + lhs.flAirAbsorptionHF == rhs.flAirAbsorptionHF && + lhs.flHFReference == rhs.flHFReference && + lhs.flLFReference == rhs.flLFReference && + lhs.flRoomRolloffFactor == rhs.flRoomRolloffFactor && + lhs.ulFlags == rhs.ulFlags; +} + +bool operator!=( + const EAXREVERBPROPERTIES& lhs, + const EAXREVERBPROPERTIES& rhs) noexcept +{ + return !(lhs == rhs); +} + + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_GENERIC = +{ + EAXREVERB_DEFAULTENVIRONMENT, + EAXREVERB_DEFAULTENVIRONMENTSIZE, + EAXREVERB_DEFAULTENVIRONMENTDIFFUSION, + EAXREVERB_DEFAULTROOM, + EAXREVERB_DEFAULTROOMHF, + EAXREVERB_DEFAULTROOMLF, + EAXREVERB_DEFAULTDECAYTIME, + EAXREVERB_DEFAULTDECAYHFRATIO, + EAXREVERB_DEFAULTDECAYLFRATIO, + EAXREVERB_DEFAULTREFLECTIONS, + EAXREVERB_DEFAULTREFLECTIONSDELAY, + EAXREVERB_DEFAULTREFLECTIONSPAN, + EAXREVERB_DEFAULTREVERB, + EAXREVERB_DEFAULTREVERBDELAY, + EAXREVERB_DEFAULTREVERBPAN, + EAXREVERB_DEFAULTECHOTIME, + EAXREVERB_DEFAULTECHODEPTH, + EAXREVERB_DEFAULTMODULATIONTIME, + EAXREVERB_DEFAULTMODULATIONDEPTH, + EAXREVERB_DEFAULTAIRABSORPTIONHF, + EAXREVERB_DEFAULTHFREFERENCE, + EAXREVERB_DEFAULTLFREFERENCE, + EAXREVERB_DEFAULTROOMROLLOFFFACTOR, + EAXREVERB_DEFAULTFLAGS, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_PADDEDCELL = +{ + EAX_ENVIRONMENT_PADDEDCELL, + 1.4F, + 1.0F, + -1'000L, + -6'000L, + 0L, + 0.17F, + 0.10F, + 1.0F, + -1'204L, + 0.001F, + EAXVECTOR{}, + 207L, + 0.002F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_ROOM = +{ + EAX_ENVIRONMENT_ROOM, + 1.9F, + 1.0F, + -1'000L, + -454L, + 0L, + 0.40F, + 0.83F, + 1.0F, + -1'646L, + 0.002F, + EAXVECTOR{}, + 53L, + 0.003F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_BATHROOM = +{ + EAX_ENVIRONMENT_BATHROOM, + 1.4F, + 1.0F, + -1'000L, + -1'200L, + 0L, + 1.49F, + 0.54F, + 1.0F, + -370L, + 0.007F, + EAXVECTOR{}, + 1'030L, + 0.011F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_LIVINGROOM = +{ + EAX_ENVIRONMENT_LIVINGROOM, + 2.5F, + 1.0F, + -1'000L, + -6'000L, + 0L, + 0.50F, + 0.10F, + 1.0F, + -1'376, + 0.003F, + EAXVECTOR{}, + -1'104L, + 0.004F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_STONEROOM = +{ + EAX_ENVIRONMENT_STONEROOM, + 11.6F, + 1.0F, + -1'000L, + -300L, + 0L, + 2.31F, + 0.64F, + 1.0F, + -711L, + 0.012F, + EAXVECTOR{}, + 83L, + 0.017F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_AUDITORIUM = +{ + EAX_ENVIRONMENT_AUDITORIUM, + 21.6F, + 1.0F, + -1'000L, + -476L, + 0L, + 4.32F, + 0.59F, + 1.0F, + -789L, + 0.020F, + EAXVECTOR{}, + -289L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_CONCERTHALL = +{ + EAX_ENVIRONMENT_CONCERTHALL, + 19.6F, + 1.0F, + -1'000L, + -500L, + 0L, + 3.92F, + 0.70F, + 1.0F, + -1'230L, + 0.020F, + EAXVECTOR{}, + -2L, + 0.029F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_CAVE = +{ + EAX_ENVIRONMENT_CAVE, + 14.6F, + 1.0F, + -1'000L, + 0L, + 0L, + 2.91F, + 1.30F, + 1.0F, + -602L, + 0.015F, + EAXVECTOR{}, + -302L, + 0.022F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_ARENA = +{ + EAX_ENVIRONMENT_ARENA, + 36.2F, + 1.0F, + -1'000L, + -698L, + 0L, + 7.24F, + 0.33F, + 1.0F, + -1'166L, + 0.020F, + EAXVECTOR{}, + 16L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_HANGAR = +{ + EAX_ENVIRONMENT_HANGAR, + 50.3F, + 1.0F, + -1'000L, + -1'000L, + 0L, + 10.05F, + 0.23F, + 1.0F, + -602L, + 0.020F, + EAXVECTOR{}, + 198L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_CARPETTEDHALLWAY = +{ + EAX_ENVIRONMENT_CARPETEDHALLWAY, + 1.9F, + 1.0F, + -1'000L, + -4'000L, + 0L, + 0.30F, + 0.10F, + 1.0F, + -1'831L, + 0.002F, + EAXVECTOR{}, + -1'630L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_HALLWAY = +{ + EAX_ENVIRONMENT_HALLWAY, + 1.8F, + 1.0F, + -1'000L, + -300L, + 0L, + 1.49F, + 0.59F, + 1.0F, + -1'219L, + 0.007F, + EAXVECTOR{}, + 441L, + 0.011F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_STONECORRIDOR = +{ + EAX_ENVIRONMENT_STONECORRIDOR, + 13.5F, + 1.0F, + -1'000L, + -237L, + 0L, + 2.70F, + 0.79F, + 1.0F, + -1'214L, + 0.013F, + EAXVECTOR{}, + 395L, + 0.020F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_ALLEY = +{ + EAX_ENVIRONMENT_ALLEY, + 7.5F, + 0.300F, + -1'000L, + -270L, + 0L, + 1.49F, + 0.86F, + 1.0F, + -1'204L, + 0.007F, + EAXVECTOR{}, + -4L, + 0.011F, + EAXVECTOR{}, + 0.125F, + 0.950F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_FOREST = +{ + EAX_ENVIRONMENT_FOREST, + 38.0F, + 0.300F, + -1'000L, + -3'300L, + 0L, + 1.49F, + 0.54F, + 1.0F, + -2'560L, + 0.162F, + EAXVECTOR{}, + -229L, + 0.088F, + EAXVECTOR{}, + 0.125F, + 1.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_CITY = +{ + EAX_ENVIRONMENT_CITY, + 7.5F, + 0.500F, + -1'000L, + -800L, + 0L, + 1.49F, + 0.67F, + 1.0F, + -2'273L, + 0.007F, + EAXVECTOR{}, + -1'691L, + 0.011F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_MOUNTAINS = +{ + EAX_ENVIRONMENT_MOUNTAINS, + 100.0F, + 0.270F, + -1'000L, + -2'500L, + 0L, + 1.49F, + 0.21F, + 1.0F, + -2'780L, + 0.300F, + EAXVECTOR{}, + -1'434L, + 0.100F, + EAXVECTOR{}, + 0.250F, + 1.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_QUARRY = +{ + EAX_ENVIRONMENT_QUARRY, + 17.5F, + 1.0F, + -1'000L, + -1'000L, + 0L, + 1.49F, + 0.83F, + 1.0F, + -10'000L, + 0.061F, + EAXVECTOR{}, + 500L, + 0.025F, + EAXVECTOR{}, + 0.125F, + 0.700F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_PLAIN = +{ + EAX_ENVIRONMENT_PLAIN, + 42.5F, + 0.210F, + -1'000L, + -2'000L, + 0L, + 1.49F, + 0.50F, + 1.0F, + -2'466L, + 0.179F, + EAXVECTOR{}, + -1'926L, + 0.100F, + EAXVECTOR{}, + 0.250F, + 1.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_PARKINGLOT = +{ + EAX_ENVIRONMENT_PARKINGLOT, + 8.3F, + 1.0F, + -1'000L, + 0L, + 0L, + 1.65F, + 1.50F, + 1.0F, + -1'363L, + 0.008F, + EAXVECTOR{}, + -1'153L, + 0.012F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_SEWERPIPE = +{ + EAX_ENVIRONMENT_SEWERPIPE, + 1.7F, + 0.800F, + -1'000L, + -1'000L, + 0L, + 2.81F, + 0.14F, + 1.0F, + 429L, + 0.014F, + EAXVECTOR{}, + 1'023L, + 0.021F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_UNDERWATER = +{ + EAX_ENVIRONMENT_UNDERWATER, + 1.8F, + 1.0F, + -1'000L, + -4'000L, + 0L, + 1.49F, + 0.10F, + 1.0F, + -449L, + 0.007F, + EAXVECTOR{}, + 1'700L, + 0.011F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 1.180F, + 0.348F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_DRUGGED = +{ + EAX_ENVIRONMENT_DRUGGED, + 1.9F, + 0.500F, + -1'000L, + 0L, + 0L, + 8.39F, + 1.39F, + 1.0F, + -115L, + 0.002F, + EAXVECTOR{}, + 985L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 1.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_DIZZY = +{ + EAX_ENVIRONMENT_DIZZY, + 1.8F, + 0.600F, + -1'000L, + -400L, + 0L, + 17.23F, + 0.56F, + 1.0F, + -1'713L, + 0.020F, + EAXVECTOR{}, + -613L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 1.0F, + 0.810F, + 0.310F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +const EAXREVERBPROPERTIES EAXREVERB_PRESET_PSYCHOTIC = +{ + EAX_ENVIRONMENT_PSYCHOTIC, + 1.0F, + 0.500F, + -1'000L, + -151L, + 0L, + 7.56F, + 0.91F, + 1.0F, + -626L, + 0.020F, + EAXVECTOR{}, + 774L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 4.0F, + 1.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + + +const EaxReverbPresets EAXREVERB_PRESETS = +{ + EAXREVERB_PRESET_GENERIC, + EAXREVERB_PRESET_PADDEDCELL, + EAXREVERB_PRESET_ROOM, + EAXREVERB_PRESET_BATHROOM, + EAXREVERB_PRESET_LIVINGROOM, + EAXREVERB_PRESET_STONEROOM, + EAXREVERB_PRESET_AUDITORIUM, + EAXREVERB_PRESET_CONCERTHALL, + EAXREVERB_PRESET_CAVE, + EAXREVERB_PRESET_ARENA, + EAXREVERB_PRESET_HANGAR, + EAXREVERB_PRESET_CARPETTEDHALLWAY, + EAXREVERB_PRESET_HALLWAY, + EAXREVERB_PRESET_STONECORRIDOR, + EAXREVERB_PRESET_ALLEY, + EAXREVERB_PRESET_FOREST, + EAXREVERB_PRESET_CITY, + EAXREVERB_PRESET_MOUNTAINS, + EAXREVERB_PRESET_QUARRY, + EAXREVERB_PRESET_PLAIN, + EAXREVERB_PRESET_PARKINGLOT, + EAXREVERB_PRESET_SEWERPIPE, + EAXREVERB_PRESET_UNDERWATER, + EAXREVERB_PRESET_DRUGGED, + EAXREVERB_PRESET_DIZZY, + EAXREVERB_PRESET_PSYCHOTIC, +}; diff --git a/al/eax_api.h b/al/eax_api.h new file mode 100644 index 00000000..98eb1fc5 --- /dev/null +++ b/al/eax_api.h @@ -0,0 +1,1542 @@ +#ifndef EAX_API_INCLUDED +#define EAX_API_INCLUDED + + +// +// EAX API. +// +// Based on headers `eax[2-5].h` included in Doom 3 source code: +// https://github.com/id-Software/DOOM-3/tree/master/neo/openal/include +// + + +#include +#include + +#include + +#include "AL/al.h" + + +#ifndef GUID_DEFINED +#define GUID_DEFINED +typedef struct _GUID +{ + std::uint32_t Data1; + std::uint16_t Data2; + std::uint16_t Data3; + std::uint8_t Data4[8]; +} GUID; + +inline constexpr bool operator==( + const GUID& lhs, + const GUID& rhs) noexcept +{ + return + lhs.Data1 == rhs.Data1 && + lhs.Data2 == rhs.Data2 && + lhs.Data3 == rhs.Data3 && + lhs.Data4[0] == rhs.Data4[0] && + lhs.Data4[1] == rhs.Data4[1] && + lhs.Data4[2] == rhs.Data4[2] && + lhs.Data4[3] == rhs.Data4[3] && + lhs.Data4[4] == rhs.Data4[4] && + lhs.Data4[5] == rhs.Data4[5] && + lhs.Data4[6] == rhs.Data4[6] && + lhs.Data4[7] == rhs.Data4[7]; +} + +inline constexpr bool operator!=( + const GUID& lhs, + const GUID& rhs) noexcept +{ + return !(lhs == rhs); +} +#endif // GUID_DEFINED + + +extern "C" const GUID DSPROPSETID_EAX20_ListenerProperties; + +enum DSPROPERTY_EAX20_LISTENERPROPERTY : + unsigned int +{ + DSPROPERTY_EAX20LISTENER_NONE, + DSPROPERTY_EAX20LISTENER_ALLPARAMETERS, + DSPROPERTY_EAX20LISTENER_ROOM, + DSPROPERTY_EAX20LISTENER_ROOMHF, + DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR, + DSPROPERTY_EAX20LISTENER_DECAYTIME, + DSPROPERTY_EAX20LISTENER_DECAYHFRATIO, + DSPROPERTY_EAX20LISTENER_REFLECTIONS, + DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY, + DSPROPERTY_EAX20LISTENER_REVERB, + DSPROPERTY_EAX20LISTENER_REVERBDELAY, + DSPROPERTY_EAX20LISTENER_ENVIRONMENT, + DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE, + DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION, + DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF, + DSPROPERTY_EAX20LISTENER_FLAGS +}; // DSPROPERTY_EAX20_LISTENERPROPERTY + +struct EAX20LISTENERPROPERTIES +{ + long lRoom; // room effect level at low frequencies + long lRoomHF; // room effect high-frequency level re. low frequency level + float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + float flDecayTime; // reverberation decay time at low frequencies + float flDecayHFRatio; // high-frequency to low-frequency decay time ratio + long lReflections; // early reflections level relative to room effect + float flReflectionsDelay; // initial reflection delay time + long lReverb; // late reverberation level relative to room effect + float flReverbDelay; // late reverberation delay time relative to initial reflection + unsigned long dwEnvironment; // sets all listener properties + float flEnvironmentSize; // environment size in meters + float flEnvironmentDiffusion; // environment diffusion + float flAirAbsorptionHF; // change in level per meter at 5 kHz + unsigned long dwFlags; // modifies the behavior of properties +}; // EAX20LISTENERPROPERTIES + + +extern "C" const GUID DSPROPSETID_EAX20_BufferProperties; + + +enum DSPROPERTY_EAX20_BUFFERPROPERTY : + unsigned int +{ + DSPROPERTY_EAX20BUFFER_NONE, + DSPROPERTY_EAX20BUFFER_ALLPARAMETERS, + DSPROPERTY_EAX20BUFFER_DIRECT, + DSPROPERTY_EAX20BUFFER_DIRECTHF, + DSPROPERTY_EAX20BUFFER_ROOM, + DSPROPERTY_EAX20BUFFER_ROOMHF, + DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR, + DSPROPERTY_EAX20BUFFER_OBSTRUCTION, + DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO, + DSPROPERTY_EAX20BUFFER_OCCLUSION, + DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO, + DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO, + DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF, + DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR, + DSPROPERTY_EAX20BUFFER_FLAGS +}; // DSPROPERTY_EAX20_BUFFERPROPERTY + + +struct EAX20BUFFERPROPERTIES +{ + long lDirect; // direct path level + long lDirectHF; // direct path level at high frequencies + long lRoom; // room effect level + long lRoomHF; // room effect level at high frequencies + float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + long lObstruction; // main obstruction control (attenuation at high frequencies) + float flObstructionLFRatio; // obstruction low-frequency level re. main control + long lOcclusion; // main occlusion control (attenuation at high frequencies) + float flOcclusionLFRatio; // occlusion low-frequency level re. main control + float flOcclusionRoomRatio; // occlusion room effect level re. main control + long lOutsideVolumeHF; // outside sound cone level at high frequencies + float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF + unsigned long dwFlags; // modifies the behavior of properties +}; // EAX20BUFFERPROPERTIES + + +extern "C" const GUID DSPROPSETID_EAX30_ListenerProperties; + +extern "C" const GUID DSPROPSETID_EAX30_BufferProperties; + + +constexpr auto EAX_MAX_FXSLOTS = 4; + +constexpr auto EAX40_MAX_ACTIVE_FXSLOTS = 2; +constexpr auto EAX50_MAX_ACTIVE_FXSLOTS = 4; + + +constexpr auto EAX_OK = 0L; +constexpr auto EAXERR_INVALID_OPERATION = -1L; +constexpr auto EAXERR_INVALID_VALUE = -2L; +constexpr auto EAXERR_NO_EFFECT_LOADED = -3L; +constexpr auto EAXERR_UNKNOWN_EFFECT = -4L; +constexpr auto EAXERR_INCOMPATIBLE_SOURCE_TYPE = -5L; +constexpr auto EAXERR_INCOMPATIBLE_EAX_VERSION = -6L; + + +extern "C" const GUID EAX_NULL_GUID; + +extern "C" const GUID EAX_PrimaryFXSlotID; + + +struct EAXVECTOR +{ + float x; + float y; + float z; +}; // EAXVECTOR + +bool operator==( + const EAXVECTOR& lhs, + const EAXVECTOR& rhs) noexcept; + +bool operator!=( + const EAXVECTOR& lhs, + const EAXVECTOR& rhs) noexcept; + + +extern "C" const GUID EAXPROPERTYID_EAX40_Context; + +extern "C" const GUID EAXPROPERTYID_EAX50_Context; + +// EAX50 +enum : + unsigned long +{ + HEADPHONES = 0, + SPEAKERS_2, + SPEAKERS_4, + SPEAKERS_5, // 5.1 speakers + SPEAKERS_6, // 6.1 speakers + SPEAKERS_7, // 7.1 speakers +}; + +// EAX50 +enum : + unsigned long +{ + EAX_40 = 5, // EAX 4.0 + EAX_50 = 6, // EAX 5.0 +}; + +constexpr auto EAXCONTEXT_MINEAXSESSION = EAX_40; +constexpr auto EAXCONTEXT_MAXEAXSESSION = EAX_50; +constexpr auto EAXCONTEXT_DEFAULTEAXSESSION = EAX_40; + +constexpr auto EAXCONTEXT_MINMAXACTIVESENDS = 2UL; +constexpr auto EAXCONTEXT_MAXMAXACTIVESENDS = 4UL; +constexpr auto EAXCONTEXT_DEFAULTMAXACTIVESENDS = 2UL; + +// EAX50 +struct EAXSESSIONPROPERTIES +{ + unsigned long ulEAXVersion; + unsigned long ulMaxActiveSends; +}; // EAXSESSIONPROPERTIES + +enum EAXCONTEXT_PROPERTY : + unsigned int +{ + EAXCONTEXT_NONE = 0, + EAXCONTEXT_ALLPARAMETERS, + EAXCONTEXT_PRIMARYFXSLOTID, + EAXCONTEXT_DISTANCEFACTOR, + EAXCONTEXT_AIRABSORPTIONHF, + EAXCONTEXT_HFREFERENCE, + EAXCONTEXT_LASTERROR, + + // EAX50 + EAXCONTEXT_SPEAKERCONFIG, + EAXCONTEXT_EAXSESSION, + EAXCONTEXT_MACROFXFACTOR, +}; // EAXCONTEXT_PROPERTY + +struct EAX40CONTEXTPROPERTIES +{ + GUID guidPrimaryFXSlotID; + float flDistanceFactor; + float flAirAbsorptionHF; + float flHFReference; +}; // EAX40CONTEXTPROPERTIES + +struct EAX50CONTEXTPROPERTIES : + public EAX40CONTEXTPROPERTIES +{ + float flMacroFXFactor; +}; // EAX40CONTEXTPROPERTIES + + +bool operator==( + const EAX40CONTEXTPROPERTIES& lhs, + const EAX40CONTEXTPROPERTIES& rhs) noexcept; + +bool operator==( + const EAX50CONTEXTPROPERTIES& lhs, + const EAX50CONTEXTPROPERTIES& rhs) noexcept; + + +constexpr auto EAXCONTEXT_MINDISTANCEFACTOR = FLT_MIN; +constexpr auto EAXCONTEXT_MAXDISTANCEFACTOR = FLT_MAX; +constexpr auto EAXCONTEXT_DEFAULTDISTANCEFACTOR = 1.0F; + +constexpr auto EAXCONTEXT_MINAIRABSORPTIONHF = -100.0F; +constexpr auto EAXCONTEXT_MAXAIRABSORPTIONHF = 0.0F; +constexpr auto EAXCONTEXT_DEFAULTAIRABSORPTIONHF = -5.0F; + +constexpr auto EAXCONTEXT_MINHFREFERENCE = 1000.0F; +constexpr auto EAXCONTEXT_MAXHFREFERENCE = 20000.0F; +constexpr auto EAXCONTEXT_DEFAULTHFREFERENCE = 5000.0F; + +constexpr auto EAXCONTEXT_MINMACROFXFACTOR = 0.0F; +constexpr auto EAXCONTEXT_MAXMACROFXFACTOR = 1.0F; +constexpr auto EAXCONTEXT_DEFAULTMACROFXFACTOR = 0.0F; + + +extern "C" const GUID EAXPROPERTYID_EAX40_FXSlot0; + +extern "C" const GUID EAXPROPERTYID_EAX50_FXSlot0; + +extern "C" const GUID EAXPROPERTYID_EAX40_FXSlot1; + +extern "C" const GUID EAXPROPERTYID_EAX50_FXSlot1; + +extern "C" const GUID EAXPROPERTYID_EAX40_FXSlot2; + +extern "C" const GUID EAXPROPERTYID_EAX50_FXSlot2; + +extern "C" const GUID EAXPROPERTYID_EAX40_FXSlot3; + +extern "C" const GUID EAXPROPERTYID_EAX50_FXSlot3; + +extern "C" const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID; + +enum EAXFXSLOT_PROPERTY : + unsigned int +{ + EAXFXSLOT_PARAMETER = 0, + + EAXFXSLOT_NONE = 0x10000, + EAXFXSLOT_ALLPARAMETERS, + EAXFXSLOT_LOADEFFECT, + EAXFXSLOT_VOLUME, + EAXFXSLOT_LOCK, + EAXFXSLOT_FLAGS, + + // EAX50 + EAXFXSLOT_OCCLUSION, + EAXFXSLOT_OCCLUSIONLFRATIO, +}; // EAXFXSLOT_PROPERTY + +constexpr auto EAXFXSLOTFLAGS_ENVIRONMENT = 0x00000001UL; +// EAX50 +constexpr auto EAXFXSLOTFLAGS_UPMIX = 0x00000002UL; + +constexpr auto EAX40FXSLOTFLAGS_RESERVED = 0xFFFFFFFEUL; // reserved future use +constexpr auto EAX50FXSLOTFLAGS_RESERVED = 0xFFFFFFFCUL; // reserved future use + + +constexpr auto EAXFXSLOT_MINVOLUME = -10'000L; +constexpr auto EAXFXSLOT_MAXVOLUME = 0L; +constexpr auto EAXFXSLOT_DEFAULTVOLUME = 0L; + +constexpr auto EAXFXSLOT_MINLOCK = 0L; +constexpr auto EAXFXSLOT_MAXLOCK = 1L; + +enum : + long +{ + EAXFXSLOT_UNLOCKED = 0, + EAXFXSLOT_LOCKED = 1 +}; + +constexpr auto EAXFXSLOT_MINOCCLUSION = -10'000L; +constexpr auto EAXFXSLOT_MAXOCCLUSION = 0L; +constexpr auto EAXFXSLOT_DEFAULTOCCLUSION = 0L; + +constexpr auto EAXFXSLOT_MINOCCLUSIONLFRATIO = 0.0F; +constexpr auto EAXFXSLOT_MAXOCCLUSIONLFRATIO = 1.0F; +constexpr auto EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO = 0.25F; + +constexpr auto EAX40FXSLOT_DEFAULTFLAGS = EAXFXSLOTFLAGS_ENVIRONMENT; + +constexpr auto EAX50FXSLOT_DEFAULTFLAGS = + EAXFXSLOTFLAGS_ENVIRONMENT | + EAXFXSLOTFLAGS_UPMIX; // ignored for reverb; + +struct EAX40FXSLOTPROPERTIES +{ + GUID guidLoadEffect; + long lVolume; + long lLock; + unsigned long ulFlags; +}; // EAX40FXSLOTPROPERTIES + +struct EAX50FXSLOTPROPERTIES : + public EAX40FXSLOTPROPERTIES +{ + long lOcclusion; + float flOcclusionLFRatio; +}; // EAX50FXSLOTPROPERTIES + +bool operator==( + const EAX40FXSLOTPROPERTIES& lhs, + const EAX40FXSLOTPROPERTIES& rhs) noexcept; + +bool operator==( + const EAX50FXSLOTPROPERTIES& lhs, + const EAX50FXSLOTPROPERTIES& rhs) noexcept; + +extern "C" const GUID EAXPROPERTYID_EAX40_Source; + +extern "C" const GUID EAXPROPERTYID_EAX50_Source; + +// Source object properties +enum EAXSOURCE_PROPERTY : + unsigned int +{ + // EAX30 + + EAXSOURCE_NONE, + EAXSOURCE_ALLPARAMETERS, + EAXSOURCE_OBSTRUCTIONPARAMETERS, + EAXSOURCE_OCCLUSIONPARAMETERS, + EAXSOURCE_EXCLUSIONPARAMETERS, + EAXSOURCE_DIRECT, + EAXSOURCE_DIRECTHF, + EAXSOURCE_ROOM, + EAXSOURCE_ROOMHF, + EAXSOURCE_OBSTRUCTION, + EAXSOURCE_OBSTRUCTIONLFRATIO, + EAXSOURCE_OCCLUSION, + EAXSOURCE_OCCLUSIONLFRATIO, + EAXSOURCE_OCCLUSIONROOMRATIO, + EAXSOURCE_OCCLUSIONDIRECTRATIO, + EAXSOURCE_EXCLUSION, + EAXSOURCE_EXCLUSIONLFRATIO, + EAXSOURCE_OUTSIDEVOLUMEHF, + EAXSOURCE_DOPPLERFACTOR, + EAXSOURCE_ROLLOFFFACTOR, + EAXSOURCE_ROOMROLLOFFFACTOR, + EAXSOURCE_AIRABSORPTIONFACTOR, + EAXSOURCE_FLAGS, + + // EAX40 + + EAXSOURCE_SENDPARAMETERS, + EAXSOURCE_ALLSENDPARAMETERS, + EAXSOURCE_OCCLUSIONSENDPARAMETERS, + EAXSOURCE_EXCLUSIONSENDPARAMETERS, + EAXSOURCE_ACTIVEFXSLOTID, + + // EAX50 + + EAXSOURCE_MACROFXFACTOR, + EAXSOURCE_SPEAKERLEVELS, + EAXSOURCE_ALL2DPARAMETERS, +}; // EAXSOURCE_PROPERTY + + +constexpr auto EAXSOURCEFLAGS_DIRECTHFAUTO = 0x00000001UL; // relates to EAXSOURCE_DIRECTHF +constexpr auto EAXSOURCEFLAGS_ROOMAUTO = 0x00000002UL; // relates to EAXSOURCE_ROOM +constexpr auto EAXSOURCEFLAGS_ROOMHFAUTO = 0x00000004UL; // relates to EAXSOURCE_ROOMHF +// EAX50 +constexpr auto EAXSOURCEFLAGS_3DELEVATIONFILTER = 0x00000008UL; +// EAX50 +constexpr auto EAXSOURCEFLAGS_UPMIX = 0x00000010UL; +// EAX50 +constexpr auto EAXSOURCEFLAGS_APPLYSPEAKERLEVELS = 0x00000020UL; + +constexpr auto EAX20SOURCEFLAGS_RESERVED = 0xFFFFFFF8UL; // reserved future use +constexpr auto EAX50SOURCEFLAGS_RESERVED = 0xFFFFFFC0UL; // reserved future use + + +constexpr auto EAXSOURCE_MINSEND = -10'000L; +constexpr auto EAXSOURCE_MAXSEND = 0L; +constexpr auto EAXSOURCE_DEFAULTSEND = 0L; + +constexpr auto EAXSOURCE_MINSENDHF = -10'000L; +constexpr auto EAXSOURCE_MAXSENDHF = 0L; +constexpr auto EAXSOURCE_DEFAULTSENDHF = 0L; + +constexpr auto EAXSOURCE_MINDIRECT = -10'000L; +constexpr auto EAXSOURCE_MAXDIRECT = 1'000L; +constexpr auto EAXSOURCE_DEFAULTDIRECT = 0L; + +constexpr auto EAXSOURCE_MINDIRECTHF = -10'000L; +constexpr auto EAXSOURCE_MAXDIRECTHF = 0L; +constexpr auto EAXSOURCE_DEFAULTDIRECTHF = 0L; + +constexpr auto EAXSOURCE_MINROOM = -10'000L; +constexpr auto EAXSOURCE_MAXROOM = 1'000L; +constexpr auto EAXSOURCE_DEFAULTROOM = 0L; + +constexpr auto EAXSOURCE_MINROOMHF = -10'000L; +constexpr auto EAXSOURCE_MAXROOMHF = 0L; +constexpr auto EAXSOURCE_DEFAULTROOMHF = 0L; + +constexpr auto EAXSOURCE_MINOBSTRUCTION = -10'000L; +constexpr auto EAXSOURCE_MAXOBSTRUCTION = 0L; +constexpr auto EAXSOURCE_DEFAULTOBSTRUCTION = 0L; + +constexpr auto EAXSOURCE_MINOBSTRUCTIONLFRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXOBSTRUCTIONLFRATIO = 1.0F; +constexpr auto EAXSOURCE_DEFAULTOBSTRUCTIONLFRATIO = 0.0F; + +constexpr auto EAXSOURCE_MINOCCLUSION = -10'000L; +constexpr auto EAXSOURCE_MAXOCCLUSION = 0L; +constexpr auto EAXSOURCE_DEFAULTOCCLUSION = 0L; + +constexpr auto EAXSOURCE_MINOCCLUSIONLFRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXOCCLUSIONLFRATIO = 1.0F; +constexpr auto EAXSOURCE_DEFAULTOCCLUSIONLFRATIO = 0.25F; + +constexpr auto EAXSOURCE_MINOCCLUSIONROOMRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXOCCLUSIONROOMRATIO = 10.0F; +constexpr auto EAXSOURCE_DEFAULTOCCLUSIONROOMRATIO = 1.5F; + +constexpr auto EAXSOURCE_MINOCCLUSIONDIRECTRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXOCCLUSIONDIRECTRATIO = 10.0F; +constexpr auto EAXSOURCE_DEFAULTOCCLUSIONDIRECTRATIO = 1.0F; + +constexpr auto EAXSOURCE_MINEXCLUSION = -10'000L; +constexpr auto EAXSOURCE_MAXEXCLUSION = 0L; +constexpr auto EAXSOURCE_DEFAULTEXCLUSION = 0L; + +constexpr auto EAXSOURCE_MINEXCLUSIONLFRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXEXCLUSIONLFRATIO = 1.0F; +constexpr auto EAXSOURCE_DEFAULTEXCLUSIONLFRATIO = 1.0F; + +constexpr auto EAXSOURCE_MINOUTSIDEVOLUMEHF = -10'000L; +constexpr auto EAXSOURCE_MAXOUTSIDEVOLUMEHF = 0L; +constexpr auto EAXSOURCE_DEFAULTOUTSIDEVOLUMEHF = 0L; + +constexpr auto EAXSOURCE_MINDOPPLERFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXDOPPLERFACTOR = 10.0F; +constexpr auto EAXSOURCE_DEFAULTDOPPLERFACTOR = 1.0F; + +constexpr auto EAXSOURCE_MINROLLOFFFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXROLLOFFFACTOR = 10.0F; +constexpr auto EAXSOURCE_DEFAULTROLLOFFFACTOR = 0.0F; + +constexpr auto EAXSOURCE_MINROOMROLLOFFFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXROOMROLLOFFFACTOR = 10.0F; +constexpr auto EAXSOURCE_DEFAULTROOMROLLOFFFACTOR = 0.0F; + +constexpr auto EAXSOURCE_MINAIRABSORPTIONFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXAIRABSORPTIONFACTOR = 10.0F; +constexpr auto EAXSOURCE_DEFAULTAIRABSORPTIONFACTOR = 0.0F; + +// EAX50 + +constexpr auto EAXSOURCE_MINMACROFXFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXMACROFXFACTOR = 1.0F; +constexpr auto EAXSOURCE_DEFAULTMACROFXFACTOR = 1.0F; + +// EAX50 + +constexpr auto EAXSOURCE_MINSPEAKERLEVEL = -10'000L; +constexpr auto EAXSOURCE_MAXSPEAKERLEVEL = 0L; +constexpr auto EAXSOURCE_DEFAULTSPEAKERLEVEL = -10'000L; + +constexpr auto EAXSOURCE_DEFAULTFLAGS = + EAXSOURCEFLAGS_DIRECTHFAUTO | + EAXSOURCEFLAGS_ROOMAUTO | + EAXSOURCEFLAGS_ROOMHFAUTO; + +enum : + long +{ + EAXSPEAKER_FRONT_LEFT = 1, + EAXSPEAKER_FRONT_CENTER = 2, + EAXSPEAKER_FRONT_RIGHT = 3, + EAXSPEAKER_SIDE_RIGHT = 4, + EAXSPEAKER_REAR_RIGHT = 5, + EAXSPEAKER_REAR_CENTER = 6, + EAXSPEAKER_REAR_LEFT = 7, + EAXSPEAKER_SIDE_LEFT = 8, + EAXSPEAKER_LOW_FREQUENCY = 9 +}; + +// EAXSOURCEFLAGS_DIRECTHFAUTO, EAXSOURCEFLAGS_ROOMAUTO and EAXSOURCEFLAGS_ROOMHFAUTO are ignored for 2D sources +// EAXSOURCEFLAGS_UPMIX is ignored for 3D sources +constexpr auto EAX50SOURCE_DEFAULTFLAGS = + EAXSOURCEFLAGS_DIRECTHFAUTO | + EAXSOURCEFLAGS_ROOMAUTO | + EAXSOURCEFLAGS_ROOMHFAUTO | + EAXSOURCEFLAGS_UPMIX; + +struct EAX30SOURCEPROPERTIES +{ + long lDirect; // direct path level (at low and mid frequencies) + long lDirectHF; // relative direct path level at high frequencies + long lRoom; // room effect level (at low and mid frequencies) + long lRoomHF; // relative room effect level at high frequencies + long lObstruction; // main obstruction control (attenuation at high frequencies) + float flObstructionLFRatio; // obstruction low-frequency level re. main control + long lOcclusion; // main occlusion control (attenuation at high frequencies) + float flOcclusionLFRatio; // occlusion low-frequency level re. main control + float flOcclusionRoomRatio; // relative occlusion control for room effect + float flOcclusionDirectRatio; // relative occlusion control for direct path + long lExclusion; // main exlusion control (attenuation at high frequencies) + float flExclusionLFRatio; // exclusion low-frequency level re. main control + long lOutsideVolumeHF; // outside sound cone level at high frequencies + float flDopplerFactor; // like DS3D flDopplerFactor but per source + float flRolloffFactor; // like DS3D flRolloffFactor but per source + float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + float flAirAbsorptionFactor; // multiplies EAXREVERB_AIRABSORPTIONHF + unsigned long ulFlags; // modifies the behavior of properties +}; // EAX30SOURCEPROPERTIES + +struct EAX50SOURCEPROPERTIES : + public EAX30SOURCEPROPERTIES +{ + float flMacroFXFactor; +}; // EAX50SOURCEPROPERTIES + +struct EAXSOURCEALLSENDPROPERTIES +{ + GUID guidReceivingFXSlotID; + long lSend; // send level (at low and mid frequencies) + long lSendHF; // relative send level at high frequencies + long lOcclusion; + float flOcclusionLFRatio; + float flOcclusionRoomRatio; + float flOcclusionDirectRatio; + long lExclusion; + float flExclusionLFRatio; +}; // EAXSOURCEALLSENDPROPERTIES + +struct EAXSOURCE2DPROPERTIES +{ + long lDirect; // direct path level (at low and mid frequencies) + long lDirectHF; // relative direct path level at high frequencies + long lRoom; // room effect level (at low and mid frequencies) + long lRoomHF; // relative room effect level at high frequencies + unsigned long ulFlags; // modifies the behavior of properties +}; // EAXSOURCE2DPROPERTIES + +struct EAXSPEAKERLEVELPROPERTIES +{ + long lSpeakerID; + long lLevel; +}; // EAXSPEAKERLEVELPROPERTIES + +struct EAX40ACTIVEFXSLOTS +{ + GUID guidActiveFXSlots[EAX40_MAX_ACTIVE_FXSLOTS]; +}; // EAX40ACTIVEFXSLOTS + +struct EAX50ACTIVEFXSLOTS +{ + GUID guidActiveFXSlots[EAX50_MAX_ACTIVE_FXSLOTS]; +}; // EAX50ACTIVEFXSLOTS + +bool operator==( + const EAX50ACTIVEFXSLOTS& lhs, + const EAX50ACTIVEFXSLOTS& rhs) noexcept; + +bool operator!=( + const EAX50ACTIVEFXSLOTS& lhs, + const EAX50ACTIVEFXSLOTS& rhs) noexcept; + +// Use this structure for EAXSOURCE_OBSTRUCTIONPARAMETERS property. +struct EAXOBSTRUCTIONPROPERTIES +{ + long lObstruction; + float flObstructionLFRatio; +}; // EAXOBSTRUCTIONPROPERTIES + +// Use this structure for EAXSOURCE_OCCLUSIONPARAMETERS property. +struct EAXOCCLUSIONPROPERTIES +{ + long lOcclusion; + float flOcclusionLFRatio; + float flOcclusionRoomRatio; + float flOcclusionDirectRatio; +}; // EAXOCCLUSIONPROPERTIES + +// Use this structure for EAXSOURCE_EXCLUSIONPARAMETERS property. +struct EAXEXCLUSIONPROPERTIES +{ + long lExclusion; + float flExclusionLFRatio; +}; // EAXEXCLUSIONPROPERTIES + +// Use this structure for EAXSOURCE_SENDPARAMETERS properties. +struct EAXSOURCESENDPROPERTIES +{ + GUID guidReceivingFXSlotID; + long lSend; + long lSendHF; +}; // EAXSOURCESENDPROPERTIES + +// Use this structure for EAXSOURCE_OCCLUSIONSENDPARAMETERS +struct EAXSOURCEOCCLUSIONSENDPROPERTIES +{ + GUID guidReceivingFXSlotID; + long lOcclusion; + float flOcclusionLFRatio; + float flOcclusionRoomRatio; + float flOcclusionDirectRatio; +}; // EAXSOURCEOCCLUSIONSENDPROPERTIES + +// Use this structure for EAXSOURCE_EXCLUSIONSENDPARAMETERS +struct EAXSOURCEEXCLUSIONSENDPROPERTIES +{ + GUID guidReceivingFXSlotID; + long lExclusion; + float flExclusionLFRatio; +}; // EAXSOURCEEXCLUSIONSENDPROPERTIES + +extern const EAX50ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID; + +extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID; + +extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID; + + +// EAX Reverb Effect + +extern "C" const GUID EAX_REVERB_EFFECT; + +// Reverb effect properties +enum EAXREVERB_PROPERTY : + unsigned int +{ + EAXREVERB_NONE, + EAXREVERB_ALLPARAMETERS, + EAXREVERB_ENVIRONMENT, + EAXREVERB_ENVIRONMENTSIZE, + EAXREVERB_ENVIRONMENTDIFFUSION, + EAXREVERB_ROOM, + EAXREVERB_ROOMHF, + EAXREVERB_ROOMLF, + EAXREVERB_DECAYTIME, + EAXREVERB_DECAYHFRATIO, + EAXREVERB_DECAYLFRATIO, + EAXREVERB_REFLECTIONS, + EAXREVERB_REFLECTIONSDELAY, + EAXREVERB_REFLECTIONSPAN, + EAXREVERB_REVERB, + EAXREVERB_REVERBDELAY, + EAXREVERB_REVERBPAN, + EAXREVERB_ECHOTIME, + EAXREVERB_ECHODEPTH, + EAXREVERB_MODULATIONTIME, + EAXREVERB_MODULATIONDEPTH, + EAXREVERB_AIRABSORPTIONHF, + EAXREVERB_HFREFERENCE, + EAXREVERB_LFREFERENCE, + EAXREVERB_ROOMROLLOFFFACTOR, + EAXREVERB_FLAGS, +}; // EAXREVERB_PROPERTY + +// used by EAXREVERB_ENVIRONMENT +enum : + unsigned long +{ + EAX_ENVIRONMENT_GENERIC, + EAX_ENVIRONMENT_PADDEDCELL, + EAX_ENVIRONMENT_ROOM, + EAX_ENVIRONMENT_BATHROOM, + EAX_ENVIRONMENT_LIVINGROOM, + EAX_ENVIRONMENT_STONEROOM, + EAX_ENVIRONMENT_AUDITORIUM, + EAX_ENVIRONMENT_CONCERTHALL, + EAX_ENVIRONMENT_CAVE, + EAX_ENVIRONMENT_ARENA, + EAX_ENVIRONMENT_HANGAR, + EAX_ENVIRONMENT_CARPETEDHALLWAY, + EAX_ENVIRONMENT_HALLWAY, + EAX_ENVIRONMENT_STONECORRIDOR, + EAX_ENVIRONMENT_ALLEY, + EAX_ENVIRONMENT_FOREST, + EAX_ENVIRONMENT_CITY, + EAX_ENVIRONMENT_MOUNTAINS, + EAX_ENVIRONMENT_QUARRY, + EAX_ENVIRONMENT_PLAIN, + EAX_ENVIRONMENT_PARKINGLOT, + EAX_ENVIRONMENT_SEWERPIPE, + EAX_ENVIRONMENT_UNDERWATER, + EAX_ENVIRONMENT_DRUGGED, + EAX_ENVIRONMENT_DIZZY, + EAX_ENVIRONMENT_PSYCHOTIC, + + // EAX30 + EAX_ENVIRONMENT_UNDEFINED, + + EAX_ENVIRONMENT_COUNT, +}; + + +// reverberation decay time +constexpr auto EAXREVERBFLAGS_DECAYTIMESCALE = 0x00000001UL; + +// reflection level +constexpr auto EAXREVERBFLAGS_REFLECTIONSSCALE = 0x00000002UL; + +// initial reflection delay time +constexpr auto EAXREVERBFLAGS_REFLECTIONSDELAYSCALE = 0x00000004UL; + +// reflections level +constexpr auto EAXREVERBFLAGS_REVERBSCALE = 0x00000008UL; + +// late reverberation delay time +constexpr auto EAXREVERBFLAGS_REVERBDELAYSCALE = 0x00000010UL; + +// echo time +// EAX30+ +constexpr auto EAXREVERBFLAGS_ECHOTIMESCALE = 0x00000040UL; + +// modulation time +// EAX30+ +constexpr auto EAXREVERBFLAGS_MODULATIONTIMESCALE = 0x00000080UL; + +// This flag limits high-frequency decay time according to air absorption. +constexpr auto EAXREVERBFLAGS_DECAYHFLIMIT = 0x00000020UL; + +constexpr auto EAXREVERBFLAGS_RESERVED = 0xFFFFFF00UL; // reserved future use + + +struct EAXREVERBPROPERTIES +{ + unsigned long ulEnvironment; // sets all reverb properties + float flEnvironmentSize; // environment size in meters + float flEnvironmentDiffusion; // environment diffusion + long lRoom; // room effect level (at mid frequencies) + long lRoomHF; // relative room effect level at high frequencies + long lRoomLF; // relative room effect level at low frequencies + float flDecayTime; // reverberation decay time at mid frequencies + float flDecayHFRatio; // high-frequency to mid-frequency decay time ratio + float flDecayLFRatio; // low-frequency to mid-frequency decay time ratio + long lReflections; // early reflections level relative to room effect + float flReflectionsDelay; // initial reflection delay time + EAXVECTOR vReflectionsPan; // early reflections panning vector + long lReverb; // late reverberation level relative to room effect + float flReverbDelay; // late reverberation delay time relative to initial reflection + EAXVECTOR vReverbPan; // late reverberation panning vector + float flEchoTime; // echo time + float flEchoDepth; // echo depth + float flModulationTime; // modulation time + float flModulationDepth; // modulation depth + float flAirAbsorptionHF; // change in level per meter at high frequencies + float flHFReference; // reference high frequency + float flLFReference; // reference low frequency + float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + unsigned long ulFlags; // modifies the behavior of properties +}; // EAXREVERBPROPERTIES + +bool operator==( + const EAXREVERBPROPERTIES& lhs, + const EAXREVERBPROPERTIES& rhs) noexcept; + +bool operator!=( + const EAXREVERBPROPERTIES& lhs, + const EAXREVERBPROPERTIES& rhs) noexcept; + + +constexpr auto EAXREVERB_MINENVIRONMENT = 0UL; +constexpr auto EAX20REVERB_MAXENVIRONMENT = EAX_ENVIRONMENT_COUNT - 2UL; +constexpr auto EAX30REVERB_MAXENVIRONMENT = EAX_ENVIRONMENT_COUNT - 1UL; +constexpr auto EAXREVERB_DEFAULTENVIRONMENT = EAX_ENVIRONMENT_GENERIC; + +constexpr auto EAXREVERB_MINENVIRONMENTSIZE = 1.0F; +constexpr auto EAXREVERB_MAXENVIRONMENTSIZE = 100.0F; +constexpr auto EAXREVERB_DEFAULTENVIRONMENTSIZE = 7.5F; + +constexpr auto EAXREVERB_MINENVIRONMENTDIFFUSION = 0.0F; +constexpr auto EAXREVERB_MAXENVIRONMENTDIFFUSION = 1.0F; +constexpr auto EAXREVERB_DEFAULTENVIRONMENTDIFFUSION = 1.0F; + +constexpr auto EAXREVERB_MINROOM = -10'000L; +constexpr auto EAXREVERB_MAXROOM = 0L; +constexpr auto EAXREVERB_DEFAULTROOM = -1'000L; + +constexpr auto EAXREVERB_MINROOMHF = -10'000L; +constexpr auto EAXREVERB_MAXROOMHF = 0L; +constexpr auto EAXREVERB_DEFAULTROOMHF = -100L; + +constexpr auto EAXREVERB_MINROOMLF = -10'000L; +constexpr auto EAXREVERB_MAXROOMLF = 0L; +constexpr auto EAXREVERB_DEFAULTROOMLF = 0L; + +constexpr auto EAXREVERB_MINDECAYTIME = 0.1F; +constexpr auto EAXREVERB_MAXDECAYTIME = 20.0F; +constexpr auto EAXREVERB_DEFAULTDECAYTIME = 1.49F; + +constexpr auto EAXREVERB_MINDECAYHFRATIO = 0.1F; +constexpr auto EAXREVERB_MAXDECAYHFRATIO = 2.0F; +constexpr auto EAXREVERB_DEFAULTDECAYHFRATIO = 0.83F; + +constexpr auto EAXREVERB_MINDECAYLFRATIO = 0.1F; +constexpr auto EAXREVERB_MAXDECAYLFRATIO = 2.0F; +constexpr auto EAXREVERB_DEFAULTDECAYLFRATIO = 1.0F; + +constexpr auto EAXREVERB_MINREFLECTIONS = -10'000L; +constexpr auto EAXREVERB_MAXREFLECTIONS = 1'000L; +constexpr auto EAXREVERB_DEFAULTREFLECTIONS = -2'602L; + +constexpr auto EAXREVERB_MINREFLECTIONSDELAY = 0.0F; +constexpr auto EAXREVERB_MAXREFLECTIONSDELAY = 0.3F; +constexpr auto EAXREVERB_DEFAULTREFLECTIONSDELAY = 0.007F; + +constexpr auto EAXREVERB_DEFAULTREFLECTIONSPAN = EAXVECTOR{0.0F, 0.0F, 0.0F}; + +constexpr auto EAXREVERB_MINREVERB = -10'000L; +constexpr auto EAXREVERB_MAXREVERB = 2'000L; +constexpr auto EAXREVERB_DEFAULTREVERB = 200L; + +constexpr auto EAXREVERB_MINREVERBDELAY = 0.0F; +constexpr auto EAXREVERB_MAXREVERBDELAY = 0.1F; +constexpr auto EAXREVERB_DEFAULTREVERBDELAY = 0.011F; + +constexpr auto EAXREVERB_DEFAULTREVERBPAN = EAXVECTOR{0.0F, 0.0F, 0.0F}; + +constexpr auto EAXREVERB_MINECHOTIME = 0.075F; +constexpr auto EAXREVERB_MAXECHOTIME = 0.25F; +constexpr auto EAXREVERB_DEFAULTECHOTIME = 0.25F; + +constexpr auto EAXREVERB_MINECHODEPTH = 0.0F; +constexpr auto EAXREVERB_MAXECHODEPTH = 1.0F; +constexpr auto EAXREVERB_DEFAULTECHODEPTH = 0.0F; + +constexpr auto EAXREVERB_MINMODULATIONTIME = 0.04F; +constexpr auto EAXREVERB_MAXMODULATIONTIME = 4.0F; +constexpr auto EAXREVERB_DEFAULTMODULATIONTIME = 0.25F; + +constexpr auto EAXREVERB_MINMODULATIONDEPTH = 0.0F; +constexpr auto EAXREVERB_MAXMODULATIONDEPTH = 1.0F; +constexpr auto EAXREVERB_DEFAULTMODULATIONDEPTH = 0.0F; + +constexpr auto EAXREVERB_MINAIRABSORPTIONHF = -100.0F; +constexpr auto EAXREVERB_MAXAIRABSORPTIONHF = 0.0F; +constexpr auto EAXREVERB_DEFAULTAIRABSORPTIONHF = -5.0F; + +constexpr auto EAXREVERB_MINHFREFERENCE = 1'000.0F; +constexpr auto EAXREVERB_MAXHFREFERENCE = 20'000.0F; +constexpr auto EAXREVERB_DEFAULTHFREFERENCE = 5'000.0F; + +constexpr auto EAXREVERB_MINLFREFERENCE = 20.0F; +constexpr auto EAXREVERB_MAXLFREFERENCE = 1'000.0F; +constexpr auto EAXREVERB_DEFAULTLFREFERENCE = 250.0F; + +constexpr auto EAXREVERB_MINROOMROLLOFFFACTOR = 0.0F; +constexpr auto EAXREVERB_MAXROOMROLLOFFFACTOR = 10.0F; +constexpr auto EAXREVERB_DEFAULTROOMROLLOFFFACTOR = 0.0F; + +constexpr auto EAXREVERB_DEFAULTFLAGS = + EAXREVERBFLAGS_DECAYTIMESCALE | + EAXREVERBFLAGS_REFLECTIONSSCALE | + EAXREVERBFLAGS_REFLECTIONSDELAYSCALE | + EAXREVERBFLAGS_REVERBSCALE | + EAXREVERBFLAGS_REVERBDELAYSCALE | + EAXREVERBFLAGS_DECAYHFLIMIT; + + +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_GENERIC; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_PADDEDCEL; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_ROOM; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_BATHROOM; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_LIVINGROOM; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_STONEROOM; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_AUDITORIUM; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_CONCERTHAL; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_CAVE; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_ARENA; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_HANGAR; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_CARPETTEDHALLWAY; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_HALLWAY; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_STONECORRIDOR; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_ALLEY; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_FOREST; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_CITY; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_MOUNTAINS; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_QUARRY; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_PLAIN; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_PARKINGLOT; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_SEWERPIPE; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_UNDERWATER; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_DRUGGED; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_DIZZY; +extern const EAXREVERBPROPERTIES EAXREVERB_PRESET_PSYCHOTIC; + + +using EaxReverbPresets = std::array; +extern const EaxReverbPresets EAXREVERB_PRESETS; + + +// AGC Compressor Effect + +extern "C" const GUID EAX_AGCCOMPRESSOR_EFFECT; + +enum EAXAGCCOMPRESSOR_PROPERTY : + unsigned int +{ + EAXAGCCOMPRESSOR_NONE, + EAXAGCCOMPRESSOR_ALLPARAMETERS, + EAXAGCCOMPRESSOR_ONOFF, +}; // EAXAGCCOMPRESSOR_PROPERTY + +struct EAXAGCCOMPRESSORPROPERTIES +{ + unsigned long ulOnOff; // Switch Compressor on or off +}; // EAXAGCCOMPRESSORPROPERTIES + + +constexpr auto EAXAGCCOMPRESSOR_MINONOFF = 0UL; +constexpr auto EAXAGCCOMPRESSOR_MAXONOFF = 1UL; +constexpr auto EAXAGCCOMPRESSOR_DEFAULTONOFF = EAXAGCCOMPRESSOR_MAXONOFF; + + +// Autowah Effect + +extern "C" const GUID EAX_AUTOWAH_EFFECT; + +enum EAXAUTOWAH_PROPERTY : + unsigned int +{ + EAXAUTOWAH_NONE, + EAXAUTOWAH_ALLPARAMETERS, + EAXAUTOWAH_ATTACKTIME, + EAXAUTOWAH_RELEASETIME, + EAXAUTOWAH_RESONANCE, + EAXAUTOWAH_PEAKLEVEL, +}; // EAXAUTOWAH_PROPERTY + +struct EAXAUTOWAHPROPERTIES +{ + float flAttackTime; // Attack time (seconds) + float flReleaseTime; // Release time (seconds) + long lResonance; // Resonance (mB) + long lPeakLevel; // Peak level (mB) +}; // EAXAUTOWAHPROPERTIES + + +constexpr auto EAXAUTOWAH_MINATTACKTIME = 0.0001F; +constexpr auto EAXAUTOWAH_MAXATTACKTIME = 1.0F; +constexpr auto EAXAUTOWAH_DEFAULTATTACKTIME = 0.06F; + +constexpr auto EAXAUTOWAH_MINRELEASETIME = 0.0001F; +constexpr auto EAXAUTOWAH_MAXRELEASETIME = 1.0F; +constexpr auto EAXAUTOWAH_DEFAULTRELEASETIME = 0.06F; + +constexpr auto EAXAUTOWAH_MINRESONANCE = 600L; +constexpr auto EAXAUTOWAH_MAXRESONANCE = 6000L; +constexpr auto EAXAUTOWAH_DEFAULTRESONANCE = 6000L; + +constexpr auto EAXAUTOWAH_MINPEAKLEVEL = -9000L; +constexpr auto EAXAUTOWAH_MAXPEAKLEVEL = 9000L; +constexpr auto EAXAUTOWAH_DEFAULTPEAKLEVEL = 2100L; + + +// Chorus Effect + +extern "C" const GUID EAX_CHORUS_EFFECT; + + +enum EAXCHORUS_PROPERTY : + unsigned int +{ + EAXCHORUS_NONE, + EAXCHORUS_ALLPARAMETERS, + EAXCHORUS_WAVEFORM, + EAXCHORUS_PHASE, + EAXCHORUS_RATE, + EAXCHORUS_DEPTH, + EAXCHORUS_FEEDBACK, + EAXCHORUS_DELAY, +}; // EAXCHORUS_PROPERTY + +enum : + unsigned long +{ + EAX_CHORUS_SINUSOID, + EAX_CHORUS_TRIANGLE, +}; + +struct EAXCHORUSPROPERTIES +{ + unsigned long ulWaveform; // Waveform selector - see enum above + long lPhase; // Phase (Degrees) + float flRate; // Rate (Hz) + float flDepth; // Depth (0 to 1) + float flFeedback; // Feedback (-1 to 1) + float flDelay; // Delay (seconds) +}; // EAXCHORUSPROPERTIES + + +constexpr auto EAXCHORUS_MINWAVEFORM = 0UL; +constexpr auto EAXCHORUS_MAXWAVEFORM = 1UL; +constexpr auto EAXCHORUS_DEFAULTWAVEFORM = 1UL; + +constexpr auto EAXCHORUS_MINPHASE = -180L; +constexpr auto EAXCHORUS_MAXPHASE = 180L; +constexpr auto EAXCHORUS_DEFAULTPHASE = 90L; + +constexpr auto EAXCHORUS_MINRATE = 0.0F; +constexpr auto EAXCHORUS_MAXRATE = 10.0F; +constexpr auto EAXCHORUS_DEFAULTRATE = 1.1F; + +constexpr auto EAXCHORUS_MINDEPTH = 0.0F; +constexpr auto EAXCHORUS_MAXDEPTH = 1.0F; +constexpr auto EAXCHORUS_DEFAULTDEPTH = 0.1F; + +constexpr auto EAXCHORUS_MINFEEDBACK = -1.0F; +constexpr auto EAXCHORUS_MAXFEEDBACK = 1.0F; +constexpr auto EAXCHORUS_DEFAULTFEEDBACK = 0.25F; + +constexpr auto EAXCHORUS_MINDELAY = 0.0002F; +constexpr auto EAXCHORUS_MAXDELAY = 0.016F; +constexpr auto EAXCHORUS_DEFAULTDELAY = 0.016F; + + +// Distortion Effect + +extern "C" const GUID EAX_DISTORTION_EFFECT; + +enum EAXDISTORTION_PROPERTY : + unsigned int +{ + EAXDISTORTION_NONE, + EAXDISTORTION_ALLPARAMETERS, + EAXDISTORTION_EDGE, + EAXDISTORTION_GAIN, + EAXDISTORTION_LOWPASSCUTOFF, + EAXDISTORTION_EQCENTER, + EAXDISTORTION_EQBANDWIDTH, +}; // EAXDISTORTION_PROPERTY + + +struct EAXDISTORTIONPROPERTIES +{ + float flEdge; // Controls the shape of the distortion (0 to 1) + long lGain; // Controls the post distortion gain (mB) + float flLowPassCutOff; // Controls the cut-off of the filter pre-distortion (Hz) + float flEQCenter; // Controls the center frequency of the EQ post-distortion (Hz) + float flEQBandwidth; // Controls the bandwidth of the EQ post-distortion (Hz) +}; // EAXDISTORTIONPROPERTIES + + +constexpr auto EAXDISTORTION_MINEDGE = 0.0F; +constexpr auto EAXDISTORTION_MAXEDGE = 1.0F; +constexpr auto EAXDISTORTION_DEFAULTEDGE = 0.2F; + +constexpr auto EAXDISTORTION_MINGAIN = -6000L; +constexpr auto EAXDISTORTION_MAXGAIN = 0L; +constexpr auto EAXDISTORTION_DEFAULTGAIN = -2600L; + +constexpr auto EAXDISTORTION_MINLOWPASSCUTOFF = 80.0F; +constexpr auto EAXDISTORTION_MAXLOWPASSCUTOFF = 24000.0F; +constexpr auto EAXDISTORTION_DEFAULTLOWPASSCUTOFF = 8000.0F; + +constexpr auto EAXDISTORTION_MINEQCENTER = 80.0F; +constexpr auto EAXDISTORTION_MAXEQCENTER = 24000.0F; +constexpr auto EAXDISTORTION_DEFAULTEQCENTER = 3600.0F; + +constexpr auto EAXDISTORTION_MINEQBANDWIDTH = 80.0F; +constexpr auto EAXDISTORTION_MAXEQBANDWIDTH = 24000.0F; +constexpr auto EAXDISTORTION_DEFAULTEQBANDWIDTH = 3600.0F; + + +// Echo Effect + +extern "C" const GUID EAX_ECHO_EFFECT; + + +enum EAXECHO_PROPERTY : + unsigned int +{ + EAXECHO_NONE, + EAXECHO_ALLPARAMETERS, + EAXECHO_DELAY, + EAXECHO_LRDELAY, + EAXECHO_DAMPING, + EAXECHO_FEEDBACK, + EAXECHO_SPREAD, +}; // EAXECHO_PROPERTY + + +struct EAXECHOPROPERTIES +{ + float flDelay; // Controls the initial delay time (seconds) + float flLRDelay; // Controls the delay time between the first and second taps (seconds) + float flDamping; // Controls a low-pass filter that dampens the echoes (0 to 1) + float flFeedback; // Controls the duration of echo repetition (0 to 1) + float flSpread; // Controls the left-right spread of the echoes +}; // EAXECHOPROPERTIES + + +constexpr auto EAXECHO_MINDAMPING = 0.0F; +constexpr auto EAXECHO_MAXDAMPING = 0.99F; +constexpr auto EAXECHO_DEFAULTDAMPING = 0.5F; + +constexpr auto EAXECHO_MINDELAY = 0.002F; +constexpr auto EAXECHO_MAXDELAY = 0.207F; +constexpr auto EAXECHO_DEFAULTDELAY = 0.1F; + +constexpr auto EAXECHO_MINLRDELAY = 0.0F; +constexpr auto EAXECHO_MAXLRDELAY = 0.404F; +constexpr auto EAXECHO_DEFAULTLRDELAY = 0.1F; + +constexpr auto EAXECHO_MINFEEDBACK = 0.0F; +constexpr auto EAXECHO_MAXFEEDBACK = 1.0F; +constexpr auto EAXECHO_DEFAULTFEEDBACK = 0.5F; + +constexpr auto EAXECHO_MINSPREAD = -1.0F; +constexpr auto EAXECHO_MAXSPREAD = 1.0F; +constexpr auto EAXECHO_DEFAULTSPREAD = -1.0F; + + +// Equalizer Effect + +extern "C" const GUID EAX_EQUALIZER_EFFECT; + + +enum EAXEQUALIZER_PROPERTY : + unsigned int +{ + EAXEQUALIZER_NONE, + EAXEQUALIZER_ALLPARAMETERS, + EAXEQUALIZER_LOWGAIN, + EAXEQUALIZER_LOWCUTOFF, + EAXEQUALIZER_MID1GAIN, + EAXEQUALIZER_MID1CENTER, + EAXEQUALIZER_MID1WIDTH, + EAXEQUALIZER_MID2GAIN, + EAXEQUALIZER_MID2CENTER, + EAXEQUALIZER_MID2WIDTH, + EAXEQUALIZER_HIGHGAIN, + EAXEQUALIZER_HIGHCUTOFF, +}; // EAXEQUALIZER_PROPERTY + + +struct EAXEQUALIZERPROPERTIES +{ + long lLowGain; // (mB) + float flLowCutOff; // (Hz) + long lMid1Gain; // (mB) + float flMid1Center; // (Hz) + float flMid1Width; // (octaves) + long lMid2Gain; // (mB) + float flMid2Center; // (Hz) + float flMid2Width; // (octaves) + long lHighGain; // (mB) + float flHighCutOff; // (Hz) +}; // EAXEQUALIZERPROPERTIES + + +constexpr auto EAXEQUALIZER_MINLOWGAIN = -1800L; +constexpr auto EAXEQUALIZER_MAXLOWGAIN = 1800L; +constexpr auto EAXEQUALIZER_DEFAULTLOWGAIN = 0L; + +constexpr auto EAXEQUALIZER_MINLOWCUTOFF = 50.0F; +constexpr auto EAXEQUALIZER_MAXLOWCUTOFF = 800.0F; +constexpr auto EAXEQUALIZER_DEFAULTLOWCUTOFF = 200.0F; + +constexpr auto EAXEQUALIZER_MINMID1GAIN = -1800L; +constexpr auto EAXEQUALIZER_MAXMID1GAIN = 1800L; +constexpr auto EAXEQUALIZER_DEFAULTMID1GAIN = 0L; + +constexpr auto EAXEQUALIZER_MINMID1CENTER = 200.0F; +constexpr auto EAXEQUALIZER_MAXMID1CENTER = 3000.0F; +constexpr auto EAXEQUALIZER_DEFAULTMID1CENTER = 500.0F; + +constexpr auto EAXEQUALIZER_MINMID1WIDTH = 0.01F; +constexpr auto EAXEQUALIZER_MAXMID1WIDTH = 1.0F; +constexpr auto EAXEQUALIZER_DEFAULTMID1WIDTH = 1.0F; + +constexpr auto EAXEQUALIZER_MINMID2GAIN = -1800L; +constexpr auto EAXEQUALIZER_MAXMID2GAIN = 1800L; +constexpr auto EAXEQUALIZER_DEFAULTMID2GAIN = 0L; + +constexpr auto EAXEQUALIZER_MINMID2CENTER = 1000.0F; +constexpr auto EAXEQUALIZER_MAXMID2CENTER = 8000.0F; +constexpr auto EAXEQUALIZER_DEFAULTMID2CENTER = 3000.0F; + +constexpr auto EAXEQUALIZER_MINMID2WIDTH = 0.01F; +constexpr auto EAXEQUALIZER_MAXMID2WIDTH = 1.0F; +constexpr auto EAXEQUALIZER_DEFAULTMID2WIDTH = 1.0F; + +constexpr auto EAXEQUALIZER_MINHIGHGAIN = -1800L; +constexpr auto EAXEQUALIZER_MAXHIGHGAIN = 1800L; +constexpr auto EAXEQUALIZER_DEFAULTHIGHGAIN = 0L; + +constexpr auto EAXEQUALIZER_MINHIGHCUTOFF = 4000.0F; +constexpr auto EAXEQUALIZER_MAXHIGHCUTOFF = 16000.0F; +constexpr auto EAXEQUALIZER_DEFAULTHIGHCUTOFF = 6000.0F; + + +// Flanger Effect + +extern "C" const GUID EAX_FLANGER_EFFECT; + +enum EAXFLANGER_PROPERTY : + unsigned int +{ + EAXFLANGER_NONE, + EAXFLANGER_ALLPARAMETERS, + EAXFLANGER_WAVEFORM, + EAXFLANGER_PHASE, + EAXFLANGER_RATE, + EAXFLANGER_DEPTH, + EAXFLANGER_FEEDBACK, + EAXFLANGER_DELAY, +}; // EAXFLANGER_PROPERTY + +enum : + unsigned long +{ + EAX_FLANGER_SINUSOID, + EAX_FLANGER_TRIANGLE, +}; + +struct EAXFLANGERPROPERTIES +{ + unsigned long ulWaveform; // Waveform selector - see enum above + long lPhase; // Phase (Degrees) + float flRate; // Rate (Hz) + float flDepth; // Depth (0 to 1) + float flFeedback; // Feedback (0 to 1) + float flDelay; // Delay (seconds) +}; // EAXFLANGERPROPERTIES + + +constexpr auto EAXFLANGER_MINWAVEFORM = 0UL; +constexpr auto EAXFLANGER_MAXWAVEFORM = 1UL; +constexpr auto EAXFLANGER_DEFAULTWAVEFORM = 1UL; + +constexpr auto EAXFLANGER_MINPHASE = -180L; +constexpr auto EAXFLANGER_MAXPHASE = 180L; +constexpr auto EAXFLANGER_DEFAULTPHASE = 0L; + +constexpr auto EAXFLANGER_MINRATE = 0.0F; +constexpr auto EAXFLANGER_MAXRATE = 10.0F; +constexpr auto EAXFLANGER_DEFAULTRATE = 0.27F; + +constexpr auto EAXFLANGER_MINDEPTH = 0.0F; +constexpr auto EAXFLANGER_MAXDEPTH = 1.0F; +constexpr auto EAXFLANGER_DEFAULTDEPTH = 1.0F; + +constexpr auto EAXFLANGER_MINFEEDBACK = -1.0F; +constexpr auto EAXFLANGER_MAXFEEDBACK = 1.0F; +constexpr auto EAXFLANGER_DEFAULTFEEDBACK = -0.5F; + +constexpr auto EAXFLANGER_MINDELAY = 0.0002F; +constexpr auto EAXFLANGER_MAXDELAY = 0.004F; +constexpr auto EAXFLANGER_DEFAULTDELAY = 0.002F; + + +// Frequency Shifter Effect + +extern "C" const GUID EAX_FREQUENCYSHIFTER_EFFECT; + +enum EAXFREQUENCYSHIFTER_PROPERTY : + unsigned int +{ + EAXFREQUENCYSHIFTER_NONE, + EAXFREQUENCYSHIFTER_ALLPARAMETERS, + EAXFREQUENCYSHIFTER_FREQUENCY, + EAXFREQUENCYSHIFTER_LEFTDIRECTION, + EAXFREQUENCYSHIFTER_RIGHTDIRECTION, +}; // EAXFREQUENCYSHIFTER_PROPERTY + +enum : + unsigned long +{ + EAX_FREQUENCYSHIFTER_DOWN, + EAX_FREQUENCYSHIFTER_UP, + EAX_FREQUENCYSHIFTER_OFF +}; + +struct EAXFREQUENCYSHIFTERPROPERTIES +{ + float flFrequency; // (Hz) + unsigned long ulLeftDirection; // see enum above + unsigned long ulRightDirection; // see enum above +}; // EAXFREQUENCYSHIFTERPROPERTIES + + +constexpr auto EAXFREQUENCYSHIFTER_MINFREQUENCY = 0.0F; +constexpr auto EAXFREQUENCYSHIFTER_MAXFREQUENCY = 24000.0F; +constexpr auto EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY = EAXFREQUENCYSHIFTER_MINFREQUENCY; + +constexpr auto EAXFREQUENCYSHIFTER_MINLEFTDIRECTION = 0UL; +constexpr auto EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION = 2UL; +constexpr auto EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION = EAXFREQUENCYSHIFTER_MINLEFTDIRECTION; + +constexpr auto EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION = 0UL; +constexpr auto EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION = 2UL; +constexpr auto EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION = EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION; + + +// Vocal Morpher Effect + +extern "C" const GUID EAX_VOCALMORPHER_EFFECT; + +enum EAXVOCALMORPHER_PROPERTY : + unsigned int +{ + EAXVOCALMORPHER_NONE, + EAXVOCALMORPHER_ALLPARAMETERS, + EAXVOCALMORPHER_PHONEMEA, + EAXVOCALMORPHER_PHONEMEACOARSETUNING, + EAXVOCALMORPHER_PHONEMEB, + EAXVOCALMORPHER_PHONEMEBCOARSETUNING, + EAXVOCALMORPHER_WAVEFORM, + EAXVOCALMORPHER_RATE, +}; // EAXVOCALMORPHER_PROPERTY + +enum : + unsigned long +{ + A, + E, + I, + O, + U, + AA, + AE, + AH, + AO, + EH, + ER, + IH, + IY, + UH, + UW, + B, + D, + F, + G, + J, + K, + L, + M, + N, + P, + R, + S, + T, + V, + Z, +}; + +enum : + unsigned long +{ + EAX_VOCALMORPHER_SINUSOID, + EAX_VOCALMORPHER_TRIANGLE, + EAX_VOCALMORPHER_SAWTOOTH +}; + +// Use this structure for EAXVOCALMORPHER_ALLPARAMETERS +struct EAXVOCALMORPHERPROPERTIES +{ + unsigned long ulPhonemeA; // see enum above + long lPhonemeACoarseTuning; // (semitones) + unsigned long ulPhonemeB; // see enum above + long lPhonemeBCoarseTuning; // (semitones) + unsigned long ulWaveform; // Waveform selector - see enum above + float flRate; // (Hz) +}; // EAXVOCALMORPHERPROPERTIES + + +constexpr auto EAXVOCALMORPHER_MINPHONEMEA = 0UL; +constexpr auto EAXVOCALMORPHER_MAXPHONEMEA = 29UL; +constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEA = EAXVOCALMORPHER_MINPHONEMEA; + +constexpr auto EAXVOCALMORPHER_MINPHONEMEACOARSETUNING = -24L; +constexpr auto EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING = 24L; +constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING = 0L; + +constexpr auto EAXVOCALMORPHER_MINPHONEMEB = 0UL; +constexpr auto EAXVOCALMORPHER_MAXPHONEMEB = 29UL; +constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEB = 10UL; + +constexpr auto EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING = -24L; +constexpr auto EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING = 24L; +constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING = 0L; + +constexpr auto EAXVOCALMORPHER_MINWAVEFORM = 0UL; +constexpr auto EAXVOCALMORPHER_MAXWAVEFORM = 2UL; +constexpr auto EAXVOCALMORPHER_DEFAULTWAVEFORM = EAXVOCALMORPHER_MINWAVEFORM; + +constexpr auto EAXVOCALMORPHER_MINRATE = 0.0F; +constexpr auto EAXVOCALMORPHER_MAXRATE = 10.0F; +constexpr auto EAXVOCALMORPHER_DEFAULTRATE = 1.41F; + + +// Pitch Shifter Effect + +extern "C" const GUID EAX_PITCHSHIFTER_EFFECT; + +enum EAXPITCHSHIFTER_PROPERTY : + unsigned int +{ + EAXPITCHSHIFTER_NONE, + EAXPITCHSHIFTER_ALLPARAMETERS, + EAXPITCHSHIFTER_COARSETUNE, + EAXPITCHSHIFTER_FINETUNE, +}; // EAXPITCHSHIFTER_PROPERTY + +struct EAXPITCHSHIFTERPROPERTIES +{ + long lCoarseTune; // Amount of pitch shift (semitones) + long lFineTune; // Amount of pitch shift (cents) +}; // EAXPITCHSHIFTERPROPERTIES + + +constexpr auto EAXPITCHSHIFTER_MINCOARSETUNE = -12L; +constexpr auto EAXPITCHSHIFTER_MAXCOARSETUNE = 12L; +constexpr auto EAXPITCHSHIFTER_DEFAULTCOARSETUNE = 12L; + +constexpr auto EAXPITCHSHIFTER_MINFINETUNE = -50L; +constexpr auto EAXPITCHSHIFTER_MAXFINETUNE = 50L; +constexpr auto EAXPITCHSHIFTER_DEFAULTFINETUNE = 0L; + + +// Ring Modulator Effect + +extern "C" const GUID EAX_RINGMODULATOR_EFFECT; + +enum EAXRINGMODULATOR_PROPERTY : + unsigned int +{ + EAXRINGMODULATOR_NONE, + EAXRINGMODULATOR_ALLPARAMETERS, + EAXRINGMODULATOR_FREQUENCY, + EAXRINGMODULATOR_HIGHPASSCUTOFF, + EAXRINGMODULATOR_WAVEFORM, +}; // EAXRINGMODULATOR_PROPERTY + +enum : + unsigned long +{ + EAX_RINGMODULATOR_SINUSOID, + EAX_RINGMODULATOR_SAWTOOTH, + EAX_RINGMODULATOR_SQUARE, +}; + +// Use this structure for EAXRINGMODULATOR_ALLPARAMETERS +struct EAXRINGMODULATORPROPERTIES +{ + float flFrequency; // Frequency of modulation (Hz) + float flHighPassCutOff; // Cut-off frequency of high-pass filter (Hz) + unsigned long ulWaveform; // Waveform selector - see enum above +}; // EAXRINGMODULATORPROPERTIES + + +constexpr auto EAXRINGMODULATOR_MINFREQUENCY = 0.0F; +constexpr auto EAXRINGMODULATOR_MAXFREQUENCY = 8000.0F; +constexpr auto EAXRINGMODULATOR_DEFAULTFREQUENCY = 440.0F; + +constexpr auto EAXRINGMODULATOR_MINHIGHPASSCUTOFF = 0.0F; +constexpr auto EAXRINGMODULATOR_MAXHIGHPASSCUTOFF = 24000.0F; +constexpr auto EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF = 800.0F; + +constexpr auto EAXRINGMODULATOR_MINWAVEFORM = 0UL; +constexpr auto EAXRINGMODULATOR_MAXWAVEFORM = 2UL; +constexpr auto EAXRINGMODULATOR_DEFAULTWAVEFORM = EAXRINGMODULATOR_MINWAVEFORM; + + +using LPEAXSET = ALenum(AL_APIENTRY*)( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + +using LPEAXGET = ALenum(AL_APIENTRY*)( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + + +#endif // !EAX_API_INCLUDED diff --git a/al/eax_eax_call.cpp b/al/eax_eax_call.cpp new file mode 100644 index 00000000..e6967ded --- /dev/null +++ b/al/eax_eax_call.cpp @@ -0,0 +1,370 @@ +#include "al/eax_eax_call.h" + +#include "al/eax_exception.h" + + +namespace +{ + + +class EaxEaxCallException : + public EaxException +{ +public: + explicit EaxEaxCallException( + const char* message) + : + EaxException{"EAX_EAX_CALL", message} + { + } +}; // EaxEaxCallException + + +} // namespace + + +EaxEaxCall::EaxEaxCall( + bool is_get, + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size) +{ + if (!property_set_id) + { + fail("Null property set ID."); + } + + is_get_ = is_get; + + constexpr auto deferred_flag = 0x80000000U; + is_deferred_ = ((property_id & 0x80000000U) != 0); + + version_ = 0; + fx_slot_index_.reset(); + property_set_id_ = EaxEaxCallPropertySetId::none; + + property_set_guid_ = *property_set_id; + property_id_ = property_id & (~deferred_flag); + property_source_id_ = property_source_id; + property_buffer_ = property_buffer; + property_size_ = property_size; + + if (false) + { + } + else if (property_set_guid_ == EAXPROPERTYID_EAX40_Context) + { + version_ = 4; + property_set_id_ = EaxEaxCallPropertySetId::context; + } + else if (property_set_guid_ == EAXPROPERTYID_EAX50_Context) + { + version_ = 5; + property_set_id_ = EaxEaxCallPropertySetId::context; + } + else if (property_set_guid_ == DSPROPSETID_EAX20_ListenerProperties) + { + version_ = 2; + fx_slot_index_ = 0; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; + property_id_ = convert_eax_v2_0_listener_property_id(property_id_); + } + else if (property_set_guid_ == DSPROPSETID_EAX30_ListenerProperties) + { + version_ = 3; + fx_slot_index_ = 0; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid_ == EAXPROPERTYID_EAX40_FXSlot0) + { + version_ = 4; + fx_slot_index_ = 0; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid_ == EAXPROPERTYID_EAX50_FXSlot0) + { + version_ = 5; + fx_slot_index_ = 0; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid_ == EAXPROPERTYID_EAX40_FXSlot1) + { + version_ = 4; + fx_slot_index_ = 1; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid_ == EAXPROPERTYID_EAX50_FXSlot1) + { + version_ = 5; + fx_slot_index_ = 1; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid_ == EAXPROPERTYID_EAX40_FXSlot2) + { + version_ = 4; + fx_slot_index_ = 2; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid_ == EAXPROPERTYID_EAX50_FXSlot2) + { + version_ = 5; + fx_slot_index_ = 2; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid_ == EAXPROPERTYID_EAX40_FXSlot3) + { + version_ = 4; + fx_slot_index_ = 3; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid_ == EAXPROPERTYID_EAX50_FXSlot3) + { + version_ = 5; + fx_slot_index_ = 3; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid_ == DSPROPSETID_EAX20_BufferProperties) + { + version_ = 2; + property_set_id_ = EaxEaxCallPropertySetId::source; + property_id_ = convert_eax_v2_0_buffer_property_id(property_id_); + } + else if (property_set_guid_ == DSPROPSETID_EAX30_BufferProperties) + { + version_ = 3; + property_set_id_ = EaxEaxCallPropertySetId::source; + } + else if (property_set_guid_ == EAXPROPERTYID_EAX40_Source) + { + version_ = 4; + property_set_id_ = EaxEaxCallPropertySetId::source; + } + else if (property_set_guid_ == EAXPROPERTYID_EAX50_Source) + { + version_ = 5; + property_set_id_ = EaxEaxCallPropertySetId::source; + } + else + { + fail("Unsupported property set id."); + } + + if (version_ < 2 || version_ > 5) + { + fail("EAX version out of range."); + } + + if (is_deferred_) + { + if (is_get_) + { + fail("Getting deferred properties not supported."); + } + } + else + { + if (property_set_id_ != EaxEaxCallPropertySetId::fx_slot && + property_id_ != 0) + { + if (!property_buffer) + { + fail("Null property buffer."); + } + + if (property_size == 0) + { + fail("Empty property."); + } + } + } + + if (property_set_id_ == EaxEaxCallPropertySetId::source && + property_source_id_ == 0) + { + fail("Null AL source id."); + } + + if (property_set_id_ == EaxEaxCallPropertySetId::fx_slot) + { + if (property_id_ < EAXFXSLOT_NONE) + { + property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; + } + } +} + +bool EaxEaxCall::is_get() const noexcept +{ + return is_get_; +} + +bool EaxEaxCall::is_deferred() const noexcept +{ + return is_deferred_; +} + +int EaxEaxCall::get_version() const noexcept +{ + return version_; +} + +EaxEaxCallPropertySetId EaxEaxCall::get_property_set_id() const noexcept +{ + return property_set_id_; +} + +ALuint EaxEaxCall::get_property_id() const noexcept +{ + return property_id_; +} + +ALuint EaxEaxCall::get_property_al_name() const noexcept +{ + return property_source_id_; +} + +EaxFxSlotIndex EaxEaxCall::get_fx_slot_index() const noexcept +{ + return fx_slot_index_; +} + +[[noreturn]] +void EaxEaxCall::fail( + const char* message) +{ + throw EaxEaxCallException{message}; +} + +ALuint EaxEaxCall::convert_eax_v2_0_listener_property_id( + ALuint property_id) +{ + switch (property_id) + { + case DSPROPERTY_EAX20LISTENER_NONE: + return EAXREVERB_NONE; + + case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: + return EAXREVERB_ALLPARAMETERS; + + case DSPROPERTY_EAX20LISTENER_ROOM: + return EAXREVERB_ROOM; + + case DSPROPERTY_EAX20LISTENER_ROOMHF: + return EAXREVERB_ROOMHF; + + case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: + return EAXREVERB_ROOMROLLOFFFACTOR; + + case DSPROPERTY_EAX20LISTENER_DECAYTIME: + return EAXREVERB_DECAYTIME; + + case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: + return EAXREVERB_DECAYHFRATIO; + + case DSPROPERTY_EAX20LISTENER_REFLECTIONS: + return EAXREVERB_REFLECTIONS; + + case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: + return EAXREVERB_REFLECTIONSDELAY; + + case DSPROPERTY_EAX20LISTENER_REVERB: + return EAXREVERB_REVERB; + + case DSPROPERTY_EAX20LISTENER_REVERBDELAY: + return EAXREVERB_REVERBDELAY; + + case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: + return EAXREVERB_ENVIRONMENT; + + case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE: + return EAXREVERB_ENVIRONMENTSIZE; + + case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION: + return EAXREVERB_ENVIRONMENTDIFFUSION; + + case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: + return EAXREVERB_AIRABSORPTIONHF; + + case DSPROPERTY_EAX20LISTENER_FLAGS: + return EAXREVERB_FLAGS; + + default: + fail("Unsupported EAX 2.0 listener property id."); + } +} + +ALuint EaxEaxCall::convert_eax_v2_0_buffer_property_id( + ALuint property_id) +{ + switch (property_id) + { + case DSPROPERTY_EAX20BUFFER_NONE: + return EAXSOURCE_NONE; + + case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS: + return EAXSOURCE_ALLPARAMETERS; + + case DSPROPERTY_EAX20BUFFER_DIRECT: + return EAXSOURCE_DIRECT; + + case DSPROPERTY_EAX20BUFFER_DIRECTHF: + return EAXSOURCE_DIRECTHF; + + case DSPROPERTY_EAX20BUFFER_ROOM: + return EAXSOURCE_ROOM; + + case DSPROPERTY_EAX20BUFFER_ROOMHF: + return EAXSOURCE_ROOMHF; + + case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR: + return EAXSOURCE_ROOMROLLOFFFACTOR; + + case DSPROPERTY_EAX20BUFFER_OBSTRUCTION: + return EAXSOURCE_OBSTRUCTION; + + case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO: + return EAXSOURCE_OBSTRUCTIONLFRATIO; + + case DSPROPERTY_EAX20BUFFER_OCCLUSION: + return EAXSOURCE_OCCLUSION; + + case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO: + return EAXSOURCE_OCCLUSIONLFRATIO; + + case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO: + return EAXSOURCE_OCCLUSIONROOMRATIO; + + case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF: + return EAXSOURCE_OUTSIDEVOLUMEHF; + + case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR: + return EAXSOURCE_AIRABSORPTIONFACTOR; + + case DSPROPERTY_EAX20BUFFER_FLAGS: + return EAXSOURCE_FLAGS; + + default: + fail("Unsupported EAX 2.0 buffer property id."); + } +} + + +EaxEaxCall create_eax_call( + bool is_get, + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size) +{ + return EaxEaxCall{ + is_get, + property_set_id, + property_id, + property_source_id, + property_buffer, + property_size + }; +} diff --git a/al/eax_eax_call.h b/al/eax_eax_call.h new file mode 100644 index 00000000..ec632b7d --- /dev/null +++ b/al/eax_eax_call.h @@ -0,0 +1,128 @@ +#ifndef EAX_EAX_CALL_INCLUDED +#define EAX_EAX_CALL_INCLUDED + + +#include "AL/al.h" + +#include "alspan.h" + +#include "eax_api.h" +#include "eax_fx_slot_index.h" + + +enum class EaxEaxCallPropertySetId +{ + none, + + context, + fx_slot, + source, + fx_slot_effect, +}; // EaxEaxCallPropertySetId + + +class EaxEaxCall +{ +public: + EaxEaxCall( + bool is_get, + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + + + bool is_get() const noexcept; + + bool is_deferred() const noexcept; + + int get_version() const noexcept; + + EaxEaxCallPropertySetId get_property_set_id() const noexcept; + + ALuint get_property_id() const noexcept; + + ALuint get_property_al_name() const noexcept; + + EaxFxSlotIndex get_fx_slot_index() const noexcept; + + + template< + typename TException, + typename TValue + > + TValue& get_value() const + { + if (property_size_ < static_cast(sizeof(TValue))) + { + throw TException{"Property buffer too small."}; + } + + return *static_cast(property_buffer_); + } + + template< + typename TException, + typename TValue + > + al::span get_values() const + { + if (property_size_ < static_cast(sizeof(TValue))) + { + throw TException{"Property buffer too small."}; + } + + const auto count = property_size_ / sizeof(TValue); + + return al::span{static_cast(property_buffer_), count}; + } + + template< + typename TException, + typename TValue + > + void set_value( + const TValue& value) const + { + get_value() = value; + } + + +private: + bool is_get_; + bool is_deferred_; + int version_; + EaxFxSlotIndex fx_slot_index_; + EaxEaxCallPropertySetId property_set_id_; + + GUID property_set_guid_; + ALuint property_id_; + ALuint property_source_id_; + ALvoid* property_buffer_; + ALuint property_size_; + + + [[noreturn]] + static void fail( + const char* message); + + + static ALuint convert_eax_v2_0_listener_property_id( + ALuint property_id); + + static ALuint convert_eax_v2_0_buffer_property_id( + ALuint property_id); +}; // EaxEaxCall + + +EaxEaxCall create_eax_call( + bool is_get, + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + + +#endif // !EAX_EAX_CALL_INCLUDED diff --git a/al/eax_effect.cpp b/al/eax_effect.cpp new file mode 100644 index 00000000..72af94fc --- /dev/null +++ b/al/eax_effect.cpp @@ -0,0 +1 @@ +#include "eax_effect.h" diff --git a/al/eax_effect.h b/al/eax_effect.h new file mode 100644 index 00000000..23dbb73e --- /dev/null +++ b/al/eax_effect.h @@ -0,0 +1,28 @@ +#ifndef EAX_EFFECT_INCLUDED +#define EAX_EFFECT_INCLUDED + + +#include + +#include "eax_eax_call.h" + + +class EaxEffect +{ +public: + EaxEffect() = default; + + virtual ~EaxEffect() = default; + + + // Returns "true" if any immediated property was changed. + // [[nodiscard]] + virtual bool dispatch( + const EaxEaxCall& eax_call) = 0; +}; // EaxEffect + + +using EaxEffectUPtr = std::unique_ptr; + + +#endif // !EAX_EFFECT_INCLUDED diff --git a/al/eax_exception.cpp b/al/eax_exception.cpp new file mode 100644 index 00000000..e3635793 --- /dev/null +++ b/al/eax_exception.cpp @@ -0,0 +1,61 @@ +#include "eax_exception.h" + +#include + +#include + + +EaxException::EaxException( + const char* context, + const char* message) + : + std::runtime_error{make_message(context, message)} +{ +} + +std::string EaxException::make_message( + const char* context, + const char* message) +{ + const auto context_size = (context ? std::string::traits_type::length(context) : 0); + const auto has_contex = (context_size > 0); + + const auto message_size = (message ? std::string::traits_type::length(message) : 0); + const auto has_message = (message_size > 0); + + if (!has_contex && !has_message) + { + return std::string{}; + } + + constexpr auto left_prefix = "["; + const auto left_prefix_size = std::string::traits_type::length(left_prefix); + + constexpr auto right_prefix = "] "; + const auto right_prefix_size = std::string::traits_type::length(right_prefix); + + const auto what_size = + ( + has_contex ? + left_prefix_size + context_size + right_prefix_size : + 0) + + message_size + + 1; + + auto what = std::string{}; + what.reserve(what_size); + + if (has_contex) + { + what.append(left_prefix, left_prefix_size); + what.append(context, context_size); + what.append(right_prefix, right_prefix_size); + } + + if (has_message) + { + what.append(message, message_size); + } + + return what; +} diff --git a/al/eax_exception.h b/al/eax_exception.h new file mode 100644 index 00000000..9a7acf71 --- /dev/null +++ b/al/eax_exception.h @@ -0,0 +1,25 @@ +#ifndef EAX_EXCEPTION_INCLUDED +#define EAX_EXCEPTION_INCLUDED + + +#include +#include + + +class EaxException : + public std::runtime_error +{ +public: + EaxException( + const char* context, + const char* message); + + +private: + static std::string make_message( + const char* context, + const char* message); +}; // EaxException + + +#endif // !EAX_EXCEPTION_INCLUDED diff --git a/al/eax_fx_slot_index.cpp b/al/eax_fx_slot_index.cpp new file mode 100644 index 00000000..dffaef47 --- /dev/null +++ b/al/eax_fx_slot_index.cpp @@ -0,0 +1,164 @@ +#include "eax_fx_slot_index.h" + +#include "eax_exception.h" + + +namespace +{ + + +class EaxFxSlotIndexException : + public EaxException +{ +public: + explicit EaxFxSlotIndexException( + const char* message) + : + EaxException{"EAX_FX_SLOT_INDEX", message} + { + } +}; // EaxFxSlotIndexException + + +} // namespace + + +EaxFxSlotIndex::EaxFxSlotIndex( + EaxFxSlotIndexValue index) +{ + set(index); +} + +EaxFxSlotIndex::EaxFxSlotIndex( + const EaxFxSlotIndex& rhs) noexcept + : + has_value_{rhs.has_value_}, + value_{rhs.value_} +{ +} + +void EaxFxSlotIndex::operator=( + EaxFxSlotIndexValue index) +{ + set(index); +} + +void EaxFxSlotIndex::operator=( + const GUID& guid) +{ + set(guid); +} + +void EaxFxSlotIndex::operator=( + const EaxFxSlotIndex& rhs) noexcept +{ + has_value_ = rhs.has_value_; + value_ = rhs.value_; +} + +bool EaxFxSlotIndex::has_value() const noexcept +{ + return has_value_; +} + +EaxFxSlotIndexValue EaxFxSlotIndex::get() const +{ + if (!has_value_) + { + throw EaxFxSlotIndexException{"No value."}; + } + + return value_; +} + +void EaxFxSlotIndex::reset() noexcept +{ + has_value_ = false; +} + +void EaxFxSlotIndex::set( + EaxFxSlotIndexValue index) +{ + if (index >= static_cast(EAX_MAX_FXSLOTS)) + { + fail("Index out of range."); + } + + has_value_ = true; + value_ = index; +} + +void EaxFxSlotIndex::set( + const GUID& guid) +{ + if (false) + { + } + else if (guid == EAX_NULL_GUID) + { + has_value_ = false; + } + else if (guid == EAXPROPERTYID_EAX40_FXSlot0 || guid == EAXPROPERTYID_EAX50_FXSlot0) + { + has_value_ = true; + value_ = 0; + } + else if (guid == EAXPROPERTYID_EAX40_FXSlot1 || guid == EAXPROPERTYID_EAX50_FXSlot1) + { + has_value_ = true; + value_ = 1; + } + else if (guid == EAXPROPERTYID_EAX40_FXSlot2 || guid == EAXPROPERTYID_EAX50_FXSlot2) + { + has_value_ = true; + value_ = 2; + } + else if (guid == EAXPROPERTYID_EAX40_FXSlot3 || guid == EAXPROPERTYID_EAX50_FXSlot3) + { + has_value_ = true; + value_ = 3; + } + else + { + fail("Unsupported GUID."); + } +} + +EaxFxSlotIndex::operator EaxFxSlotIndexValue() const +{ + return get(); +} + +[[noreturn]] +void EaxFxSlotIndex::fail( + const char* message) +{ + throw EaxFxSlotIndexException{message}; +} + + +bool operator==( + const EaxFxSlotIndex& lhs, + const EaxFxSlotIndex& rhs) noexcept +{ + if (lhs.has_value() != rhs.has_value()) + { + return false; + } + + if (lhs.has_value()) + { + return lhs.get() == rhs.get(); + } + else + { + return true; + } +} + +bool operator!=( + const EaxFxSlotIndex& lhs, + const EaxFxSlotIndex& rhs) noexcept +{ + return !(lhs == rhs); +} diff --git a/al/eax_fx_slot_index.h b/al/eax_fx_slot_index.h new file mode 100644 index 00000000..95ff9313 --- /dev/null +++ b/al/eax_fx_slot_index.h @@ -0,0 +1,69 @@ +#ifndef EAX_FX_SLOT_INDEX_INCLUDED +#define EAX_FX_SLOT_INDEX_INCLUDED + + +#include + +#include "eax_api.h" + + +using EaxFxSlotIndexValue = std::size_t; + + +class EaxFxSlotIndex +{ +public: + EaxFxSlotIndex() noexcept = default; + + EaxFxSlotIndex( + EaxFxSlotIndexValue index); + + EaxFxSlotIndex( + const EaxFxSlotIndex& rhs) noexcept; + + void operator=( + EaxFxSlotIndexValue index); + + void operator=( + const GUID& guid); + + void operator=( + const EaxFxSlotIndex& rhs) noexcept; + + + bool has_value() const noexcept; + + EaxFxSlotIndexValue get() const; + + void reset() noexcept; + + void set( + EaxFxSlotIndexValue index); + + void set( + const GUID& guid); + + operator EaxFxSlotIndexValue() const; + + +private: + [[noreturn]] + static void fail( + const char* message); + + + bool has_value_{}; + EaxFxSlotIndexValue value_{}; +}; // EaxFxSlotIndex + + +bool operator==( + const EaxFxSlotIndex& lhs, + const EaxFxSlotIndex& rhs) noexcept; + +bool operator!=( + const EaxFxSlotIndex& lhs, + const EaxFxSlotIndex& rhs) noexcept; + + +#endif // !EAX_FX_SLOT_INDEX_INCLUDED diff --git a/al/eax_fx_slots.cpp b/al/eax_fx_slots.cpp new file mode 100644 index 00000000..41b18f77 --- /dev/null +++ b/al/eax_fx_slots.cpp @@ -0,0 +1,81 @@ +#include "eax_fx_slots.h" + +#include + +#include "eax_exception.h" + +#include "eax_api.h" + + +namespace +{ + + +class EaxFxSlotsException : + public EaxException +{ +public: + explicit EaxFxSlotsException( + const char* message) + : + EaxException{"EAX_FX_SLOTS", message} + { + } +}; // EaxFxSlotsException + + +} // namespace + + +void EaxFxSlots::initialize( + ALCcontext& al_context) +{ + initialize_fx_slots(al_context); +} + +void EaxFxSlots::uninitialize() noexcept +{ + for (auto& fx_slot : fx_slots_) + { + fx_slot->eax_uninitialize(); + fx_slot = nullptr; + } +} + +const ALeffectslot& EaxFxSlots::get( + EaxFxSlotIndex index) const +{ + if (!index.has_value()) + { + fail("Empty index."); + } + + return *fx_slots_[index.get()]; +} + +ALeffectslot& EaxFxSlots::get( + EaxFxSlotIndex index) +{ + return const_cast(const_cast(this)->get(index)); +} + + +[[noreturn]] +void EaxFxSlots::fail( + const char* message) +{ + throw EaxFxSlotsException{message}; +} + +void EaxFxSlots::initialize_fx_slots( + ALCcontext& al_context) +{ + auto fx_slot_index = EaxFxSlotIndexValue{}; + + for (auto& fx_slot : fx_slots_) + { + fx_slot = eax_create_al_effect_slot(al_context); + fx_slot->eax_initialize(al_context, fx_slot_index); + fx_slot_index += 1; + } +} diff --git a/al/eax_fx_slots.h b/al/eax_fx_slots.h new file mode 100644 index 00000000..6abe61b6 --- /dev/null +++ b/al/eax_fx_slots.h @@ -0,0 +1,46 @@ +#ifndef EAX_FX_SLOTS_INCLUDED +#define EAX_FX_SLOTS_INCLUDED + + +#include + +#include "al/auxeffectslot.h" + +#include "eax_api.h" + +#include "eax_fx_slot_index.h" + + +class EaxFxSlots +{ +public: + void initialize( + ALCcontext& al_context); + + void uninitialize() noexcept; + + + const ALeffectslot& get( + EaxFxSlotIndex index) const; + + ALeffectslot& get( + EaxFxSlotIndex index); + + +private: + using Items = std::array; + + + Items fx_slots_{}; + + + [[noreturn]] + static void fail( + const char* message); + + void initialize_fx_slots( + ALCcontext& al_context); +}; // EaxFxSlots + + +#endif // !EAX_FX_SLOTS_INCLUDED diff --git a/al/eax_globals.cpp b/al/eax_globals.cpp new file mode 100644 index 00000000..e2f4681e --- /dev/null +++ b/al/eax_globals.cpp @@ -0,0 +1,18 @@ +#include "eax_globals.h" + + +bool eax_g_is_enabled = true; + + +const char* eax_v2_0_ext_name = "EAX2.0"; +const char* eax_v3_0_ext_name = "EAX3.0"; +const char* eax_v4_0_ext_name = "EAX4.0"; +const char* eax_v5_0_ext_name = "EAX5.0"; + +const char* eax_x_ram_ext_name = "EAX-RAM"; + +const char* eax_eax_set_func_name = "EAXSet"; +const char* eax_eax_get_func_name = "EAXGet"; + +const char* eax_eax_set_buffer_mode_func_name = "EAXSetBufferMode"; +const char* eax_eax_get_buffer_mode_func_name = "EAXGetBufferMode"; diff --git a/al/eax_globals.h b/al/eax_globals.h new file mode 100644 index 00000000..dd2434ed --- /dev/null +++ b/al/eax_globals.h @@ -0,0 +1,22 @@ +#ifndef EAX_GLOBALS_INCLUDED +#define EAX_GLOBALS_INCLUDED + + +extern bool eax_g_is_enabled; + + +extern const char* eax_v2_0_ext_name; +extern const char* eax_v3_0_ext_name; +extern const char* eax_v4_0_ext_name; +extern const char* eax_v5_0_ext_name; + +extern const char* eax_x_ram_ext_name; + +extern const char* eax_eax_set_func_name; +extern const char* eax_eax_get_func_name; + +extern const char* eax_eax_set_buffer_mode_func_name; +extern const char* eax_eax_get_buffer_mode_func_name; + + +#endif // !EAX_GLOBALS_INCLUDED diff --git a/al/eax_utils.cpp b/al/eax_utils.cpp new file mode 100644 index 00000000..9a8f04f1 --- /dev/null +++ b/al/eax_utils.cpp @@ -0,0 +1,35 @@ +#include "eax_utils.h" + +#include + +#include + +#include "core/logging.h" + + +void eax_log_exception( + const char* message) noexcept +{ + const auto exception_ptr = std::current_exception(); + + assert(exception_ptr); + + if (message) + { + ERR("%s\n", message); + } + + try + { + std::rethrow_exception(exception_ptr); + } + catch (const std::exception& ex) + { + const auto ex_message = ex.what(); + ERR("%s\n", ex_message); + } + catch (...) + { + ERR("%s\n", "Generic exception."); + } +} diff --git a/al/eax_utils.h b/al/eax_utils.h new file mode 100644 index 00000000..68e35fcd --- /dev/null +++ b/al/eax_utils.h @@ -0,0 +1,164 @@ +#ifndef EAX_UTILS_INCLUDED +#define EAX_UTILS_INCLUDED + + +#include + +#include +#include +#include + + +struct ALCcontext; + + +struct EaxAlLowPassParam +{ + float gain; + float gain_hf; +}; // EaxAlLowPassParam + + +// Required to call macro `DO_UPDATEPROPS`. +class EaxAlContextWrapper +{ +public: + explicit EaxAlContextWrapper( + ALCcontext& al_context) noexcept + : + al_context_{&al_context} + { + } + + constexpr ALCcontext* get() noexcept + { + return al_context_; + } + + constexpr ALCcontext* operator->() noexcept + { + return al_context_; + } + + +private: + ALCcontext* al_context_; +}; // EaxAlContextWrapper + + +void eax_log_exception( + const char* message = nullptr) noexcept; + + +template< + typename TException, + typename TValue +> +void eax_validate_range( + const char* value_name, + const TValue& value, + const TValue& min_value, + const TValue& max_value) +{ + if (value >= min_value && value <= max_value) + { + return; + } + + const auto message = + std::string{value_name} + + " out of range (value: " + + std::to_string(value) + "; min: " + + std::to_string(min_value) + "; max: " + + std::to_string(max_value) + ")."; + + throw TException{message.c_str()}; +} + + +namespace detail +{ + + +template< + typename T +> +struct EaxIsBitFieldStruct +{ +private: + using yes = std::true_type; + using no = std::false_type; + + template< + typename U + > + static auto test(int) -> decltype(std::declval(), yes{}); + + template< + typename + > + static no test(...); + + +public: + static constexpr auto value = std::is_same(0)), yes>::value; +}; // EaxIsBitFieldStruct + + +template< + typename T, + typename TValue +> +inline bool eax_bit_fields_are_equal( + const T& lhs, + const T& rhs) noexcept +{ + static_assert(sizeof(T) == sizeof(TValue), "Invalid type size."); + + return reinterpret_cast(lhs) == reinterpret_cast(rhs); +} + + +} // namespace detail + + +template< + typename T, + std::enable_if_t::value, int> = 0 +> +inline bool operator==( + const T& lhs, + const T& rhs) noexcept +{ + using Value = std::conditional_t< + sizeof(T) == 1, + std::uint8_t, + std::conditional_t< + sizeof(T) == 2, + std::uint16_t, + std::conditional_t< + sizeof(T) == 4, + std::uint32_t, + void + > + > + >; + + static_assert(!std::is_same::value, "Unsupported type."); + + return detail::eax_bit_fields_are_equal(lhs, rhs); +} + +template< + typename T, + std::enable_if_t::value, int> = 0 +> +inline bool operator!=( + const T& lhs, + const T& rhs) noexcept +{ + return !(lhs == rhs); +} + + +#endif // !EAX_UTILS_INCLUDED diff --git a/al/eax_x_ram.cpp b/al/eax_x_ram.cpp new file mode 100644 index 00000000..d11a03ab --- /dev/null +++ b/al/eax_x_ram.cpp @@ -0,0 +1 @@ +#include "eax_x_ram.h" diff --git a/al/eax_x_ram.h b/al/eax_x_ram.h new file mode 100644 index 00000000..438b9916 --- /dev/null +++ b/al/eax_x_ram.h @@ -0,0 +1,38 @@ +#ifndef EAX_X_RAM_INCLUDED +#define EAX_X_RAM_INCLUDED + + +#include "AL/al.h" + + +constexpr auto eax_x_ram_min_size = ALsizei{}; +constexpr auto eax_x_ram_max_size = ALsizei{64 * 1'024 * 1'024}; + + +constexpr auto AL_EAX_RAM_SIZE = ALenum{0x202201}; +constexpr auto AL_EAX_RAM_FREE = ALenum{0x202202}; + +constexpr auto AL_STORAGE_AUTOMATIC = ALenum{0x202203}; +constexpr auto AL_STORAGE_HARDWARE = ALenum{0x202204}; +constexpr auto AL_STORAGE_ACCESSIBLE = ALenum{0x202205}; + + +constexpr auto AL_EAX_RAM_SIZE_NAME = "AL_EAX_RAM_SIZE"; +constexpr auto AL_EAX_RAM_FREE_NAME = "AL_EAX_RAM_FREE"; + +constexpr auto AL_STORAGE_AUTOMATIC_NAME = "AL_STORAGE_AUTOMATIC"; +constexpr auto AL_STORAGE_HARDWARE_NAME = "AL_STORAGE_HARDWARE"; +constexpr auto AL_STORAGE_ACCESSIBLE_NAME = "AL_STORAGE_ACCESSIBLE"; + + +ALboolean AL_APIENTRY EAXSetBufferMode( + ALsizei n, + const ALuint* buffers, + ALint value); + +ALenum AL_APIENTRY EAXGetBufferMode( + ALuint buffer, + ALint* pReserved); + + +#endif // !EAX_X_RAM_INCLUDED diff --git a/al/effect.cpp b/al/effect.cpp index 217cc1c2..79cd7fab 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -51,6 +51,11 @@ #include "opthelpers.h" #include "vector.h" +#if ALSOFT_EAX +#include + +#include "eax_exception.h" +#endif // ALSOFT_EAX const EffectList gEffectList[16]{ { "eaxreverb", EAXREVERB_EFFECT, AL_EFFECT_EAXREVERB }, @@ -745,3 +750,141 @@ void LoadReverbPreset(const char *name, ALeffect *effect) WARN("Reverb preset '%s' not found\n", name); } + +#if ALSOFT_EAX +namespace +{ + +class EaxAlEffectException : + public EaxException +{ +public: + explicit EaxAlEffectException( + const char* message) + : + EaxException{"[EAX_AL_EFFECT]", message} + { + } +}; // EaxAlEffectException + + +} // namespace + + +void ALeffect::eax_initialize() +{ + eax_effect = nullptr; + eax_effect = eax_create_eax_effect(type, Props); +} + +void ALeffect::eax_al_set_effect( + ALenum al_effect_type) +{ + if (al_effect_type != AL_EFFECT_NULL) + { + auto has_effect = false; + + for (const auto &effect_item : gEffectList) + { + if (al_effect_type == effect_item.val && !DisabledEffects[effect_item.type]) + { + has_effect = true; + break; + } + } + + if (!has_effect) + { + eax_fail("Effect not available."); + } + } + + InitEffectParams(this, al_effect_type); +} + +[[noreturn]] +void ALeffect::eax_fail( + const char* message) +{ + throw EaxAlEffectException{message}; +} + +EaxAlEffectDeleter::EaxAlEffectDeleter( + ALCcontext& context) noexcept + : + context_{&context} +{ +} + +void EaxAlEffectDeleter::operator()( + ALeffect* effect) const +{ + assert(effect); + + eax_al_delete_effect(*context_, *effect); +} + +EaxAlEffectUPtr eax_create_al_effect( + ALCcontext& context, + ALenum effect_type) +{ +#define EAX_PREFIX "[EAX_MAKE_EFFECT] " + + auto& device = *context.mALDevice; + std::lock_guard effect_lock{device.EffectLock}; + + // Allocate. + // + if (!EnsureEffects(&device, 1)) + { + ERR(EAX_PREFIX "%s\n", "Failed to ensure."); + return nullptr; + } + + auto effect = EaxAlEffectUPtr{AllocEffect(&device), EaxAlEffectDeleter{context}}; + + if (!effect) + { + ERR(EAX_PREFIX "%s\n", "Failed to allocate."); + return nullptr; + } + + // Set the type. + // + auto is_supported = (effect_type == AL_EFFECT_NULL); + + if (!is_supported) + { + for (const auto& effect_item : gEffectList) + { + if(effect_type == effect_item.val && !DisabledEffects[effect_item.type]) + { + is_supported = true; + break; + } + } + } + + if (!is_supported) + { + ERR(EAX_PREFIX "Effect type 0x%04x not supported.\n", effect_type); + return nullptr; + } + + InitEffectParams(effect.get(), effect_type); + + return effect; + +#undef EAX_PREFIX +} + +void eax_al_delete_effect( + ALCcontext& context, + ALeffect& effect) +{ + auto& device = *context.mALDevice; + std::lock_guard effect_lock{device.EffectLock}; + + FreeEffect(&device, &effect); +} +#endif // ALSOFT_EAX diff --git a/al/effect.h b/al/effect.h index 10a692c9..5b5e4b03 100644 --- a/al/effect.h +++ b/al/effect.h @@ -7,6 +7,12 @@ #include "al/effects/effects.h" #include "alc/effects/base.h" +#if ALSOFT_EAX +#include + +#include "eax_effect.h" +#endif // ALSOFT_EAX + enum { EAXREVERB_EFFECT = 0, @@ -51,10 +57,57 @@ struct ALeffect { ALuint id{0u}; DISABLE_ALLOC() + + +#if ALSOFT_EAX +public: + EaxEffectUPtr eax_effect{}; + + + void eax_initialize(); + + void eax_al_set_effect( + ALenum al_effect_type); + + +private: + [[noreturn]] + static void eax_fail( + const char* message); +#endif // ALSOFT_EAX }; void InitEffect(ALeffect *effect); void LoadReverbPreset(const char *name, ALeffect *effect); +#if ALSOFT_EAX +class EaxAlEffectDeleter +{ +public: + EaxAlEffectDeleter() noexcept = default; + + EaxAlEffectDeleter( + ALCcontext& context) noexcept; + + void operator()( + ALeffect* effect) const; + + +private: + ALCcontext* context_{}; +}; // EaxAlEffectDeleter + +using EaxAlEffectUPtr = std::unique_ptr; + + +EaxAlEffectUPtr eax_create_al_effect( + ALCcontext& context, + ALenum effect_type); + +void eax_al_delete_effect( + ALCcontext& context, + ALeffect& effect); +#endif // ALSOFT_EAX + #endif diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 9abef1f7..bdd1bc09 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -11,6 +11,14 @@ #include "alc/effects/base.h" #include "effects.h" +#if ALSOFT_EAX +#include "alnumeric.h" + +#include "al/eax_exception.h" +#include "al/eax_utils.h" +#endif // ALSOFT_EAX + + namespace { void Autowah_setParamf(EffectProps *props, ALenum param, float val) @@ -107,3 +115,466 @@ EffectProps genDefaultProps() noexcept DEFINE_ALEFFECT_VTABLE(Autowah); const EffectProps AutowahEffectProps{genDefaultProps()}; + +#if ALSOFT_EAX +namespace +{ + + +using EaxAutoWahEffectDirtyFlagsValue = std::uint_least8_t; + +struct EaxAutoWahEffectDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxAutoWahEffectDirtyFlagsValue flAttackTime : 1; + EaxAutoWahEffectDirtyFlagsValue flReleaseTime : 1; + EaxAutoWahEffectDirtyFlagsValue lResonance : 1; + EaxAutoWahEffectDirtyFlagsValue lPeakLevel : 1; +}; // EaxAutoWahEffectDirtyFlags + + +class EaxAutoWahEffect final : + public EaxEffect +{ +public: + EaxAutoWahEffect( + EffectProps& al_effect_props); + + + // [[nodiscard]] + bool dispatch( + const EaxEaxCall& eax_call) override; + + +private: + EffectProps& al_effect_props_; + + EAXAUTOWAHPROPERTIES eax_{}; + EAXAUTOWAHPROPERTIES eax_d_{}; + EaxAutoWahEffectDirtyFlags eax_dirty_flags_{}; + + + void set_eax_defaults(); + + + void set_efx_attack_time(); + + void set_efx_release_time(); + + void set_efx_resonance(); + + void set_efx_peak_gain(); + + void set_efx_defaults(); + + + // [[nodiscard]] + bool get( + const EaxEaxCall& eax_call); + + + void validate_attack_time( + float flAttackTime); + + void validate_release_time( + float flReleaseTime); + + void validate_resonance( + long lResonance); + + void validate_peak_level( + long lPeakLevel); + + void validate_all( + const EAXAUTOWAHPROPERTIES& eax_all); + + + void defer_attack_time( + float flAttackTime); + + void defer_release_time( + float flReleaseTime); + + void defer_resonance( + long lResonance); + + void defer_peak_level( + long lPeakLevel); + + void defer_all( + const EAXAUTOWAHPROPERTIES& eax_all); + + + void defer_attack_time( + const EaxEaxCall& eax_call); + + void defer_release_time( + const EaxEaxCall& eax_call); + + void defer_resonance( + const EaxEaxCall& eax_call); + + void defer_peak_level( + const EaxEaxCall& eax_call); + + void defer_all( + const EaxEaxCall& eax_call); + + // [[nodiscard]] + bool apply_deferred(); + + // [[nodiscard]] + bool set( + const EaxEaxCall& eax_call); +}; // EaxAutoWahEffect + + +class EaxAutoWahEffectException : + public EaxException +{ +public: + explicit EaxAutoWahEffectException( + const char* message) + : + EaxException{"EAX_AUTO_WAH_EFFECT", message} + { + } +}; // EaxAutoWahEffectException + + +EaxAutoWahEffect::EaxAutoWahEffect( + EffectProps& al_effect_props) + : + al_effect_props_{al_effect_props} +{ + set_eax_defaults(); + set_efx_defaults(); +} + +// [[nodiscard]] +bool EaxAutoWahEffect::dispatch( + const EaxEaxCall& eax_call) +{ + return eax_call.is_get() ? get(eax_call) : set(eax_call); +} + +void EaxAutoWahEffect::set_eax_defaults() +{ + eax_.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME; + eax_.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME; + eax_.lResonance = EAXAUTOWAH_DEFAULTRESONANCE; + eax_.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL; + + eax_d_ = eax_; +} + +void EaxAutoWahEffect::set_efx_attack_time() +{ + const auto attack_time = clamp( + eax_.flAttackTime, + AL_AUTOWAH_MIN_ATTACK_TIME, + AL_AUTOWAH_MAX_ATTACK_TIME); + + al_effect_props_.Autowah.AttackTime = attack_time; +} + +void EaxAutoWahEffect::set_efx_release_time() +{ + const auto release_time = clamp( + eax_.flReleaseTime, + AL_AUTOWAH_MIN_RELEASE_TIME, + AL_AUTOWAH_MAX_RELEASE_TIME); + + al_effect_props_.Autowah.ReleaseTime = release_time; +} + +void EaxAutoWahEffect::set_efx_resonance() +{ + const auto resonance = clamp( + level_mb_to_gain(static_cast(eax_.lResonance)), + AL_AUTOWAH_MIN_RESONANCE, + AL_AUTOWAH_MAX_RESONANCE); + + al_effect_props_.Autowah.Resonance = resonance; +} + +void EaxAutoWahEffect::set_efx_peak_gain() +{ + const auto peak_gain = clamp( + level_mb_to_gain(static_cast(eax_.lPeakLevel)), + AL_AUTOWAH_MIN_PEAK_GAIN, + AL_AUTOWAH_MAX_PEAK_GAIN); + + al_effect_props_.Autowah.PeakGain = peak_gain; +} + +void EaxAutoWahEffect::set_efx_defaults() +{ + set_efx_attack_time(); + set_efx_release_time(); + set_efx_resonance(); + set_efx_peak_gain(); +} + +bool EaxAutoWahEffect::get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXAUTOWAH_NONE: + break; + + case EAXAUTOWAH_ALLPARAMETERS: + eax_call.set_value(eax_); + break; + + case EAXAUTOWAH_ATTACKTIME: + eax_call.set_value(eax_.flAttackTime); + break; + + case EAXAUTOWAH_RELEASETIME: + eax_call.set_value(eax_.flReleaseTime); + break; + + case EAXAUTOWAH_RESONANCE: + eax_call.set_value(eax_.lResonance); + break; + + case EAXAUTOWAH_PEAKLEVEL: + eax_call.set_value(eax_.lPeakLevel); + break; + + default: + throw EaxAutoWahEffectException{"Unsupported property id."}; + } + + return false; +} + +void EaxAutoWahEffect::validate_attack_time( + float flAttackTime) +{ + eax_validate_range( + "Attack Time", + flAttackTime, + EAXAUTOWAH_MINATTACKTIME, + EAXAUTOWAH_MAXATTACKTIME); +} + +void EaxAutoWahEffect::validate_release_time( + float flReleaseTime) +{ + eax_validate_range( + "Release Time", + flReleaseTime, + EAXAUTOWAH_MINRELEASETIME, + EAXAUTOWAH_MAXRELEASETIME); +} + +void EaxAutoWahEffect::validate_resonance( + long lResonance) +{ + eax_validate_range( + "Resonance", + lResonance, + EAXAUTOWAH_MINRESONANCE, + EAXAUTOWAH_MAXRESONANCE); +} + +void EaxAutoWahEffect::validate_peak_level( + long lPeakLevel) +{ + eax_validate_range( + "Peak Level", + lPeakLevel, + EAXAUTOWAH_MINPEAKLEVEL, + EAXAUTOWAH_MAXPEAKLEVEL); +} + +void EaxAutoWahEffect::validate_all( + const EAXAUTOWAHPROPERTIES& eax_all) +{ + validate_attack_time(eax_all.flAttackTime); + validate_release_time(eax_all.flReleaseTime); + validate_resonance(eax_all.lResonance); + validate_peak_level(eax_all.lPeakLevel); +} + +void EaxAutoWahEffect::defer_attack_time( + float flAttackTime) +{ + eax_d_.flAttackTime = flAttackTime; + eax_dirty_flags_.flAttackTime = (eax_.flAttackTime != eax_d_.flAttackTime); +} + +void EaxAutoWahEffect::defer_release_time( + float flReleaseTime) +{ + eax_d_.flReleaseTime = flReleaseTime; + eax_dirty_flags_.flReleaseTime = (eax_.flReleaseTime != eax_d_.flReleaseTime); +} + +void EaxAutoWahEffect::defer_resonance( + long lResonance) +{ + eax_d_.lResonance = lResonance; + eax_dirty_flags_.lResonance = (eax_.lResonance != eax_d_.lResonance); +} + +void EaxAutoWahEffect::defer_peak_level( + long lPeakLevel) +{ + eax_d_.lPeakLevel = lPeakLevel; + eax_dirty_flags_.lPeakLevel = (eax_.lPeakLevel != eax_d_.lPeakLevel); +} + +void EaxAutoWahEffect::defer_all( + const EAXAUTOWAHPROPERTIES& eax_all) +{ + validate_all(eax_all); + + defer_attack_time(eax_all.flAttackTime); + defer_release_time(eax_all.flReleaseTime); + defer_resonance(eax_all.lResonance); + defer_peak_level(eax_all.lPeakLevel); +} + +void EaxAutoWahEffect::defer_attack_time( + const EaxEaxCall& eax_call) +{ + const auto& attack_time = + eax_call.get_value(); + + validate_attack_time(attack_time); + defer_attack_time(attack_time); +} + +void EaxAutoWahEffect::defer_release_time( + const EaxEaxCall& eax_call) +{ + const auto& release_time = + eax_call.get_value(); + + validate_release_time(release_time); + defer_release_time(release_time); +} + +void EaxAutoWahEffect::defer_resonance( + const EaxEaxCall& eax_call) +{ + const auto& resonance = + eax_call.get_value(); + + validate_resonance(resonance); + defer_resonance(resonance); +} + +void EaxAutoWahEffect::defer_peak_level( + const EaxEaxCall& eax_call) +{ + const auto& peak_level = + eax_call.get_value(); + + validate_peak_level(peak_level); + defer_peak_level(peak_level); +} + +void EaxAutoWahEffect::defer_all( + const EaxEaxCall& eax_call) +{ + const auto& all = + eax_call.get_value(); + + validate_all(all); + defer_all(all); +} + +// [[nodiscard]] +bool EaxAutoWahEffect::apply_deferred() +{ + if (eax_dirty_flags_ == EaxAutoWahEffectDirtyFlags{}) + { + return false; + } + + eax_ = eax_d_; + + if (eax_dirty_flags_.flAttackTime) + { + set_efx_attack_time(); + } + + if (eax_dirty_flags_.flReleaseTime) + { + set_efx_release_time(); + } + + if (eax_dirty_flags_.lResonance) + { + set_efx_resonance(); + } + + if (eax_dirty_flags_.lPeakLevel) + { + set_efx_peak_gain(); + } + + eax_dirty_flags_ = EaxAutoWahEffectDirtyFlags{}; + + return true; +} + +// [[nodiscard]] +bool EaxAutoWahEffect::set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXAUTOWAH_NONE: + break; + + case EAXAUTOWAH_ALLPARAMETERS: + defer_all(eax_call); + break; + + case EAXAUTOWAH_ATTACKTIME: + defer_attack_time(eax_call); + break; + + case EAXAUTOWAH_RELEASETIME: + defer_release_time(eax_call); + break; + + case EAXAUTOWAH_RESONANCE: + defer_resonance(eax_call); + break; + + case EAXAUTOWAH_PEAKLEVEL: + defer_peak_level(eax_call); + break; + + default: + throw EaxAutoWahEffectException{"Unsupported property id."}; + } + + if (!eax_call.is_deferred()) + { + return apply_deferred(); + } + + return false; +} + + +} // namespace + + +EaxEffectUPtr eax_create_eax_auto_wah_effect( + EffectProps& al_effect_props) +{ + return std::make_unique<::EaxAutoWahEffect>(al_effect_props); +} + + +#endif // ALSOFT_EAX diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index 2466d97e..ed994fbb 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -11,6 +11,15 @@ #include "core/logging.h" #include "effects.h" +#if ALSOFT_EAX +#include + +#include "alnumeric.h" + +#include "al/eax_exception.h" +#include "al/eax_utils.h" +#endif // ALSOFT_EAX + namespace { @@ -279,3 +288,1234 @@ const EffectProps ChorusEffectProps{genDefaultChorusProps()}; DEFINE_ALEFFECT_VTABLE(Flanger); const EffectProps FlangerEffectProps{genDefaultFlangerProps()}; + + +#if ALSOFT_EAX +namespace +{ + + +void eax_set_efx_waveform( + ALenum waveform, + EffectProps& al_effect_props) +{ + const auto efx_waveform = WaveformFromEnum(waveform); + assert(efx_waveform.has_value()); + al_effect_props.Chorus.Waveform = *efx_waveform; +} + +void eax_set_efx_phase( + ALint phase, + EffectProps& al_effect_props) +{ + al_effect_props.Chorus.Phase = phase; +} + +void eax_set_efx_rate( + ALfloat rate, + EffectProps& al_effect_props) +{ + al_effect_props.Chorus.Rate = rate; +} + +void eax_set_efx_depth( + ALfloat depth, + EffectProps& al_effect_props) +{ + al_effect_props.Chorus.Depth = depth; +} + +void eax_set_efx_feedback( + ALfloat feedback, + EffectProps& al_effect_props) +{ + al_effect_props.Chorus.Feedback = feedback; +} + +void eax_set_efx_delay( + ALfloat delay, + EffectProps& al_effect_props) +{ + al_effect_props.Chorus.Delay = delay; +} + + +using EaxChorusEffectDirtyFlagsValue = std::uint_least8_t; + +struct EaxChorusEffectDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxChorusEffectDirtyFlagsValue ulWaveform : 1; + EaxChorusEffectDirtyFlagsValue lPhase : 1; + EaxChorusEffectDirtyFlagsValue flRate : 1; + EaxChorusEffectDirtyFlagsValue flDepth : 1; + EaxChorusEffectDirtyFlagsValue flFeedback : 1; + EaxChorusEffectDirtyFlagsValue flDelay : 1; +}; // EaxChorusEffectDirtyFlags + + +class EaxChorusEffect final : + public EaxEffect +{ +public: + EaxChorusEffect( + EffectProps& al_effect_props); + + + // [[nodiscard]] + bool dispatch( + const EaxEaxCall& eax_call) override; + + +private: + EffectProps& al_effect_props_; + EAXCHORUSPROPERTIES eax_{}; + EAXCHORUSPROPERTIES eax_d_{}; + EaxChorusEffectDirtyFlags eax_dirty_flags_{}; + + + void set_eax_defaults() noexcept; + + + void set_efx_waveform(); + + void set_efx_phase(); + + void set_efx_rate(); + + void set_efx_depth(); + + void set_efx_feedback(); + + void set_efx_delay(); + + void set_efx_defaults(); + + + // [[nodiscard]] + bool get( + const EaxEaxCall& eax_call); + + + void validate_waveform( + unsigned long ulWaveform); + + void validate_phase( + long lPhase); + + void validate_rate( + float flRate); + + void validate_depth( + float flDepth); + + void validate_feedback( + float flFeedback); + + void validate_delay( + float flDelay); + + void validate_all( + const EAXCHORUSPROPERTIES& eax_all); + + + void defer_waveform( + unsigned long ulWaveform); + + void defer_phase( + long lPhase); + + void defer_rate( + float flRate); + + void defer_depth( + float flDepth); + + void defer_feedback( + float flFeedback); + + void defer_delay( + float flDelay); + + void defer_all( + const EAXCHORUSPROPERTIES& eax_all); + + + void defer_waveform( + const EaxEaxCall& eax_call); + + void defer_phase( + const EaxEaxCall& eax_call); + + void defer_rate( + const EaxEaxCall& eax_call); + + void defer_depth( + const EaxEaxCall& eax_call); + + void defer_feedback( + const EaxEaxCall& eax_call); + + void defer_delay( + const EaxEaxCall& eax_call); + + void defer_all( + const EaxEaxCall& eax_call); + + + // [[nodiscard]] + bool apply_deferred(); + + // [[nodiscard]] + bool set( + const EaxEaxCall& eax_call); +}; // EaxChorusEffect + + +class EaxChorusEffectException : + public EaxException +{ +public: + explicit EaxChorusEffectException( + const char* message) + : + EaxException{"EAX_CHORUS_EFFECT", message} + { + } +}; // EaxChorusEffectException + + +EaxChorusEffect::EaxChorusEffect( + EffectProps& al_effect_props) + : + al_effect_props_{al_effect_props} +{ + set_eax_defaults(); + set_efx_defaults(); +} + +// [[nodiscard]] +bool EaxChorusEffect::dispatch( + const EaxEaxCall& eax_call) +{ + return eax_call.is_get() ? get(eax_call) : set(eax_call); +} + +void EaxChorusEffect::set_eax_defaults() noexcept +{ + eax_.ulWaveform = EAXCHORUS_DEFAULTWAVEFORM; + eax_.lPhase = EAXCHORUS_DEFAULTPHASE; + eax_.flRate = EAXCHORUS_DEFAULTRATE; + eax_.flDepth = EAXCHORUS_DEFAULTDEPTH; + eax_.flFeedback = EAXCHORUS_DEFAULTFEEDBACK; + eax_.flDelay = EAXCHORUS_DEFAULTDELAY; + + eax_d_ = eax_; +} + +void EaxChorusEffect::set_efx_waveform() +{ + const auto waveform = clamp( + static_cast(eax_.ulWaveform), + AL_CHORUS_MIN_WAVEFORM, + AL_CHORUS_MAX_WAVEFORM); + + eax_set_efx_waveform(waveform, al_effect_props_); +} + +void EaxChorusEffect::set_efx_phase() +{ + const auto phase = clamp( + static_cast(eax_.lPhase), + AL_CHORUS_MIN_PHASE, + AL_CHORUS_MAX_PHASE); + + eax_set_efx_phase(phase, al_effect_props_); +} + +void EaxChorusEffect::set_efx_rate() +{ + const auto rate = clamp( + eax_.flRate, + AL_CHORUS_MIN_RATE, + AL_CHORUS_MAX_RATE); + + eax_set_efx_rate(rate, al_effect_props_); +} + +void EaxChorusEffect::set_efx_depth() +{ + const auto depth = clamp( + eax_.flDepth, + AL_CHORUS_MIN_DEPTH, + AL_CHORUS_MAX_DEPTH); + + eax_set_efx_depth(depth, al_effect_props_); +} + +void EaxChorusEffect::set_efx_feedback() +{ + const auto feedback = clamp( + eax_.flFeedback, + AL_CHORUS_MIN_FEEDBACK, + AL_CHORUS_MAX_FEEDBACK); + + eax_set_efx_feedback(feedback, al_effect_props_); +} + +void EaxChorusEffect::set_efx_delay() +{ + const auto delay = clamp( + eax_.flDelay, + AL_CHORUS_MIN_DELAY, + AL_CHORUS_MAX_DELAY); + + eax_set_efx_delay(delay, al_effect_props_); +} + +void EaxChorusEffect::set_efx_defaults() +{ + set_efx_waveform(); + set_efx_phase(); + set_efx_rate(); + set_efx_depth(); + set_efx_feedback(); + set_efx_delay(); +} + +bool EaxChorusEffect::get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXCHORUS_NONE: + break; + + case EAXCHORUS_ALLPARAMETERS: + eax_call.set_value(eax_); + break; + + case EAXCHORUS_WAVEFORM: + eax_call.set_value(eax_.ulWaveform); + break; + + case EAXCHORUS_PHASE: + eax_call.set_value(eax_.lPhase); + break; + + case EAXCHORUS_RATE: + eax_call.set_value(eax_.flRate); + break; + + case EAXCHORUS_DEPTH: + eax_call.set_value(eax_.flDepth); + break; + + case EAXCHORUS_FEEDBACK: + eax_call.set_value(eax_.flFeedback); + break; + + case EAXCHORUS_DELAY: + eax_call.set_value(eax_.flDelay); + break; + + default: + throw EaxChorusEffectException{"Unsupported property id."}; + } + + return false; +} + +void EaxChorusEffect::validate_waveform( + unsigned long ulWaveform) +{ + eax_validate_range( + "Waveform", + ulWaveform, + EAXCHORUS_MINWAVEFORM, + EAXCHORUS_MAXWAVEFORM); +} + +void EaxChorusEffect::validate_phase( + long lPhase) +{ + eax_validate_range( + "Phase", + lPhase, + EAXCHORUS_MINPHASE, + EAXCHORUS_MAXPHASE); +} + +void EaxChorusEffect::validate_rate( + float flRate) +{ + eax_validate_range( + "Rate", + flRate, + EAXCHORUS_MINRATE, + EAXCHORUS_MAXRATE); +} + +void EaxChorusEffect::validate_depth( + float flDepth) +{ + eax_validate_range( + "Depth", + flDepth, + EAXCHORUS_MINDEPTH, + EAXCHORUS_MAXDEPTH); +} + +void EaxChorusEffect::validate_feedback( + float flFeedback) +{ + eax_validate_range( + "Feedback", + flFeedback, + EAXCHORUS_MINFEEDBACK, + EAXCHORUS_MAXFEEDBACK); +} + +void EaxChorusEffect::validate_delay( + float flDelay) +{ + eax_validate_range( + "Delay", + flDelay, + EAXCHORUS_MINDELAY, + EAXCHORUS_MAXDELAY); +} + +void EaxChorusEffect::validate_all( + const EAXCHORUSPROPERTIES& eax_all) +{ + validate_waveform(eax_all.ulWaveform); + validate_phase(eax_all.lPhase); + validate_rate(eax_all.flRate); + validate_depth(eax_all.flDepth); + validate_feedback(eax_all.flFeedback); + validate_delay(eax_all.flDelay); +} + +void EaxChorusEffect::defer_waveform( + unsigned long ulWaveform) +{ + eax_d_.ulWaveform = ulWaveform; + eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform); +} + +void EaxChorusEffect::defer_phase( + long lPhase) +{ + eax_d_.lPhase = lPhase; + eax_dirty_flags_.lPhase = (eax_.lPhase != eax_d_.lPhase); +} + +void EaxChorusEffect::defer_rate( + float flRate) +{ + eax_d_.flRate = flRate; + eax_dirty_flags_.flRate = (eax_.flRate != eax_d_.flRate); +} + +void EaxChorusEffect::defer_depth( + float flDepth) +{ + eax_d_.flDepth = flDepth; + eax_dirty_flags_.flDepth = (eax_.flDepth != eax_d_.flDepth); +} + +void EaxChorusEffect::defer_feedback( + float flFeedback) +{ + eax_d_.flFeedback = flFeedback; + eax_dirty_flags_.flFeedback = (eax_.flFeedback != eax_d_.flFeedback); +} + +void EaxChorusEffect::defer_delay( + float flDelay) +{ + eax_d_.flDelay = flDelay; + eax_dirty_flags_.flDelay = (eax_.flDelay != eax_d_.flDelay); +} + +void EaxChorusEffect::defer_all( + const EAXCHORUSPROPERTIES& eax_all) +{ + defer_waveform(eax_all.ulWaveform); + defer_phase(eax_all.lPhase); + defer_rate(eax_all.flRate); + defer_depth(eax_all.flDepth); + defer_feedback(eax_all.flFeedback); + defer_delay(eax_all.flDelay); +} + +void EaxChorusEffect::defer_waveform( + const EaxEaxCall& eax_call) +{ + const auto& waveform = + eax_call.get_value(); + + validate_waveform(waveform); + defer_waveform(waveform); +} + +void EaxChorusEffect::defer_phase( + const EaxEaxCall& eax_call) +{ + const auto& phase = + eax_call.get_value(); + + validate_phase(phase); + defer_phase(phase); +} + +void EaxChorusEffect::defer_rate( + const EaxEaxCall& eax_call) +{ + const auto& rate = + eax_call.get_value(); + + validate_rate(rate); + defer_rate(rate); +} + +void EaxChorusEffect::defer_depth( + const EaxEaxCall& eax_call) +{ + const auto& depth = + eax_call.get_value(); + + validate_depth(depth); + defer_depth(depth); +} + +void EaxChorusEffect::defer_feedback( + const EaxEaxCall& eax_call) +{ + const auto& feedback = + eax_call.get_value(); + + validate_feedback(feedback); + defer_feedback(feedback); +} + +void EaxChorusEffect::defer_delay( + const EaxEaxCall& eax_call) +{ + const auto& delay = + eax_call.get_value(); + + validate_delay(delay); + defer_delay(delay); +} + +void EaxChorusEffect::defer_all( + const EaxEaxCall& eax_call) +{ + const auto& all = + eax_call.get_value(); + + validate_all(all); + defer_all(all); +} + +// [[nodiscard]] +bool EaxChorusEffect::apply_deferred() +{ + if (eax_dirty_flags_ == EaxChorusEffectDirtyFlags{}) + { + return false; + } + + eax_ = eax_d_; + + if (eax_dirty_flags_.ulWaveform) + { + set_efx_waveform(); + } + + if (eax_dirty_flags_.lPhase) + { + set_efx_phase(); + } + + if (eax_dirty_flags_.flRate) + { + set_efx_rate(); + } + + if (eax_dirty_flags_.flDepth) + { + set_efx_depth(); + } + + if (eax_dirty_flags_.flFeedback) + { + set_efx_feedback(); + } + + if (eax_dirty_flags_.flDelay) + { + set_efx_delay(); + } + + eax_dirty_flags_ = EaxChorusEffectDirtyFlags{}; + + return true; +} + +// [[nodiscard]] +bool EaxChorusEffect::set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXCHORUS_NONE: + break; + + case EAXCHORUS_ALLPARAMETERS: + defer_all(eax_call); + break; + + case EAXCHORUS_WAVEFORM: + defer_waveform(eax_call); + break; + + case EAXCHORUS_PHASE: + defer_phase(eax_call); + break; + + case EAXCHORUS_RATE: + defer_rate(eax_call); + break; + + case EAXCHORUS_DEPTH: + defer_depth(eax_call); + break; + + case EAXCHORUS_FEEDBACK: + defer_feedback(eax_call); + break; + + case EAXCHORUS_DELAY: + defer_delay(eax_call); + break; + + default: + throw EaxChorusEffectException{"Unsupported property id."}; + } + + if (!eax_call.is_deferred()) + { + return apply_deferred(); + } + + return false; +} + + +} // namespace + + +EaxEffectUPtr eax_create_eax_chorus_effect( + EffectProps& al_effect_props) +{ + return std::make_unique<::EaxChorusEffect>(al_effect_props); +} + + +namespace +{ + + +using EaxFlangerEffectDirtyFlagsValue = std::uint_least8_t; + +struct EaxFlangerEffectDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxFlangerEffectDirtyFlagsValue ulWaveform : 1; + EaxFlangerEffectDirtyFlagsValue lPhase : 1; + EaxFlangerEffectDirtyFlagsValue flRate : 1; + EaxFlangerEffectDirtyFlagsValue flDepth : 1; + EaxFlangerEffectDirtyFlagsValue flFeedback : 1; + EaxFlangerEffectDirtyFlagsValue flDelay : 1; +}; // EaxFlangerEffectDirtyFlags + + +class EaxFlangerEffect final : + public EaxEffect +{ +public: + EaxFlangerEffect( + EffectProps& al_effect_props); + + + // [[nodiscard]] + bool dispatch( + const EaxEaxCall& eax_call) override; + + +private: + EffectProps& al_effect_props_; + + EAXFLANGERPROPERTIES eax_{}; + EAXFLANGERPROPERTIES eax_d_{}; + EaxFlangerEffectDirtyFlags eax_dirty_flags_{}; + + + void set_eax_defaults(); + + + void set_efx_waveform(); + + void set_efx_phase(); + + void set_efx_rate(); + + void set_efx_depth(); + + void set_efx_feedback(); + + void set_efx_delay(); + + void set_efx_defaults(); + + + // [[nodiscard]] + bool get( + const EaxEaxCall& eax_call); + + + void validate_waveform( + unsigned long ulWaveform); + + void validate_phase( + long lPhase); + + void validate_rate( + float flRate); + + void validate_depth( + float flDepth); + + void validate_feedback( + float flFeedback); + + void validate_delay( + float flDelay); + + void validate_all( + const EAXFLANGERPROPERTIES& all); + + + void defer_waveform( + unsigned long ulWaveform); + + void defer_phase( + long lPhase); + + void defer_rate( + float flRate); + + void defer_depth( + float flDepth); + + void defer_feedback( + float flFeedback); + + void defer_delay( + float flDelay); + + void defer_all( + const EAXFLANGERPROPERTIES& all); + + + void defer_waveform( + const EaxEaxCall& eax_call); + + void defer_phase( + const EaxEaxCall& eax_call); + + void defer_rate( + const EaxEaxCall& eax_call); + + void defer_depth( + const EaxEaxCall& eax_call); + + void defer_feedback( + const EaxEaxCall& eax_call); + + void defer_delay( + const EaxEaxCall& eax_call); + + void defer_all( + const EaxEaxCall& eax_call); + + + // [[nodiscard]] + bool apply_deferred(); + + // [[nodiscard]] + bool set( + const EaxEaxCall& eax_call); +}; // EaxFlangerEffect + + +class EaxFlangerEffectException : + public EaxException +{ +public: + explicit EaxFlangerEffectException( + const char* message) + : + EaxException{"EAX_FLANGER_EFFECT", message} + { + } +}; // EaxFlangerEffectException + + +EaxFlangerEffect::EaxFlangerEffect( + EffectProps& al_effect_props) + : + al_effect_props_{al_effect_props} +{ + set_eax_defaults(); + set_efx_defaults(); +} + +// [[nodiscard]] +bool EaxFlangerEffect::dispatch( + const EaxEaxCall& eax_call) +{ + return eax_call.is_get() ? get(eax_call) : set(eax_call); +} + +void EaxFlangerEffect::set_eax_defaults() +{ + eax_.ulWaveform = EAXFLANGER_DEFAULTWAVEFORM; + eax_.lPhase = EAXFLANGER_DEFAULTPHASE; + eax_.flRate = EAXFLANGER_DEFAULTRATE; + eax_.flDepth = EAXFLANGER_DEFAULTDEPTH; + eax_.flFeedback = EAXFLANGER_DEFAULTFEEDBACK; + eax_.flDelay = EAXFLANGER_DEFAULTDELAY; + + eax_d_ = eax_; +} + +void EaxFlangerEffect::set_efx_waveform() +{ + const auto waveform = clamp( + static_cast(eax_.ulWaveform), + AL_FLANGER_MIN_WAVEFORM, + AL_FLANGER_MAX_WAVEFORM); + + eax_set_efx_waveform(waveform, al_effect_props_); +} + +void EaxFlangerEffect::set_efx_phase() +{ + const auto phase = clamp( + static_cast(eax_.lPhase), + AL_FLANGER_MIN_PHASE, + AL_FLANGER_MAX_PHASE); + + eax_set_efx_phase(phase, al_effect_props_); +} + +void EaxFlangerEffect::set_efx_rate() +{ + const auto rate = clamp( + eax_.flRate, + AL_FLANGER_MIN_RATE, + AL_FLANGER_MAX_RATE); + + eax_set_efx_rate(rate, al_effect_props_); +} + +void EaxFlangerEffect::set_efx_depth() +{ + const auto depth = clamp( + eax_.flDepth, + AL_FLANGER_MIN_DEPTH, + AL_FLANGER_MAX_DEPTH); + + eax_set_efx_depth(depth, al_effect_props_); +} + +void EaxFlangerEffect::set_efx_feedback() +{ + const auto feedback = clamp( + eax_.flFeedback, + AL_FLANGER_MIN_FEEDBACK, + AL_FLANGER_MAX_FEEDBACK); + + eax_set_efx_feedback(feedback, al_effect_props_); +} + +void EaxFlangerEffect::set_efx_delay() +{ + const auto delay = clamp( + eax_.flDelay, + AL_FLANGER_MIN_DELAY, + AL_FLANGER_MAX_DELAY); + + eax_set_efx_delay(delay, al_effect_props_); +} + +void EaxFlangerEffect::set_efx_defaults() +{ + set_efx_waveform(); + set_efx_phase(); + set_efx_rate(); + set_efx_depth(); + set_efx_feedback(); + set_efx_delay(); +} + +// [[nodiscard]] +bool EaxFlangerEffect::get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXFLANGER_NONE: + break; + + case EAXFLANGER_ALLPARAMETERS: + eax_call.set_value(eax_); + break; + + case EAXFLANGER_WAVEFORM: + eax_call.set_value(eax_.ulWaveform); + break; + + case EAXFLANGER_PHASE: + eax_call.set_value(eax_.lPhase); + break; + + case EAXFLANGER_RATE: + eax_call.set_value(eax_.flRate); + break; + + case EAXFLANGER_DEPTH: + eax_call.set_value(eax_.flDepth); + break; + + case EAXFLANGER_FEEDBACK: + eax_call.set_value(eax_.flFeedback); + break; + + case EAXFLANGER_DELAY: + eax_call.set_value(eax_.flDelay); + break; + + default: + throw EaxFlangerEffectException{"Unsupported property id."}; + } + + return false; +} + +void EaxFlangerEffect::validate_waveform( + unsigned long ulWaveform) +{ + eax_validate_range( + "Waveform", + ulWaveform, + EAXFLANGER_MINWAVEFORM, + EAXFLANGER_MAXWAVEFORM); +} + +void EaxFlangerEffect::validate_phase( + long lPhase) +{ + eax_validate_range( + "Phase", + lPhase, + EAXFLANGER_MINPHASE, + EAXFLANGER_MAXPHASE); +} + +void EaxFlangerEffect::validate_rate( + float flRate) +{ + eax_validate_range( + "Rate", + flRate, + EAXFLANGER_MINRATE, + EAXFLANGER_MAXRATE); +} + +void EaxFlangerEffect::validate_depth( + float flDepth) +{ + eax_validate_range( + "Depth", + flDepth, + EAXFLANGER_MINDEPTH, + EAXFLANGER_MAXDEPTH); +} + +void EaxFlangerEffect::validate_feedback( + float flFeedback) +{ + eax_validate_range( + "Feedback", + flFeedback, + EAXFLANGER_MINFEEDBACK, + EAXFLANGER_MAXFEEDBACK); +} + +void EaxFlangerEffect::validate_delay( + float flDelay) +{ + eax_validate_range( + "Delay", + flDelay, + EAXFLANGER_MINDELAY, + EAXFLANGER_MAXDELAY); +} + +void EaxFlangerEffect::validate_all( + const EAXFLANGERPROPERTIES& all) +{ + validate_waveform(all.ulWaveform); + validate_phase(all.lPhase); + validate_rate(all.flRate); + validate_depth(all.flDepth); + validate_feedback(all.flDelay); + validate_delay(all.flDelay); +} + +void EaxFlangerEffect::defer_waveform( + unsigned long ulWaveform) +{ + eax_d_.ulWaveform = ulWaveform; + eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform); +} + +void EaxFlangerEffect::defer_phase( + long lPhase) +{ + eax_d_.lPhase = lPhase; + eax_dirty_flags_.lPhase = (eax_.lPhase != eax_d_.lPhase); +} + +void EaxFlangerEffect::defer_rate( + float flRate) +{ + eax_d_.flRate = flRate; + eax_dirty_flags_.flRate = (eax_.flRate != eax_d_.flRate); +} + +void EaxFlangerEffect::defer_depth( + float flDepth) +{ + eax_d_.flDepth = flDepth; + eax_dirty_flags_.flDepth = (eax_.flDepth != eax_d_.flDepth); +} + +void EaxFlangerEffect::defer_feedback( + float flFeedback) +{ + eax_d_.flFeedback = flFeedback; + eax_dirty_flags_.flFeedback = (eax_.flFeedback != eax_d_.flFeedback); +} + +void EaxFlangerEffect::defer_delay( + float flDelay) +{ + eax_d_.flDelay = flDelay; + eax_dirty_flags_.flDelay = (eax_.flDelay != eax_d_.flDelay); +} + +void EaxFlangerEffect::defer_all( + const EAXFLANGERPROPERTIES& all) +{ + defer_waveform(all.ulWaveform); + defer_phase(all.lPhase); + defer_rate(all.flRate); + defer_depth(all.flDepth); + defer_feedback(all.flDelay); + defer_delay(all.flDelay); +} + +void EaxFlangerEffect::defer_waveform( + const EaxEaxCall& eax_call) +{ + const auto& waveform = + eax_call.get_value(); + + validate_waveform(waveform); + defer_waveform(waveform); +} + +void EaxFlangerEffect::defer_phase( + const EaxEaxCall& eax_call) +{ + const auto& phase = + eax_call.get_value(); + + validate_phase(phase); + defer_phase(phase); +} + +void EaxFlangerEffect::defer_rate( + const EaxEaxCall& eax_call) +{ + const auto& rate = + eax_call.get_value(); + + validate_rate(rate); + defer_rate(rate); +} + +void EaxFlangerEffect::defer_depth( + const EaxEaxCall& eax_call) +{ + const auto& depth = + eax_call.get_value(); + + validate_depth(depth); + defer_depth(depth); +} + +void EaxFlangerEffect::defer_feedback( + const EaxEaxCall& eax_call) +{ + const auto& feedback = + eax_call.get_value(); + + validate_feedback(feedback); + defer_feedback(feedback); +} + +void EaxFlangerEffect::defer_delay( + const EaxEaxCall& eax_call) +{ + const auto& delay = + eax_call.get_value(); + + validate_delay(delay); + defer_delay(delay); +} + +void EaxFlangerEffect::defer_all( + const EaxEaxCall& eax_call) +{ + const auto& all = + eax_call.get_value(); + + validate_all(all); + defer_all(all); +} + +// [[nodiscard]] +bool EaxFlangerEffect::apply_deferred() +{ + if (eax_dirty_flags_ == EaxFlangerEffectDirtyFlags{}) + { + return false; + } + + eax_ = eax_d_; + + if (eax_dirty_flags_.ulWaveform) + { + set_efx_waveform(); + } + + if (eax_dirty_flags_.lPhase) + { + set_efx_phase(); + } + + if (eax_dirty_flags_.flRate) + { + set_efx_rate(); + } + + if (eax_dirty_flags_.flDepth) + { + set_efx_depth(); + } + + if (eax_dirty_flags_.flFeedback) + { + set_efx_feedback(); + } + + if (eax_dirty_flags_.flDelay) + { + set_efx_delay(); + } + + eax_dirty_flags_ = EaxFlangerEffectDirtyFlags{}; + + return true; +} + +// [[nodiscard]] +bool EaxFlangerEffect::set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXFLANGER_NONE: + break; + + case EAXFLANGER_ALLPARAMETERS: + defer_all(eax_call); + break; + + case EAXFLANGER_WAVEFORM: + defer_waveform(eax_call); + break; + + case EAXFLANGER_PHASE: + defer_phase(eax_call); + break; + + case EAXFLANGER_RATE: + defer_rate(eax_call); + break; + + case EAXFLANGER_DEPTH: + defer_depth(eax_call); + break; + + case EAXFLANGER_FEEDBACK: + defer_feedback(eax_call); + break; + + case EAXFLANGER_DELAY: + defer_delay(eax_call); + break; + + default: + throw EaxFlangerEffectException{"Unsupported property id."}; + } + + if (!eax_call.is_deferred()) + { + return apply_deferred(); + } + + return false; +} + + +} // namespace + + +EaxEffectUPtr eax_create_eax_flanger_effect( + EffectProps& al_effect_props) +{ + return std::make_unique(al_effect_props); +} + + +#endif // ALSOFT_EAX diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp index f5db2a6f..868c5c1b 100644 --- a/al/effects/compressor.cpp +++ b/al/effects/compressor.cpp @@ -7,6 +7,13 @@ #include "alc/effects/base.h" #include "effects.h" +#if ALSOFT_EAX +#include "alnumeric.h" + +#include "al/eax_exception.h" +#include "al/eax_utils.h" +#endif // ALSOFT_EAX + namespace { @@ -70,3 +77,268 @@ EffectProps genDefaultProps() noexcept DEFINE_ALEFFECT_VTABLE(Compressor); const EffectProps CompressorEffectProps{genDefaultProps()}; + +#if ALSOFT_EAX +namespace +{ + + +using EaxCompressorEffectDirtyFlagsValue = std::uint_least8_t; + +struct EaxCompressorEffectDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxCompressorEffectDirtyFlagsValue ulOnOff : 1; +}; // EaxCompressorEffectDirtyFlags + + +class EaxCompressorEffect final : + public EaxEffect +{ +public: + EaxCompressorEffect( + EffectProps& al_effect_props); + + + // [[nodiscard]] + bool dispatch( + const EaxEaxCall& eax_call) override; + + +private: + EffectProps& al_effect_props_; + + EAXAGCCOMPRESSORPROPERTIES eax_{}; + EAXAGCCOMPRESSORPROPERTIES eax_d_{}; + EaxCompressorEffectDirtyFlags eax_dirty_flags_{}; + + + void set_eax_defaults(); + + + void set_efx_on_off(); + + void set_efx_defaults(); + + + // [[nodiscard]] + bool get( + const EaxEaxCall& eax_call); + + + void validate_on_off( + unsigned long ulOnOff); + + void validate_all( + const EAXAGCCOMPRESSORPROPERTIES& eax_all); + + + void defer_on_off( + unsigned long ulOnOff); + + void defer_all( + const EAXAGCCOMPRESSORPROPERTIES& eax_all); + + + void defer_on_off( + const EaxEaxCall& eax_call); + + void defer_all( + const EaxEaxCall& eax_call); + + + // [[nodiscard]] + bool apply_deferred(); + + // [[nodiscard]] + bool set( + const EaxEaxCall& eax_call); +}; // EaxCompressorEffect + + +class EaxCompressorEffectException : + public EaxException +{ +public: + explicit EaxCompressorEffectException( + const char* message) + : + EaxException{"EAX_COMPRESSOR_EFFECT", message} + { + } +}; // EaxCompressorEffectException + + +EaxCompressorEffect::EaxCompressorEffect( + EffectProps& al_effect_props) + : + al_effect_props_{al_effect_props} +{ + set_eax_defaults(); + set_efx_defaults(); +} + +// [[nodiscard]] +bool EaxCompressorEffect::dispatch( + const EaxEaxCall& eax_call) +{ + return eax_call.is_get() ? get(eax_call) : set(eax_call); +} + +void EaxCompressorEffect::set_eax_defaults() +{ + eax_.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF; + + eax_d_ = eax_; +} + +void EaxCompressorEffect::set_efx_on_off() +{ + const auto on_off = clamp( + static_cast(eax_.ulOnOff), + AL_COMPRESSOR_MIN_ONOFF, + AL_COMPRESSOR_MAX_ONOFF); + + al_effect_props_.Compressor.OnOff = (on_off != AL_FALSE); +} + +void EaxCompressorEffect::set_efx_defaults() +{ + set_efx_on_off(); +} + +// [[nodiscard]] +bool EaxCompressorEffect::get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXAGCCOMPRESSOR_NONE: + break; + + case EAXAGCCOMPRESSOR_ALLPARAMETERS: + eax_call.set_value(eax_); + break; + + case EAXAGCCOMPRESSOR_ONOFF: + eax_call.set_value(eax_.ulOnOff); + break; + + default: + throw EaxCompressorEffectException{"Unsupported property id."}; + } + + return false; +} + +void EaxCompressorEffect::validate_on_off( + unsigned long ulOnOff) +{ + eax_validate_range( + "On-Off", + ulOnOff, + EAXAGCCOMPRESSOR_MINONOFF, + EAXAGCCOMPRESSOR_MAXONOFF); +} + +void EaxCompressorEffect::validate_all( + const EAXAGCCOMPRESSORPROPERTIES& eax_all) +{ + validate_on_off(eax_all.ulOnOff); +} + +void EaxCompressorEffect::defer_on_off( + unsigned long ulOnOff) +{ + eax_d_.ulOnOff = ulOnOff; + eax_dirty_flags_.ulOnOff = (eax_.ulOnOff != eax_d_.ulOnOff); +} + +void EaxCompressorEffect::defer_all( + const EAXAGCCOMPRESSORPROPERTIES& eax_all) +{ + defer_on_off(eax_all.ulOnOff); +} + +void EaxCompressorEffect::defer_on_off( + const EaxEaxCall& eax_call) +{ + const auto& on_off = + eax_call.get_value(); + + validate_on_off(on_off); + defer_on_off(on_off); +} + +void EaxCompressorEffect::defer_all( + const EaxEaxCall& eax_call) +{ + const auto& all = + eax_call.get_value(); + + validate_all(all); + defer_all(all); +} + +// [[nodiscard]] +bool EaxCompressorEffect::apply_deferred() +{ + if (eax_dirty_flags_ == EaxCompressorEffectDirtyFlags{}) + { + return false; + } + + eax_ = eax_d_; + + if (eax_dirty_flags_.ulOnOff) + { + set_efx_on_off(); + } + + eax_dirty_flags_ = EaxCompressorEffectDirtyFlags{}; + + return true; +} + +// [[nodiscard]] +bool EaxCompressorEffect::set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXAGCCOMPRESSOR_NONE: + break; + + case EAXAGCCOMPRESSOR_ALLPARAMETERS: + defer_all(eax_call); + break; + + case EAXAGCCOMPRESSOR_ONOFF: + defer_on_off(eax_call); + break; + + default: + throw EaxCompressorEffectException{"Unsupported property id."}; + } + + if (!eax_call.is_deferred()) + { + return apply_deferred(); + } + + return false; +} + + +} // namespace + + +EaxEffectUPtr eax_create_eax_compressor_effect( + EffectProps& al_effect_props) +{ + return std::make_unique(al_effect_props); +} + + +#endif // ALSOFT_EAX diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index f5d64a9a..062cdc54 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -7,6 +7,13 @@ #include "alc/effects/base.h" #include "effects.h" +#if ALSOFT_EAX +#include "alnumeric.h" + +#include "al/eax_exception.h" +#include "al/eax_utils.h" +#endif // ALSOFT_EAX + namespace { @@ -112,3 +119,532 @@ EffectProps genDefaultProps() noexcept DEFINE_ALEFFECT_VTABLE(Distortion); const EffectProps DistortionEffectProps{genDefaultProps()}; + +#if ALSOFT_EAX +namespace +{ + + +using EaxDistortionEffectDirtyFlagsValue = std::uint_least8_t; + +struct EaxDistortionEffectDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxDistortionEffectDirtyFlagsValue flEdge : 1; + EaxDistortionEffectDirtyFlagsValue lGain : 1; + EaxDistortionEffectDirtyFlagsValue flLowPassCutOff : 1; + EaxDistortionEffectDirtyFlagsValue flEQCenter : 1; + EaxDistortionEffectDirtyFlagsValue flEQBandwidth : 1; +}; // EaxDistortionEffectDirtyFlags + + +class EaxDistortionEffect final : + public EaxEffect +{ +public: + EaxDistortionEffect( + EffectProps& al_effect_props); + + + // [[nodiscard]] + bool dispatch( + const EaxEaxCall& eax_call) override; + + +private: + EffectProps& al_effect_props_; + + EAXDISTORTIONPROPERTIES eax_{}; + EAXDISTORTIONPROPERTIES eax_d_{}; + EaxDistortionEffectDirtyFlags eax_dirty_flags_{}; + + + void set_eax_defaults(); + + + void set_efx_edge(); + + void set_efx_gain(); + + void set_efx_lowpass_cutoff(); + + void set_efx_eq_center(); + + void set_efx_eq_bandwidth(); + + void set_efx_defaults(); + + + // [[nodiscard]] + bool get( + const EaxEaxCall& eax_call); + + + void validate_edge( + float flEdge); + + void validate_gain( + long lGain); + + void validate_lowpass_cutoff( + float flLowPassCutOff); + + void validate_eq_center( + float flEQCenter); + + void validate_eq_bandwidth( + float flEQBandwidth); + + void validate_all( + const EAXDISTORTIONPROPERTIES& eax_all); + + + void defer_edge( + float flEdge); + + void defer_gain( + long lGain); + + void defer_low_pass_cutoff( + float flLowPassCutOff); + + void defer_eq_center( + float flEQCenter); + + void defer_eq_bandwidth( + float flEQBandwidth); + + void defer_all( + const EAXDISTORTIONPROPERTIES& eax_all); + + + void defer_edge( + const EaxEaxCall& eax_call); + + void defer_gain( + const EaxEaxCall& eax_call); + + void defer_low_pass_cutoff( + const EaxEaxCall& eax_call); + + void defer_eq_center( + const EaxEaxCall& eax_call); + + void defer_eq_bandwidth( + const EaxEaxCall& eax_call); + + void defer_all( + const EaxEaxCall& eax_call); + + + // [[nodiscard]] + bool apply_deferred(); + + // [[nodiscard]] + bool set( + const EaxEaxCall& eax_call); +}; // EaxDistortionEffect + + +class EaxDistortionEffectException : + public EaxException +{ +public: + explicit EaxDistortionEffectException( + const char* message) + : + EaxException{"EAX_DISTORTION_EFFECT", message} + { + } +}; // EaxDistortionEffectException + + +EaxDistortionEffect::EaxDistortionEffect( + EffectProps& al_effect_props) + : + al_effect_props_{al_effect_props} +{ + set_eax_defaults(); + set_efx_defaults(); +} + +// [[nodiscard]] +bool EaxDistortionEffect::dispatch( + const EaxEaxCall& eax_call) +{ + return eax_call.is_get() ? get(eax_call) : set(eax_call); +} + +void EaxDistortionEffect::set_eax_defaults() +{ + eax_.flEdge = EAXDISTORTION_DEFAULTEDGE; + eax_.lGain = EAXDISTORTION_DEFAULTGAIN; + eax_.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF; + eax_.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER; + eax_.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH; + + eax_d_ = eax_; +} + +void EaxDistortionEffect::set_efx_edge() +{ + const auto edge = clamp( + eax_.flEdge, + AL_DISTORTION_MIN_EDGE, + AL_DISTORTION_MAX_EDGE); + + al_effect_props_.Distortion.Edge = edge; +} + +void EaxDistortionEffect::set_efx_gain() +{ + const auto gain = clamp( + level_mb_to_gain(static_cast(eax_.lGain)), + AL_DISTORTION_MIN_GAIN, + AL_DISTORTION_MAX_GAIN); + + al_effect_props_.Distortion.Gain = gain; +} + +void EaxDistortionEffect::set_efx_lowpass_cutoff() +{ + const auto lowpass_cutoff = clamp( + eax_.flLowPassCutOff, + AL_DISTORTION_MIN_LOWPASS_CUTOFF, + AL_DISTORTION_MAX_LOWPASS_CUTOFF); + + al_effect_props_.Distortion.LowpassCutoff = lowpass_cutoff; +} + +void EaxDistortionEffect::set_efx_eq_center() +{ + const auto eq_center = clamp( + eax_.flEQCenter, + AL_DISTORTION_MIN_EQCENTER, + AL_DISTORTION_MAX_EQCENTER); + + al_effect_props_.Distortion.EQCenter = eq_center; +} + +void EaxDistortionEffect::set_efx_eq_bandwidth() +{ + const auto eq_bandwidth = clamp( + eax_.flEdge, + AL_DISTORTION_MIN_EQBANDWIDTH, + AL_DISTORTION_MAX_EQBANDWIDTH); + + al_effect_props_.Distortion.EQBandwidth = eq_bandwidth; +} + +void EaxDistortionEffect::set_efx_defaults() +{ + set_efx_edge(); + set_efx_gain(); + set_efx_lowpass_cutoff(); + set_efx_eq_center(); + set_efx_eq_bandwidth(); +} + +// [[nodiscard]] +bool EaxDistortionEffect::get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXDISTORTION_NONE: + break; + + case EAXDISTORTION_ALLPARAMETERS: + eax_call.set_value(eax_); + break; + + case EAXDISTORTION_EDGE: + eax_call.set_value(eax_.flEdge); + break; + + case EAXDISTORTION_GAIN: + eax_call.set_value(eax_.lGain); + break; + + case EAXDISTORTION_LOWPASSCUTOFF: + eax_call.set_value(eax_.flLowPassCutOff); + break; + + case EAXDISTORTION_EQCENTER: + eax_call.set_value(eax_.flEQCenter); + break; + + case EAXDISTORTION_EQBANDWIDTH: + eax_call.set_value(eax_.flEQBandwidth); + break; + + default: + throw EaxDistortionEffectException{"Unsupported property id."}; + } + + return false; +} + +void EaxDistortionEffect::validate_edge( + float flEdge) +{ + eax_validate_range( + "Edge", + flEdge, + EAXDISTORTION_MINEDGE, + EAXDISTORTION_MAXEDGE); +} + +void EaxDistortionEffect::validate_gain( + long lGain) +{ + eax_validate_range( + "Gain", + lGain, + EAXDISTORTION_MINGAIN, + EAXDISTORTION_MAXGAIN); +} + +void EaxDistortionEffect::validate_lowpass_cutoff( + float flLowPassCutOff) +{ + eax_validate_range( + "Low-pass Cut-off", + flLowPassCutOff, + EAXDISTORTION_MINLOWPASSCUTOFF, + EAXDISTORTION_MAXLOWPASSCUTOFF); +} + +void EaxDistortionEffect::validate_eq_center( + float flEQCenter) +{ + eax_validate_range( + "EQ Center", + flEQCenter, + EAXDISTORTION_MINEQCENTER, + EAXDISTORTION_MAXEQCENTER); +} + +void EaxDistortionEffect::validate_eq_bandwidth( + float flEQBandwidth) +{ + eax_validate_range( + "EQ Bandwidth", + flEQBandwidth, + EAXDISTORTION_MINEQBANDWIDTH, + EAXDISTORTION_MAXEQBANDWIDTH); +} + +void EaxDistortionEffect::validate_all( + const EAXDISTORTIONPROPERTIES& eax_all) +{ + validate_edge(eax_all.flEdge); + validate_gain(eax_all.lGain); + validate_lowpass_cutoff(eax_all.flLowPassCutOff); + validate_eq_center(eax_all.flEQCenter); + validate_eq_bandwidth(eax_all.flEQBandwidth); +} + +void EaxDistortionEffect::defer_edge( + float flEdge) +{ + eax_d_.flEdge = flEdge; + eax_dirty_flags_.flEdge = (eax_.flEdge != eax_d_.flEdge); +} + +void EaxDistortionEffect::defer_gain( + long lGain) +{ + eax_d_.lGain = lGain; + eax_dirty_flags_.lGain = (eax_.lGain != eax_d_.lGain); +} + +void EaxDistortionEffect::defer_low_pass_cutoff( + float flLowPassCutOff) +{ + eax_d_.flLowPassCutOff = flLowPassCutOff; + eax_dirty_flags_.flLowPassCutOff = (eax_.flLowPassCutOff != eax_d_.flLowPassCutOff); +} + +void EaxDistortionEffect::defer_eq_center( + float flEQCenter) +{ + eax_d_.flEQCenter = flEQCenter; + eax_dirty_flags_.flEQCenter = (eax_.flEQCenter != eax_d_.flEQCenter); +} + +void EaxDistortionEffect::defer_eq_bandwidth( + float flEQBandwidth) +{ + eax_d_.flEQBandwidth = flEQBandwidth; + eax_dirty_flags_.flEQBandwidth = (eax_.flEQBandwidth != eax_d_.flEQBandwidth); +} + +void EaxDistortionEffect::defer_all( + const EAXDISTORTIONPROPERTIES& eax_all) +{ + defer_edge(eax_all.flEdge); + defer_gain(eax_all.lGain); + defer_low_pass_cutoff(eax_all.flLowPassCutOff); + defer_eq_center(eax_all.flEQCenter); + defer_eq_bandwidth(eax_all.flEQBandwidth); +} + +void EaxDistortionEffect::defer_edge( + const EaxEaxCall& eax_call) +{ + const auto& edge = + eax_call.get_value(); + + validate_edge(edge); + defer_edge(edge); +} + +void EaxDistortionEffect::defer_gain( + const EaxEaxCall& eax_call) +{ + const auto& gain = + eax_call.get_value(); + + validate_gain(gain); + defer_gain(gain); +} + +void EaxDistortionEffect::defer_low_pass_cutoff( + const EaxEaxCall& eax_call) +{ + const auto& lowpass_cutoff = + eax_call.get_value(); + + validate_lowpass_cutoff(lowpass_cutoff); + defer_low_pass_cutoff(lowpass_cutoff); +} + +void EaxDistortionEffect::defer_eq_center( + const EaxEaxCall& eax_call) +{ + const auto& eq_center = + eax_call.get_value(); + + validate_eq_center(eq_center); + defer_eq_center(eq_center); +} + +void EaxDistortionEffect::defer_eq_bandwidth( + const EaxEaxCall& eax_call) +{ + const auto& eq_bandwidth = + eax_call.get_value(); + + validate_eq_bandwidth(eq_bandwidth); + defer_eq_bandwidth(eq_bandwidth); +} + +void EaxDistortionEffect::defer_all( + const EaxEaxCall& eax_call) +{ + const auto& all = + eax_call.get_value(); + + validate_all(all); + defer_all(all); +} + +// [[nodiscard]] +bool EaxDistortionEffect::apply_deferred() +{ + if (eax_dirty_flags_ == EaxDistortionEffectDirtyFlags{}) + { + return false; + } + + eax_ = eax_d_; + + if (eax_dirty_flags_.flEdge) + { + set_efx_edge(); + } + + if (eax_dirty_flags_.lGain) + { + set_efx_gain(); + } + + if (eax_dirty_flags_.flLowPassCutOff) + { + set_efx_lowpass_cutoff(); + } + + if (eax_dirty_flags_.flEQCenter) + { + set_efx_eq_center(); + } + + if (eax_dirty_flags_.flEQBandwidth) + { + set_efx_eq_bandwidth(); + } + + eax_dirty_flags_ = EaxDistortionEffectDirtyFlags{}; + + return true; +} + +// [[nodiscard]] +bool EaxDistortionEffect::set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXDISTORTION_NONE: + break; + + case EAXDISTORTION_ALLPARAMETERS: + defer_all(eax_call); + break; + + case EAXDISTORTION_EDGE: + defer_edge(eax_call); + break; + + case EAXDISTORTION_GAIN: + defer_gain(eax_call); + break; + + case EAXDISTORTION_LOWPASSCUTOFF: + defer_low_pass_cutoff(eax_call); + break; + + case EAXDISTORTION_EQCENTER: + defer_eq_center(eax_call); + break; + + case EAXDISTORTION_EQBANDWIDTH: + defer_eq_bandwidth(eax_call); + break; + + default: + throw EaxDistortionEffectException{"Unsupported property id."}; + } + + if (!eax_call.is_deferred()) + { + return apply_deferred(); + } + + return false; +} + + +} // namespace + + +EaxEffectUPtr eax_create_eax_distortion_effect( + EffectProps& al_effect_props) +{ + return std::make_unique(al_effect_props); +} + + +#endif // ALSOFT_EAX diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index 65f691c6..5ceb161d 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -7,6 +7,13 @@ #include "alc/effects/base.h" #include "effects.h" +#if ALSOFT_EAX +#include "alnumeric.h" + +#include "al/eax_exception.h" +#include "al/eax_utils.h" +#endif // ALSOFT_EAX + namespace { @@ -109,3 +116,530 @@ EffectProps genDefaultProps() noexcept DEFINE_ALEFFECT_VTABLE(Echo); const EffectProps EchoEffectProps{genDefaultProps()}; + +#if ALSOFT_EAX +namespace +{ + + +using EaxEchoEffectDirtyFlagsValue = std::uint_least8_t; + +struct EaxEchoEffectDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxEchoEffectDirtyFlagsValue flDelay : 1; + EaxEchoEffectDirtyFlagsValue flLRDelay : 1; + EaxEchoEffectDirtyFlagsValue flDamping : 1; + EaxEchoEffectDirtyFlagsValue flFeedback : 1; + EaxEchoEffectDirtyFlagsValue flSpread : 1; +}; // EaxEchoEffectDirtyFlags + + +class EaxEchoEffect final : + public EaxEffect +{ +public: + EaxEchoEffect( + EffectProps& al_effect_props); + + + // [[nodiscard]] + bool dispatch( + const EaxEaxCall& eax_call) override; + + +private: + EffectProps& al_effect_props_; + + EAXECHOPROPERTIES eax_{}; + EAXECHOPROPERTIES eax_d_{}; + EaxEchoEffectDirtyFlags eax_dirty_flags_{}; + + + void set_eax_defaults(); + + + void set_efx_delay(); + + void set_efx_lr_delay(); + + void set_efx_damping(); + + void set_efx_feedback(); + + void set_efx_spread(); + + void set_efx_defaults(); + + + // [[nodiscard]] + bool get( + const EaxEaxCall& eax_call); + + + void validate_delay( + float flDelay); + + void validate_lr_delay( + float flLRDelay); + + void validate_damping( + float flDamping); + + void validate_feedback( + float flFeedback); + + void validate_spread( + float flSpread); + + void validate_all( + const EAXECHOPROPERTIES& all); + + + void defer_delay( + float flDelay); + + void defer_lr_delay( + float flLRDelay); + + void defer_damping( + float flDamping); + + void defer_feedback( + float flFeedback); + + void defer_spread( + float flSpread); + + void defer_all( + const EAXECHOPROPERTIES& all); + + + void defer_delay( + const EaxEaxCall& eax_call); + + void defer_lr_delay( + const EaxEaxCall& eax_call); + + void defer_damping( + const EaxEaxCall& eax_call); + + void defer_feedback( + const EaxEaxCall& eax_call); + + void defer_spread( + const EaxEaxCall& eax_call); + + void defer_all( + const EaxEaxCall& eax_call); + + + bool apply_deferred(); + + bool set( + const EaxEaxCall& eax_call); +}; // EaxEchoEffect + + +class EaxEchoEffectException : + public EaxException +{ +public: + explicit EaxEchoEffectException( + const char* message) + : + EaxException{"EAX_ECHO_EFFECT", message} + { + } +}; // EaxEchoEffectException + + +EaxEchoEffect::EaxEchoEffect( + EffectProps& al_effect_props) + : + al_effect_props_{al_effect_props} +{ + set_eax_defaults(); + set_efx_defaults(); +} + +// [[nodiscard]] +bool EaxEchoEffect::dispatch( + const EaxEaxCall& eax_call) +{ + return eax_call.is_get() ? get(eax_call) : set(eax_call); +} + +void EaxEchoEffect::set_eax_defaults() +{ + eax_.flDelay = EAXECHO_DEFAULTDELAY; + eax_.flLRDelay = EAXECHO_DEFAULTLRDELAY; + eax_.flDamping = EAXECHO_DEFAULTDAMPING; + eax_.flFeedback = EAXECHO_DEFAULTFEEDBACK; + eax_.flSpread = EAXECHO_DEFAULTSPREAD; + + eax_d_ = eax_; +} + +void EaxEchoEffect::set_efx_delay() +{ + const auto delay = clamp( + eax_.flDelay, + AL_ECHO_MIN_DELAY, + AL_ECHO_MAX_DELAY); + + al_effect_props_.Echo.Delay = delay; +} + +void EaxEchoEffect::set_efx_lr_delay() +{ + const auto lr_delay = clamp( + eax_.flLRDelay, + AL_ECHO_MIN_LRDELAY, + AL_ECHO_MAX_LRDELAY); + + al_effect_props_.Echo.LRDelay = lr_delay; +} + +void EaxEchoEffect::set_efx_damping() +{ + const auto damping = clamp( + eax_.flDamping, + AL_ECHO_MIN_DAMPING, + AL_ECHO_MAX_DAMPING); + + al_effect_props_.Echo.Damping = damping; +} + +void EaxEchoEffect::set_efx_feedback() +{ + const auto feedback = clamp( + eax_.flFeedback, + AL_ECHO_MIN_FEEDBACK, + AL_ECHO_MAX_FEEDBACK); + + al_effect_props_.Echo.Feedback = feedback; +} + +void EaxEchoEffect::set_efx_spread() +{ + const auto spread = clamp( + eax_.flSpread, + AL_ECHO_MIN_SPREAD, + AL_ECHO_MAX_SPREAD); + + al_effect_props_.Echo.Spread = spread; +} + +void EaxEchoEffect::set_efx_defaults() +{ + set_efx_delay(); + set_efx_lr_delay(); + set_efx_damping(); + set_efx_feedback(); + set_efx_spread(); +} + +// [[nodiscard]] +bool EaxEchoEffect::get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXECHO_NONE: + break; + + case EAXECHO_ALLPARAMETERS: + eax_call.set_value(eax_); + break; + + case EAXECHO_DELAY: + eax_call.set_value(eax_.flDelay); + break; + + case EAXECHO_LRDELAY: + eax_call.set_value(eax_.flLRDelay); + break; + + case EAXECHO_DAMPING: + eax_call.set_value(eax_.flDamping); + break; + + case EAXECHO_FEEDBACK: + eax_call.set_value(eax_.flFeedback); + break; + + case EAXECHO_SPREAD: + eax_call.set_value(eax_.flSpread); + break; + + default: + throw EaxEchoEffectException{"Unsupported property id."}; + } + + return false; +} + +void EaxEchoEffect::validate_delay( + float flDelay) +{ + eax_validate_range( + "Delay", + flDelay, + EAXECHO_MINDELAY, + EAXECHO_MAXDELAY); +} + +void EaxEchoEffect::validate_lr_delay( + float flLRDelay) +{ + eax_validate_range( + "LR Delay", + flLRDelay, + EAXECHO_MINLRDELAY, + EAXECHO_MAXLRDELAY); +} + +void EaxEchoEffect::validate_damping( + float flDamping) +{ + eax_validate_range( + "Damping", + flDamping, + EAXECHO_MINDAMPING, + EAXECHO_MAXDAMPING); +} + +void EaxEchoEffect::validate_feedback( + float flFeedback) +{ + eax_validate_range( + "Feedback", + flFeedback, + EAXECHO_MINFEEDBACK, + EAXECHO_MAXFEEDBACK); +} + +void EaxEchoEffect::validate_spread( + float flSpread) +{ + eax_validate_range( + "Spread", + flSpread, + EAXECHO_MINSPREAD, + EAXECHO_MAXSPREAD); +} + +void EaxEchoEffect::validate_all( + const EAXECHOPROPERTIES& all) +{ + validate_delay(all.flDelay); + validate_lr_delay(all.flLRDelay); + validate_damping(all.flDamping); + validate_feedback(all.flFeedback); + validate_spread(all.flSpread); +} + +void EaxEchoEffect::defer_delay( + float flDelay) +{ + eax_d_.flDelay = flDelay; + eax_dirty_flags_.flDelay = (eax_.flDelay != eax_d_.flDelay); +} + +void EaxEchoEffect::defer_lr_delay( + float flLRDelay) +{ + eax_d_.flLRDelay = flLRDelay; + eax_dirty_flags_.flLRDelay = (eax_.flLRDelay != eax_d_.flLRDelay); +} + +void EaxEchoEffect::defer_damping( + float flDamping) +{ + eax_d_.flDamping = flDamping; + eax_dirty_flags_.flDamping = (eax_.flDamping != eax_d_.flDamping); +} + +void EaxEchoEffect::defer_feedback( + float flFeedback) +{ + eax_d_.flFeedback = flFeedback; + eax_dirty_flags_.flFeedback = (eax_.flFeedback != eax_d_.flFeedback); +} + +void EaxEchoEffect::defer_spread( + float flSpread) +{ + eax_d_.flSpread = flSpread; + eax_dirty_flags_.flSpread = (eax_.flSpread != eax_d_.flSpread); +} + +void EaxEchoEffect::defer_all( + const EAXECHOPROPERTIES& all) +{ + defer_delay(all.flDelay); + defer_lr_delay(all.flLRDelay); + defer_damping(all.flDamping); + defer_feedback(all.flFeedback); + defer_spread(all.flSpread); +} + +void EaxEchoEffect::defer_delay( + const EaxEaxCall& eax_call) +{ + const auto& delay = + eax_call.get_value(); + + validate_delay(delay); + defer_delay(delay); +} + +void EaxEchoEffect::defer_lr_delay( + const EaxEaxCall& eax_call) +{ + const auto& lr_delay = + eax_call.get_value(); + + validate_lr_delay(lr_delay); + defer_lr_delay(lr_delay); +} + +void EaxEchoEffect::defer_damping( + const EaxEaxCall& eax_call) +{ + const auto& damping = + eax_call.get_value(); + + validate_damping(damping); + defer_damping(damping); +} + +void EaxEchoEffect::defer_feedback( + const EaxEaxCall& eax_call) +{ + const auto& feedback = + eax_call.get_value(); + + validate_feedback(feedback); + defer_feedback(feedback); +} + +void EaxEchoEffect::defer_spread( + const EaxEaxCall& eax_call) +{ + const auto& spread = + eax_call.get_value(); + + validate_spread(spread); + defer_spread(spread); +} + +void EaxEchoEffect::defer_all( + const EaxEaxCall& eax_call) +{ + const auto& all = + eax_call.get_value(); + + validate_all(all); + defer_all(all); +} + +// [[nodiscard]] +bool EaxEchoEffect::apply_deferred() +{ + if (eax_dirty_flags_ == EaxEchoEffectDirtyFlags{}) + { + return false; + } + + eax_ = eax_d_; + + if (eax_dirty_flags_.flDelay) + { + set_efx_delay(); + } + + if (eax_dirty_flags_.flLRDelay) + { + set_efx_lr_delay(); + } + + if (eax_dirty_flags_.flDamping) + { + set_efx_damping(); + } + + if (eax_dirty_flags_.flFeedback) + { + set_efx_feedback(); + } + + if (eax_dirty_flags_.flSpread) + { + set_efx_spread(); + } + + eax_dirty_flags_ = EaxEchoEffectDirtyFlags{}; + + return true; +} + +// [[nodiscard]] +bool EaxEchoEffect::set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXECHO_NONE: + break; + + case EAXECHO_ALLPARAMETERS: + defer_all(eax_call); + break; + + case EAXECHO_DELAY: + defer_delay(eax_call); + break; + + case EAXECHO_LRDELAY: + defer_lr_delay(eax_call); + break; + + case EAXECHO_DAMPING: + defer_damping(eax_call); + break; + + case EAXECHO_FEEDBACK: + defer_feedback(eax_call); + break; + + case EAXECHO_SPREAD: + defer_spread(eax_call); + break; + + default: + throw EaxEchoEffectException{"Unsupported property id."}; + } + + if (!eax_call.is_deferred()) + { + return apply_deferred(); + } + + return false; +} + + +} // namespace + + +EaxEffectUPtr eax_create_eax_echo_effect( + EffectProps& al_effect_props) +{ + return std::make_unique(al_effect_props); +} + + +#endif // ALSOFT_EAX diff --git a/al/effects/effects.cpp b/al/effects/effects.cpp new file mode 100644 index 00000000..55abfdc5 --- /dev/null +++ b/al/effects/effects.cpp @@ -0,0 +1,106 @@ +#if ALSOFT_EAX + + +#include + +#include "AL/efx.h" + +#include "effects.h" + + +EaxEffectUPtr eax_create_eax_null_effect(); + +EaxEffectUPtr eax_create_eax_chorus_effect( + EffectProps& al_effect_props); + +EaxEffectUPtr eax_create_eax_distortion_effect( + EffectProps& al_effect_props); + +EaxEffectUPtr eax_create_eax_echo_effect( + EffectProps& al_effect_props); + +EaxEffectUPtr eax_create_eax_flanger_effect( + EffectProps& al_effect_props); + +EaxEffectUPtr eax_create_eax_frequency_shifter_effect( + EffectProps& al_effect_props); + +EaxEffectUPtr eax_create_eax_vocal_morpher_effect( + EffectProps& al_effect_props); + +EaxEffectUPtr eax_create_eax_pitch_shifter_effect( + EffectProps& al_effect_props); + +EaxEffectUPtr eax_create_eax_ring_modulator_effect( + EffectProps& al_effect_props); + +EaxEffectUPtr eax_create_eax_auto_wah_effect( + EffectProps& al_effect_props); + +EaxEffectUPtr eax_create_eax_compressor_effect( + EffectProps& al_effect_props); + +EaxEffectUPtr eax_create_eax_equalizer_effect( + EffectProps& al_effect_props); + +EaxEffectUPtr eax_create_eax_reverb_effect( + EffectProps& al_effect_props); + + +EaxEffectUPtr eax_create_eax_effect( + ALenum al_effect_type, + EffectProps& al_effect_props) +{ +#define EAX_PREFIX "[EAX_MAKE_EAX_EFFECT] " + + switch (al_effect_type) + { + case AL_EFFECT_NULL: + return eax_create_eax_null_effect(); + + case AL_EFFECT_CHORUS: + return eax_create_eax_chorus_effect(al_effect_props); + + case AL_EFFECT_DISTORTION: + return eax_create_eax_distortion_effect(al_effect_props); + + case AL_EFFECT_ECHO: + return eax_create_eax_echo_effect(al_effect_props); + + case AL_EFFECT_FLANGER: + return eax_create_eax_flanger_effect(al_effect_props); + + case AL_EFFECT_FREQUENCY_SHIFTER: + return eax_create_eax_frequency_shifter_effect(al_effect_props); + + case AL_EFFECT_VOCAL_MORPHER: + return eax_create_eax_vocal_morpher_effect(al_effect_props); + + case AL_EFFECT_PITCH_SHIFTER: + return eax_create_eax_pitch_shifter_effect(al_effect_props); + + case AL_EFFECT_RING_MODULATOR: + return eax_create_eax_ring_modulator_effect(al_effect_props); + + case AL_EFFECT_AUTOWAH: + return eax_create_eax_auto_wah_effect(al_effect_props); + + case AL_EFFECT_COMPRESSOR: + return eax_create_eax_compressor_effect(al_effect_props); + + case AL_EFFECT_EQUALIZER: + return eax_create_eax_equalizer_effect(al_effect_props); + + case AL_EFFECT_EAXREVERB: + return eax_create_eax_reverb_effect(al_effect_props); + + default: + assert(false && "Unsupported AL effect type."); + return nullptr; + } + +#undef EAX_PREFIX +} + + +#endif // ALSOFT_EAX diff --git a/al/effects/effects.h b/al/effects/effects.h index 30b4bd75..6813beaa 100644 --- a/al/effects/effects.h +++ b/al/effects/effects.h @@ -5,6 +5,10 @@ #include "core/except.h" +#if ALSOFT_EAX +#include "al/eax_effect.h" +#endif // ALSOFT_EAX + union EffectProps; @@ -80,4 +84,11 @@ extern const EffectVtable VmorpherEffectVtable; extern const EffectVtable DedicatedEffectVtable; extern const EffectVtable ConvolutionEffectVtable; + +#if ALSOFT_EAX +EaxEffectUPtr eax_create_eax_effect( + ALenum al_effect_type, + EffectProps& al_effect_props); +#endif // ALSOFT_EAX + #endif /* AL_EFFECTS_EFFECTS_H */ diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index 3c039688..c052db3e 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -7,6 +7,13 @@ #include "alc/effects/base.h" #include "effects.h" +#if ALSOFT_EAX +#include "alnumeric.h" + +#include "al/eax_exception.h" +#include "al/eax_utils.h" +#endif // ALSOFT_EAX + namespace { @@ -167,3 +174,862 @@ EffectProps genDefaultProps() noexcept DEFINE_ALEFFECT_VTABLE(Equalizer); const EffectProps EqualizerEffectProps{genDefaultProps()}; + +#if ALSOFT_EAX +namespace +{ + + +using EaxEqualizerEffectDirtyFlagsValue = std::uint_least16_t; + +struct EaxEqualizerEffectDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxEqualizerEffectDirtyFlagsValue lLowGain : 1; + EaxEqualizerEffectDirtyFlagsValue flLowCutOff : 1; + EaxEqualizerEffectDirtyFlagsValue lMid1Gain : 1; + EaxEqualizerEffectDirtyFlagsValue flMid1Center : 1; + EaxEqualizerEffectDirtyFlagsValue flMid1Width : 1; + EaxEqualizerEffectDirtyFlagsValue lMid2Gain : 1; + EaxEqualizerEffectDirtyFlagsValue flMid2Center : 1; + EaxEqualizerEffectDirtyFlagsValue flMid2Width : 1; + EaxEqualizerEffectDirtyFlagsValue lHighGain : 1; + EaxEqualizerEffectDirtyFlagsValue flHighCutOff : 1; +}; // EaxEqualizerEffectDirtyFlags + + +class EaxEqualizerEffect final : + public EaxEffect +{ +public: + EaxEqualizerEffect( + EffectProps& al_effect_props); + + + // [[nodiscard]] + bool dispatch( + const EaxEaxCall& eax_call) override; + + +private: + EffectProps& al_effect_props_; + + EAXEQUALIZERPROPERTIES eax_{}; + EAXEQUALIZERPROPERTIES eax_d_{}; + EaxEqualizerEffectDirtyFlags eax_dirty_flags_{}; + + + void set_eax_defaults(); + + + void set_efx_low_gain(); + + void set_efx_low_cutoff(); + + void set_efx_mid1_gain(); + + void set_efx_mid1_center(); + + void set_efx_mid1_width(); + + void set_efx_mid2_gain(); + + void set_efx_mid2_center(); + + void set_efx_mid2_width(); + + void set_efx_high_gain(); + + void set_efx_high_cutoff(); + + void set_efx_defaults(); + + + // [[nodiscard]] + bool get( + const EaxEaxCall& eax_call); + + + void validate_low_gain( + long lLowGain); + + void validate_low_cutoff( + float flLowCutOff); + + void validate_mid1_gain( + long lMid1Gain); + + void validate_mid1_center( + float flMid1Center); + + void validate_mid1_width( + float flMid1Width); + + void validate_mid2_gain( + long lMid2Gain); + + void validate_mid2_center( + float flMid2Center); + + void validate_mid2_width( + float flMid2Width); + + void validate_high_gain( + long lHighGain); + + void validate_high_cutoff( + float flHighCutOff); + + void validate_all( + const EAXEQUALIZERPROPERTIES& all); + + + void defer_low_gain( + long lLowGain); + + void defer_low_cutoff( + float flLowCutOff); + + void defer_mid1_gain( + long lMid1Gain); + + void defer_mid1_center( + float flMid1Center); + + void defer_mid1_width( + float flMid1Width); + + void defer_mid2_gain( + long lMid2Gain); + + void defer_mid2_center( + float flMid2Center); + + void defer_mid2_width( + float flMid2Width); + + void defer_high_gain( + long lHighGain); + + void defer_high_cutoff( + float flHighCutOff); + + void defer_all( + const EAXEQUALIZERPROPERTIES& all); + + + void defer_low_gain( + const EaxEaxCall& eax_call); + + void defer_low_cutoff( + const EaxEaxCall& eax_call); + + void defer_mid1_gain( + const EaxEaxCall& eax_call); + + void defer_mid1_center( + const EaxEaxCall& eax_call); + + void defer_mid1_width( + const EaxEaxCall& eax_call); + + void defer_mid2_gain( + const EaxEaxCall& eax_call); + + void defer_mid2_center( + const EaxEaxCall& eax_call); + + void defer_mid2_width( + const EaxEaxCall& eax_call); + + void defer_high_gain( + const EaxEaxCall& eax_call); + + void defer_high_cutoff( + const EaxEaxCall& eax_call); + + void defer_all( + const EaxEaxCall& eax_call); + + + // [[nodiscard]] + bool apply_deferred(); + + // [[nodiscard]] + bool set( + const EaxEaxCall& eax_call); +}; // EaxEqualizerEffect + + +class EaxEqualizerEffectException : + public EaxException +{ +public: + explicit EaxEqualizerEffectException( + const char* message) + : + EaxException{"EAX_EQUALIZER_EFFECT", message} + { + } +}; // EaxEqualizerEffectException + + +EaxEqualizerEffect::EaxEqualizerEffect( + EffectProps& al_effect_props) + : + al_effect_props_{al_effect_props} +{ + set_eax_defaults(); + set_efx_defaults(); +} + +// [[nodiscard]] +bool EaxEqualizerEffect::dispatch( + const EaxEaxCall& eax_call) +{ + return eax_call.is_get() ? get(eax_call) : set(eax_call); +} + +void EaxEqualizerEffect::set_eax_defaults() +{ + eax_.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN; + eax_.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF; + eax_.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN; + eax_.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER; + eax_.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH; + eax_.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN; + eax_.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER; + eax_.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH; + eax_.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN; + eax_.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF; + + eax_d_ = eax_; +} + +void EaxEqualizerEffect::set_efx_low_gain() +{ + const auto low_gain = clamp( + level_mb_to_gain(static_cast(eax_.lLowGain)), + AL_EQUALIZER_MIN_LOW_GAIN, + AL_EQUALIZER_MAX_LOW_GAIN); + + al_effect_props_.Equalizer.LowGain = low_gain; +} + +void EaxEqualizerEffect::set_efx_low_cutoff() +{ + const auto low_cutoff = clamp( + eax_.flLowCutOff, + AL_EQUALIZER_MIN_LOW_CUTOFF, + AL_EQUALIZER_MAX_LOW_CUTOFF); + + al_effect_props_.Equalizer.LowCutoff = low_cutoff; +} + +void EaxEqualizerEffect::set_efx_mid1_gain() +{ + const auto mid1_gain = clamp( + level_mb_to_gain(static_cast(eax_.lMid1Gain)), + AL_EQUALIZER_MIN_MID1_GAIN, + AL_EQUALIZER_MAX_MID1_GAIN); + + al_effect_props_.Equalizer.Mid1Gain = mid1_gain; +} + +void EaxEqualizerEffect::set_efx_mid1_center() +{ + const auto mid1_center = clamp( + eax_.flMid1Center, + AL_EQUALIZER_MIN_MID1_CENTER, + AL_EQUALIZER_MAX_MID1_CENTER); + + al_effect_props_.Equalizer.Mid1Center = mid1_center; +} + +void EaxEqualizerEffect::set_efx_mid1_width() +{ + const auto mid1_width = clamp( + eax_.flMid1Width, + AL_EQUALIZER_MIN_MID1_WIDTH, + AL_EQUALIZER_MAX_MID1_WIDTH); + + al_effect_props_.Equalizer.Mid1Width = mid1_width; +} + +void EaxEqualizerEffect::set_efx_mid2_gain() +{ + const auto mid2_gain = clamp( + level_mb_to_gain(static_cast(eax_.lMid2Gain)), + AL_EQUALIZER_MIN_MID2_GAIN, + AL_EQUALIZER_MAX_MID2_GAIN); + + al_effect_props_.Equalizer.Mid2Gain = mid2_gain; +} + +void EaxEqualizerEffect::set_efx_mid2_center() +{ + const auto mid2_center = clamp( + eax_.flMid2Center, + AL_EQUALIZER_MIN_MID2_CENTER, + AL_EQUALIZER_MAX_MID2_CENTER); + + al_effect_props_.Equalizer.Mid2Center = mid2_center; +} + +void EaxEqualizerEffect::set_efx_mid2_width() +{ + const auto mid2_width = clamp( + eax_.flMid2Width, + AL_EQUALIZER_MIN_MID2_WIDTH, + AL_EQUALIZER_MAX_MID2_WIDTH); + + al_effect_props_.Equalizer.Mid2Width = mid2_width; +} + +void EaxEqualizerEffect::set_efx_high_gain() +{ + const auto high_gain = clamp( + level_mb_to_gain(static_cast(eax_.lHighGain)), + AL_EQUALIZER_MIN_HIGH_GAIN, + AL_EQUALIZER_MAX_HIGH_GAIN); + + al_effect_props_.Equalizer.HighGain = high_gain; +} + +void EaxEqualizerEffect::set_efx_high_cutoff() +{ + const auto high_cutoff = clamp( + eax_.flHighCutOff, + AL_EQUALIZER_MIN_HIGH_CUTOFF, + AL_EQUALIZER_MAX_HIGH_CUTOFF); + + al_effect_props_.Equalizer.HighCutoff = high_cutoff; +} + +void EaxEqualizerEffect::set_efx_defaults() +{ + set_efx_low_gain(); + set_efx_low_cutoff(); + set_efx_mid1_gain(); + set_efx_mid1_center(); + set_efx_mid1_width(); + set_efx_mid2_gain(); + set_efx_mid2_center(); + set_efx_mid2_width(); + set_efx_high_gain(); + set_efx_high_cutoff(); +} + +// [[nodiscard]] +bool EaxEqualizerEffect::get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXEQUALIZER_NONE: + break; + + case EAXEQUALIZER_ALLPARAMETERS: + eax_call.set_value(eax_); + break; + + case EAXEQUALIZER_LOWGAIN: + eax_call.set_value(eax_.lLowGain); + break; + + case EAXEQUALIZER_LOWCUTOFF: + eax_call.set_value(eax_.flLowCutOff); + break; + + case EAXEQUALIZER_MID1GAIN: + eax_call.set_value(eax_.lMid1Gain); + break; + + case EAXEQUALIZER_MID1CENTER: + eax_call.set_value(eax_.flMid1Center); + break; + + case EAXEQUALIZER_MID1WIDTH: + eax_call.set_value(eax_.flMid1Width); + break; + + case EAXEQUALIZER_MID2GAIN: + eax_call.set_value(eax_.lMid2Gain); + break; + + case EAXEQUALIZER_MID2CENTER: + eax_call.set_value(eax_.flMid2Center); + break; + + case EAXEQUALIZER_MID2WIDTH: + eax_call.set_value(eax_.flMid2Width); + break; + + case EAXEQUALIZER_HIGHGAIN: + eax_call.set_value(eax_.lHighGain); + break; + + case EAXEQUALIZER_HIGHCUTOFF: + eax_call.set_value(eax_.flHighCutOff); + break; + + default: + throw EaxEqualizerEffectException{"Unsupported property id."}; + } + + return false; +} + +void EaxEqualizerEffect::validate_low_gain( + long lLowGain) +{ + eax_validate_range( + "Low Gain", + lLowGain, + EAXEQUALIZER_MINLOWGAIN, + EAXEQUALIZER_MAXLOWGAIN); +} + +void EaxEqualizerEffect::validate_low_cutoff( + float flLowCutOff) +{ + eax_validate_range( + "Low Cutoff", + flLowCutOff, + EAXEQUALIZER_MINLOWCUTOFF, + EAXEQUALIZER_MAXLOWCUTOFF); +} + +void EaxEqualizerEffect::validate_mid1_gain( + long lMid1Gain) +{ + eax_validate_range( + "Mid1 Gain", + lMid1Gain, + EAXEQUALIZER_MINMID1GAIN, + EAXEQUALIZER_MAXMID1GAIN); +} + +void EaxEqualizerEffect::validate_mid1_center( + float flMid1Center) +{ + eax_validate_range( + "Mid1 Center", + flMid1Center, + EAXEQUALIZER_MINMID1CENTER, + EAXEQUALIZER_MAXMID1CENTER); +} + +void EaxEqualizerEffect::validate_mid1_width( + float flMid1Width) +{ + eax_validate_range( + "Mid1 Width", + flMid1Width, + EAXEQUALIZER_MINMID1WIDTH, + EAXEQUALIZER_MAXMID1WIDTH); +} + +void EaxEqualizerEffect::validate_mid2_gain( + long lMid2Gain) +{ + eax_validate_range( + "Mid2 Gain", + lMid2Gain, + EAXEQUALIZER_MINMID2GAIN, + EAXEQUALIZER_MAXMID2GAIN); +} + +void EaxEqualizerEffect::validate_mid2_center( + float flMid2Center) +{ + eax_validate_range( + "Mid2 Center", + flMid2Center, + EAXEQUALIZER_MINMID2CENTER, + EAXEQUALIZER_MAXMID2CENTER); +} + +void EaxEqualizerEffect::validate_mid2_width( + float flMid2Width) +{ + eax_validate_range( + "Mid2 Width", + flMid2Width, + EAXEQUALIZER_MINMID2WIDTH, + EAXEQUALIZER_MAXMID2WIDTH); +} + +void EaxEqualizerEffect::validate_high_gain( + long lHighGain) +{ + eax_validate_range( + "High Gain", + lHighGain, + EAXEQUALIZER_MINHIGHGAIN, + EAXEQUALIZER_MAXHIGHGAIN); +} + +void EaxEqualizerEffect::validate_high_cutoff( + float flHighCutOff) +{ + eax_validate_range( + "High Cutoff", + flHighCutOff, + EAXEQUALIZER_MINHIGHCUTOFF, + EAXEQUALIZER_MAXHIGHCUTOFF); +} + +void EaxEqualizerEffect::validate_all( + const EAXEQUALIZERPROPERTIES& all) +{ + validate_low_gain(all.lLowGain); + validate_low_cutoff(all.flLowCutOff); + validate_mid1_gain(all.lMid1Gain); + validate_mid1_center(all.flMid1Center); + validate_mid1_width(all.flMid1Width); + validate_mid2_gain(all.lMid2Gain); + validate_mid2_center(all.flMid2Center); + validate_mid2_width(all.flMid2Width); + validate_high_gain(all.lHighGain); + validate_high_cutoff(all.flHighCutOff); +} + +void EaxEqualizerEffect::defer_low_gain( + long lLowGain) +{ + eax_d_.lLowGain = lLowGain; + eax_dirty_flags_.lLowGain = (eax_.lLowGain != eax_d_.lLowGain); +} + +void EaxEqualizerEffect::defer_low_cutoff( + float flLowCutOff) +{ + eax_d_.flLowCutOff = flLowCutOff; + eax_dirty_flags_.flLowCutOff = (eax_.flLowCutOff != eax_d_.flLowCutOff); +} + +void EaxEqualizerEffect::defer_mid1_gain( + long lMid1Gain) +{ + eax_d_.lMid1Gain = lMid1Gain; + eax_dirty_flags_.lMid1Gain = (eax_.lMid1Gain != eax_d_.lMid1Gain); +} + +void EaxEqualizerEffect::defer_mid1_center( + float flMid1Center) +{ + eax_d_.flMid1Center = flMid1Center; + eax_dirty_flags_.flMid1Center = (eax_.flMid1Center != eax_d_.flMid1Center); +} + +void EaxEqualizerEffect::defer_mid1_width( + float flMid1Width) +{ + eax_d_.flMid1Width = flMid1Width; + eax_dirty_flags_.flMid1Width = (eax_.flMid1Width != eax_d_.flMid1Width); +} + +void EaxEqualizerEffect::defer_mid2_gain( + long lMid2Gain) +{ + eax_d_.lMid2Gain = lMid2Gain; + eax_dirty_flags_.lMid2Gain = (eax_.lMid2Gain != eax_d_.lMid2Gain); +} + +void EaxEqualizerEffect::defer_mid2_center( + float flMid2Center) +{ + eax_d_.flMid2Center = flMid2Center; + eax_dirty_flags_.flMid2Center = (eax_.flMid2Center != eax_d_.flMid2Center); +} + +void EaxEqualizerEffect::defer_mid2_width( + float flMid2Width) +{ + eax_d_.flMid2Width = flMid2Width; + eax_dirty_flags_.flMid2Width = (eax_.flMid2Width != eax_d_.flMid2Width); +} + +void EaxEqualizerEffect::defer_high_gain( + long lHighGain) +{ + eax_d_.lHighGain = lHighGain; + eax_dirty_flags_.lHighGain = (eax_.lHighGain != eax_d_.lHighGain); +} + +void EaxEqualizerEffect::defer_high_cutoff( + float flHighCutOff) +{ + eax_d_.flHighCutOff = flHighCutOff; + eax_dirty_flags_.flHighCutOff = (eax_.flHighCutOff != eax_d_.flHighCutOff); +} + +void EaxEqualizerEffect::defer_all( + const EAXEQUALIZERPROPERTIES& all) +{ + defer_low_gain(all.lLowGain); + defer_low_cutoff(all.flLowCutOff); + defer_mid1_gain(all.lMid1Gain); + defer_mid1_center(all.flMid1Center); + defer_mid1_width(all.flMid1Width); + defer_mid2_gain(all.lMid2Gain); + defer_mid2_center(all.flMid2Center); + defer_mid2_width(all.flMid2Width); + defer_high_gain(all.lHighGain); + defer_high_cutoff(all.flHighCutOff); +} + +void EaxEqualizerEffect::defer_low_gain( + const EaxEaxCall& eax_call) +{ + const auto& low_gain = + eax_call.get_value(); + + validate_low_gain(low_gain); + defer_low_gain(low_gain); +} + +void EaxEqualizerEffect::defer_low_cutoff( + const EaxEaxCall& eax_call) +{ + const auto& low_cutoff = + eax_call.get_value(); + + validate_low_cutoff(low_cutoff); + defer_low_cutoff(low_cutoff); +} + +void EaxEqualizerEffect::defer_mid1_gain( + const EaxEaxCall& eax_call) +{ + const auto& mid1_gain = + eax_call.get_value(); + + validate_mid1_gain(mid1_gain); + defer_mid1_gain(mid1_gain); +} + +void EaxEqualizerEffect::defer_mid1_center( + const EaxEaxCall& eax_call) +{ + const auto& mid1_center = + eax_call.get_value(); + + validate_mid1_center(mid1_center); + defer_mid1_center(mid1_center); +} + +void EaxEqualizerEffect::defer_mid1_width( + const EaxEaxCall& eax_call) +{ + const auto& mid1_width = + eax_call.get_value(); + + validate_mid1_width(mid1_width); + defer_mid1_width(mid1_width); +} + +void EaxEqualizerEffect::defer_mid2_gain( + const EaxEaxCall& eax_call) +{ + const auto& mid2_gain = + eax_call.get_value(); + + validate_mid2_gain(mid2_gain); + defer_mid2_gain(mid2_gain); +} + +void EaxEqualizerEffect::defer_mid2_center( + const EaxEaxCall& eax_call) +{ + const auto& mid2_center = + eax_call.get_value(); + + validate_mid2_center(mid2_center); + defer_mid2_center(mid2_center); +} + +void EaxEqualizerEffect::defer_mid2_width( + const EaxEaxCall& eax_call) +{ + const auto& mid2_width = + eax_call.get_value(); + + validate_mid2_width(mid2_width); + defer_mid2_width(mid2_width); +} + +void EaxEqualizerEffect::defer_high_gain( + const EaxEaxCall& eax_call) +{ + const auto& high_gain = + eax_call.get_value(); + + validate_high_gain(high_gain); + defer_high_gain(high_gain); +} + +void EaxEqualizerEffect::defer_high_cutoff( + const EaxEaxCall& eax_call) +{ + const auto& high_cutoff = + eax_call.get_value(); + + validate_high_cutoff(high_cutoff); + defer_high_cutoff(high_cutoff); +} + +void EaxEqualizerEffect::defer_all( + const EaxEaxCall& eax_call) +{ + const auto& all = + eax_call.get_value(); + + validate_all(all); + defer_all(all); +} + +// [[nodiscard]] +bool EaxEqualizerEffect::apply_deferred() +{ + if (eax_dirty_flags_ == EaxEqualizerEffectDirtyFlags{}) + { + return false; + } + + eax_ = eax_d_; + + if (eax_dirty_flags_.lLowGain) + { + set_efx_low_gain(); + } + + if (eax_dirty_flags_.flLowCutOff) + { + set_efx_low_cutoff(); + } + + if (eax_dirty_flags_.lMid1Gain) + { + set_efx_mid1_gain(); + } + + if (eax_dirty_flags_.flMid1Center) + { + set_efx_mid1_center(); + } + + if (eax_dirty_flags_.flMid1Width) + { + set_efx_mid1_width(); + } + + if (eax_dirty_flags_.lMid2Gain) + { + set_efx_mid2_gain(); + } + + if (eax_dirty_flags_.flMid2Center) + { + set_efx_mid2_center(); + } + + if (eax_dirty_flags_.flMid2Width) + { + set_efx_mid2_width(); + } + + if (eax_dirty_flags_.lHighGain) + { + set_efx_high_gain(); + } + + if (eax_dirty_flags_.flHighCutOff) + { + set_efx_high_cutoff(); + } + + eax_dirty_flags_ = EaxEqualizerEffectDirtyFlags{}; + + return true; +} + +// [[nodiscard]] +bool EaxEqualizerEffect::set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXEQUALIZER_NONE: + break; + + case EAXEQUALIZER_ALLPARAMETERS: + defer_all(eax_call); + break; + + case EAXEQUALIZER_LOWGAIN: + defer_low_gain(eax_call); + break; + + case EAXEQUALIZER_LOWCUTOFF: + defer_low_cutoff(eax_call); + break; + + case EAXEQUALIZER_MID1GAIN: + defer_mid1_gain(eax_call); + break; + + case EAXEQUALIZER_MID1CENTER: + defer_mid1_center(eax_call); + break; + + case EAXEQUALIZER_MID1WIDTH: + defer_mid1_width(eax_call); + break; + + case EAXEQUALIZER_MID2GAIN: + defer_mid2_gain(eax_call); + break; + + case EAXEQUALIZER_MID2CENTER: + defer_mid2_center(eax_call); + break; + + case EAXEQUALIZER_MID2WIDTH: + defer_mid2_width(eax_call); + break; + + case EAXEQUALIZER_HIGHGAIN: + defer_high_gain(eax_call); + break; + + case EAXEQUALIZER_HIGHCUTOFF: + defer_high_cutoff(eax_call); + break; + + default: + throw EaxEqualizerEffectException{"Unsupported property id."}; + } + + if (!eax_call.is_deferred()) + { + return apply_deferred(); + } + + return false; +} + + +} // namespace + + +EaxEffectUPtr eax_create_eax_equalizer_effect( + EffectProps& al_effect_props) +{ + return std::make_unique(al_effect_props); +} + + +#endif // ALSOFT_EAX diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index 4aa860a2..aa4ddadb 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -10,6 +10,15 @@ #include "aloptional.h" #include "effects.h" +#if ALSOFT_EAX +#include + +#include "alnumeric.h" + +#include "al/eax_exception.h" +#include "al/eax_utils.h" +#endif // ALSOFT_EAX + namespace { @@ -128,3 +137,408 @@ EffectProps genDefaultProps() noexcept DEFINE_ALEFFECT_VTABLE(Fshifter); const EffectProps FshifterEffectProps{genDefaultProps()}; + +#if ALSOFT_EAX +namespace +{ + + +using EaxFrequencyShifterEffectDirtyFlagsValue = std::uint_least8_t; + +struct EaxFrequencyShifterEffectDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxFrequencyShifterEffectDirtyFlagsValue flFrequency : 1; + EaxFrequencyShifterEffectDirtyFlagsValue ulLeftDirection : 1; + EaxFrequencyShifterEffectDirtyFlagsValue ulRightDirection : 1; +}; // EaxFrequencyShifterEffectDirtyFlags + + +class EaxFrequencyShifterEffect final : + public EaxEffect +{ +public: + EaxFrequencyShifterEffect( + EffectProps& al_effect_props); + + + // [[nodiscard]] + bool dispatch( + const EaxEaxCall& eax_call) override; + + +private: + EffectProps& al_effect_props_; + + EAXFREQUENCYSHIFTERPROPERTIES eax_{}; + EAXFREQUENCYSHIFTERPROPERTIES eax_d_{}; + EaxFrequencyShifterEffectDirtyFlags eax_dirty_flags_{}; + + + void set_eax_defaults(); + + + void set_efx_frequency(); + + void set_efx_left_direction(); + + void set_efx_right_direction(); + + void set_efx_defaults(); + + + // [[nodiscard]] + bool get( + const EaxEaxCall& eax_call); + + + void validate_frequency( + float flFrequency); + + void validate_left_direction( + unsigned long ulLeftDirection); + + void validate_right_direction( + unsigned long ulRightDirection); + + void validate_all( + const EAXFREQUENCYSHIFTERPROPERTIES& all); + + + void defer_frequency( + float flFrequency); + + void defer_left_direction( + unsigned long ulLeftDirection); + + void defer_right_direction( + unsigned long ulRightDirection); + + void defer_all( + const EAXFREQUENCYSHIFTERPROPERTIES& all); + + + void defer_frequency( + const EaxEaxCall& eax_call); + + void defer_left_direction( + const EaxEaxCall& eax_call); + + void defer_right_direction( + const EaxEaxCall& eax_call); + + void defer_all( + const EaxEaxCall& eax_call); + + + // [[nodiscard]] + bool apply_deferred(); + + // [[nodiscard]] + bool set( + const EaxEaxCall& eax_call); +}; // EaxFrequencyShifterEffect + + +class EaxFrequencyShifterEffectException : + public EaxException +{ +public: + explicit EaxFrequencyShifterEffectException( + const char* message) + : + EaxException{"EAX_FREQUENCY_SHIFTER_EFFECT", message} + { + } +}; // EaxFrequencyShifterEffectException + + +EaxFrequencyShifterEffect::EaxFrequencyShifterEffect( + EffectProps& al_effect_props) + : + al_effect_props_{al_effect_props} +{ + set_eax_defaults(); + set_efx_defaults(); +} + +// [[nodiscard]] +bool EaxFrequencyShifterEffect::dispatch( + const EaxEaxCall& eax_call) +{ + return eax_call.is_get() ? get(eax_call) : set(eax_call); +} + +void EaxFrequencyShifterEffect::set_eax_defaults() +{ + eax_.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY; + eax_.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION; + eax_.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION; + + eax_d_ = eax_; +} + +void EaxFrequencyShifterEffect::set_efx_frequency() +{ + const auto frequency = clamp( + eax_.flFrequency, + AL_FREQUENCY_SHIFTER_MIN_FREQUENCY, + AL_FREQUENCY_SHIFTER_MAX_FREQUENCY); + + al_effect_props_.Fshifter.Frequency = frequency; +} + +void EaxFrequencyShifterEffect::set_efx_left_direction() +{ + const auto left_direction = clamp( + static_cast(eax_.ulLeftDirection), + AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION, + AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION); + + const auto efx_left_direction = DirectionFromEmum(left_direction); + assert(efx_left_direction.has_value()); + al_effect_props_.Fshifter.LeftDirection = *efx_left_direction; +} + +void EaxFrequencyShifterEffect::set_efx_right_direction() +{ + const auto right_direction = clamp( + static_cast(eax_.ulRightDirection), + AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION, + AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION); + + const auto efx_right_direction = DirectionFromEmum(right_direction); + assert(efx_right_direction.has_value()); + al_effect_props_.Fshifter.RightDirection = *efx_right_direction; +} + +void EaxFrequencyShifterEffect::set_efx_defaults() +{ + set_efx_frequency(); + set_efx_left_direction(); + set_efx_right_direction(); +} + +// [[nodiscard]] +bool EaxFrequencyShifterEffect::get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXFREQUENCYSHIFTER_NONE: + break; + + case EAXFREQUENCYSHIFTER_ALLPARAMETERS: + eax_call.set_value(eax_); + break; + + case EAXFREQUENCYSHIFTER_FREQUENCY: + eax_call.set_value(eax_.flFrequency); + break; + + case EAXFREQUENCYSHIFTER_LEFTDIRECTION: + eax_call.set_value(eax_.ulLeftDirection); + break; + + case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: + eax_call.set_value(eax_.ulRightDirection); + break; + + default: + throw EaxFrequencyShifterEffectException{"Unsupported property id."}; + } + + return false; +} + +void EaxFrequencyShifterEffect::validate_frequency( + float flFrequency) +{ + eax_validate_range( + "Frequency", + flFrequency, + EAXFREQUENCYSHIFTER_MINFREQUENCY, + EAXFREQUENCYSHIFTER_MAXFREQUENCY); +} + +void EaxFrequencyShifterEffect::validate_left_direction( + unsigned long ulLeftDirection) +{ + eax_validate_range( + "Left Direction", + ulLeftDirection, + EAXFREQUENCYSHIFTER_MINLEFTDIRECTION, + EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION); +} + +void EaxFrequencyShifterEffect::validate_right_direction( + unsigned long ulRightDirection) +{ + eax_validate_range( + "Right Direction", + ulRightDirection, + EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION, + EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION); +} + +void EaxFrequencyShifterEffect::validate_all( + const EAXFREQUENCYSHIFTERPROPERTIES& all) +{ + validate_frequency(all.flFrequency); + validate_left_direction(all.ulLeftDirection); + validate_right_direction(all.ulRightDirection); +} + +void EaxFrequencyShifterEffect::defer_frequency( + float flFrequency) +{ + eax_d_.flFrequency = flFrequency; + eax_dirty_flags_.flFrequency = (eax_.flFrequency != eax_d_.flFrequency); +} + +void EaxFrequencyShifterEffect::defer_left_direction( + unsigned long ulLeftDirection) +{ + eax_d_.ulLeftDirection = ulLeftDirection; + eax_dirty_flags_.ulLeftDirection = (eax_.ulLeftDirection != eax_d_.ulLeftDirection); +} + +void EaxFrequencyShifterEffect::defer_right_direction( + unsigned long ulRightDirection) +{ + eax_d_.ulRightDirection = ulRightDirection; + eax_dirty_flags_.ulRightDirection = (eax_.ulRightDirection != eax_d_.ulRightDirection); +} + +void EaxFrequencyShifterEffect::defer_all( + const EAXFREQUENCYSHIFTERPROPERTIES& all) +{ + defer_frequency(all.flFrequency); + defer_left_direction(all.ulLeftDirection); + defer_right_direction(all.ulRightDirection); +} + +void EaxFrequencyShifterEffect::defer_frequency( + const EaxEaxCall& eax_call) +{ + const auto& frequency = + eax_call.get_value< + EaxFrequencyShifterEffectException, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::flFrequency)>(); + + validate_frequency(frequency); + defer_frequency(frequency); +} + +void EaxFrequencyShifterEffect::defer_left_direction( + const EaxEaxCall& eax_call) +{ + const auto& left_direction = + eax_call.get_value< + EaxFrequencyShifterEffectException, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::ulLeftDirection)>(); + + validate_left_direction(left_direction); + defer_left_direction(left_direction); +} + +void EaxFrequencyShifterEffect::defer_right_direction( + const EaxEaxCall& eax_call) +{ + const auto& right_direction = + eax_call.get_value< + EaxFrequencyShifterEffectException, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::ulRightDirection)>(); + + validate_right_direction(right_direction); + defer_right_direction(right_direction); +} + +void EaxFrequencyShifterEffect::defer_all( + const EaxEaxCall& eax_call) +{ + const auto& all = + eax_call.get_value< + EaxFrequencyShifterEffectException, const EAXFREQUENCYSHIFTERPROPERTIES>(); + + validate_all(all); + defer_all(all); +} + +// [[nodiscard]] +bool EaxFrequencyShifterEffect::apply_deferred() +{ + if (eax_dirty_flags_ == EaxFrequencyShifterEffectDirtyFlags{}) + { + return false; + } + + eax_ = eax_d_; + + if (eax_dirty_flags_.flFrequency) + { + set_efx_frequency(); + } + + if (eax_dirty_flags_.ulLeftDirection) + { + set_efx_left_direction(); + } + + if (eax_dirty_flags_.ulRightDirection) + { + set_efx_right_direction(); + } + + eax_dirty_flags_ = EaxFrequencyShifterEffectDirtyFlags{}; + + return true; +} + +// [[nodiscard]] +bool EaxFrequencyShifterEffect::set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXFREQUENCYSHIFTER_NONE: + break; + + case EAXFREQUENCYSHIFTER_ALLPARAMETERS: + defer_all(eax_call); + break; + + case EAXFREQUENCYSHIFTER_FREQUENCY: + defer_frequency(eax_call); + break; + + case EAXFREQUENCYSHIFTER_LEFTDIRECTION: + defer_left_direction(eax_call); + break; + + case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: + defer_right_direction(eax_call); + break; + + default: + throw EaxFrequencyShifterEffectException{"Unsupported property id."}; + } + + if (!eax_call.is_deferred()) + { + return apply_deferred(); + } + + return false; +} + + +} // namespace + + +EaxEffectUPtr eax_create_eax_frequency_shifter_effect( + EffectProps& al_effect_props) +{ + return std::make_unique(al_effect_props); +} + + +#endif // ALSOFT_EAX diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index d8a1bed6..6a30dc09 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -10,6 +10,15 @@ #include "aloptional.h" #include "effects.h" +#if ALSOFT_EAX +#include + +#include "alnumeric.h" + +#include "al/eax_exception.h" +#include "al/eax_utils.h" +#endif // ALSOFT_EAX + namespace { @@ -134,3 +143,405 @@ EffectProps genDefaultProps() noexcept DEFINE_ALEFFECT_VTABLE(Modulator); const EffectProps ModulatorEffectProps{genDefaultProps()}; + +#if ALSOFT_EAX +namespace +{ + + +using EaxRingModulatorEffectDirtyFlagsValue = std::uint_least8_t; + +struct EaxRingModulatorEffectDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxRingModulatorEffectDirtyFlagsValue flFrequency : 1; + EaxRingModulatorEffectDirtyFlagsValue flHighPassCutOff : 1; + EaxRingModulatorEffectDirtyFlagsValue ulWaveform : 1; +}; // EaxPitchShifterEffectDirtyFlags + + +class EaxRingModulatorEffect final : + public EaxEffect +{ +public: + EaxRingModulatorEffect( + EffectProps& al_effect_props); + + + // [[nodiscard]] + bool dispatch( + const EaxEaxCall& eax_call) override; + + +private: + EffectProps& al_effect_props_; + + EAXRINGMODULATORPROPERTIES eax_{}; + EAXRINGMODULATORPROPERTIES eax_d_{}; + EaxRingModulatorEffectDirtyFlags eax_dirty_flags_{}; + + + void set_eax_defaults(); + + + void set_efx_frequency(); + + void set_efx_high_pass_cutoff(); + + void set_efx_waveform(); + + void set_efx_defaults(); + + + // [[nodiscard]] + bool get( + const EaxEaxCall& eax_call); + + + void validate_frequency( + float flFrequency); + + void validate_high_pass_cutoff( + float flHighPassCutOff); + + void validate_waveform( + unsigned long ulWaveform); + + void validate_all( + const EAXRINGMODULATORPROPERTIES& all); + + + void defer_frequency( + float flFrequency); + + void defer_high_pass_cutoff( + float flHighPassCutOff); + + void defer_waveform( + unsigned long ulWaveform); + + void defer_all( + const EAXRINGMODULATORPROPERTIES& all); + + + void defer_frequency( + const EaxEaxCall& eax_call); + + void defer_high_pass_cutoff( + const EaxEaxCall& eax_call); + + void defer_waveform( + const EaxEaxCall& eax_call); + + void defer_all( + const EaxEaxCall& eax_call); + + + // [[nodiscard]] + bool apply_deferred(); + + // [[nodiscard]] + bool set( + const EaxEaxCall& eax_call); +}; // EaxRingModulatorEffect + + +class EaxRingModulatorEffectException : + public EaxException +{ +public: + explicit EaxRingModulatorEffectException( + const char* message) + : + EaxException{"EAX_RING_MODULATOR_EFFECT", message} + { + } +}; // EaxRingModulatorEffectException + + +EaxRingModulatorEffect::EaxRingModulatorEffect( + EffectProps& al_effect_props) + : + al_effect_props_{al_effect_props} +{ + set_eax_defaults(); + set_efx_defaults(); +} + +// [[nodiscard]] +bool EaxRingModulatorEffect::dispatch( + const EaxEaxCall& eax_call) +{ + return eax_call.is_get() ? get(eax_call) : set(eax_call); +} + +void EaxRingModulatorEffect::set_eax_defaults() +{ + eax_.flFrequency = EAXRINGMODULATOR_DEFAULTFREQUENCY; + eax_.flHighPassCutOff = EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF; + eax_.ulWaveform = EAXRINGMODULATOR_DEFAULTWAVEFORM; + + eax_d_ = eax_; +} + +void EaxRingModulatorEffect::set_efx_frequency() +{ + const auto frequency = clamp( + eax_.flFrequency, + AL_RING_MODULATOR_MIN_FREQUENCY, + AL_RING_MODULATOR_MAX_FREQUENCY); + + al_effect_props_.Modulator.Frequency = frequency; +} + +void EaxRingModulatorEffect::set_efx_high_pass_cutoff() +{ + const auto high_pass_cutoff = clamp( + eax_.flHighPassCutOff, + AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF, + AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF); + + al_effect_props_.Modulator.HighPassCutoff = high_pass_cutoff; +} + +void EaxRingModulatorEffect::set_efx_waveform() +{ + const auto waveform = clamp( + static_cast(eax_.ulWaveform), + AL_RING_MODULATOR_MIN_WAVEFORM, + AL_RING_MODULATOR_MAX_WAVEFORM); + + const auto efx_waveform = WaveformFromEmum(waveform); + assert(efx_waveform.has_value()); + al_effect_props_.Modulator.Waveform = *efx_waveform; +} + +void EaxRingModulatorEffect::set_efx_defaults() +{ + set_efx_frequency(); + set_efx_high_pass_cutoff(); + set_efx_waveform(); +} + +// [[nodiscard]] +bool EaxRingModulatorEffect::get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXRINGMODULATOR_NONE: + break; + + case EAXRINGMODULATOR_ALLPARAMETERS: + eax_call.set_value(eax_); + break; + + case EAXRINGMODULATOR_FREQUENCY: + eax_call.set_value(eax_.flFrequency); + break; + + case EAXRINGMODULATOR_HIGHPASSCUTOFF: + eax_call.set_value(eax_.flHighPassCutOff); + break; + + case EAXRINGMODULATOR_WAVEFORM: + eax_call.set_value(eax_.ulWaveform); + break; + + default: + throw EaxRingModulatorEffectException{"Unsupported property id."}; + } + + return false; +} + +void EaxRingModulatorEffect::validate_frequency( + float flFrequency) +{ + eax_validate_range( + "Frequency", + flFrequency, + EAXRINGMODULATOR_MINFREQUENCY, + EAXRINGMODULATOR_MAXFREQUENCY); +} + +void EaxRingModulatorEffect::validate_high_pass_cutoff( + float flHighPassCutOff) +{ + eax_validate_range( + "High-Pass Cutoff", + flHighPassCutOff, + EAXRINGMODULATOR_MINHIGHPASSCUTOFF, + EAXRINGMODULATOR_MAXHIGHPASSCUTOFF); +} + +void EaxRingModulatorEffect::validate_waveform( + unsigned long ulWaveform) +{ + eax_validate_range( + "Waveform", + ulWaveform, + EAXRINGMODULATOR_MINWAVEFORM, + EAXRINGMODULATOR_MAXWAVEFORM); +} + +void EaxRingModulatorEffect::validate_all( + const EAXRINGMODULATORPROPERTIES& all) +{ + validate_frequency(all.flFrequency); + validate_high_pass_cutoff(all.flHighPassCutOff); + validate_waveform(all.ulWaveform); +} + +void EaxRingModulatorEffect::defer_frequency( + float flFrequency) +{ + eax_d_.flFrequency = flFrequency; + eax_dirty_flags_.flFrequency = (eax_.flFrequency != eax_d_.flFrequency); +} + +void EaxRingModulatorEffect::defer_high_pass_cutoff( + float flHighPassCutOff) +{ + eax_d_.flHighPassCutOff = flHighPassCutOff; + eax_dirty_flags_.flHighPassCutOff = (eax_.flHighPassCutOff != eax_d_.flHighPassCutOff); +} + +void EaxRingModulatorEffect::defer_waveform( + unsigned long ulWaveform) +{ + eax_d_.ulWaveform = ulWaveform; + eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform); +} + +void EaxRingModulatorEffect::defer_all( + const EAXRINGMODULATORPROPERTIES& all) +{ + defer_frequency(all.flFrequency); + defer_high_pass_cutoff(all.flHighPassCutOff); + defer_waveform(all.ulWaveform); +} + +void EaxRingModulatorEffect::defer_frequency( + const EaxEaxCall& eax_call) +{ + const auto& frequency = + eax_call.get_value< + EaxRingModulatorEffectException, const decltype(EAXRINGMODULATORPROPERTIES::flFrequency)>(); + + validate_frequency(frequency); + defer_frequency(frequency); +} + +void EaxRingModulatorEffect::defer_high_pass_cutoff( + const EaxEaxCall& eax_call) +{ + const auto& high_pass_cutoff = + eax_call.get_value< + EaxRingModulatorEffectException, const decltype(EAXRINGMODULATORPROPERTIES::flHighPassCutOff)>(); + + validate_high_pass_cutoff(high_pass_cutoff); + defer_high_pass_cutoff(high_pass_cutoff); +} + +void EaxRingModulatorEffect::defer_waveform( + const EaxEaxCall& eax_call) +{ + const auto& waveform = + eax_call.get_value< + EaxRingModulatorEffectException, const decltype(EAXRINGMODULATORPROPERTIES::ulWaveform)>(); + + validate_waveform(waveform); + defer_waveform(waveform); +} + +void EaxRingModulatorEffect::defer_all( + const EaxEaxCall& eax_call) +{ + const auto& all = + eax_call.get_value(); + + validate_all(all); + defer_all(all); +} + +// [[nodiscard]] +bool EaxRingModulatorEffect::apply_deferred() +{ + if (eax_dirty_flags_ == EaxRingModulatorEffectDirtyFlags{}) + { + return false; + } + + eax_ = eax_d_; + + if (eax_dirty_flags_.flFrequency) + { + set_efx_frequency(); + } + + if (eax_dirty_flags_.flHighPassCutOff) + { + set_efx_high_pass_cutoff(); + } + + if (eax_dirty_flags_.ulWaveform) + { + set_efx_waveform(); + } + + eax_dirty_flags_ = EaxRingModulatorEffectDirtyFlags{}; + + return true; +} + +// [[nodiscard]] +bool EaxRingModulatorEffect::set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXRINGMODULATOR_NONE: + break; + + case EAXRINGMODULATOR_ALLPARAMETERS: + defer_all(eax_call); + break; + + case EAXRINGMODULATOR_FREQUENCY: + defer_frequency(eax_call); + break; + + case EAXRINGMODULATOR_HIGHPASSCUTOFF: + defer_high_pass_cutoff(eax_call); + break; + + case EAXRINGMODULATOR_WAVEFORM: + defer_waveform(eax_call); + break; + + default: + throw EaxRingModulatorEffectException{"Unsupported property id."}; + } + + if (!eax_call.is_deferred()) + { + return apply_deferred(); + } + + return false; +} + + +} // namespace + + +EaxEffectUPtr eax_create_eax_ring_modulator_effect( + EffectProps& al_effect_props) +{ + return std::make_unique(al_effect_props); +} + + +#endif // ALSOFT_EAX diff --git a/al/effects/null.cpp b/al/effects/null.cpp index 516446db..44595208 100644 --- a/al/effects/null.cpp +++ b/al/effects/null.cpp @@ -7,6 +7,10 @@ #include "alc/effects/base.h" #include "effects.h" +#if ALSOFT_EAX +#include "al/eax_exception.h" +#endif // ALSOFT_EAX + namespace { @@ -91,3 +95,56 @@ EffectProps genDefaultProps() noexcept DEFINE_ALEFFECT_VTABLE(Null); const EffectProps NullEffectProps{genDefaultProps()}; + + +#if ALSOFT_EAX +namespace +{ + + +class EaxNullEffect final : + public EaxEffect +{ +public: + // [[nodiscard]] + bool dispatch( + const EaxEaxCall& eax_call) override; +}; // EaxNullEffect + + +class EaxNullEffectException : + public EaxException +{ +public: + explicit EaxNullEffectException( + const char* message) + : + EaxException{"EAX_NULL_EFFECT", message} + { + } +}; // EaxNullEffectException + + +// [[nodiscard]] +bool EaxNullEffect::dispatch( + const EaxEaxCall& eax_call) +{ + if (eax_call.get_property_id() != 0) + { + throw EaxNullEffectException{"Unsupported property id."}; + } + + return false; +} + + +} // namespace + + +EaxEffectUPtr eax_create_eax_null_effect() +{ + return std::make_unique(); +} + + +#endif // ALSOFT_EAX diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp index 56059a3c..03f9a139 100644 --- a/al/effects/pshifter.cpp +++ b/al/effects/pshifter.cpp @@ -7,6 +7,13 @@ #include "alc/effects/base.h" #include "effects.h" +#if ALSOFT_EAX +#include "alnumeric.h" + +#include "al/eax_exception.h" +#include "al/eax_utils.h" +#endif // ALSOFT_EAX + namespace { @@ -82,3 +89,334 @@ EffectProps genDefaultProps() noexcept DEFINE_ALEFFECT_VTABLE(Pshifter); const EffectProps PshifterEffectProps{genDefaultProps()}; + +#if ALSOFT_EAX +namespace +{ + + +using EaxPitchShifterEffectDirtyFlagsValue = std::uint_least8_t; + +struct EaxPitchShifterEffectDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxPitchShifterEffectDirtyFlagsValue lCoarseTune : 1; + EaxPitchShifterEffectDirtyFlagsValue lFineTune : 1; +}; // EaxPitchShifterEffectDirtyFlags + + +class EaxPitchShifterEffect final : + public EaxEffect +{ +public: + EaxPitchShifterEffect( + EffectProps& al_effect_props); + + + // [[nodiscard]] + bool dispatch( + const EaxEaxCall& eax_call) override; + + +private: + EffectProps& al_effect_props_; + + EAXPITCHSHIFTERPROPERTIES eax_{}; + EAXPITCHSHIFTERPROPERTIES eax_d_{}; + EaxPitchShifterEffectDirtyFlags eax_dirty_flags_{}; + + + void set_eax_defaults(); + + + void set_efx_coarse_tune(); + + void set_efx_fine_tune(); + + void set_efx_defaults(); + + + // [[nodiscard]] + bool get( + const EaxEaxCall& eax_call); + + + void validate_coarse_tune( + long lCoarseTune); + + void validate_fine_tune( + long lFineTune); + + void validate_all( + const EAXPITCHSHIFTERPROPERTIES& all); + + + void defer_coarse_tune( + long lCoarseTune); + + void defer_fine_tune( + long lFineTune); + + void defer_all( + const EAXPITCHSHIFTERPROPERTIES& all); + + + void defer_coarse_tune( + const EaxEaxCall& eax_call); + + void defer_fine_tune( + const EaxEaxCall& eax_call); + + void defer_all( + const EaxEaxCall& eax_call); + + + // [[nodiscard]] + bool apply_deferred(); + + // [[nodiscard]] + bool set( + const EaxEaxCall& eax_call); +}; // EaxPitchShifterEffect + + +class EaxPitchShifterEffectException : + public EaxException +{ +public: + explicit EaxPitchShifterEffectException( + const char* message) + : + EaxException{"EAX_PITCH_SHIFTER_EFFECT", message} + { + } +}; // EaxPitchShifterEffectException + + +EaxPitchShifterEffect::EaxPitchShifterEffect( + EffectProps& al_effect_props) + : + al_effect_props_{al_effect_props} +{ + set_eax_defaults(); + set_efx_defaults(); +} + +// [[nodiscard]] +bool EaxPitchShifterEffect::dispatch( + const EaxEaxCall& eax_call) +{ + return eax_call.is_get() ? get(eax_call) : set(eax_call); +} + +void EaxPitchShifterEffect::set_eax_defaults() +{ + eax_.lCoarseTune = EAXPITCHSHIFTER_DEFAULTCOARSETUNE; + eax_.lFineTune = EAXPITCHSHIFTER_DEFAULTFINETUNE; + + eax_d_ = eax_; +} + +void EaxPitchShifterEffect::set_efx_coarse_tune() +{ + const auto coarse_tune = clamp( + static_cast(eax_.lCoarseTune), + AL_PITCH_SHIFTER_MIN_COARSE_TUNE, + AL_PITCH_SHIFTER_MAX_COARSE_TUNE); + + al_effect_props_.Pshifter.CoarseTune = coarse_tune; +} + +void EaxPitchShifterEffect::set_efx_fine_tune() +{ + const auto fine_tune = clamp( + static_cast(eax_.lFineTune), + AL_PITCH_SHIFTER_MIN_FINE_TUNE, + AL_PITCH_SHIFTER_MAX_FINE_TUNE); + + al_effect_props_.Pshifter.FineTune = fine_tune; +} + +void EaxPitchShifterEffect::set_efx_defaults() +{ + set_efx_coarse_tune(); + set_efx_fine_tune(); +} + +// [[nodiscard]] +bool EaxPitchShifterEffect::get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXPITCHSHIFTER_NONE: + break; + + case EAXPITCHSHIFTER_ALLPARAMETERS: + eax_call.set_value(eax_); + break; + + case EAXPITCHSHIFTER_COARSETUNE: + eax_call.set_value(eax_.lCoarseTune); + break; + + case EAXPITCHSHIFTER_FINETUNE: + eax_call.set_value(eax_.lFineTune); + break; + + default: + throw EaxPitchShifterEffectException{"Unsupported property id."}; + } + + return false; +} + +void EaxPitchShifterEffect::validate_coarse_tune( + long lCoarseTune) +{ + eax_validate_range( + "Coarse Tune", + lCoarseTune, + EAXPITCHSHIFTER_MINCOARSETUNE, + EAXPITCHSHIFTER_MAXCOARSETUNE); +} + +void EaxPitchShifterEffect::validate_fine_tune( + long lFineTune) +{ + eax_validate_range( + "Fine Tune", + lFineTune, + EAXPITCHSHIFTER_MINFINETUNE, + EAXPITCHSHIFTER_MAXFINETUNE); +} + +void EaxPitchShifterEffect::validate_all( + const EAXPITCHSHIFTERPROPERTIES& all) +{ + validate_coarse_tune(all.lCoarseTune); + validate_fine_tune(all.lFineTune); +} + +void EaxPitchShifterEffect::defer_coarse_tune( + long lCoarseTune) +{ + eax_d_.lCoarseTune = lCoarseTune; + eax_dirty_flags_.lCoarseTune = (eax_.lCoarseTune != eax_d_.lCoarseTune); +} + +void EaxPitchShifterEffect::defer_fine_tune( + long lFineTune) +{ + eax_d_.lFineTune = lFineTune; + eax_dirty_flags_.lFineTune = (eax_.lFineTune != eax_d_.lFineTune); +} + +void EaxPitchShifterEffect::defer_all( + const EAXPITCHSHIFTERPROPERTIES& all) +{ + defer_coarse_tune(all.lCoarseTune); + defer_fine_tune(all.lFineTune); +} + +void EaxPitchShifterEffect::defer_coarse_tune( + const EaxEaxCall& eax_call) +{ + const auto& coarse_tune = + eax_call.get_value(); + + validate_coarse_tune(coarse_tune); + defer_coarse_tune(coarse_tune); +} + +void EaxPitchShifterEffect::defer_fine_tune( + const EaxEaxCall& eax_call) +{ + const auto& fine_tune = + eax_call.get_value(); + + validate_fine_tune(fine_tune); + defer_fine_tune(fine_tune); +} + +void EaxPitchShifterEffect::defer_all( + const EaxEaxCall& eax_call) +{ + const auto& all = + eax_call.get_value(); + + validate_all(all); + defer_all(all); +} + +// [[nodiscard]] +bool EaxPitchShifterEffect::apply_deferred() +{ + if (eax_dirty_flags_ == EaxPitchShifterEffectDirtyFlags{}) + { + return false; + } + + eax_ = eax_d_; + + if (eax_dirty_flags_.lCoarseTune) + { + set_efx_coarse_tune(); + } + + if (eax_dirty_flags_.lFineTune) + { + set_efx_fine_tune(); + } + + eax_dirty_flags_ = EaxPitchShifterEffectDirtyFlags{}; + + return true; +} + +// [[nodiscard]] +bool EaxPitchShifterEffect::set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXPITCHSHIFTER_NONE: + break; + + case EAXPITCHSHIFTER_ALLPARAMETERS: + defer_all(eax_call); + break; + + case EAXPITCHSHIFTER_COARSETUNE: + defer_coarse_tune(eax_call); + break; + + case EAXPITCHSHIFTER_FINETUNE: + defer_fine_tune(eax_call); + break; + + default: + throw EaxPitchShifterEffectException{"Unsupported property id."}; + } + + if (!eax_call.is_deferred()) + { + return apply_deferred(); + } + + return false; +} + + +} // namespace + + +EaxEffectUPtr eax_create_eax_pitch_shifter_effect( + EffectProps& al_effect_props) +{ + return std::make_unique(al_effect_props); +} + + +#endif // ALSOFT_EAX diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index 3f234b93..8012450d 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -9,6 +9,15 @@ #include "alc/effects/base.h" #include "effects.h" +#if ALSOFT_EAX +#include + +#include "alnumeric.h" + +#include "al/eax_exception.h" +#include "al/eax_utils.h" +#endif // ALSOFT_EAX + namespace { @@ -554,3 +563,1916 @@ const EffectProps ReverbEffectProps{genDefaultProps()}; DEFINE_ALEFFECT_VTABLE(StdReverb); const EffectProps StdReverbEffectProps{genDefaultStdProps()}; + +#if ALSOFT_EAX +namespace +{ + + +using EaxReverbEffectDirtyFlagsValue = std::uint_least32_t; + +struct EaxReverbEffectDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxReverbEffectDirtyFlagsValue ulEnvironment : 1; + EaxReverbEffectDirtyFlagsValue flEnvironmentSize : 1; + EaxReverbEffectDirtyFlagsValue flEnvironmentDiffusion : 1; + EaxReverbEffectDirtyFlagsValue lRoom : 1; + EaxReverbEffectDirtyFlagsValue lRoomHF : 1; + EaxReverbEffectDirtyFlagsValue lRoomLF : 1; + EaxReverbEffectDirtyFlagsValue flDecayTime : 1; + EaxReverbEffectDirtyFlagsValue flDecayHFRatio : 1; + EaxReverbEffectDirtyFlagsValue flDecayLFRatio : 1; + EaxReverbEffectDirtyFlagsValue lReflections : 1; + EaxReverbEffectDirtyFlagsValue flReflectionsDelay : 1; + EaxReverbEffectDirtyFlagsValue vReflectionsPan : 1; + EaxReverbEffectDirtyFlagsValue lReverb : 1; + EaxReverbEffectDirtyFlagsValue flReverbDelay : 1; + EaxReverbEffectDirtyFlagsValue vReverbPan : 1; + EaxReverbEffectDirtyFlagsValue flEchoTime : 1; + EaxReverbEffectDirtyFlagsValue flEchoDepth : 1; + EaxReverbEffectDirtyFlagsValue flModulationTime : 1; + EaxReverbEffectDirtyFlagsValue flModulationDepth : 1; + EaxReverbEffectDirtyFlagsValue flAirAbsorptionHF : 1; + EaxReverbEffectDirtyFlagsValue flHFReference : 1; + EaxReverbEffectDirtyFlagsValue flLFReference : 1; + EaxReverbEffectDirtyFlagsValue flRoomRolloffFactor : 1; + EaxReverbEffectDirtyFlagsValue ulFlags : 1; +}; // EaxReverbEffectDirtyFlags + + +class EaxReverbEffect final : + public EaxEffect +{ +public: + EaxReverbEffect( + EffectProps& al_effect_props); + + + // [[nodiscard]] + bool dispatch( + const EaxEaxCall& eax_call) override; + + +private: + EffectProps& al_effect_props_; + + EAXREVERBPROPERTIES eax_{}; + EAXREVERBPROPERTIES eax_d_{}; + EaxReverbEffectDirtyFlags eax_dirty_flags_{}; + + + void set_eax_defaults(); + + + void set_efx_density(); + + void set_efx_diffusion(); + + void set_efx_gain(); + + void set_efx_gain_hf(); + + void set_efx_gain_lf(); + + void set_efx_decay_time(); + + void set_efx_decay_hf_ratio(); + + void set_efx_decay_lf_ratio(); + + void set_efx_reflections_gain(); + + void set_efx_reflections_delay(); + + void set_efx_reflections_pan(); + + void set_efx_late_reverb_gain(); + + void set_efx_late_reverb_delay(); + + void set_efx_late_reverb_pan(); + + void set_efx_echo_time(); + + void set_efx_echo_depth(); + + void set_efx_modulation_time(); + + void set_efx_modulation_depth(); + + void set_efx_air_absorption_gain_hf(); + + void set_efx_hf_reference(); + + void set_efx_lf_reference(); + + void set_efx_room_rolloff_factor(); + + void set_efx_flags(); + + void set_efx_defaults(); + + + void get_all( + const EaxEaxCall& eax_call) const; + + // [[nodiscard]] + bool get( + const EaxEaxCall& eax_call) const; + + + void validate_environment( + unsigned long ulEnvironment, + int version, + bool is_standalone); + + void validate_environment_size( + float flEnvironmentSize); + + void validate_environment_diffusion( + float flEnvironmentDiffusion); + + void validate_room( + long lRoom); + + void validate_room_hf( + long lRoomHF); + + void validate_room_lf( + long lRoomLF); + + void validate_decay_time( + float flDecayTime); + + void validate_decay_hf_ratio( + float flDecayHFRatio); + + void validate_decay_lf_ratio( + float flDecayLFRatio); + + void validate_reflections( + long lReflections); + + void validate_reflections_delay( + float flReflectionsDelay); + + void validate_reflections_pan( + const EAXVECTOR& vReflectionsPan); + + void validate_reverb( + long lReverb); + + void validate_reverb_delay( + float flReverbDelay); + + void validate_reverb_pan( + const EAXVECTOR& vReverbPan); + + void validate_echo_time( + float flEchoTime); + + void validate_echo_depth( + float flEchoDepth); + + void validate_modulation_time( + float flModulationTime); + + void validate_modulation_depth( + float flModulationDepth); + + void validate_air_absorbtion_hf( + float air_absorbtion_hf); + + void validate_hf_reference( + float flHFReference); + + void validate_lf_reference( + float flLFReference); + + void validate_room_rolloff_factor( + float flRoomRolloffFactor); + + void validate_flags( + unsigned long ulFlags); + + void validate_all( + const EAX20LISTENERPROPERTIES& all, + int version); + + void validate_all( + const EAXREVERBPROPERTIES& all, + int version); + + + void defer_environment( + unsigned long ulEnvironment); + + void defer_environment_size( + float flEnvironmentSize); + + void defer_environment_diffusion( + float flEnvironmentDiffusion); + + void defer_room( + long lRoom); + + void defer_room_hf( + long lRoomHF); + + void defer_room_lf( + long lRoomLF); + + void defer_decay_time( + float flDecayTime); + + void defer_decay_hf_ratio( + float flDecayHFRatio); + + void defer_decay_lf_ratio( + float flDecayLFRatio); + + void defer_reflections( + long lReflections); + + void defer_reflections_delay( + float flReflectionsDelay); + + void defer_reflections_pan( + const EAXVECTOR& vReflectionsPan); + + void defer_reverb( + long lReverb); + + void defer_reverb_delay( + float flReverbDelay); + + void defer_reverb_pan( + const EAXVECTOR& vReverbPan); + + void defer_echo_time( + float flEchoTime); + + void defer_echo_depth( + float flEchoDepth); + + void defer_modulation_time( + float flModulationTime); + + void defer_modulation_depth( + float flModulationDepth); + + void defer_air_absorbtion_hf( + float flAirAbsorptionHF); + + void defer_hf_reference( + float flHFReference); + + void defer_lf_reference( + float flLFReference); + + void defer_room_rolloff_factor( + float flRoomRolloffFactor); + + void defer_flags( + unsigned long ulFlags); + + void defer_all( + const EAX20LISTENERPROPERTIES& all); + + void defer_all( + const EAXREVERBPROPERTIES& all); + + + void defer_environment( + const EaxEaxCall& eax_call); + + void defer_environment_size( + const EaxEaxCall& eax_call); + + void defer_environment_diffusion( + const EaxEaxCall& eax_call); + + void defer_room( + const EaxEaxCall& eax_call); + + void defer_room_hf( + const EaxEaxCall& eax_call); + + void defer_room_lf( + const EaxEaxCall& eax_call); + + void defer_decay_time( + const EaxEaxCall& eax_call); + + void defer_decay_hf_ratio( + const EaxEaxCall& eax_call); + + void defer_decay_lf_ratio( + const EaxEaxCall& eax_call); + + void defer_reflections( + const EaxEaxCall& eax_call); + + void defer_reflections_delay( + const EaxEaxCall& eax_call); + + void defer_reflections_pan( + const EaxEaxCall& eax_call); + + void defer_reverb( + const EaxEaxCall& eax_call); + + void defer_reverb_delay( + const EaxEaxCall& eax_call); + + void defer_reverb_pan( + const EaxEaxCall& eax_call); + + void defer_echo_time( + const EaxEaxCall& eax_call); + + void defer_echo_depth( + const EaxEaxCall& eax_call); + + void defer_modulation_time( + const EaxEaxCall& eax_call); + + void defer_modulation_depth( + const EaxEaxCall& eax_call); + + void defer_air_absorbtion_hf( + const EaxEaxCall& eax_call); + + void defer_hf_reference( + const EaxEaxCall& eax_call); + + void defer_lf_reference( + const EaxEaxCall& eax_call); + + void defer_room_rolloff_factor( + const EaxEaxCall& eax_call); + + void defer_flags( + const EaxEaxCall& eax_call); + + void defer_all( + const EaxEaxCall& eax_call); + + + // [[nodiscard]] + bool apply_deferred(); + + // [[nodiscard]] + bool set( + const EaxEaxCall& eax_call); +}; // EaxReverbEffect + + +class EaxReverbEffectException : + public EaxException +{ +public: + explicit EaxReverbEffectException( + const char* message) + : + EaxException{"EAX_REVERB_EFFECT", message} + { + } +}; // EaxReverbEffectException + + +EaxReverbEffect::EaxReverbEffect( + EffectProps& al_effect_props) + : + al_effect_props_{al_effect_props} +{ + set_eax_defaults(); + set_efx_defaults(); +} + +// [[nodiscard]] +bool EaxReverbEffect::dispatch( + const EaxEaxCall& eax_call) +{ + return eax_call.is_get() ? get(eax_call) : set(eax_call); +} + +void EaxReverbEffect::set_eax_defaults() +{ + eax_ = EAXREVERB_PRESETS[EAX_ENVIRONMENT_GENERIC]; + + eax_d_ = eax_; +} + +void EaxReverbEffect::set_efx_density() +{ + const auto eax_environment_size = eax_.flEnvironmentSize; + + const auto efx_density = clamp( + (eax_environment_size * eax_environment_size * eax_environment_size) / 16.0F, + AL_EAXREVERB_MIN_DENSITY, + AL_EAXREVERB_MAX_DENSITY); + + al_effect_props_.Reverb.Density = efx_density; +} + +void EaxReverbEffect::set_efx_diffusion() +{ + const auto efx_diffusion = clamp( + eax_.flEnvironmentDiffusion, + AL_EAXREVERB_MIN_DIFFUSION, + AL_EAXREVERB_MAX_DIFFUSION); + + al_effect_props_.Reverb.Diffusion = efx_diffusion; +} + +void EaxReverbEffect::set_efx_gain() +{ + const auto efx_gain = clamp( + level_mb_to_gain(static_cast(eax_.lRoom)), + AL_EAXREVERB_MIN_GAIN, + AL_EAXREVERB_MAX_GAIN); + + al_effect_props_.Reverb.Gain = efx_gain; +} + +void EaxReverbEffect::set_efx_gain_hf() +{ + const auto efx_gain_hf = clamp( + level_mb_to_gain(static_cast(eax_.lRoomHF)), + AL_EAXREVERB_MIN_GAINHF, + AL_EAXREVERB_MAX_GAINHF); + + al_effect_props_.Reverb.GainHF = efx_gain_hf; +} + +void EaxReverbEffect::set_efx_gain_lf() +{ + const auto efx_gain_lf = clamp( + level_mb_to_gain(static_cast(eax_.lRoomLF)), + AL_EAXREVERB_MIN_GAINLF, + AL_EAXREVERB_MAX_GAINLF); + + al_effect_props_.Reverb.GainLF = efx_gain_lf; +} + +void EaxReverbEffect::set_efx_decay_time() +{ + const auto efx_decay_time = clamp( + eax_.flDecayTime, + AL_EAXREVERB_MIN_DECAY_TIME, + AL_EAXREVERB_MAX_DECAY_TIME); + + al_effect_props_.Reverb.DecayTime = efx_decay_time; +} + +void EaxReverbEffect::set_efx_decay_hf_ratio() +{ + const auto efx_decay_hf_ratio = clamp( + eax_.flDecayHFRatio, + AL_EAXREVERB_MIN_DECAY_HFRATIO, + AL_EAXREVERB_MAX_DECAY_HFRATIO); + + al_effect_props_.Reverb.DecayHFRatio = efx_decay_hf_ratio; +} + +void EaxReverbEffect::set_efx_decay_lf_ratio() +{ + const auto efx_decay_lf_ratio = clamp( + eax_.flDecayLFRatio, + AL_EAXREVERB_MIN_DECAY_LFRATIO, + AL_EAXREVERB_MAX_DECAY_LFRATIO); + + al_effect_props_.Reverb.DecayLFRatio = efx_decay_lf_ratio; +} + +void EaxReverbEffect::set_efx_reflections_gain() +{ + const auto efx_reflections_gain = clamp( + level_mb_to_gain(static_cast(eax_.lReflections)), + AL_EAXREVERB_MIN_REFLECTIONS_GAIN, + AL_EAXREVERB_MAX_REFLECTIONS_GAIN); + + al_effect_props_.Reverb.ReflectionsGain = efx_reflections_gain; +} + +void EaxReverbEffect::set_efx_reflections_delay() +{ + const auto efx_reflections_delay = clamp( + eax_.flReflectionsDelay, + AL_EAXREVERB_MIN_REFLECTIONS_DELAY, + AL_EAXREVERB_MAX_REFLECTIONS_DELAY); + + al_effect_props_.Reverb.ReflectionsDelay = efx_reflections_delay; +} + +void EaxReverbEffect::set_efx_reflections_pan() +{ + al_effect_props_.Reverb.ReflectionsPan[0] = eax_.vReflectionsPan.x; + al_effect_props_.Reverb.ReflectionsPan[1] = eax_.vReflectionsPan.y; + al_effect_props_.Reverb.ReflectionsPan[2] = eax_.vReflectionsPan.z; +} + +void EaxReverbEffect::set_efx_late_reverb_gain() +{ + const auto efx_late_reverb_gain = clamp( + level_mb_to_gain(static_cast(eax_.lReverb)), + AL_EAXREVERB_MIN_LATE_REVERB_GAIN, + AL_EAXREVERB_MAX_LATE_REVERB_GAIN); + + al_effect_props_.Reverb.LateReverbGain = efx_late_reverb_gain; +} + +void EaxReverbEffect::set_efx_late_reverb_delay() +{ + const auto efx_late_reverb_delay = clamp( + eax_.flReverbDelay, + AL_EAXREVERB_MIN_LATE_REVERB_DELAY, + AL_EAXREVERB_MAX_LATE_REVERB_DELAY); + + al_effect_props_.Reverb.LateReverbDelay = efx_late_reverb_delay; +} + +void EaxReverbEffect::set_efx_late_reverb_pan() +{ + al_effect_props_.Reverb.LateReverbPan[0] = eax_.vReverbPan.x; + al_effect_props_.Reverb.LateReverbPan[1] = eax_.vReverbPan.y; + al_effect_props_.Reverb.LateReverbPan[2] = eax_.vReverbPan.z; +} + +void EaxReverbEffect::set_efx_echo_time() +{ + const auto efx_echo_time = clamp( + eax_.flEchoTime, + AL_EAXREVERB_MIN_ECHO_TIME, + AL_EAXREVERB_MAX_ECHO_TIME); + + al_effect_props_.Reverb.EchoTime = efx_echo_time; +} + +void EaxReverbEffect::set_efx_echo_depth() +{ + const auto efx_echo_depth = clamp( + eax_.flEchoDepth, + AL_EAXREVERB_MIN_ECHO_DEPTH, + AL_EAXREVERB_MAX_ECHO_DEPTH); + + al_effect_props_.Reverb.EchoDepth = efx_echo_depth; +} + +void EaxReverbEffect::set_efx_modulation_time() +{ + const auto efx_modulation_time = clamp( + eax_.flModulationTime, + AL_EAXREVERB_MIN_MODULATION_TIME, + AL_EAXREVERB_MAX_MODULATION_TIME); + + al_effect_props_.Reverb.ModulationTime = efx_modulation_time; +} + +void EaxReverbEffect::set_efx_modulation_depth() +{ + const auto efx_modulation_depth = clamp( + eax_.flModulationDepth, + AL_EAXREVERB_MIN_MODULATION_DEPTH, + AL_EAXREVERB_MAX_MODULATION_DEPTH); + + al_effect_props_.Reverb.ModulationDepth = efx_modulation_depth; +} + +void EaxReverbEffect::set_efx_air_absorption_gain_hf() +{ + const auto efx_air_absorption_hf = clamp( + level_mb_to_gain(eax_.flAirAbsorptionHF), + AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF, + AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF); + + al_effect_props_.Reverb.AirAbsorptionGainHF = efx_air_absorption_hf; +} + +void EaxReverbEffect::set_efx_hf_reference() +{ + const auto efx_hf_reference = clamp( + eax_.flHFReference, + AL_EAXREVERB_MIN_HFREFERENCE, + AL_EAXREVERB_MAX_HFREFERENCE); + + al_effect_props_.Reverb.HFReference = efx_hf_reference; +} + +void EaxReverbEffect::set_efx_lf_reference() +{ + const auto efx_lf_reference = clamp( + eax_.flLFReference, + AL_EAXREVERB_MIN_LFREFERENCE, + AL_EAXREVERB_MAX_LFREFERENCE); + + al_effect_props_.Reverb.LFReference = efx_lf_reference; +} + +void EaxReverbEffect::set_efx_room_rolloff_factor() +{ + const auto efx_room_rolloff_factor = clamp( + eax_.flRoomRolloffFactor, + AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR, + AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR); + + al_effect_props_.Reverb.RoomRolloffFactor = efx_room_rolloff_factor; +} + +void EaxReverbEffect::set_efx_flags() +{ + al_effect_props_.Reverb.DecayHFLimit = ((eax_.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0); +} + +void EaxReverbEffect::set_efx_defaults() +{ + set_efx_density(); + set_efx_diffusion(); + set_efx_gain(); + set_efx_gain_hf(); + set_efx_gain_lf(); + set_efx_decay_time(); + set_efx_decay_hf_ratio(); + set_efx_decay_lf_ratio(); + set_efx_reflections_gain(); + set_efx_reflections_delay(); + set_efx_reflections_pan(); + set_efx_late_reverb_gain(); + set_efx_late_reverb_delay(); + set_efx_late_reverb_pan(); + set_efx_echo_time(); + set_efx_echo_depth(); + set_efx_modulation_time(); + set_efx_modulation_depth(); + set_efx_air_absorption_gain_hf(); + set_efx_hf_reference(); + set_efx_lf_reference(); + set_efx_room_rolloff_factor(); + set_efx_flags(); +} + +void EaxReverbEffect::get_all( + const EaxEaxCall& eax_call) const +{ + if (eax_call.get_version() == 2) + { + auto& eax_reverb = eax_call.get_value(); + eax_reverb.lRoom = eax_.lRoom; + eax_reverb.lRoomHF = eax_.lRoomHF; + eax_reverb.flRoomRolloffFactor = eax_.flRoomRolloffFactor; + eax_reverb.flDecayTime = eax_.flDecayTime; + eax_reverb.flDecayHFRatio = eax_.flDecayHFRatio; + eax_reverb.lReflections = eax_.lReflections; + eax_reverb.flReflectionsDelay = eax_.flReflectionsDelay; + eax_reverb.lReverb = eax_.lReverb; + eax_reverb.flReverbDelay = eax_.flReverbDelay; + eax_reverb.dwEnvironment = eax_.ulEnvironment; + eax_reverb.flEnvironmentSize = eax_.flEnvironmentSize; + eax_reverb.flEnvironmentDiffusion = eax_.flEnvironmentDiffusion; + eax_reverb.flAirAbsorptionHF = eax_.flAirAbsorptionHF; + eax_reverb.dwFlags = eax_.ulFlags; + } + else + { + eax_call.set_value(eax_); + } +} + +// [[nodiscard]] +bool EaxReverbEffect::get( + const EaxEaxCall& eax_call) const +{ + switch (eax_call.get_property_id()) + { + case EAXREVERB_NONE: + break; + + case EAXREVERB_ALLPARAMETERS: + get_all(eax_call); + break; + + case EAXREVERB_ENVIRONMENT: + eax_call.set_value(eax_.ulEnvironment); + break; + + case EAXREVERB_ENVIRONMENTSIZE: + eax_call.set_value(eax_.flEnvironmentSize); + break; + + case EAXREVERB_ENVIRONMENTDIFFUSION: + eax_call.set_value(eax_.flEnvironmentDiffusion); + break; + + case EAXREVERB_ROOM: + eax_call.set_value(eax_.lRoom); + break; + + case EAXREVERB_ROOMHF: + eax_call.set_value(eax_.lRoomHF); + break; + + case EAXREVERB_ROOMLF: + eax_call.set_value(eax_.lRoomLF); + break; + + case EAXREVERB_DECAYTIME: + eax_call.set_value(eax_.flDecayTime); + break; + + case EAXREVERB_DECAYHFRATIO: + eax_call.set_value(eax_.flDecayHFRatio); + break; + + case EAXREVERB_DECAYLFRATIO: + eax_call.set_value(eax_.flDecayLFRatio); + break; + + case EAXREVERB_REFLECTIONS: + eax_call.set_value(eax_.lReflections); + break; + + case EAXREVERB_REFLECTIONSDELAY: + eax_call.set_value(eax_.flReflectionsDelay); + break; + + case EAXREVERB_REFLECTIONSPAN: + eax_call.set_value(eax_.vReflectionsPan); + break; + + case EAXREVERB_REVERB: + eax_call.set_value(eax_.lReverb); + break; + + case EAXREVERB_REVERBDELAY: + eax_call.set_value(eax_.flReverbDelay); + break; + + case EAXREVERB_REVERBPAN: + eax_call.set_value(eax_.vReverbPan); + break; + + case EAXREVERB_ECHOTIME: + eax_call.set_value(eax_.flEchoTime); + break; + + case EAXREVERB_ECHODEPTH: + eax_call.set_value(eax_.flEchoDepth); + break; + + case EAXREVERB_MODULATIONTIME: + eax_call.set_value(eax_.flModulationTime); + break; + + case EAXREVERB_MODULATIONDEPTH: + eax_call.set_value(eax_.flModulationDepth); + break; + + case EAXREVERB_AIRABSORPTIONHF: + eax_call.set_value(eax_.flAirAbsorptionHF); + break; + + case EAXREVERB_HFREFERENCE: + eax_call.set_value(eax_.flHFReference); + break; + + case EAXREVERB_LFREFERENCE: + eax_call.set_value(eax_.flLFReference); + break; + + case EAXREVERB_ROOMROLLOFFFACTOR: + eax_call.set_value(eax_.flRoomRolloffFactor); + break; + + case EAXREVERB_FLAGS: + eax_call.set_value(eax_.ulFlags); + break; + + default: + throw EaxReverbEffectException{"Unsupported property id."}; + } + + return false; +} + +void EaxReverbEffect::validate_environment( + unsigned long ulEnvironment, + int version, + bool is_standalone) +{ + eax_validate_range( + "Environment", + ulEnvironment, + EAXREVERB_MINENVIRONMENT, + (version == 2 || is_standalone) ? EAX20REVERB_MAXENVIRONMENT : EAX30REVERB_MAXENVIRONMENT); +} + +void EaxReverbEffect::validate_environment_size( + float flEnvironmentSize) +{ + eax_validate_range( + "Environment Size", + flEnvironmentSize, + EAXREVERB_MINENVIRONMENTSIZE, + EAXREVERB_MAXENVIRONMENTSIZE); +} + +void EaxReverbEffect::validate_environment_diffusion( + float flEnvironmentDiffusion) +{ + eax_validate_range( + "Environment Diffusion", + flEnvironmentDiffusion, + EAXREVERB_MINENVIRONMENTDIFFUSION, + EAXREVERB_MAXENVIRONMENTDIFFUSION); +} + +void EaxReverbEffect::validate_room( + long lRoom) +{ + eax_validate_range( + "Room", + lRoom, + EAXREVERB_MINROOM, + EAXREVERB_MAXROOM); +} + +void EaxReverbEffect::validate_room_hf( + long lRoomHF) +{ + eax_validate_range( + "Room HF", + lRoomHF, + EAXREVERB_MINROOMHF, + EAXREVERB_MAXROOMHF); +} + +void EaxReverbEffect::validate_room_lf( + long lRoomLF) +{ + eax_validate_range( + "Room LF", + lRoomLF, + EAXREVERB_MINROOMLF, + EAXREVERB_MAXROOMLF); +} + +void EaxReverbEffect::validate_decay_time( + float flDecayTime) +{ + eax_validate_range( + "Decay Time", + flDecayTime, + EAXREVERB_MINDECAYTIME, + EAXREVERB_MAXDECAYTIME); +} + +void EaxReverbEffect::validate_decay_hf_ratio( + float flDecayHFRatio) +{ + eax_validate_range( + "Decay HF Ratio", + flDecayHFRatio, + EAXREVERB_MINDECAYHFRATIO, + EAXREVERB_MAXDECAYHFRATIO); +} + +void EaxReverbEffect::validate_decay_lf_ratio( + float flDecayLFRatio) +{ + eax_validate_range( + "Decay LF Ratio", + flDecayLFRatio, + EAXREVERB_MINDECAYLFRATIO, + EAXREVERB_MAXDECAYLFRATIO); +} + +void EaxReverbEffect::validate_reflections( + long lReflections) +{ + eax_validate_range( + "Reflections", + lReflections, + EAXREVERB_MINREFLECTIONS, + EAXREVERB_MAXREFLECTIONS); +} + +void EaxReverbEffect::validate_reflections_delay( + float flReflectionsDelay) +{ + eax_validate_range( + "Reflections Delay", + flReflectionsDelay, + EAXREVERB_MINREFLECTIONSDELAY, + EAXREVERB_MAXREFLECTIONSDELAY); +} + +void EaxReverbEffect::validate_reflections_pan( + const EAXVECTOR& vReflectionsPan) +{ + std::ignore = vReflectionsPan; +} + +void EaxReverbEffect::validate_reverb( + long lReverb) +{ + eax_validate_range( + "Reverb", + lReverb, + EAXREVERB_MINREVERB, + EAXREVERB_MAXREVERB); +} + +void EaxReverbEffect::validate_reverb_delay( + float flReverbDelay) +{ + eax_validate_range( + "Reverb Delay", + flReverbDelay, + EAXREVERB_MINREVERBDELAY, + EAXREVERB_MAXREVERBDELAY); +} + +void EaxReverbEffect::validate_reverb_pan( + const EAXVECTOR& vReverbPan) +{ + std::ignore = vReverbPan; +} + +void EaxReverbEffect::validate_echo_time( + float flEchoTime) +{ + eax_validate_range( + "Echo Time", + flEchoTime, + EAXREVERB_MINECHOTIME, + EAXREVERB_MAXECHOTIME); +} + +void EaxReverbEffect::validate_echo_depth( + float flEchoDepth) +{ + eax_validate_range( + "Echo Depth", + flEchoDepth, + EAXREVERB_MINECHODEPTH, + EAXREVERB_MAXECHODEPTH); +} + +void EaxReverbEffect::validate_modulation_time( + float flModulationTime) +{ + eax_validate_range( + "Modulation Time", + flModulationTime, + EAXREVERB_MINMODULATIONTIME, + EAXREVERB_MAXMODULATIONTIME); +} + +void EaxReverbEffect::validate_modulation_depth( + float flModulationDepth) +{ + eax_validate_range( + "Modulation Depth", + flModulationDepth, + EAXREVERB_MINMODULATIONDEPTH, + EAXREVERB_MAXMODULATIONDEPTH); +} + +void EaxReverbEffect::validate_air_absorbtion_hf( + float air_absorbtion_hf) +{ + eax_validate_range( + "Air Absorbtion HF", + air_absorbtion_hf, + EAXREVERB_MINAIRABSORPTIONHF, + EAXREVERB_MAXAIRABSORPTIONHF); +} + +void EaxReverbEffect::validate_hf_reference( + float flHFReference) +{ + eax_validate_range( + "HF Reference", + flHFReference, + EAXREVERB_MINHFREFERENCE, + EAXREVERB_MAXHFREFERENCE); +} + +void EaxReverbEffect::validate_lf_reference( + float flLFReference) +{ + eax_validate_range( + "LF Reference", + flLFReference, + EAXREVERB_MINLFREFERENCE, + EAXREVERB_MAXLFREFERENCE); +} + +void EaxReverbEffect::validate_room_rolloff_factor( + float flRoomRolloffFactor) +{ + eax_validate_range( + "Room Rolloff Factor", + flRoomRolloffFactor, + EAXREVERB_MINROOMROLLOFFFACTOR, + EAXREVERB_MAXROOMROLLOFFFACTOR); +} + +void EaxReverbEffect::validate_flags( + unsigned long ulFlags) +{ + eax_validate_range( + "Flags", + ulFlags, + 0UL, + ~EAXREVERBFLAGS_RESERVED); +} + +void EaxReverbEffect::validate_all( + const EAX20LISTENERPROPERTIES& listener, + int version) +{ + validate_room(listener.lRoom); + validate_room_hf(listener.lRoomHF); + validate_room_rolloff_factor(listener.flRoomRolloffFactor); + validate_decay_time(listener.flDecayTime); + validate_decay_hf_ratio(listener.flDecayHFRatio); + validate_reflections(listener.lReflections); + validate_reflections_delay(listener.flReflectionsDelay); + validate_reverb(listener.lReverb); + validate_reverb_delay(listener.flReverbDelay); + validate_environment(listener.dwEnvironment, version, false); + validate_environment_size(listener.flEnvironmentSize); + validate_environment_diffusion(listener.flEnvironmentDiffusion); + validate_air_absorbtion_hf(listener.flAirAbsorptionHF); + validate_flags(listener.dwFlags); +} + +void EaxReverbEffect::validate_all( + const EAXREVERBPROPERTIES& lReverb, + int version) +{ + validate_environment(lReverb.ulEnvironment, version, false); + validate_environment_size(lReverb.flEnvironmentSize); + validate_environment_diffusion(lReverb.flEnvironmentDiffusion); + validate_room(lReverb.lRoom); + validate_room_hf(lReverb.lRoomHF); + validate_room_lf(lReverb.lRoomLF); + validate_decay_time(lReverb.flDecayTime); + validate_decay_hf_ratio(lReverb.flDecayHFRatio); + validate_decay_lf_ratio(lReverb.flDecayLFRatio); + validate_reflections(lReverb.lReflections); + validate_reflections_delay(lReverb.flReflectionsDelay); + validate_reverb(lReverb.lReverb); + validate_reverb_delay(lReverb.flReverbDelay); + validate_echo_time(lReverb.flEchoTime); + validate_echo_depth(lReverb.flEchoDepth); + validate_modulation_time(lReverb.flModulationTime); + validate_modulation_depth(lReverb.flModulationDepth); + validate_air_absorbtion_hf(lReverb.flAirAbsorptionHF); + validate_hf_reference(lReverb.flHFReference); + validate_lf_reference(lReverb.flLFReference); + validate_room_rolloff_factor(lReverb.flRoomRolloffFactor); + validate_flags(lReverb.ulFlags); +} + +void EaxReverbEffect::defer_environment( + unsigned long ulEnvironment) +{ + eax_d_.ulEnvironment = ulEnvironment; + eax_dirty_flags_.ulEnvironment = (eax_.ulEnvironment != eax_d_.ulEnvironment); +} + +void EaxReverbEffect::defer_environment_size( + float flEnvironmentSize) +{ + eax_d_.flEnvironmentSize = flEnvironmentSize; + eax_dirty_flags_.flEnvironmentSize = (eax_.flEnvironmentSize != eax_d_.flEnvironmentSize); +} + +void EaxReverbEffect::defer_environment_diffusion( + float flEnvironmentDiffusion) +{ + eax_d_.flEnvironmentDiffusion = flEnvironmentDiffusion; + eax_dirty_flags_.flEnvironmentDiffusion = (eax_.flEnvironmentDiffusion != eax_d_.flEnvironmentDiffusion); +} + +void EaxReverbEffect::defer_room( + long lRoom) +{ + eax_d_.lRoom = lRoom; + eax_dirty_flags_.lRoom = (eax_.lRoom != eax_d_.lRoom); +} + +void EaxReverbEffect::defer_room_hf( + long lRoomHF) +{ + eax_d_.lRoomHF = lRoomHF; + eax_dirty_flags_.lRoomHF = (eax_.lRoomHF != eax_d_.lRoomHF); +} + +void EaxReverbEffect::defer_room_lf( + long lRoomLF) +{ + eax_d_.lRoomLF = lRoomLF; + eax_dirty_flags_.lRoomLF = (eax_.lRoomLF != eax_d_.lRoomLF); +} + +void EaxReverbEffect::defer_decay_time( + float flDecayTime) +{ + eax_d_.flDecayTime = flDecayTime; + eax_dirty_flags_.flDecayTime = (eax_.flDecayTime != eax_d_.flDecayTime); +} + +void EaxReverbEffect::defer_decay_hf_ratio( + float flDecayHFRatio) +{ + eax_d_.flDecayHFRatio = flDecayHFRatio; + eax_dirty_flags_.flDecayHFRatio = (eax_.flDecayHFRatio != eax_d_.flDecayHFRatio); +} + +void EaxReverbEffect::defer_decay_lf_ratio( + float flDecayLFRatio) +{ + eax_d_.flDecayLFRatio = flDecayLFRatio; + eax_dirty_flags_.flDecayLFRatio = (eax_.flDecayLFRatio != eax_d_.flDecayLFRatio); +} + +void EaxReverbEffect::defer_reflections( + long lReflections) +{ + eax_d_.lReflections = lReflections; + eax_dirty_flags_.lReflections = (eax_.lReflections != eax_d_.lReflections); +} + +void EaxReverbEffect::defer_reflections_delay( + float flReflectionsDelay) +{ + eax_d_.flReflectionsDelay = flReflectionsDelay; + eax_dirty_flags_.flReflectionsDelay = (eax_.flReflectionsDelay != eax_d_.flReflectionsDelay); +} + +void EaxReverbEffect::defer_reflections_pan( + const EAXVECTOR& vReflectionsPan) +{ + eax_d_.vReflectionsPan = vReflectionsPan; + eax_dirty_flags_.vReflectionsPan = (eax_.vReflectionsPan != eax_d_.vReflectionsPan); +} + +void EaxReverbEffect::defer_reverb( + long lReverb) +{ + eax_d_.lReverb = lReverb; + eax_dirty_flags_.lReverb = (eax_.lReverb != eax_d_.lReverb); +} + +void EaxReverbEffect::defer_reverb_delay( + float flReverbDelay) +{ + eax_d_.flReverbDelay = flReverbDelay; + eax_dirty_flags_.flReverbDelay = (eax_.flReverbDelay != eax_d_.flReverbDelay); +} + +void EaxReverbEffect::defer_reverb_pan( + const EAXVECTOR& vReverbPan) +{ + eax_d_.vReverbPan = vReverbPan; + eax_dirty_flags_.vReverbPan = (eax_.vReverbPan != eax_d_.vReverbPan); +} + +void EaxReverbEffect::defer_echo_time( + float flEchoTime) +{ + eax_d_.flEchoTime = flEchoTime; + eax_dirty_flags_.flEchoTime = (eax_.flEchoTime != eax_d_.flEchoTime); +} + +void EaxReverbEffect::defer_echo_depth( + float flEchoDepth) +{ + eax_d_.flEchoDepth = flEchoDepth; + eax_dirty_flags_.flEchoDepth = (eax_.flEchoDepth != eax_d_.flEchoDepth); +} + +void EaxReverbEffect::defer_modulation_time( + float flModulationTime) +{ + eax_d_.flModulationTime = flModulationTime; + eax_dirty_flags_.flModulationTime = (eax_.flModulationTime != eax_d_.flModulationTime); +} + +void EaxReverbEffect::defer_modulation_depth( + float flModulationDepth) +{ + eax_d_.flModulationDepth = flModulationDepth; + eax_dirty_flags_.flModulationDepth = (eax_.flModulationDepth != eax_d_.flModulationDepth); +} + +void EaxReverbEffect::defer_air_absorbtion_hf( + float flAirAbsorptionHF) +{ + eax_d_.flAirAbsorptionHF = flAirAbsorptionHF; + eax_dirty_flags_.flAirAbsorptionHF = (eax_.flAirAbsorptionHF != eax_d_.flAirAbsorptionHF); +} + +void EaxReverbEffect::defer_hf_reference( + float flHFReference) +{ + eax_d_.flHFReference = flHFReference; + eax_dirty_flags_.flHFReference = (eax_.flHFReference != eax_d_.flHFReference); +} + +void EaxReverbEffect::defer_lf_reference( + float flLFReference) +{ + eax_d_.flLFReference = flLFReference; + eax_dirty_flags_.flLFReference = (eax_.flLFReference != eax_d_.flLFReference); +} + +void EaxReverbEffect::defer_room_rolloff_factor( + float flRoomRolloffFactor) +{ + eax_d_.flRoomRolloffFactor = flRoomRolloffFactor; + eax_dirty_flags_.flRoomRolloffFactor = (eax_.flRoomRolloffFactor != eax_d_.flRoomRolloffFactor); +} + +void EaxReverbEffect::defer_flags( + unsigned long ulFlags) +{ + eax_d_.ulFlags = ulFlags; + eax_dirty_flags_.ulFlags = (eax_.ulFlags != eax_d_.ulFlags); +} + +void EaxReverbEffect::defer_all( + const EAX20LISTENERPROPERTIES& listener) +{ + defer_room(listener.lRoom); + defer_room_hf(listener.lRoomHF); + defer_room_rolloff_factor(listener.flRoomRolloffFactor); + defer_decay_time(listener.flDecayTime); + defer_decay_hf_ratio(listener.flDecayHFRatio); + defer_reflections(listener.lReflections); + defer_reflections_delay(listener.flReflectionsDelay); + defer_reverb(listener.lReverb); + defer_reverb_delay(listener.flReverbDelay); + defer_environment(listener.dwEnvironment); + defer_environment_size(listener.flEnvironmentSize); + defer_environment_diffusion(listener.flEnvironmentDiffusion); + defer_air_absorbtion_hf(listener.flAirAbsorptionHF); + defer_flags(listener.dwFlags); +} + +void EaxReverbEffect::defer_all( + const EAXREVERBPROPERTIES& lReverb) +{ + defer_environment(lReverb.ulEnvironment); + defer_environment_size(lReverb.flEnvironmentSize); + defer_environment_diffusion(lReverb.flEnvironmentDiffusion); + defer_room(lReverb.lRoom); + defer_room_hf(lReverb.lRoomHF); + defer_room_lf(lReverb.lRoomLF); + defer_decay_time(lReverb.flDecayTime); + defer_decay_hf_ratio(lReverb.flDecayHFRatio); + defer_decay_lf_ratio(lReverb.flDecayLFRatio); + defer_reflections(lReverb.lReflections); + defer_reflections_delay(lReverb.flReflectionsDelay); + defer_reflections_pan(lReverb.vReflectionsPan); + defer_reverb(lReverb.lReverb); + defer_reverb_delay(lReverb.flReverbDelay); + defer_reverb_pan(lReverb.vReverbPan); + defer_echo_time(lReverb.flEchoTime); + defer_echo_depth(lReverb.flEchoDepth); + defer_modulation_time(lReverb.flModulationTime); + defer_modulation_depth(lReverb.flModulationDepth); + defer_air_absorbtion_hf(lReverb.flAirAbsorptionHF); + defer_hf_reference(lReverb.flHFReference); + defer_lf_reference(lReverb.flLFReference); + defer_room_rolloff_factor(lReverb.flRoomRolloffFactor); + defer_flags(lReverb.ulFlags); +} + +void EaxReverbEffect::defer_environment( + const EaxEaxCall& eax_call) +{ + const auto& ulEnvironment = + eax_call.get_value(); + + validate_environment(ulEnvironment, eax_call.get_version(), true); + + if (eax_d_.ulEnvironment == ulEnvironment) + { + return; + } + + const auto& reverb_preset = EAXREVERB_PRESETS[ulEnvironment]; + + defer_all(reverb_preset); +} + +void EaxReverbEffect::defer_environment_size( + const EaxEaxCall& eax_call) +{ + const auto& flEnvironmentSize = + eax_call.get_value(); + + validate_environment_size(flEnvironmentSize); + + if (eax_d_.flEnvironmentSize == flEnvironmentSize) + { + return; + } + + const auto scale = flEnvironmentSize / eax_d_.flEnvironmentSize; + + defer_environment_size(flEnvironmentSize); + + if ((eax_d_.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) + { + const auto flDecayTime = clamp( + scale * eax_d_.flDecayTime, + EAXREVERB_MINDECAYTIME, + EAXREVERB_MAXDECAYTIME); + + defer_decay_time(flDecayTime); + } + + if ((eax_d_.ulFlags & EAXREVERBFLAGS_REFLECTIONSSCALE) != 0) + { + if ((eax_d_.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0) + { + const auto lReflections = clamp( + eax_d_.lReflections - static_cast(gain_to_level_mb(scale)), + EAXREVERB_MINREFLECTIONS, + EAXREVERB_MAXREFLECTIONS); + + defer_reflections(lReflections); + } + } + + if ((eax_d_.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0) + { + const auto flReflectionsDelay = clamp( + eax_d_.flReflectionsDelay * scale, + EAXREVERB_MINREFLECTIONSDELAY, + EAXREVERB_MAXREFLECTIONSDELAY); + + defer_reflections_delay(flReflectionsDelay); + } + + if ((eax_d_.ulFlags & EAXREVERBFLAGS_REVERBSCALE) != 0) + { + const auto log_scalar = ((eax_d_.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F; + + const auto lReverb = clamp( + eax_d_.lReverb - static_cast(std::log10(scale) * log_scalar), + EAXREVERB_MINREVERB, + EAXREVERB_MAXREVERB); + + defer_reverb(lReverb); + } + + if ((eax_d_.ulFlags & EAXREVERBFLAGS_REVERBDELAYSCALE) != 0) + { + const auto flReverbDelay = clamp( + scale * eax_d_.flReverbDelay, + EAXREVERB_MINREVERBDELAY, + EAXREVERB_MAXREVERBDELAY); + + defer_reverb_delay(flReverbDelay); + } + + if ((eax_d_.ulFlags & EAXREVERBFLAGS_ECHOTIMESCALE) != 0) + { + const auto flEchoTime = clamp( + eax_d_.flEchoTime * scale, + EAXREVERB_MINECHOTIME, + EAXREVERB_MAXECHOTIME); + + defer_echo_time(flEchoTime); + } + + if ((eax_d_.ulFlags & EAXREVERBFLAGS_MODULATIONTIMESCALE) != 0) + { + const auto flModulationTime = clamp( + scale * eax_d_.flModulationTime, + EAXREVERB_MINMODULATIONTIME, + EAXREVERB_MAXMODULATIONTIME); + + defer_modulation_time(flModulationTime); + } +} + +void EaxReverbEffect::defer_environment_diffusion( + const EaxEaxCall& eax_call) +{ + const auto& flEnvironmentDiffusion = + eax_call.get_value(); + + validate_environment_diffusion(flEnvironmentDiffusion); + defer_environment_diffusion(flEnvironmentDiffusion); +} + +void EaxReverbEffect::defer_room( + const EaxEaxCall& eax_call) +{ + const auto& lRoom = + eax_call.get_value(); + + validate_room(lRoom); + defer_room(lRoom); +} + +void EaxReverbEffect::defer_room_hf( + const EaxEaxCall& eax_call) +{ + const auto& lRoomHF = + eax_call.get_value(); + + validate_room_hf(lRoomHF); + defer_room_hf(lRoomHF); +} + +void EaxReverbEffect::defer_room_lf( + const EaxEaxCall& eax_call) +{ + const auto& lRoomLF = + eax_call.get_value(); + + validate_room_lf(lRoomLF); + defer_room_lf(lRoomLF); +} + +void EaxReverbEffect::defer_decay_time( + const EaxEaxCall& eax_call) +{ + const auto& flDecayTime = + eax_call.get_value(); + + validate_decay_time(flDecayTime); + defer_decay_time(flDecayTime); +} + +void EaxReverbEffect::defer_decay_hf_ratio( + const EaxEaxCall& eax_call) +{ + const auto& flDecayHFRatio = + eax_call.get_value(); + + validate_decay_hf_ratio(flDecayHFRatio); + defer_decay_hf_ratio(flDecayHFRatio); +} + +void EaxReverbEffect::defer_decay_lf_ratio( + const EaxEaxCall& eax_call) +{ + const auto& flDecayLFRatio = + eax_call.get_value(); + + validate_decay_lf_ratio(flDecayLFRatio); + defer_decay_lf_ratio(flDecayLFRatio); +} + +void EaxReverbEffect::defer_reflections( + const EaxEaxCall& eax_call) +{ + const auto& lReflections = + eax_call.get_value(); + + validate_reflections(lReflections); + defer_reflections(lReflections); +} + +void EaxReverbEffect::defer_reflections_delay( + const EaxEaxCall& eax_call) +{ + const auto& flReflectionsDelay = + eax_call.get_value(); + + validate_reflections_delay(flReflectionsDelay); + defer_reflections_delay(flReflectionsDelay); +} + +void EaxReverbEffect::defer_reflections_pan( + const EaxEaxCall& eax_call) +{ + const auto& vReflectionsPan = + eax_call.get_value(); + + validate_reflections_pan(vReflectionsPan); + defer_reflections_pan(vReflectionsPan); +} + +void EaxReverbEffect::defer_reverb( + const EaxEaxCall& eax_call) +{ + const auto& lReverb = + eax_call.get_value(); + + validate_reverb(lReverb); + defer_reverb(lReverb); +} + +void EaxReverbEffect::defer_reverb_delay( + const EaxEaxCall& eax_call) +{ + const auto& flReverbDelay = + eax_call.get_value(); + + validate_reverb_delay(flReverbDelay); + defer_reverb_delay(flReverbDelay); +} + +void EaxReverbEffect::defer_reverb_pan( + const EaxEaxCall& eax_call) +{ + const auto& vReverbPan = + eax_call.get_value(); + + validate_reverb_pan(vReverbPan); + defer_reverb_pan(vReverbPan); +} + +void EaxReverbEffect::defer_echo_time( + const EaxEaxCall& eax_call) +{ + const auto& flEchoTime = + eax_call.get_value(); + + validate_echo_time(flEchoTime); + defer_echo_time(flEchoTime); +} + +void EaxReverbEffect::defer_echo_depth( + const EaxEaxCall& eax_call) +{ + const auto& flEchoDepth = + eax_call.get_value(); + + validate_echo_depth(flEchoDepth); + defer_echo_depth(flEchoDepth); +} + +void EaxReverbEffect::defer_modulation_time( + const EaxEaxCall& eax_call) +{ + const auto& flModulationTime = + eax_call.get_value(); + + validate_modulation_time(flModulationTime); + defer_modulation_time(flModulationTime); +} + +void EaxReverbEffect::defer_modulation_depth( + const EaxEaxCall& eax_call) +{ + const auto& flModulationDepth = + eax_call.get_value(); + + validate_modulation_depth(flModulationDepth); + defer_modulation_depth(flModulationDepth); +} + +void EaxReverbEffect::defer_air_absorbtion_hf( + const EaxEaxCall& eax_call) +{ + const auto& air_absorbtion_hf = + eax_call.get_value(); + + validate_air_absorbtion_hf(air_absorbtion_hf); + defer_air_absorbtion_hf(air_absorbtion_hf); +} + +void EaxReverbEffect::defer_hf_reference( + const EaxEaxCall& eax_call) +{ + const auto& flHFReference = + eax_call.get_value(); + + validate_hf_reference(flHFReference); + defer_hf_reference(flHFReference); +} + +void EaxReverbEffect::defer_lf_reference( + const EaxEaxCall& eax_call) +{ + const auto& flLFReference = + eax_call.get_value(); + + validate_lf_reference(flLFReference); + defer_lf_reference(flLFReference); +} + +void EaxReverbEffect::defer_room_rolloff_factor( + const EaxEaxCall& eax_call) +{ + const auto& flRoomRolloffFactor = + eax_call.get_value(); + + validate_room_rolloff_factor(flRoomRolloffFactor); + defer_room_rolloff_factor(flRoomRolloffFactor); +} + +void EaxReverbEffect::defer_flags( + const EaxEaxCall& eax_call) +{ + const auto& ulFlags = + eax_call.get_value(); + + validate_flags(ulFlags); + defer_flags(ulFlags); +} + +void EaxReverbEffect::defer_all( + const EaxEaxCall& eax_call) +{ + const auto eax_version = eax_call.get_version(); + + if (eax_version == 2) + { + const auto& listener = + eax_call.get_value(); + + validate_all(listener, eax_version); + defer_all(listener); + } + else + { + const auto& reverb_all = + eax_call.get_value(); + + validate_all(reverb_all, eax_version); + defer_all(reverb_all); + } +} + +// [[nodiscard]] +bool EaxReverbEffect::apply_deferred() +{ + if (eax_dirty_flags_ == EaxReverbEffectDirtyFlags{}) + { + return false; + } + + eax_ = eax_d_; + + if (eax_dirty_flags_.ulEnvironment) + { + } + + if (eax_dirty_flags_.flEnvironmentSize) + { + set_efx_density(); + } + + if (eax_dirty_flags_.flEnvironmentDiffusion) + { + set_efx_diffusion(); + } + + if (eax_dirty_flags_.lRoom) + { + set_efx_gain(); + } + + if (eax_dirty_flags_.lRoomHF) + { + set_efx_gain_hf(); + } + + if (eax_dirty_flags_.lRoomLF) + { + set_efx_gain_lf(); + } + + if (eax_dirty_flags_.flDecayTime) + { + set_efx_decay_time(); + } + + if (eax_dirty_flags_.flDecayHFRatio) + { + set_efx_decay_hf_ratio(); + } + + if (eax_dirty_flags_.flDecayLFRatio) + { + set_efx_decay_lf_ratio(); + } + + if (eax_dirty_flags_.lReflections) + { + set_efx_reflections_gain(); + } + + if (eax_dirty_flags_.flReflectionsDelay) + { + set_efx_reflections_delay(); + } + + if (eax_dirty_flags_.vReflectionsPan) + { + set_efx_reflections_pan(); + } + + if (eax_dirty_flags_.lReverb) + { + set_efx_late_reverb_gain(); + } + + if (eax_dirty_flags_.flReverbDelay) + { + set_efx_late_reverb_delay(); + } + + if (eax_dirty_flags_.vReverbPan) + { + set_efx_late_reverb_pan(); + } + + if (eax_dirty_flags_.flEchoTime) + { + set_efx_echo_time(); + } + + if (eax_dirty_flags_.flEchoDepth) + { + set_efx_echo_depth(); + } + + if (eax_dirty_flags_.flModulationTime) + { + set_efx_modulation_time(); + } + + if (eax_dirty_flags_.flModulationDepth) + { + set_efx_modulation_depth(); + } + + if (eax_dirty_flags_.flAirAbsorptionHF) + { + set_efx_air_absorption_gain_hf(); + } + + if (eax_dirty_flags_.flHFReference) + { + set_efx_hf_reference(); + } + + if (eax_dirty_flags_.flLFReference) + { + set_efx_lf_reference(); + } + + if (eax_dirty_flags_.flRoomRolloffFactor) + { + set_efx_room_rolloff_factor(); + } + + if (eax_dirty_flags_.ulFlags) + { + set_efx_flags(); + } + + eax_dirty_flags_ = EaxReverbEffectDirtyFlags{}; + + return true; +} + +// [[nodiscard]] +bool EaxReverbEffect::set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXREVERB_NONE: + break; + + case EAXREVERB_ALLPARAMETERS: + defer_all(eax_call); + break; + + case EAXREVERB_ENVIRONMENT: + defer_environment(eax_call); + break; + + case EAXREVERB_ENVIRONMENTSIZE: + defer_environment_size(eax_call); + break; + + case EAXREVERB_ENVIRONMENTDIFFUSION: + defer_environment_diffusion(eax_call); + break; + + case EAXREVERB_ROOM: + defer_room(eax_call); + break; + + case EAXREVERB_ROOMHF: + defer_room_hf(eax_call); + break; + + case EAXREVERB_ROOMLF: + defer_room_lf(eax_call); + break; + + case EAXREVERB_DECAYTIME: + defer_decay_time(eax_call); + break; + + case EAXREVERB_DECAYHFRATIO: + defer_decay_hf_ratio(eax_call); + break; + + case EAXREVERB_DECAYLFRATIO: + defer_decay_lf_ratio(eax_call); + break; + + case EAXREVERB_REFLECTIONS: + defer_reflections(eax_call); + break; + + case EAXREVERB_REFLECTIONSDELAY: + defer_reflections_delay(eax_call); + break; + + case EAXREVERB_REFLECTIONSPAN: + defer_reflections_pan(eax_call); + break; + + case EAXREVERB_REVERB: + defer_reverb(eax_call); + break; + + case EAXREVERB_REVERBDELAY: + defer_reverb_delay(eax_call); + break; + + case EAXREVERB_REVERBPAN: + defer_reverb_pan(eax_call); + break; + + case EAXREVERB_ECHOTIME: + defer_echo_time(eax_call); + break; + + case EAXREVERB_ECHODEPTH: + defer_echo_depth(eax_call); + break; + + case EAXREVERB_MODULATIONTIME: + defer_modulation_time(eax_call); + break; + + case EAXREVERB_MODULATIONDEPTH: + defer_modulation_depth(eax_call); + break; + + case EAXREVERB_AIRABSORPTIONHF: + defer_air_absorbtion_hf(eax_call); + break; + + case EAXREVERB_HFREFERENCE: + defer_hf_reference(eax_call); + break; + + case EAXREVERB_LFREFERENCE: + defer_lf_reference(eax_call); + break; + + case EAXREVERB_ROOMROLLOFFFACTOR: + defer_room_rolloff_factor(eax_call); + break; + + case EAXREVERB_FLAGS: + defer_flags(eax_call); + break; + + default: + throw EaxReverbEffectException{"Unsupported property id."}; + } + + if (!eax_call.is_deferred()) + { + return apply_deferred(); + } + + return false; +} + + +} // namespace + + +EaxEffectUPtr eax_create_eax_reverb_effect( + EffectProps& al_effect_props) +{ + return std::make_unique(al_effect_props); +} + + +#endif // ALSOFT_EAX diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index 1b4710ff..2a9e0702 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -10,6 +10,15 @@ #include "aloptional.h" #include "effects.h" +#if ALSOFT_EAX +#include + +#include "alnumeric.h" + +#include "al/eax_exception.h" +#include "al/eax_utils.h" +#endif // ALSOFT_EAX + namespace { @@ -247,3 +256,618 @@ EffectProps genDefaultProps() noexcept DEFINE_ALEFFECT_VTABLE(Vmorpher); const EffectProps VmorpherEffectProps{genDefaultProps()}; + +#if ALSOFT_EAX +namespace +{ + + +using EaxVocalMorpherEffectDirtyFlagsValue = std::uint_least8_t; + +struct EaxVocalMorpherEffectDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxVocalMorpherEffectDirtyFlagsValue ulPhonemeA : 1; + EaxVocalMorpherEffectDirtyFlagsValue lPhonemeACoarseTuning : 1; + EaxVocalMorpherEffectDirtyFlagsValue ulPhonemeB : 1; + EaxVocalMorpherEffectDirtyFlagsValue lPhonemeBCoarseTuning : 1; + EaxVocalMorpherEffectDirtyFlagsValue ulWaveform : 1; + EaxVocalMorpherEffectDirtyFlagsValue flRate : 1; +}; // EaxPitchShifterEffectDirtyFlags + + +class EaxVocalMorpherEffect final : + public EaxEffect +{ +public: + EaxVocalMorpherEffect( + EffectProps& al_effect_props); + + + // [[nodiscard]] + bool dispatch( + const EaxEaxCall& eax_call) override; + + +private: + EffectProps& al_effect_props_; + + EAXVOCALMORPHERPROPERTIES eax_{}; + EAXVOCALMORPHERPROPERTIES eax_d_{}; + EaxVocalMorpherEffectDirtyFlags eax_dirty_flags_{}; + + + void set_eax_defaults(); + + + void set_efx_phoneme_a(); + + void set_efx_phoneme_a_coarse_tuning(); + + void set_efx_phoneme_b(); + + void set_efx_phoneme_b_coarse_tuning(); + + void set_efx_waveform(); + + void set_efx_rate(); + + void set_efx_defaults(); + + + // [[nodiscard]] + bool get( + const EaxEaxCall& eax_call); + + + void validate_phoneme_a( + unsigned long ulPhonemeA); + + void validate_phoneme_a_coarse_tuning( + long lPhonemeACoarseTuning); + + void validate_phoneme_b( + unsigned long ulPhonemeB); + + void validate_phoneme_b_coarse_tuning( + long lPhonemeBCoarseTuning); + + void validate_waveform( + unsigned long ulWaveform); + + void validate_rate( + float flRate); + + void validate_all( + const EAXVOCALMORPHERPROPERTIES& all); + + + void defer_phoneme_a( + unsigned long ulPhonemeA); + + void defer_phoneme_a_coarse_tuning( + long lPhonemeACoarseTuning); + + void defer_phoneme_b( + unsigned long ulPhonemeB); + + void defer_phoneme_b_coarse_tuning( + long lPhonemeBCoarseTuning); + + void defer_waveform( + unsigned long ulWaveform); + + void defer_rate( + float flRate); + + void defer_all( + const EAXVOCALMORPHERPROPERTIES& all); + + + void defer_phoneme_a( + const EaxEaxCall& eax_call); + + void defer_phoneme_a_coarse_tuning( + const EaxEaxCall& eax_call); + + void defer_phoneme_b( + const EaxEaxCall& eax_call); + + void defer_phoneme_b_coarse_tuning( + const EaxEaxCall& eax_call); + + void defer_waveform( + const EaxEaxCall& eax_call); + + void defer_rate( + const EaxEaxCall& eax_call); + + void defer_all( + const EaxEaxCall& eax_call); + + + // [[nodiscard]] + bool apply_deferred(); + + // [[nodiscard]] + bool set( + const EaxEaxCall& eax_call); +}; // EaxVocalMorpherEffect + + +class EaxVocalMorpherEffectException : + public EaxException +{ +public: + explicit EaxVocalMorpherEffectException( + const char* message) + : + EaxException{"EAX_VOCAL_MORPHER_EFFECT", message} + { + } +}; // EaxVocalMorpherEffectException + + +EaxVocalMorpherEffect::EaxVocalMorpherEffect( + EffectProps& al_effect_props) + : + al_effect_props_{al_effect_props} +{ + set_eax_defaults(); + set_efx_defaults(); +} + +// [[nodiscard]] +bool EaxVocalMorpherEffect::dispatch( + const EaxEaxCall& eax_call) +{ + return eax_call.is_get() ? get(eax_call) : set(eax_call); +} + +void EaxVocalMorpherEffect::set_eax_defaults() +{ + eax_.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA; + eax_.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING; + eax_.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB; + eax_.lPhonemeBCoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING; + eax_.ulWaveform = EAXVOCALMORPHER_DEFAULTWAVEFORM; + eax_.flRate = EAXVOCALMORPHER_DEFAULTRATE; + + eax_d_ = eax_; +} + +void EaxVocalMorpherEffect::set_efx_phoneme_a() +{ + const auto phoneme_a = clamp( + static_cast(eax_.ulPhonemeA), + AL_VOCAL_MORPHER_MIN_PHONEMEA, + AL_VOCAL_MORPHER_MAX_PHONEMEA); + + const auto efx_phoneme_a = PhenomeFromEnum(phoneme_a); + assert(efx_phoneme_a.has_value()); + al_effect_props_.Vmorpher.PhonemeA = *efx_phoneme_a; +} + +void EaxVocalMorpherEffect::set_efx_phoneme_a_coarse_tuning() +{ + const auto phoneme_a_coarse_tuning = clamp( + static_cast(eax_.lPhonemeACoarseTuning), + AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING, + AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING); + + al_effect_props_.Vmorpher.PhonemeACoarseTuning = phoneme_a_coarse_tuning; +} + +void EaxVocalMorpherEffect::set_efx_phoneme_b() +{ + const auto phoneme_b = clamp( + static_cast(eax_.ulPhonemeB), + AL_VOCAL_MORPHER_MIN_PHONEMEB, + AL_VOCAL_MORPHER_MAX_PHONEMEB); + + const auto efx_phoneme_b = PhenomeFromEnum(phoneme_b); + assert(efx_phoneme_b.has_value()); + al_effect_props_.Vmorpher.PhonemeB = *efx_phoneme_b; +} + +void EaxVocalMorpherEffect::set_efx_phoneme_b_coarse_tuning() +{ + const auto phoneme_b_coarse_tuning = clamp( + static_cast(eax_.lPhonemeBCoarseTuning), + AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING, + AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING); + + al_effect_props_.Vmorpher.PhonemeBCoarseTuning = phoneme_b_coarse_tuning; +} + +void EaxVocalMorpherEffect::set_efx_waveform() +{ + const auto waveform = clamp( + static_cast(eax_.ulWaveform), + AL_VOCAL_MORPHER_MIN_WAVEFORM, + AL_VOCAL_MORPHER_MAX_WAVEFORM); + + const auto wfx_waveform = WaveformFromEmum(waveform); + assert(wfx_waveform.has_value()); + al_effect_props_.Vmorpher.Waveform = *wfx_waveform; +} + +void EaxVocalMorpherEffect::set_efx_rate() +{ + const auto rate = clamp( + eax_.flRate, + AL_VOCAL_MORPHER_MIN_RATE, + AL_VOCAL_MORPHER_MAX_RATE); + + al_effect_props_.Vmorpher.Rate = rate; +} + +void EaxVocalMorpherEffect::set_efx_defaults() +{ + set_efx_phoneme_a(); + set_efx_phoneme_a_coarse_tuning(); + set_efx_phoneme_b(); + set_efx_phoneme_b_coarse_tuning(); + set_efx_waveform(); + set_efx_rate(); +} + +// [[nodiscard]] +bool EaxVocalMorpherEffect::get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXVOCALMORPHER_NONE: + break; + + case EAXVOCALMORPHER_ALLPARAMETERS: + eax_call.set_value(eax_); + break; + + case EAXVOCALMORPHER_PHONEMEA: + eax_call.set_value(eax_.ulPhonemeA); + break; + + case EAXVOCALMORPHER_PHONEMEACOARSETUNING: + eax_call.set_value(eax_.lPhonemeACoarseTuning); + break; + + case EAXVOCALMORPHER_PHONEMEB: + eax_call.set_value(eax_.ulPhonemeB); + break; + + case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: + eax_call.set_value(eax_.lPhonemeBCoarseTuning); + break; + + case EAXVOCALMORPHER_WAVEFORM: + eax_call.set_value(eax_.ulWaveform); + break; + + case EAXVOCALMORPHER_RATE: + eax_call.set_value(eax_.flRate); + break; + + default: + throw EaxVocalMorpherEffectException{"Unsupported property id."}; + } + + return false; +} + +void EaxVocalMorpherEffect::validate_phoneme_a( + unsigned long ulPhonemeA) +{ + eax_validate_range( + "Phoneme A", + ulPhonemeA, + EAXVOCALMORPHER_MINPHONEMEA, + EAXVOCALMORPHER_MAXPHONEMEA); +} + +void EaxVocalMorpherEffect::validate_phoneme_a_coarse_tuning( + long lPhonemeACoarseTuning) +{ + eax_validate_range( + "Phoneme A Coarse Tuning", + lPhonemeACoarseTuning, + EAXVOCALMORPHER_MINPHONEMEACOARSETUNING, + EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING); +} + +void EaxVocalMorpherEffect::validate_phoneme_b( + unsigned long ulPhonemeB) +{ + eax_validate_range( + "Phoneme B", + ulPhonemeB, + EAXVOCALMORPHER_MINPHONEMEB, + EAXVOCALMORPHER_MAXPHONEMEB); +} + +void EaxVocalMorpherEffect::validate_phoneme_b_coarse_tuning( + long lPhonemeBCoarseTuning) +{ + eax_validate_range( + "Phoneme B Coarse Tuning", + lPhonemeBCoarseTuning, + EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING, + EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING); +} + +void EaxVocalMorpherEffect::validate_waveform( + unsigned long ulWaveform) +{ + eax_validate_range( + "Waveform", + ulWaveform, + EAXVOCALMORPHER_MINWAVEFORM, + EAXVOCALMORPHER_MAXWAVEFORM); +} + +void EaxVocalMorpherEffect::validate_rate( + float flRate) +{ + eax_validate_range( + "Rate", + flRate, + EAXVOCALMORPHER_MINRATE, + EAXVOCALMORPHER_MAXRATE); +} + +void EaxVocalMorpherEffect::validate_all( + const EAXVOCALMORPHERPROPERTIES& all) +{ + validate_phoneme_a(all.ulPhonemeA); + validate_phoneme_a_coarse_tuning(all.lPhonemeACoarseTuning); + validate_phoneme_b(all.ulPhonemeB); + validate_phoneme_b_coarse_tuning(all.lPhonemeBCoarseTuning); + validate_waveform(all.ulWaveform); + validate_rate(all.flRate); +} + +void EaxVocalMorpherEffect::defer_phoneme_a( + unsigned long ulPhonemeA) +{ + eax_d_.ulPhonemeA = ulPhonemeA; + eax_dirty_flags_.ulPhonemeA = (eax_.ulPhonemeA != eax_d_.ulPhonemeA); +} + +void EaxVocalMorpherEffect::defer_phoneme_a_coarse_tuning( + long lPhonemeACoarseTuning) +{ + eax_d_.lPhonemeACoarseTuning = lPhonemeACoarseTuning; + eax_dirty_flags_.lPhonemeACoarseTuning = (eax_.lPhonemeACoarseTuning != eax_d_.lPhonemeACoarseTuning); +} + +void EaxVocalMorpherEffect::defer_phoneme_b( + unsigned long ulPhonemeB) +{ + eax_d_.ulPhonemeB = ulPhonemeB; + eax_dirty_flags_.ulPhonemeB = (eax_.ulPhonemeB != eax_d_.ulPhonemeB); +} + +void EaxVocalMorpherEffect::defer_phoneme_b_coarse_tuning( + long lPhonemeBCoarseTuning) +{ + eax_d_.lPhonemeBCoarseTuning = lPhonemeBCoarseTuning; + eax_dirty_flags_.lPhonemeBCoarseTuning = (eax_.lPhonemeBCoarseTuning != eax_d_.lPhonemeBCoarseTuning); +} + +void EaxVocalMorpherEffect::defer_waveform( + unsigned long ulWaveform) +{ + eax_d_.ulWaveform = ulWaveform; + eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform); +} + +void EaxVocalMorpherEffect::defer_rate( + float flRate) +{ + eax_d_.flRate = flRate; + eax_dirty_flags_.flRate = (eax_.flRate != eax_d_.flRate); +} + +void EaxVocalMorpherEffect::defer_all( + const EAXVOCALMORPHERPROPERTIES& all) +{ + defer_phoneme_a(all.ulPhonemeA); + defer_phoneme_a_coarse_tuning(all.lPhonemeACoarseTuning); + defer_phoneme_b(all.ulPhonemeB); + defer_phoneme_b_coarse_tuning(all.lPhonemeBCoarseTuning); + defer_waveform(all.ulWaveform); + defer_rate(all.flRate); +} + +void EaxVocalMorpherEffect::defer_phoneme_a( + const EaxEaxCall& eax_call) +{ + const auto& phoneme_a = eax_call.get_value< + EaxVocalMorpherEffectException, + const decltype(EAXVOCALMORPHERPROPERTIES::ulPhonemeA) + >(); + + validate_phoneme_a(phoneme_a); + defer_phoneme_a(phoneme_a); +} + +void EaxVocalMorpherEffect::defer_phoneme_a_coarse_tuning( + const EaxEaxCall& eax_call) +{ + const auto& phoneme_a_coarse_tuning = eax_call.get_value< + EaxVocalMorpherEffectException, + const decltype(EAXVOCALMORPHERPROPERTIES::lPhonemeACoarseTuning) + >(); + + validate_phoneme_a_coarse_tuning(phoneme_a_coarse_tuning); + defer_phoneme_a_coarse_tuning(phoneme_a_coarse_tuning); +} + +void EaxVocalMorpherEffect::defer_phoneme_b( + const EaxEaxCall& eax_call) +{ + const auto& phoneme_b = eax_call.get_value< + EaxVocalMorpherEffectException, + const decltype(EAXVOCALMORPHERPROPERTIES::ulPhonemeB) + >(); + + validate_phoneme_b(phoneme_b); + defer_phoneme_b(phoneme_b); +} + +void EaxVocalMorpherEffect::defer_phoneme_b_coarse_tuning( + const EaxEaxCall& eax_call) +{ + const auto& phoneme_b_coarse_tuning = eax_call.get_value< + EaxVocalMorpherEffectException, + const decltype(EAXVOCALMORPHERPROPERTIES::lPhonemeBCoarseTuning) + >(); + + validate_phoneme_b_coarse_tuning(phoneme_b_coarse_tuning); + defer_phoneme_b_coarse_tuning(phoneme_b_coarse_tuning); +} + +void EaxVocalMorpherEffect::defer_waveform( + const EaxEaxCall& eax_call) +{ + const auto& waveform = eax_call.get_value< + EaxVocalMorpherEffectException, + const decltype(EAXVOCALMORPHERPROPERTIES::ulWaveform) + >(); + + validate_waveform(waveform); + defer_waveform(waveform); +} + +void EaxVocalMorpherEffect::defer_rate( + const EaxEaxCall& eax_call) +{ + const auto& rate = eax_call.get_value< + EaxVocalMorpherEffectException, + const decltype(EAXVOCALMORPHERPROPERTIES::flRate) + >(); + + validate_rate(rate); + defer_rate(rate); +} + +void EaxVocalMorpherEffect::defer_all( + const EaxEaxCall& eax_call) +{ + const auto& all = eax_call.get_value< + EaxVocalMorpherEffectException, + const EAXVOCALMORPHERPROPERTIES + >(); + + validate_all(all); + defer_all(all); +} + +// [[nodiscard]] +bool EaxVocalMorpherEffect::apply_deferred() +{ + if (eax_dirty_flags_ == EaxVocalMorpherEffectDirtyFlags{}) + { + return false; + } + + eax_ = eax_d_; + + if (eax_dirty_flags_.ulPhonemeA) + { + set_efx_phoneme_a(); + } + + if (eax_dirty_flags_.lPhonemeACoarseTuning) + { + set_efx_phoneme_a_coarse_tuning(); + } + + if (eax_dirty_flags_.ulPhonemeB) + { + set_efx_phoneme_b(); + } + + if (eax_dirty_flags_.lPhonemeBCoarseTuning) + { + set_efx_phoneme_b_coarse_tuning(); + } + + if (eax_dirty_flags_.ulWaveform) + { + set_efx_waveform(); + } + + if (eax_dirty_flags_.flRate) + { + set_efx_rate(); + } + + eax_dirty_flags_ = EaxVocalMorpherEffectDirtyFlags{}; + + return true; +} + +// [[nodiscard]] +bool EaxVocalMorpherEffect::set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXVOCALMORPHER_NONE: + break; + + case EAXVOCALMORPHER_ALLPARAMETERS: + defer_all(eax_call); + break; + + case EAXVOCALMORPHER_PHONEMEA: + defer_phoneme_a(eax_call); + break; + + case EAXVOCALMORPHER_PHONEMEACOARSETUNING: + defer_phoneme_a_coarse_tuning(eax_call); + break; + + case EAXVOCALMORPHER_PHONEMEB: + defer_phoneme_b(eax_call); + break; + + case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: + defer_phoneme_b_coarse_tuning(eax_call); + break; + + case EAXVOCALMORPHER_WAVEFORM: + defer_waveform(eax_call); + break; + + case EAXVOCALMORPHER_RATE: + defer_rate(eax_call); + break; + + default: + throw EaxVocalMorpherEffectException{"Unsupported property id."}; + } + + if (!eax_call.is_deferred()) + { + return apply_deferred(); + } + + return false; +} + + +} // namespace + + +EaxEffectUPtr eax_create_eax_vocal_morpher_effect( + EffectProps& al_effect_props) +{ + return std::make_unique(al_effect_props); +} + + +#endif // ALSOFT_EAX diff --git a/al/extension.cpp b/al/extension.cpp index 5dda2a86..373f87a9 100644 --- a/al/extension.cpp +++ b/al/extension.cpp @@ -32,6 +32,10 @@ #include "core/except.h" #include "opthelpers.h" +#if ALSOFT_EAX +#include "eax_globals.h" +#include "eax_x_ram.h" +#endif // ALSOFT_EAX AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName) START_API_FUNC @@ -43,6 +47,22 @@ START_API_FUNC SETERR_RETURN(context, AL_INVALID_VALUE, AL_FALSE, "NULL pointer"); size_t len{strlen(extName)}; +#if ALSOFT_EAX + if (al::strncasecmp(eax_v2_0_ext_name, extName, len) == 0 || + al::strncasecmp(eax_v3_0_ext_name, extName, len) == 0 || + al::strncasecmp(eax_v4_0_ext_name, extName, len) == 0 || + al::strncasecmp(eax_v5_0_ext_name, extName, len) == 0) + { + const auto is_present = eax_g_is_enabled && context->eax_is_capable(); + return is_present ? AL_TRUE : AL_FALSE; + } + + if (al::strncasecmp(eax_x_ram_ext_name, extName, len) == 0) + { + const auto is_present = eax_g_is_enabled; + return is_present ? AL_TRUE : AL_FALSE; + } +#endif // ALSOFT_EAX const char *ptr{context->mExtensionList}; while(ptr && *ptr) { @@ -66,6 +86,75 @@ AL_API ALvoid* AL_APIENTRY alGetProcAddress(const ALchar *funcName) START_API_FUNC { if(!funcName) return nullptr; +#if ALSOFT_EAX + if (al::strcasecmp(funcName, eax_eax_set_func_name) == 0) + { + if (!eax_g_is_enabled) + { + return nullptr; + } + + ContextRef context{GetContextRef()}; + + if (!context || !context->eax_is_capable()) + { + return nullptr; + } + + return reinterpret_cast(EAXSet); + } + + if (al::strcasecmp(funcName, eax_eax_get_func_name) == 0) + { + if (!eax_g_is_enabled) + { + return nullptr; + } + + ContextRef context{GetContextRef()}; + + if (!context || !context->eax_is_capable()) + { + return nullptr; + } + + return reinterpret_cast(EAXGet); + } + + if (al::strcasecmp(funcName, eax_eax_set_buffer_mode_func_name) == 0) + { + if (!eax_g_is_enabled) + { + return nullptr; + } + + ContextRef context{GetContextRef()}; + + if (!context) + { + return nullptr; + } + + return reinterpret_cast(EAXSetBufferMode); + } + + if (al::strcasecmp(funcName, eax_eax_get_buffer_mode_func_name) == 0) + { + if (!eax_g_is_enabled) + { + return nullptr; + } + + ContextRef context{GetContextRef()}; + + if (!context) + { + return nullptr; + } + + return reinterpret_cast(EAXGetBufferMode); + } +#endif // ALSOFT_EAX return alcGetProcAddress(nullptr, funcName); } END_API_FUNC @@ -74,6 +163,34 @@ AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *enumName) START_API_FUNC { if(!enumName) return static_cast(0); +#if ALSOFT_EAX + if (eax_g_is_enabled) + { + struct Descriptor + { + const char* name; + ALenum value; + }; // Descriptor + + constexpr Descriptor descriptors[] = + { + Descriptor{AL_EAX_RAM_SIZE_NAME, AL_EAX_RAM_SIZE}, + Descriptor{AL_EAX_RAM_FREE_NAME, AL_EAX_RAM_FREE}, + + Descriptor{AL_STORAGE_AUTOMATIC_NAME, AL_STORAGE_AUTOMATIC}, + Descriptor{AL_STORAGE_HARDWARE_NAME, AL_STORAGE_HARDWARE}, + Descriptor{AL_STORAGE_ACCESSIBLE_NAME, AL_STORAGE_ACCESSIBLE}, + }; // descriptors + + for (const auto& descriptor : descriptors) + { + if (strcmp(descriptor.name, enumName) == 0) + { + return descriptor.value; + } + } + } +#endif // ALSOFT_EAX return alcGetEnumValue(nullptr, enumName); } END_API_FUNC diff --git a/al/filter.cpp b/al/filter.cpp index 73067fd9..563fb3ef 100644 --- a/al/filter.cpp +++ b/al/filter.cpp @@ -45,6 +45,10 @@ #include "opthelpers.h" #include "vector.h" +#if ALSOFT_EAX +#include "core/logging.h" +#endif // ALSOFT_EAX + namespace { @@ -717,3 +721,80 @@ FilterSubList::~FilterSubList() al_free(Filters); Filters = nullptr; } + + +#if ALSOFT_EAX +EaxAlFilterDeleter::EaxAlFilterDeleter( + ALCcontext& context) + : + context_{&context} +{ +} + +void EaxAlFilterDeleter::operator()( + ALfilter* filter) +{ + eax_delete_low_pass_filter(*context_, *filter); +} + +EaxAlFilterUPtr eax_create_al_low_pass_filter( + ALCcontext& context) +{ +#define EAX_PREFIX "[EAX_MAKE_LOW_PASS_FILTER] " + + auto& device = *context.mALDevice; + std::lock_guard filter_lock{device.FilterLock}; + + if (!EnsureFilters(&device, 1)) + { + ERR(EAX_PREFIX "%s\n", "Failed to ensure."); + return nullptr; + } + + auto filter = EaxAlFilterUPtr{AllocFilter(&device), EaxAlFilterDeleter{context}}; + + if (!filter) + { + ERR(EAX_PREFIX "%s\n", "Failed to allocate."); + return nullptr; + } + + InitFilterParams(filter.get(), AL_FILTER_LOWPASS); + + return filter; + +#undef EAX_PREFIX +} + +void eax_delete_low_pass_filter( + ALCcontext& context, + ALfilter& filter) +{ + auto& device = *context.mALDevice; + std::lock_guard filter_lock{device.FilterLock}; + + FreeFilter(&device, &filter); +} + +void ALfilter::eax_set_low_pass_params( + ALCcontext& context, + const EaxAlLowPassParam& param) +{ +#define EAX_PREFIX "[EAX_SET_LOW_PASS_FILTER_PARAMS] " + + auto& device = *context.mALDevice; + std::lock_guard filter_lock{device.FilterLock}; + + try + { + setParamf(AL_LOWPASS_GAIN, param.gain); + setParamf(AL_LOWPASS_GAINHF, param.gain_hf); + } + catch (const filter_exception &e) + { + ERR(EAX_PREFIX "%s\n", e.what()); + } + +#undef EAX_PREFIX +} +#endif // ALSOFT_EAX diff --git a/al/filter.h b/al/filter.h index 123e64b0..222a6917 100644 --- a/al/filter.h +++ b/al/filter.h @@ -1,12 +1,18 @@ #ifndef AL_FILTER_H #define AL_FILTER_H + #include "AL/al.h" #include "AL/alc.h" #include "AL/alext.h" #include "almalloc.h" +#if ALSOFT_EAX +#include + +#include "eax_utils.h" +#endif // ALSOFT_EAX #define LOWPASSFREQREF 5000.0f #define HIGHPASSFREQREF 250.0f @@ -47,6 +53,40 @@ struct ALfilter { void getParamfv(ALenum param, float *values) const { vtab->getParamfv(this, param, values); } DISABLE_ALLOC() + +#if ALSOFT_EAX +public: + void eax_set_low_pass_params( + ALCcontext& context, + const EaxAlLowPassParam& param); +#endif // ALSOFT_EAX }; +#if ALSOFT_EAX +class EaxAlFilterDeleter +{ +public: + EaxAlFilterDeleter() noexcept = default; + + EaxAlFilterDeleter( + ALCcontext& context); + + + void operator()( + ALfilter* filter); + +private: + ALCcontext* context_{}; +}; // EaxAlFilterDeleter + +using EaxAlFilterUPtr = std::unique_ptr; + +EaxAlFilterUPtr eax_create_al_low_pass_filter( + ALCcontext& context); + +void eax_delete_low_pass_filter( + ALCcontext& context, + ALfilter& filter); +#endif // ALSOFT_EAX + #endif diff --git a/al/listener.cpp b/al/listener.cpp index 0997ff95..1909c644 100644 --- a/al/listener.cpp +++ b/al/listener.cpp @@ -450,3 +450,25 @@ void UpdateListenerProps(ALCcontext *context) AtomicReplaceHead(context->mFreeListenerProps, props); } } + +#if ALSOFT_EAX +// `alListenerf(AL_METERS_PER_UNIT, value)` +void eax_set_al_listener_meters_per_unit( + ALCcontext& al_context, + ALfloat meters_per_unit) +{ + auto context = EaxAlContextWrapper{al_context}; + + auto& listener = context->mListener; + + if (meters_per_unit < AL_MIN_METERS_PER_UNIT || + meters_per_unit > AL_MAX_METERS_PER_UNIT) + { + SETERR_RETURN(context, AL_INVALID_VALUE,, "Listener meters per unit out of range"); + } + + listener.mMetersPerUnit = meters_per_unit; + + DO_UPDATEPROPS(); +} +#endif // ALSOFT_EAX diff --git a/al/listener.h b/al/listener.h index f3332763..05cd3abf 100644 --- a/al/listener.h +++ b/al/listener.h @@ -29,4 +29,11 @@ struct ALlistener { void UpdateListenerProps(ALCcontext *context); +#if ALSOFT_EAX +// `alListenerf(AL_METERS_PER_UNIT, value)` +void eax_set_al_listener_meters_per_unit( + ALCcontext& al_context, + ALfloat meters_per_unit); +#endif // ALSOFT_EAX + #endif diff --git a/al/source.cpp b/al/source.cpp index f7b07338..3f7fa540 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -72,6 +72,10 @@ #include "ringbuffer.h" #include "threads.h" +#if ALSOFT_EAX +#include "eax_exception.h" +#include "eax_globals.h" +#endif // ALSOFT_EAX namespace { @@ -2414,16 +2418,52 @@ START_API_FUNC { ALsource *source{AllocSource(context.get())}; sources[0] = source->id; + +#if ALSOFT_EAX + if (context->has_eax()) + { + std::unique_lock prop_lock{context->mPropLock}; + context->eax_initialize_source(*source); + } +#endif // ALSOFT_EAX } else { +#if ALSOFT_EAX + auto eax_sources = al::vector{}; + + if (context->has_eax()) + { + eax_sources.reserve(static_cast(n)); + } +#endif // ALSOFT_EAX + al::vector ids; ids.reserve(static_cast(n)); do { ALsource *source{AllocSource(context.get())}; ids.emplace_back(source->id); + +#if ALSOFT_EAX + if (context->has_eax()) + { + eax_sources.emplace_back(source); + } +#endif // ALSOFT_EAX } while(--n); std::copy(ids.cbegin(), ids.cend(), sources); + +#if ALSOFT_EAX + if (context->has_eax()) + { + std::unique_lock prop_lock{context->mPropLock}; + + for (auto& eax_source : eax_sources) + { + context->eax_initialize_source(*eax_source); + } + } +#endif // ALSOFT_EAX } } END_API_FUNC @@ -3555,6 +3595,10 @@ ALsource::ALsource() ALsource::~ALsource() { +#if ALSOFT_EAX + eax_uninitialize(); +#endif // ALSOFT_EAX + for(auto &item : mQueue) { if(ALbuffer *buffer{item.mBuffer}) @@ -3597,3 +3641,2447 @@ SourceSubList::~SourceSubList() al_free(Sources); Sources = nullptr; } + + +#if ALSOFT_EAX +class EaxSourceException : + public EaxException +{ +public: + explicit EaxSourceException( + const char* message) + : + EaxException{"EAX_SOURCE", message} + { + } +}; // EaxSourceException + + +class EaxSourceActiveFxSlotsException : + public EaxException +{ +public: + explicit EaxSourceActiveFxSlotsException( + const char* message) + : + EaxException{"EAX_SOURCE_ACTIVE_FX_SLOTS", message} + { + } +}; // EaxSourceActiveFxSlotsException + + +class EaxSourceSendException : + public EaxException +{ +public: + explicit EaxSourceSendException( + const char* message) + : + EaxException{"EAX_SOURCE_SEND", message} + { + } +}; // EaxSourceSendException + + +void ALsource::eax_initialize( + const EaxSourceInitParam& param) noexcept +{ + eax_validate_init_param(param); + eax_copy_init_param(param); + eax_set_defaults(); + eax_initialize_fx_slots(); + + eax_d_ = eax_; +} + +void ALsource::eax_uninitialize() +{ + if (!eax_al_context_) + { + return; + } + + if (eax_al_context_->has_eax()) + { + for (auto i = 0; i < EAX_MAX_FXSLOTS; ++i) + { + eax_al_source_3i( + AL_AUXILIARY_SEND_FILTER, + AL_EFFECTSLOT_NULL, + static_cast(i), + AL_FILTER_NULL + ); + } + } + + eax_al_context_ = nullptr; +} + +void ALsource::eax_dispatch( + const EaxEaxCall& eax_call) +{ + if (eax_call.is_get()) + { + eax_get(eax_call); + } + else + { + eax_set(eax_call); + } +} + +void ALsource::eax_update_filters() +{ + eax_update_filters_internal(); +} + +void ALsource::eax_update( + EaxContextSharedDirtyFlags dirty_flags) +{ + if (dirty_flags.primary_fx_slot_id) + { + if (eax_uses_primary_id_) + { + eax_update_primary_fx_slot_id(); + } + } + + if (dirty_flags.air_absorption_hf) + { + eax_set_air_absorption_factor(); + } +} + +ALsource* ALsource::eax_lookup_source( + ALCcontext& al_context, + ALuint source_id) noexcept +{ + return LookupSource(&al_context, source_id); +} + +[[noreturn]] +void ALsource::eax_fail( + const char* message) +{ + throw EaxSourceException{message}; +} + +void ALsource::eax_validate_init_param( + const EaxSourceInitParam& param) +{ + if (!param.al_context) + { + eax_fail("Null context."); + } + + if (!param.al_filter) + { + eax_fail("Null filter."); + } +} + +void ALsource::eax_copy_init_param( + const EaxSourceInitParam& param) +{ + eax_al_context_ = param.al_context; + eax_al_filter_ = param.al_filter; +} + +void ALsource::eax_set_source_defaults() +{ + eax_.source.lDirect = EAXSOURCE_DEFAULTDIRECT; + eax_.source.lDirectHF = EAXSOURCE_DEFAULTDIRECTHF; + eax_.source.lRoom = EAXSOURCE_DEFAULTROOM; + eax_.source.lRoomHF = EAXSOURCE_DEFAULTROOMHF; + eax_.source.lObstruction = EAXSOURCE_DEFAULTOBSTRUCTION; + eax_.source.flObstructionLFRatio = EAXSOURCE_DEFAULTOBSTRUCTIONLFRATIO; + eax_.source.lOcclusion = EAXSOURCE_DEFAULTOCCLUSION; + eax_.source.flOcclusionLFRatio = EAXSOURCE_DEFAULTOCCLUSIONLFRATIO; + eax_.source.flOcclusionRoomRatio = EAXSOURCE_DEFAULTOCCLUSIONROOMRATIO; + eax_.source.flOcclusionDirectRatio = EAXSOURCE_DEFAULTOCCLUSIONDIRECTRATIO; + eax_.source.lExclusion = EAXSOURCE_DEFAULTEXCLUSION; + eax_.source.flExclusionLFRatio = EAXSOURCE_DEFAULTEXCLUSIONLFRATIO; + eax_.source.lOutsideVolumeHF = EAXSOURCE_DEFAULTOUTSIDEVOLUMEHF; + eax_.source.flDopplerFactor = EAXSOURCE_DEFAULTDOPPLERFACTOR; + eax_.source.flRolloffFactor = EAXSOURCE_DEFAULTROLLOFFFACTOR; + eax_.source.flRoomRolloffFactor = EAXSOURCE_DEFAULTROOMROLLOFFFACTOR; + eax_.source.flAirAbsorptionFactor = EAXSOURCE_DEFAULTAIRABSORPTIONFACTOR; + eax_.source.ulFlags = EAXSOURCE_DEFAULTFLAGS; +} + +void ALsource::eax_set_active_fx_slots_defaults() +{ + eax_.active_fx_slots = EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID; +} + +void ALsource::eax_set_send_defaults( + EAXSOURCEALLSENDPROPERTIES& eax_send) +{ + eax_send.guidReceivingFXSlotID = EAX_NULL_GUID; + eax_send.lSend = EAXSOURCE_DEFAULTSEND; + eax_send.lSendHF = EAXSOURCE_DEFAULTSENDHF; + eax_send.lOcclusion = EAXSOURCE_DEFAULTOCCLUSION; + eax_send.flOcclusionLFRatio = EAXSOURCE_DEFAULTOCCLUSIONLFRATIO; + eax_send.flOcclusionRoomRatio = EAXSOURCE_DEFAULTOCCLUSIONROOMRATIO; + eax_send.flOcclusionDirectRatio = EAXSOURCE_DEFAULTOCCLUSIONDIRECTRATIO; + eax_send.lExclusion = EAXSOURCE_DEFAULTEXCLUSION; + eax_send.flExclusionLFRatio = EAXSOURCE_DEFAULTEXCLUSIONLFRATIO; +} + +void ALsource::eax_set_sends_defaults() +{ + for (auto& eax_send : eax_.sends) + { + eax_set_send_defaults(eax_send); + } +} + +void ALsource::eax_set_speaker_levels_defaults() +{ + std::fill(eax_.speaker_levels.begin(), eax_.speaker_levels.end(), EAXSOURCE_DEFAULTSPEAKERLEVEL); +} + +void ALsource::eax_set_defaults() +{ + eax_set_source_defaults(); + eax_set_active_fx_slots_defaults(); + eax_set_sends_defaults(); + eax_set_speaker_levels_defaults(); +} + +float ALsource::eax_calculate_dst_occlusion_mb( + long src_occlusion_mb, + float path_ratio, + float lf_ratio) noexcept +{ + const auto ratio_1 = path_ratio + lf_ratio - 1.0F; + const auto ratio_2 = path_ratio * lf_ratio; + const auto ratio = (ratio_2 > ratio_1) ? ratio_2 : ratio_1; + const auto dst_occlustion_mb = static_cast(src_occlusion_mb) * ratio; + + return dst_occlustion_mb; +} + +EaxAlLowPassParam ALsource::eax_create_direct_filter_param() const noexcept +{ + auto gain_mb = + static_cast(eax_.source.lDirect) + + + (static_cast(eax_.source.lObstruction) * eax_.source.flObstructionLFRatio) + + + eax_calculate_dst_occlusion_mb( + eax_.source.lOcclusion, + eax_.source.flOcclusionDirectRatio, + eax_.source.flOcclusionLFRatio); + + auto gain_hf_mb = + static_cast(eax_.source.lDirectHF) + + + static_cast(eax_.source.lObstruction) + + + (static_cast(eax_.source.lOcclusion) * eax_.source.flOcclusionDirectRatio); + + for (auto i = std::size_t{}; i < EAX_MAX_FXSLOTS; ++i) + { + if (eax_active_fx_slots_[i]) + { + const auto& send = eax_.sends[i]; + + gain_mb += eax_calculate_dst_occlusion_mb( + send.lOcclusion, + send.flOcclusionDirectRatio, + send.flOcclusionLFRatio); + + gain_hf_mb += static_cast(send.lOcclusion) * send.flOcclusionDirectRatio; + } + } + + const auto max_gain = eax_al_context_->eax_get_max_filter_gain(); + + const auto al_low_pass_param = EaxAlLowPassParam + { + clamp(level_mb_to_gain(gain_mb), 0.0F, max_gain), + clamp(level_mb_to_gain(gain_hf_mb), 0.0F, max_gain) + }; + + return al_low_pass_param; +} + +EaxAlLowPassParam ALsource::eax_create_room_filter_param( + const ALeffectslot& fx_slot, + const EAXSOURCEALLSENDPROPERTIES& send) const noexcept +{ + const auto& fx_slot_eax = fx_slot.eax_get_eax_fx_slot(); + + const auto gain_mb = + static_cast( + eax_.source.lRoom + + send.lSend) + + + eax_calculate_dst_occlusion_mb( + eax_.source.lOcclusion, + eax_.source.flOcclusionRoomRatio, + eax_.source.flOcclusionLFRatio + ) + + + eax_calculate_dst_occlusion_mb( + send.lOcclusion, + send.flOcclusionRoomRatio, + send.flOcclusionLFRatio + ) + + + (static_cast(eax_.source.lExclusion) * eax_.source.flExclusionLFRatio) + + (static_cast(send.lExclusion) * send.flExclusionLFRatio) + + + 0.0F; + + const auto gain_hf_mb = + static_cast( + eax_.source.lRoomHF + + send.lSendHF) + + + (static_cast(fx_slot_eax.lOcclusion + eax_.source.lOcclusion) * eax_.source.flOcclusionRoomRatio) + + (static_cast(send.lOcclusion) * send.flOcclusionRoomRatio) + + + static_cast( + eax_.source.lExclusion + + send.lExclusion) + + + 0.0F; + + const auto max_gain = eax_al_context_->eax_get_max_filter_gain(); + + const auto al_low_pass_param = EaxAlLowPassParam + { + clamp(level_mb_to_gain(gain_mb), 0.0F, max_gain), + clamp(level_mb_to_gain(gain_hf_mb), 0.0F, max_gain) + }; + + return al_low_pass_param; +} + +void ALsource::eax_set_al_filter_parameters( + const EaxAlLowPassParam& al_low_pass_param) const noexcept +{ + eax_al_filter_->eax_set_low_pass_params(*eax_al_context_, al_low_pass_param); +} + +void ALsource::eax_set_fx_slots() +{ + eax_uses_primary_id_ = false; + eax_has_active_fx_slots_ = false; + + for (auto i = 0; i < EAX_MAX_FXSLOTS; ++i) + { + const auto& eax_active_fx_slot_id = eax_.active_fx_slots.guidActiveFXSlots[i]; + + auto fx_slot_index = EaxFxSlotIndex{}; + + if (eax_active_fx_slot_id == EAX_PrimaryFXSlotID) + { + eax_uses_primary_id_ = true; + fx_slot_index = eax_al_context_->eax_get_primary_fx_slot_index(); + } + else + { + fx_slot_index = eax_active_fx_slot_id; + } + + if (fx_slot_index.has_value()) + { + eax_has_active_fx_slots_ = true; + eax_active_fx_slots_[fx_slot_index] = true; + } + } + + for (auto i = 0; i < EAX_MAX_FXSLOTS; ++i) + { + if (!eax_active_fx_slots_[static_cast(i)]) + { + eax_al_source_3i( + AL_AUXILIARY_SEND_FILTER, + AL_EFFECTSLOT_NULL, + i, + AL_FILTER_NULL); + } + } +} + +void ALsource::eax_initialize_fx_slots() +{ + eax_set_fx_slots(); + eax_update_filters_internal(); +} + +void ALsource::eax_update_direct_filter_internal() +{ + const auto& direct_param = eax_create_direct_filter_param(); + eax_set_al_filter_parameters(direct_param); + + eax_al_source_i( + AL_DIRECT_FILTER, + static_cast(eax_al_filter_->id)); +} + +void ALsource::eax_update_room_filters_internal() +{ + if (!eax_has_active_fx_slots_) + { + return; + } + + for (auto i = 0; i < EAX_MAX_FXSLOTS; ++i) + { + if (eax_active_fx_slots_[static_cast(i)]) + { + const auto& fx_slot = eax_al_context_->eax_get_fx_slot(static_cast(i)); + const auto& send = eax_.sends[static_cast(i)]; + const auto& room_param = eax_create_room_filter_param(fx_slot, send); + + eax_set_al_filter_parameters(room_param); + + eax_al_source_3i( + AL_AUXILIARY_SEND_FILTER, + static_cast(fx_slot.id), + i, + static_cast(eax_al_filter_->id) + ); + } + } +} + +void ALsource::eax_update_filters_internal() +{ + eax_update_direct_filter_internal(); + eax_update_room_filters_internal(); +} + +void ALsource::eax_update_primary_fx_slot_id() +{ + const auto& previous_primary_fx_slot_index = eax_al_context_->eax_get_previous_primary_fx_slot_index(); + const auto& primary_fx_slot_index = eax_al_context_->eax_get_primary_fx_slot_index(); + + if (previous_primary_fx_slot_index == primary_fx_slot_index) + { + return; + } + + if (previous_primary_fx_slot_index.has_value()) + { + const auto fx_slot_index = previous_primary_fx_slot_index.get(); + eax_active_fx_slots_[fx_slot_index] = false; + + eax_al_source_3i( + AL_AUXILIARY_SEND_FILTER, + AL_EFFECTSLOT_NULL, + static_cast(fx_slot_index), + static_cast(AL_FILTER_NULL)); + } + + if (primary_fx_slot_index.has_value()) + { + const auto fx_slot_index = primary_fx_slot_index.get(); + eax_active_fx_slots_[fx_slot_index] = true; + + const auto& fx_slot = eax_al_context_->eax_get_fx_slot(fx_slot_index); + const auto& send = eax_.sends[fx_slot_index]; + const auto& room_param = eax_create_room_filter_param(fx_slot, send); + + eax_set_al_filter_parameters(room_param); + + eax_al_source_3i( + AL_AUXILIARY_SEND_FILTER, + static_cast(fx_slot.id), + static_cast(fx_slot_index), + static_cast(eax_al_filter_->id)); + } + + eax_has_active_fx_slots_ = std::any_of( + eax_active_fx_slots_.cbegin(), + eax_active_fx_slots_.cend(), + [](const auto& item) + { + return item; + } + ); +} + +void ALsource::eax_defer_active_fx_slots( + const EaxEaxCall& eax_call) +{ + const auto active_fx_slots_span = + eax_call.get_values(); + + const auto fx_slot_count = active_fx_slots_span.size(); + + if (fx_slot_count <= 0 || fx_slot_count > EAX_MAX_FXSLOTS) + { + throw EaxSourceActiveFxSlotsException{"Count out of range."}; + } + + for (auto i = std::size_t{}; i < fx_slot_count; ++i) + { + const auto& fx_slot_guid = active_fx_slots_span[i]; + + if (fx_slot_guid != EAX_NULL_GUID && + fx_slot_guid != EAX_PrimaryFXSlotID && + fx_slot_guid != EAXPROPERTYID_EAX40_FXSlot0 && + fx_slot_guid != EAXPROPERTYID_EAX50_FXSlot0 && + fx_slot_guid != EAXPROPERTYID_EAX40_FXSlot1 && + fx_slot_guid != EAXPROPERTYID_EAX50_FXSlot1 && + fx_slot_guid != EAXPROPERTYID_EAX40_FXSlot2 && + fx_slot_guid != EAXPROPERTYID_EAX50_FXSlot2 && + fx_slot_guid != EAXPROPERTYID_EAX40_FXSlot3 && + fx_slot_guid != EAXPROPERTYID_EAX50_FXSlot3) + { + throw EaxSourceActiveFxSlotsException{"Unsupported GUID."}; + } + } + + for (auto i = std::size_t{}; i < fx_slot_count; ++i) + { + eax_d_.active_fx_slots.guidActiveFXSlots[i] = active_fx_slots_span[i]; + } + + for (auto i = fx_slot_count; i < EAX_MAX_FXSLOTS; ++i) + { + eax_d_.active_fx_slots.guidActiveFXSlots[i] = EAX_NULL_GUID; + } + + eax_are_active_fx_slots_dirty_ = (eax_d_.active_fx_slots != eax_.active_fx_slots); +} + + +const char* ALsource::eax_get_exclusion_name() noexcept +{ + return "Exclusion"; +} + +const char* ALsource::eax_get_exclusion_lf_ratio_name() noexcept +{ + return "Exclusion LF Ratio"; +} + +const char* ALsource::eax_get_occlusion_name() noexcept +{ + return "Occlusion"; +} + +const char* ALsource::eax_get_occlusion_lf_ratio_name() noexcept +{ + return "Occlusion LF Ratio"; +} + +const char* ALsource::eax_get_occlusion_direct_ratio_name() noexcept +{ + return "Occlusion Direct Ratio"; +} + +const char* ALsource::eax_get_occlusion_room_ratio_name() noexcept +{ + return "Occlusion Room Ratio"; +} + + +void ALsource::eax_validate_send_receiving_fx_slot_guid( + const GUID& guidReceivingFXSlotID) +{ + if (guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot0 && + guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot0 && + guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot1 && + guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot1 && + guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot2 && + guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot2 && + guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot3 && + guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot3) + { + throw EaxSourceSendException{"Unsupported receiving FX slot GUID."}; + } +} + +void ALsource::eax_validate_send_send( + long lSend) +{ + eax_validate_range( + "Send", + lSend, + EAXSOURCE_MINSEND, + EAXSOURCE_MAXSEND); +} + +void ALsource::eax_validate_send_send_hf( + long lSendHF) +{ + eax_validate_range( + "Send HF", + lSendHF, + EAXSOURCE_MINSENDHF, + EAXSOURCE_MAXSENDHF); +} + +void ALsource::eax_validate_send_occlusion( + long lOcclusion) +{ + eax_validate_range( + eax_get_occlusion_name(), + lOcclusion, + EAXSOURCE_MINOCCLUSION, + EAXSOURCE_MAXOCCLUSION); +} + +void ALsource::eax_validate_send_occlusion_lf_ratio( + float flOcclusionLFRatio) +{ + eax_validate_range( + eax_get_occlusion_lf_ratio_name(), + flOcclusionLFRatio, + EAXSOURCE_MINOCCLUSIONLFRATIO, + EAXSOURCE_MAXOCCLUSIONLFRATIO); +} + +void ALsource::eax_validate_send_occlusion_room_ratio( + float flOcclusionRoomRatio) +{ + eax_validate_range( + eax_get_occlusion_room_ratio_name(), + flOcclusionRoomRatio, + EAXSOURCE_MINOCCLUSIONROOMRATIO, + EAXSOURCE_MAXOCCLUSIONROOMRATIO); +} + +void ALsource::eax_validate_send_occlusion_direct_ratio( + float flOcclusionDirectRatio) +{ + eax_validate_range( + eax_get_occlusion_direct_ratio_name(), + flOcclusionDirectRatio, + EAXSOURCE_MINOCCLUSIONDIRECTRATIO, + EAXSOURCE_MAXOCCLUSIONDIRECTRATIO); +} + +void ALsource::eax_validate_send_exclusion( + long lExclusion) +{ + eax_validate_range( + eax_get_exclusion_name(), + lExclusion, + EAXSOURCE_MINEXCLUSION, + EAXSOURCE_MAXEXCLUSION); +} + +void ALsource::eax_validate_send_exclusion_lf_ratio( + float flExclusionLFRatio) +{ + eax_validate_range( + eax_get_exclusion_lf_ratio_name(), + flExclusionLFRatio, + EAXSOURCE_MINEXCLUSIONLFRATIO, + EAXSOURCE_MAXEXCLUSIONLFRATIO); +} + +void ALsource::eax_validate_send( + const EAXSOURCESENDPROPERTIES& all) +{ + eax_validate_send_receiving_fx_slot_guid(all.guidReceivingFXSlotID); + eax_validate_send_send(all.lSend); + eax_validate_send_send_hf(all.lSendHF); +} + +void ALsource::eax_validate_send_exclusion_all( + const EAXSOURCEEXCLUSIONSENDPROPERTIES& all) +{ + eax_validate_send_receiving_fx_slot_guid(all.guidReceivingFXSlotID); + eax_validate_send_exclusion(all.lExclusion); + eax_validate_send_exclusion_lf_ratio(all.flExclusionLFRatio); +} + +void ALsource::eax_validate_send_occlusion_all( + const EAXSOURCEOCCLUSIONSENDPROPERTIES& all) +{ + eax_validate_send_receiving_fx_slot_guid(all.guidReceivingFXSlotID); + eax_validate_send_occlusion(all.lOcclusion); + eax_validate_send_occlusion_lf_ratio(all.flOcclusionLFRatio); + eax_validate_send_occlusion_room_ratio(all.flOcclusionRoomRatio); + eax_validate_send_occlusion_direct_ratio(all.flOcclusionDirectRatio); +} + +void ALsource::eax_validate_send_all( + const EAXSOURCEALLSENDPROPERTIES& all) +{ + eax_validate_send_receiving_fx_slot_guid(all.guidReceivingFXSlotID); + eax_validate_send_send(all.lSend); + eax_validate_send_send_hf(all.lSendHF); + eax_validate_send_occlusion(all.lOcclusion); + eax_validate_send_occlusion_lf_ratio(all.flOcclusionLFRatio); + eax_validate_send_occlusion_room_ratio(all.flOcclusionRoomRatio); + eax_validate_send_occlusion_direct_ratio(all.flOcclusionDirectRatio); + eax_validate_send_exclusion(all.lExclusion); + eax_validate_send_exclusion_lf_ratio(all.flExclusionLFRatio); +} + +EaxFxSlotIndexValue ALsource::eax_get_send_index( + const GUID& send_guid) +{ + if (false) + { + } + else if (send_guid == EAXPROPERTYID_EAX40_FXSlot0 || send_guid == EAXPROPERTYID_EAX50_FXSlot0) + { + return 0; + } + else if (send_guid == EAXPROPERTYID_EAX40_FXSlot1 || send_guid == EAXPROPERTYID_EAX50_FXSlot1) + { + return 1; + } + else if (send_guid == EAXPROPERTYID_EAX40_FXSlot2 || send_guid == EAXPROPERTYID_EAX50_FXSlot2) + { + return 2; + } + else if (send_guid == EAXPROPERTYID_EAX40_FXSlot3 || send_guid == EAXPROPERTYID_EAX50_FXSlot3) + { + return 3; + } + else + { + throw EaxSourceSendException{"Unsupported receiving FX slot GUID."}; + } +} + +void ALsource::eax_defer_send_send( + long lSend, + EaxFxSlotIndexValue index) +{ + eax_d_.sends[index].lSend = lSend; + + eax_sends_dirty_flags_.sends[index].lSend = + (eax_.sends[index].lSend != eax_d_.sends[index].lSend); +} + +void ALsource::eax_defer_send_send_hf( + long lSendHF, + EaxFxSlotIndexValue index) +{ + eax_d_.sends[index].lSendHF = lSendHF; + + eax_sends_dirty_flags_.sends[index].lSendHF = + (eax_.sends[index].lSendHF != eax_d_.sends[index].lSendHF); +} + +void ALsource::eax_defer_send_occlusion( + long lOcclusion, + EaxFxSlotIndexValue index) +{ + eax_d_.sends[index].lOcclusion = lOcclusion; + + eax_sends_dirty_flags_.sends[index].lOcclusion = + (eax_.sends[index].lOcclusion != eax_d_.sends[index].lOcclusion); +} + +void ALsource::eax_defer_send_occlusion_lf_ratio( + float flOcclusionLFRatio, + EaxFxSlotIndexValue index) +{ + eax_d_.sends[index].flOcclusionLFRatio = flOcclusionLFRatio; + + eax_sends_dirty_flags_.sends[index].flOcclusionLFRatio = + (eax_.sends[index].flOcclusionLFRatio != eax_d_.sends[index].flOcclusionLFRatio); +} + +void ALsource::eax_defer_send_occlusion_room_ratio( + float flOcclusionRoomRatio, + EaxFxSlotIndexValue index) +{ + eax_d_.sends[index].flOcclusionRoomRatio = flOcclusionRoomRatio; + + eax_sends_dirty_flags_.sends[index].flOcclusionRoomRatio = + (eax_.sends[index].flOcclusionRoomRatio != eax_d_.sends[index].flOcclusionRoomRatio); +} + +void ALsource::eax_defer_send_occlusion_direct_ratio( + float flOcclusionDirectRatio, + EaxFxSlotIndexValue index) +{ + eax_d_.sends[index].flOcclusionDirectRatio = flOcclusionDirectRatio; + + eax_sends_dirty_flags_.sends[index].flOcclusionDirectRatio = + (eax_.sends[index].flOcclusionDirectRatio != eax_d_.sends[index].flOcclusionDirectRatio); +} + +void ALsource::eax_defer_send_exclusion( + long lExclusion, + EaxFxSlotIndexValue index) +{ + eax_d_.sends[index].lExclusion = lExclusion; + + eax_sends_dirty_flags_.sends[index].lExclusion = + (eax_.sends[index].lExclusion != eax_d_.sends[index].lExclusion); +} + +void ALsource::eax_defer_send_exclusion_lf_ratio( + float flExclusionLFRatio, + EaxFxSlotIndexValue index) +{ + eax_d_.sends[index].flExclusionLFRatio = flExclusionLFRatio; + + eax_sends_dirty_flags_.sends[index].flExclusionLFRatio = + (eax_.sends[index].flExclusionLFRatio != eax_d_.sends[index].flExclusionLFRatio); +} + +void ALsource::eax_defer_send( + const EAXSOURCESENDPROPERTIES& all, + EaxFxSlotIndexValue index) +{ + eax_defer_send_send(all.lSend, index); + eax_defer_send_send_hf(all.lSendHF, index); +} + +void ALsource::eax_defer_send_exclusion_all( + const EAXSOURCEEXCLUSIONSENDPROPERTIES& all, + EaxFxSlotIndexValue index) +{ + eax_defer_send_exclusion(all.lExclusion, index); + eax_defer_send_exclusion_lf_ratio(all.flExclusionLFRatio, index); +} + +void ALsource::eax_defer_send_occlusion_all( + const EAXSOURCEOCCLUSIONSENDPROPERTIES& all, + EaxFxSlotIndexValue index) +{ + eax_defer_send_occlusion(all.lOcclusion, index); + eax_defer_send_occlusion_lf_ratio(all.flOcclusionLFRatio, index); + eax_defer_send_occlusion_room_ratio(all.flOcclusionRoomRatio, index); + eax_defer_send_occlusion_direct_ratio(all.flOcclusionDirectRatio, index); +} + +void ALsource::eax_defer_send_all( + const EAXSOURCEALLSENDPROPERTIES& all, + EaxFxSlotIndexValue index) +{ + eax_defer_send_send(all.lSend, index); + eax_defer_send_send_hf(all.lSendHF, index); + eax_defer_send_occlusion(all.lOcclusion, index); + eax_defer_send_occlusion_lf_ratio(all.flOcclusionLFRatio, index); + eax_defer_send_occlusion_room_ratio(all.flOcclusionRoomRatio, index); + eax_defer_send_occlusion_direct_ratio(all.flOcclusionDirectRatio, index); + eax_defer_send_exclusion(all.lExclusion, index); + eax_defer_send_exclusion_lf_ratio(all.flExclusionLFRatio, index); +} + +void ALsource::eax_defer_send( + const EaxEaxCall& eax_call) +{ + const auto eax_all_span = + eax_call.get_values(); + + const auto count = eax_all_span.size(); + + if (count <= 0 || count > EAX_MAX_FXSLOTS) + { + throw EaxSourceSendException{"Send count out of range."}; + } + + for (auto i = std::size_t{}; i < count; ++i) + { + const auto& all = eax_all_span[i]; + eax_validate_send(all); + } + + for (auto i = std::size_t{}; i < count; ++i) + { + const auto& all = eax_all_span[i]; + const auto send_index = eax_get_send_index(all.guidReceivingFXSlotID); + eax_defer_send(all, send_index); + } +} + +void ALsource::eax_defer_send_exclusion_all( + const EaxEaxCall& eax_call) +{ + const auto eax_all_span = + eax_call.get_values(); + + const auto count = eax_all_span.size(); + + if (count <= 0 || count > EAX_MAX_FXSLOTS) + { + throw EaxSourceSendException{"Send exclusion all count out of range."}; + } + + for (auto i = std::size_t{}; i < count; ++i) + { + const auto& all = eax_all_span[i]; + eax_validate_send_exclusion_all(all); + } + + for (auto i = std::size_t{}; i < count; ++i) + { + const auto& all = eax_all_span[i]; + const auto send_index = eax_get_send_index(all.guidReceivingFXSlotID); + eax_defer_send_exclusion_all(all, send_index); + } +} + +void ALsource::eax_defer_send_occlusion_all( + const EaxEaxCall& eax_call) +{ + const auto eax_all_span = + eax_call.get_values(); + + const auto count = eax_all_span.size(); + + if (count <= 0 || count > EAX_MAX_FXSLOTS) + { + throw EaxSourceSendException{"Send occlusion all count out of range."}; + } + + for (auto i = std::size_t{}; i < count; ++i) + { + const auto& all = eax_all_span[i]; + eax_validate_send_occlusion_all(all); + } + + for (auto i = std::size_t{}; i < count; ++i) + { + const auto& all = eax_all_span[i]; + const auto send_index = eax_get_send_index(all.guidReceivingFXSlotID); + eax_defer_send_occlusion_all(all, send_index); + } +} + +void ALsource::eax_defer_send_all( + const EaxEaxCall& eax_call) +{ + const auto eax_all_span = + eax_call.get_values(); + + const auto count = eax_all_span.size(); + + if (count <= 0 || count > EAX_MAX_FXSLOTS) + { + throw EaxSourceSendException{"Send all count out of range."}; + } + + for (auto i = std::size_t{}; i < count; ++i) + { + const auto& all = eax_all_span[i]; + eax_validate_send_all(all); + } + + for (auto i = std::size_t{}; i < count; ++i) + { + const auto& all = eax_all_span[i]; + const auto send_index = eax_get_send_index(all.guidReceivingFXSlotID); + eax_defer_send_all(all, send_index); + } +} + + +void ALsource::eax_validate_source_direct( + long direct) +{ + eax_validate_range( + "Direct", + direct, + EAXSOURCE_MINDIRECT, + EAXSOURCE_MAXDIRECT); +} + +void ALsource::eax_validate_source_direct_hf( + long direct_hf) +{ + eax_validate_range( + "Direct HF", + direct_hf, + EAXSOURCE_MINDIRECTHF, + EAXSOURCE_MAXDIRECTHF); +} + +void ALsource::eax_validate_source_room( + long room) +{ + eax_validate_range( + "Room", + room, + EAXSOURCE_MINROOM, + EAXSOURCE_MAXROOM); +} + +void ALsource::eax_validate_source_room_hf( + long room_hf) +{ + eax_validate_range( + "Room HF", + room_hf, + EAXSOURCE_MINROOMHF, + EAXSOURCE_MAXROOMHF); +} + +void ALsource::eax_validate_source_obstruction( + long obstruction) +{ + eax_validate_range( + "Obstruction", + obstruction, + EAXSOURCE_MINOBSTRUCTION, + EAXSOURCE_MAXOBSTRUCTION); +} + +void ALsource::eax_validate_source_obstruction_lf_ratio( + float obstruction_lf_ratio) +{ + eax_validate_range( + "Obstruction LF Ratio", + obstruction_lf_ratio, + EAXSOURCE_MINOBSTRUCTIONLFRATIO, + EAXSOURCE_MAXOBSTRUCTIONLFRATIO); +} + +void ALsource::eax_validate_source_occlusion( + long occlusion) +{ + eax_validate_range( + eax_get_occlusion_name(), + occlusion, + EAXSOURCE_MINOCCLUSION, + EAXSOURCE_MAXOCCLUSION); +} + +void ALsource::eax_validate_source_occlusion_lf_ratio( + float occlusion_lf_ratio) +{ + eax_validate_range( + eax_get_occlusion_lf_ratio_name(), + occlusion_lf_ratio, + EAXSOURCE_MINOCCLUSIONLFRATIO, + EAXSOURCE_MAXOCCLUSIONLFRATIO); +} + +void ALsource::eax_validate_source_occlusion_room_ratio( + float occlusion_room_ratio) +{ + eax_validate_range( + eax_get_occlusion_room_ratio_name(), + occlusion_room_ratio, + EAXSOURCE_MINOCCLUSIONROOMRATIO, + EAXSOURCE_MAXOCCLUSIONROOMRATIO); +} + +void ALsource::eax_validate_source_occlusion_direct_ratio( + float occlusion_direct_ratio) +{ + eax_validate_range( + eax_get_occlusion_direct_ratio_name(), + occlusion_direct_ratio, + EAXSOURCE_MINOCCLUSIONDIRECTRATIO, + EAXSOURCE_MAXOCCLUSIONDIRECTRATIO); +} + +void ALsource::eax_validate_source_exclusion( + long exclusion) +{ + eax_validate_range( + eax_get_exclusion_name(), + exclusion, + EAXSOURCE_MINEXCLUSION, + EAXSOURCE_MAXEXCLUSION); +} + +void ALsource::eax_validate_source_exclusion_lf_ratio( + float exclusion_lf_ratio) +{ + eax_validate_range( + eax_get_exclusion_lf_ratio_name(), + exclusion_lf_ratio, + EAXSOURCE_MINEXCLUSIONLFRATIO, + EAXSOURCE_MAXEXCLUSIONLFRATIO); +} + +void ALsource::eax_validate_source_outside_volume_hf( + long outside_volume_hf) +{ + eax_validate_range( + "Outside Volume HF", + outside_volume_hf, + EAXSOURCE_MINOUTSIDEVOLUMEHF, + EAXSOURCE_MAXOUTSIDEVOLUMEHF); +} + +void ALsource::eax_validate_source_doppler_factor( + float doppler_factor) +{ + eax_validate_range( + "Doppler Factor", + doppler_factor, + EAXSOURCE_MINDOPPLERFACTOR, + EAXSOURCE_MAXDOPPLERFACTOR); +} + +void ALsource::eax_validate_source_rolloff_factor( + float rolloff_factor) +{ + eax_validate_range( + "Rolloff Factor", + rolloff_factor, + EAXSOURCE_MINROLLOFFFACTOR, + EAXSOURCE_MAXROLLOFFFACTOR); +} + +void ALsource::eax_validate_source_room_rolloff_factor( + float room_rolloff_factor) +{ + eax_validate_range( + "Room Rolloff Factor", + room_rolloff_factor, + EAXSOURCE_MINROOMROLLOFFFACTOR, + EAXSOURCE_MAXROOMROLLOFFFACTOR); +} + +void ALsource::eax_validate_source_air_absorption_factor( + float air_absorption_factor) +{ + eax_validate_range( + "Air Absorption Factor", + air_absorption_factor, + EAXSOURCE_MINAIRABSORPTIONFACTOR, + EAXSOURCE_MAXAIRABSORPTIONFACTOR); +} + +void ALsource::eax_validate_source_flags( + unsigned long flags, + int eax_version) +{ + eax_validate_range( + "Flags", + flags, + 0UL, + ~((eax_version == 5) ? EAX50SOURCEFLAGS_RESERVED : EAX20SOURCEFLAGS_RESERVED)); +} + +void ALsource::eax_validate_source_macro_fx_factor( + float macro_fx_factor) +{ + eax_validate_range( + "Macro FX Factor", + macro_fx_factor, + EAXSOURCE_MINMACROFXFACTOR, + EAXSOURCE_MAXMACROFXFACTOR); +} + +void ALsource::eax_validate_source_2d_all( + const EAXSOURCE2DPROPERTIES& all, + int eax_version) +{ + eax_validate_source_direct(all.lDirect); + eax_validate_source_direct_hf(all.lDirectHF); + eax_validate_source_room(all.lRoom); + eax_validate_source_room_hf(all.lRoomHF); + eax_validate_source_flags(all.ulFlags, eax_version); +} + +void ALsource::eax_validate_source_obstruction_all( + const EAXOBSTRUCTIONPROPERTIES& all) +{ + eax_validate_source_obstruction(all.lObstruction); + eax_validate_source_obstruction_lf_ratio(all.flObstructionLFRatio); +} + +void ALsource::eax_validate_source_exclusion_all( + const EAXEXCLUSIONPROPERTIES& all) +{ + eax_validate_source_exclusion(all.lExclusion); + eax_validate_source_exclusion_lf_ratio(all.flExclusionLFRatio); +} + +void ALsource::eax_validate_source_occlusion_all( + const EAXOCCLUSIONPROPERTIES& all) +{ + eax_validate_source_occlusion(all.lOcclusion); + eax_validate_source_occlusion_lf_ratio(all.flOcclusionLFRatio); + eax_validate_source_occlusion_room_ratio(all.flOcclusionRoomRatio); + eax_validate_source_occlusion_direct_ratio(all.flOcclusionDirectRatio); +} + +void ALsource::eax_validate_source_all( + const EAX20BUFFERPROPERTIES& all, + int eax_version) +{ + eax_validate_source_direct(all.lDirect); + eax_validate_source_direct_hf(all.lDirectHF); + eax_validate_source_room(all.lRoom); + eax_validate_source_room_hf(all.lRoomHF); + eax_validate_source_obstruction(all.lObstruction); + eax_validate_source_obstruction_lf_ratio(all.flObstructionLFRatio); + eax_validate_source_occlusion(all.lOcclusion); + eax_validate_source_occlusion_lf_ratio(all.flOcclusionLFRatio); + eax_validate_source_occlusion_room_ratio(all.flOcclusionRoomRatio); + eax_validate_source_outside_volume_hf(all.lOutsideVolumeHF); + eax_validate_source_room_rolloff_factor(all.flRoomRolloffFactor); + eax_validate_source_air_absorption_factor(all.flAirAbsorptionFactor); + eax_validate_source_flags(all.dwFlags, eax_version); +} + +void ALsource::eax_validate_source_all( + const EAX30SOURCEPROPERTIES& all, + int eax_version) +{ + eax_validate_source_direct(all.lDirect); + eax_validate_source_direct_hf(all.lDirectHF); + eax_validate_source_room(all.lRoom); + eax_validate_source_room_hf(all.lRoomHF); + eax_validate_source_obstruction(all.lObstruction); + eax_validate_source_obstruction_lf_ratio(all.flObstructionLFRatio); + eax_validate_source_occlusion(all.lOcclusion); + eax_validate_source_occlusion_lf_ratio(all.flOcclusionLFRatio); + eax_validate_source_occlusion_room_ratio(all.flOcclusionRoomRatio); + eax_validate_source_occlusion_direct_ratio(all.flOcclusionDirectRatio); + eax_validate_source_exclusion(all.lExclusion); + eax_validate_source_exclusion_lf_ratio(all.flExclusionLFRatio); + eax_validate_source_outside_volume_hf(all.lOutsideVolumeHF); + eax_validate_source_doppler_factor(all.flDopplerFactor); + eax_validate_source_rolloff_factor(all.flRolloffFactor); + eax_validate_source_room_rolloff_factor(all.flRoomRolloffFactor); + eax_validate_source_air_absorption_factor(all.flAirAbsorptionFactor); + eax_validate_source_flags(all.ulFlags, eax_version); +} + +void ALsource::eax_validate_source_all( + const EAX50SOURCEPROPERTIES& all, + int eax_version) +{ + eax_validate_source_all(static_cast(all), eax_version); + eax_validate_source_macro_fx_factor(all.flMacroFXFactor); +} + +void ALsource::eax_validate_source_speaker_id( + long speaker_id) +{ + eax_validate_range( + "Speaker Id", + speaker_id, + static_cast(EAXSPEAKER_FRONT_LEFT), + static_cast(EAXSPEAKER_LOW_FREQUENCY)); +} + +void ALsource::eax_validate_source_speaker_level( + long speaker_level) +{ + eax_validate_range( + "Speaker Level", + speaker_level, + EAXSOURCE_MINSPEAKERLEVEL, + EAXSOURCE_MAXSPEAKERLEVEL); +} + +void ALsource::eax_validate_source_speaker_level_all( + const EAXSPEAKERLEVELPROPERTIES& all) +{ + eax_validate_source_speaker_id(all.lSpeakerID); + eax_validate_source_speaker_level(all.lLevel); +} + +void ALsource::eax_defer_source_direct( + long lDirect) +{ + eax_d_.source.lDirect = lDirect; + eax_source_dirty_filter_flags_.lDirect = (eax_.source.lDirect != eax_d_.source.lDirect); +} + +void ALsource::eax_defer_source_direct_hf( + long lDirectHF) +{ + eax_d_.source.lDirectHF = lDirectHF; + eax_source_dirty_filter_flags_.lDirectHF = (eax_.source.lDirectHF != eax_d_.source.lDirectHF); +} + +void ALsource::eax_defer_source_room( + long lRoom) +{ + eax_d_.source.lRoom = lRoom; + eax_source_dirty_filter_flags_.lRoom = (eax_.source.lRoom != eax_d_.source.lRoom); +} + +void ALsource::eax_defer_source_room_hf( + long lRoomHF) +{ + eax_d_.source.lRoomHF = lRoomHF; + eax_source_dirty_filter_flags_.lRoomHF = (eax_.source.lRoomHF != eax_d_.source.lRoomHF); +} + +void ALsource::eax_defer_source_obstruction( + long lObstruction) +{ + eax_d_.source.lObstruction = lObstruction; + eax_source_dirty_filter_flags_.lObstruction = (eax_.source.lObstruction != eax_d_.source.lObstruction); +} + +void ALsource::eax_defer_source_obstruction_lf_ratio( + float flObstructionLFRatio) +{ + eax_d_.source.flObstructionLFRatio = flObstructionLFRatio; + eax_source_dirty_filter_flags_.flObstructionLFRatio = (eax_.source.flObstructionLFRatio != eax_d_.source.flObstructionLFRatio); +} + +void ALsource::eax_defer_source_occlusion( + long lOcclusion) +{ + eax_d_.source.lOcclusion = lOcclusion; + eax_source_dirty_filter_flags_.lOcclusion = (eax_.source.lOcclusion != eax_d_.source.lOcclusion); +} + +void ALsource::eax_defer_source_occlusion_lf_ratio( + float flOcclusionLFRatio) +{ + eax_d_.source.flOcclusionLFRatio = flOcclusionLFRatio; + eax_source_dirty_filter_flags_.flOcclusionLFRatio = (eax_.source.flOcclusionLFRatio != eax_d_.source.flOcclusionLFRatio); +} + +void ALsource::eax_defer_source_occlusion_room_ratio( + float flOcclusionRoomRatio) +{ + eax_d_.source.flOcclusionRoomRatio = flOcclusionRoomRatio; + eax_source_dirty_filter_flags_.flOcclusionRoomRatio = (eax_.source.flOcclusionRoomRatio != eax_d_.source.flOcclusionRoomRatio); +} + +void ALsource::eax_defer_source_occlusion_direct_ratio( + float flOcclusionDirectRatio) +{ + eax_d_.source.flOcclusionDirectRatio = flOcclusionDirectRatio; + eax_source_dirty_filter_flags_.flOcclusionDirectRatio = (eax_.source.flOcclusionDirectRatio != eax_d_.source.flOcclusionDirectRatio); +} + +void ALsource::eax_defer_source_exclusion( + long lExclusion) +{ + eax_d_.source.lExclusion = lExclusion; + eax_source_dirty_filter_flags_.lExclusion = (eax_.source.lExclusion != eax_d_.source.lExclusion); +} + +void ALsource::eax_defer_source_exclusion_lf_ratio( + float flExclusionLFRatio) +{ + eax_d_.source.flExclusionLFRatio = flExclusionLFRatio; + eax_source_dirty_filter_flags_.flExclusionLFRatio = (eax_.source.flExclusionLFRatio != eax_d_.source.flExclusionLFRatio); +} + +void ALsource::eax_defer_source_outside_volume_hf( + long lOutsideVolumeHF) +{ + eax_d_.source.lOutsideVolumeHF = lOutsideVolumeHF; + eax_source_dirty_misc_flags_.lOutsideVolumeHF = (eax_.source.lOutsideVolumeHF != eax_d_.source.lOutsideVolumeHF); +} + +void ALsource::eax_defer_source_doppler_factor( + float flDopplerFactor) +{ + eax_d_.source.flDopplerFactor = flDopplerFactor; + eax_source_dirty_misc_flags_.flDopplerFactor = (eax_.source.flDopplerFactor != eax_d_.source.flDopplerFactor); +} + +void ALsource::eax_defer_source_rolloff_factor( + float flRolloffFactor) +{ + eax_d_.source.flRolloffFactor = flRolloffFactor; + eax_source_dirty_misc_flags_.flRolloffFactor = (eax_.source.flRolloffFactor != eax_d_.source.flRolloffFactor); +} + +void ALsource::eax_defer_source_room_rolloff_factor( + float flRoomRolloffFactor) +{ + eax_d_.source.flRoomRolloffFactor = flRoomRolloffFactor; + eax_source_dirty_misc_flags_.flRoomRolloffFactor = (eax_.source.flRoomRolloffFactor != eax_d_.source.flRoomRolloffFactor); +} + +void ALsource::eax_defer_source_air_absorption_factor( + float flAirAbsorptionFactor) +{ + eax_d_.source.flAirAbsorptionFactor = flAirAbsorptionFactor; + eax_source_dirty_misc_flags_.flAirAbsorptionFactor = (eax_.source.flAirAbsorptionFactor != eax_d_.source.flAirAbsorptionFactor); +} + +void ALsource::eax_defer_source_flags( + unsigned long ulFlags) +{ + eax_d_.source.ulFlags = ulFlags; + eax_source_dirty_misc_flags_.ulFlags = (eax_.source.ulFlags != eax_d_.source.ulFlags); +} + +void ALsource::eax_defer_source_macro_fx_factor( + float flMacroFXFactor) +{ + eax_d_.source.flMacroFXFactor = flMacroFXFactor; + eax_source_dirty_misc_flags_.flMacroFXFactor = (eax_.source.flMacroFXFactor != eax_d_.source.flMacroFXFactor); +} + +void ALsource::eax_defer_source_2d_all( + const EAXSOURCE2DPROPERTIES& all) +{ + eax_defer_source_direct(all.lDirect); + eax_defer_source_direct_hf(all.lDirectHF); + eax_defer_source_room(all.lRoom); + eax_defer_source_room_hf(all.lRoomHF); + eax_defer_source_flags(all.ulFlags); +} + +void ALsource::eax_defer_source_obstruction_all( + const EAXOBSTRUCTIONPROPERTIES& all) +{ + eax_defer_source_obstruction(all.lObstruction); + eax_defer_source_obstruction_lf_ratio(all.flObstructionLFRatio); +} + +void ALsource::eax_defer_source_exclusion_all( + const EAXEXCLUSIONPROPERTIES& all) +{ + eax_defer_source_exclusion(all.lExclusion); + eax_defer_source_exclusion_lf_ratio(all.flExclusionLFRatio); +} + +void ALsource::eax_defer_source_occlusion_all( + const EAXOCCLUSIONPROPERTIES& all) +{ + eax_defer_source_occlusion(all.lOcclusion); + eax_defer_source_occlusion_lf_ratio(all.flOcclusionLFRatio); + eax_defer_source_occlusion_room_ratio(all.flOcclusionRoomRatio); + eax_defer_source_occlusion_direct_ratio(all.flOcclusionDirectRatio); +} + +void ALsource::eax_defer_source_all( + const EAX20BUFFERPROPERTIES& all) +{ + eax_defer_source_direct(all.lDirect); + eax_defer_source_direct_hf(all.lDirectHF); + eax_defer_source_room(all.lRoom); + eax_defer_source_room_hf(all.lRoomHF); + eax_defer_source_obstruction(all.lObstruction); + eax_defer_source_obstruction_lf_ratio(all.flObstructionLFRatio); + eax_defer_source_occlusion(all.lOcclusion); + eax_defer_source_occlusion_lf_ratio(all.flOcclusionLFRatio); + eax_defer_source_occlusion_room_ratio(all.flOcclusionRoomRatio); + eax_defer_source_outside_volume_hf(all.lOutsideVolumeHF); + eax_defer_source_room_rolloff_factor(all.flRoomRolloffFactor); + eax_defer_source_air_absorption_factor(all.flAirAbsorptionFactor); + eax_defer_source_flags(all.dwFlags); +} + +void ALsource::eax_defer_source_all( + const EAX30SOURCEPROPERTIES& all) +{ + eax_defer_source_direct(all.lDirect); + eax_defer_source_direct_hf(all.lDirectHF); + eax_defer_source_room(all.lRoom); + eax_defer_source_room_hf(all.lRoomHF); + eax_defer_source_obstruction(all.lObstruction); + eax_defer_source_obstruction_lf_ratio(all.flObstructionLFRatio); + eax_defer_source_occlusion(all.lOcclusion); + eax_defer_source_occlusion_lf_ratio(all.flOcclusionLFRatio); + eax_defer_source_occlusion_room_ratio(all.flOcclusionRoomRatio); + eax_defer_source_occlusion_direct_ratio(all.flOcclusionDirectRatio); + eax_defer_source_exclusion(all.lExclusion); + eax_defer_source_exclusion_lf_ratio(all.flExclusionLFRatio); + eax_defer_source_outside_volume_hf(all.lOutsideVolumeHF); + eax_defer_source_doppler_factor(all.flDopplerFactor); + eax_defer_source_rolloff_factor(all.flRolloffFactor); + eax_defer_source_room_rolloff_factor(all.flRoomRolloffFactor); + eax_defer_source_air_absorption_factor(all.flAirAbsorptionFactor); + eax_defer_source_flags(all.ulFlags); +} + +void ALsource::eax_defer_source_all( + const EAX50SOURCEPROPERTIES& all) +{ + eax_defer_source_all(static_cast(all)); + eax_defer_source_macro_fx_factor(all.flMacroFXFactor); +} + +void ALsource::eax_defer_source_speaker_level_all( + const EAXSPEAKERLEVELPROPERTIES& all) +{ + const auto speaker_index = static_cast(all.lSpeakerID - 1); + auto& speaker_level_d = eax_d_.speaker_levels[speaker_index]; + const auto& speaker_level = eax_.speaker_levels[speaker_index]; + + if (speaker_level != speaker_level_d) + { + eax_source_dirty_misc_flags_.speaker_levels = true; + } +} + +void ALsource::eax_defer_source_direct( + const EaxEaxCall& eax_call) +{ + const auto direct = + eax_call.get_value(); + + eax_validate_source_direct(direct); + eax_defer_source_direct(direct); +} + +void ALsource::eax_defer_source_direct_hf( + const EaxEaxCall& eax_call) +{ + const auto direct_hf = + eax_call.get_value(); + + eax_validate_source_direct_hf(direct_hf); + eax_defer_source_direct_hf(direct_hf); +} + +void ALsource::eax_defer_source_room( + const EaxEaxCall& eax_call) +{ + const auto room = + eax_call.get_value(); + + eax_validate_source_room(room); + eax_defer_source_room(room); +} + +void ALsource::eax_defer_source_room_hf( + const EaxEaxCall& eax_call) +{ + const auto room_hf = + eax_call.get_value(); + + eax_validate_source_room_hf(room_hf); + eax_defer_source_room_hf(room_hf); +} + +void ALsource::eax_defer_source_obstruction( + const EaxEaxCall& eax_call) +{ + const auto obstruction = + eax_call.get_value(); + + eax_validate_source_obstruction(obstruction); + eax_defer_source_obstruction(obstruction); +} + +void ALsource::eax_defer_source_obstruction_lf_ratio( + const EaxEaxCall& eax_call) +{ + const auto obstruction_lf_ratio = + eax_call.get_value(); + + eax_validate_source_obstruction_lf_ratio(obstruction_lf_ratio); + eax_defer_source_obstruction_lf_ratio(obstruction_lf_ratio); +} + +void ALsource::eax_defer_source_occlusion( + const EaxEaxCall& eax_call) +{ + const auto occlusion = + eax_call.get_value(); + + eax_validate_source_occlusion(occlusion); + eax_defer_source_occlusion(occlusion); +} + +void ALsource::eax_defer_source_occlusion_lf_ratio( + const EaxEaxCall& eax_call) +{ + const auto occlusion_lf_ratio = + eax_call.get_value(); + + eax_validate_source_occlusion_lf_ratio(occlusion_lf_ratio); + eax_defer_source_occlusion_lf_ratio(occlusion_lf_ratio); +} + +void ALsource::eax_defer_source_occlusion_room_ratio( + const EaxEaxCall& eax_call) +{ + const auto occlusion_room_ratio = + eax_call.get_value(); + + eax_validate_source_occlusion_room_ratio(occlusion_room_ratio); + eax_defer_source_occlusion_room_ratio(occlusion_room_ratio); +} + +void ALsource::eax_defer_source_occlusion_direct_ratio( + const EaxEaxCall& eax_call) +{ + const auto occlusion_direct_ratio = + eax_call.get_value(); + + eax_validate_source_occlusion_direct_ratio(occlusion_direct_ratio); + eax_defer_source_occlusion_direct_ratio(occlusion_direct_ratio); +} + +void ALsource::eax_defer_source_exclusion( + const EaxEaxCall& eax_call) +{ + const auto exclusion = + eax_call.get_value(); + + eax_validate_source_exclusion(exclusion); + eax_defer_source_exclusion(exclusion); +} + +void ALsource::eax_defer_source_exclusion_lf_ratio( + const EaxEaxCall& eax_call) +{ + const auto exclusion_lf_ratio = + eax_call.get_value(); + + eax_validate_source_exclusion_lf_ratio(exclusion_lf_ratio); + eax_defer_source_exclusion_lf_ratio(exclusion_lf_ratio); +} + +void ALsource::eax_defer_source_outside_volume_hf( + const EaxEaxCall& eax_call) +{ + const auto outside_volume_hf = + eax_call.get_value(); + + eax_validate_source_outside_volume_hf(outside_volume_hf); + eax_defer_source_outside_volume_hf(outside_volume_hf); +} + +void ALsource::eax_defer_source_doppler_factor( + const EaxEaxCall& eax_call) +{ + const auto doppler_factor = + eax_call.get_value(); + + eax_validate_source_doppler_factor(doppler_factor); + eax_defer_source_doppler_factor(doppler_factor); +} + +void ALsource::eax_defer_source_rolloff_factor( + const EaxEaxCall& eax_call) +{ + const auto rolloff_factor = + eax_call.get_value(); + + eax_validate_source_rolloff_factor(rolloff_factor); + eax_defer_source_rolloff_factor(rolloff_factor); +} + +void ALsource::eax_defer_source_room_rolloff_factor( + const EaxEaxCall& eax_call) +{ + const auto room_rolloff_factor = + eax_call.get_value(); + + eax_validate_source_room_rolloff_factor(room_rolloff_factor); + eax_defer_source_room_rolloff_factor(room_rolloff_factor); +} + +void ALsource::eax_defer_source_air_absorption_factor( + const EaxEaxCall& eax_call) +{ + const auto air_absorption_factor = + eax_call.get_value(); + + eax_validate_source_air_absorption_factor(air_absorption_factor); + eax_defer_source_air_absorption_factor(air_absorption_factor); +} + +void ALsource::eax_defer_source_flags( + const EaxEaxCall& eax_call) +{ + const auto flags = + eax_call.get_value(); + + eax_validate_source_flags(flags, eax_call.get_version()); + eax_defer_source_flags(flags); +} + +void ALsource::eax_defer_source_macro_fx_factor( + const EaxEaxCall& eax_call) +{ + const auto macro_fx_factor = + eax_call.get_value(); + + eax_validate_source_macro_fx_factor(macro_fx_factor); + eax_defer_source_macro_fx_factor(macro_fx_factor); +} + +void ALsource::eax_defer_source_2d_all( + const EaxEaxCall& eax_call) +{ + const auto all = eax_call.get_value(); + + eax_validate_source_2d_all(all, eax_call.get_version()); + eax_defer_source_2d_all(all); +} + +void ALsource::eax_defer_source_obstruction_all( + const EaxEaxCall& eax_call) +{ + const auto all = eax_call.get_value(); + + eax_validate_source_obstruction_all(all); + eax_defer_source_obstruction_all(all); +} + +void ALsource::eax_defer_source_exclusion_all( + const EaxEaxCall& eax_call) +{ + const auto all = eax_call.get_value(); + + eax_validate_source_exclusion_all(all); + eax_defer_source_exclusion_all(all); +} + +void ALsource::eax_defer_source_occlusion_all( + const EaxEaxCall& eax_call) +{ + const auto all = eax_call.get_value(); + + eax_validate_source_occlusion_all(all); + eax_defer_source_occlusion_all(all); +} + +void ALsource::eax_defer_source_all( + const EaxEaxCall& eax_call) +{ + const auto eax_version = eax_call.get_version(); + + if (eax_version == 2) + { + const auto all = eax_call.get_value(); + + eax_validate_source_all(all, eax_version); + eax_defer_source_all(all); + } + else if (eax_version < 5) + { + const auto all = eax_call.get_value(); + + eax_validate_source_all(all, eax_version); + eax_defer_source_all(all); + } + else + { + const auto all = eax_call.get_value(); + + eax_validate_source_all(all, eax_version); + eax_defer_source_all(all); + } +} + +void ALsource::eax_defer_source_speaker_level_all( + const EaxEaxCall& eax_call) +{ + const auto speaker_level_properties = eax_call.get_value(); + + eax_validate_source_speaker_level_all(speaker_level_properties); + eax_defer_source_speaker_level_all(speaker_level_properties); +} + +void ALsource::eax_set_outside_volume_hf() +{ + const auto efx_gain_hf = clamp( + level_mb_to_gain(static_cast(eax_.source.lOutsideVolumeHF)), + AL_MIN_CONE_OUTER_GAINHF, + AL_MAX_CONE_OUTER_GAINHF + ); + + eax_al_source_f( + AL_CONE_OUTER_GAINHF, + efx_gain_hf + ); +} + +void ALsource::eax_set_doppler_factor() +{ + eax_al_source_f( + AL_DOPPLER_FACTOR, + eax_.source.flDopplerFactor + ); +} + +void ALsource::eax_set_rolloff_factor() +{ + eax_al_source_f( + AL_ROLLOFF_FACTOR, + eax_.source.flRolloffFactor + ); +} + +void ALsource::eax_set_room_rolloff_factor() +{ + eax_al_source_f( + AL_ROOM_ROLLOFF_FACTOR, + eax_.source.flRoomRolloffFactor + ); +} + +void ALsource::eax_set_air_absorption_factor() +{ + const auto air_absorption_factor = + eax_al_context_->eax_get_air_absorption_factor() * eax_.source.flAirAbsorptionFactor; + + eax_al_source_f( + AL_AIR_ABSORPTION_FACTOR, + air_absorption_factor + ); +} + +void ALsource::eax_set_direct_hf_auto_flag() +{ + const auto is_enable = (eax_.source.ulFlags & EAXSOURCEFLAGS_DIRECTHFAUTO) != 0; + const auto al_value = static_cast(is_enable ? AL_TRUE : AL_FALSE); + + eax_al_source_i( + AL_DIRECT_FILTER_GAINHF_AUTO, + al_value + ); +} + +void ALsource::eax_set_room_auto_flag() +{ + const auto is_enable = (eax_.source.ulFlags & EAXSOURCEFLAGS_ROOMAUTO) != 0; + const auto al_value = static_cast(is_enable ? AL_TRUE : AL_FALSE); + + eax_al_source_i( + AL_AUXILIARY_SEND_FILTER_GAIN_AUTO, + al_value + ); +} + +void ALsource::eax_set_room_hf_auto_flag() +{ + const auto is_enable = (eax_.source.ulFlags & EAXSOURCEFLAGS_ROOMHFAUTO) != 0; + const auto al_value = static_cast(is_enable ? AL_TRUE : AL_FALSE); + + eax_al_source_i( + AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO, + al_value + ); +} + +void ALsource::eax_set_flags() +{ + eax_set_direct_hf_auto_flag(); + eax_set_room_auto_flag(); + eax_set_room_hf_auto_flag(); + eax_set_speaker_levels(); +} + +void ALsource::eax_set_macro_fx_factor() +{ + // TODO +} + +void ALsource::eax_set_speaker_levels() +{ + // TODO +} + +void ALsource::eax_apply_deferred() +{ + if (!eax_are_active_fx_slots_dirty_ && + eax_sends_dirty_flags_ == EaxSourceSendsDirtyFlags{} && + eax_source_dirty_filter_flags_ == EaxSourceSourceFilterDirtyFlags{} && + eax_source_dirty_misc_flags_ == EaxSourceSourceMiscDirtyFlags{}) + { + return; + } + + eax_ = eax_d_; + + if (eax_are_active_fx_slots_dirty_) + { + eax_are_active_fx_slots_dirty_ = false; + eax_set_fx_slots(); + eax_update_filters_internal(); + } + else if (eax_has_active_fx_slots_) + { + if (eax_source_dirty_filter_flags_ != EaxSourceSourceFilterDirtyFlags{}) + { + eax_update_filters_internal(); + } + else if (eax_sends_dirty_flags_ != EaxSourceSendsDirtyFlags{}) + { + for (auto i = std::size_t{}; i < EAX_MAX_FXSLOTS; ++i) + { + if (eax_active_fx_slots_[i]) + { + if (eax_sends_dirty_flags_.sends[i] != EaxSourceSendDirtyFlags{}) + { + eax_update_filters_internal(); + break; + } + } + } + } + } + + if (eax_source_dirty_misc_flags_ != EaxSourceSourceMiscDirtyFlags{}) + { + if (eax_source_dirty_misc_flags_.lOutsideVolumeHF) + { + eax_set_outside_volume_hf(); + } + + if (eax_source_dirty_misc_flags_.flDopplerFactor) + { + eax_set_doppler_factor(); + } + + if (eax_source_dirty_misc_flags_.flRolloffFactor) + { + eax_set_rolloff_factor(); + } + + if (eax_source_dirty_misc_flags_.flRoomRolloffFactor) + { + eax_set_room_rolloff_factor(); + } + + if (eax_source_dirty_misc_flags_.flAirAbsorptionFactor) + { + eax_set_air_absorption_factor(); + } + + if (eax_source_dirty_misc_flags_.ulFlags) + { + eax_set_flags(); + } + + if (eax_source_dirty_misc_flags_.flMacroFXFactor) + { + eax_set_macro_fx_factor(); + } + + eax_source_dirty_misc_flags_ = EaxSourceSourceMiscDirtyFlags{}; + } + + eax_sends_dirty_flags_ = EaxSourceSendsDirtyFlags{}; + eax_source_dirty_filter_flags_ = EaxSourceSourceFilterDirtyFlags{}; +} + +void ALsource::eax_set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXSOURCE_NONE: + break; + + case EAXSOURCE_ALLPARAMETERS: + eax_defer_source_all(eax_call); + break; + + case EAXSOURCE_OBSTRUCTIONPARAMETERS: + eax_defer_source_obstruction_all(eax_call); + break; + + case EAXSOURCE_OCCLUSIONPARAMETERS: + eax_defer_source_occlusion_all(eax_call); + break; + + case EAXSOURCE_EXCLUSIONPARAMETERS: + eax_defer_source_exclusion_all(eax_call); + break; + + case EAXSOURCE_DIRECT: + eax_defer_source_direct(eax_call); + break; + + case EAXSOURCE_DIRECTHF: + eax_defer_source_direct_hf(eax_call); + break; + + case EAXSOURCE_ROOM: + eax_defer_source_room(eax_call); + break; + + case EAXSOURCE_ROOMHF: + eax_defer_source_room_hf(eax_call); + break; + + case EAXSOURCE_OBSTRUCTION: + eax_defer_source_obstruction(eax_call); + break; + + case EAXSOURCE_OBSTRUCTIONLFRATIO: + eax_defer_source_obstruction_lf_ratio(eax_call); + break; + + case EAXSOURCE_OCCLUSION: + eax_defer_source_occlusion(eax_call); + break; + + case EAXSOURCE_OCCLUSIONLFRATIO: + eax_defer_source_occlusion_lf_ratio(eax_call); + break; + + case EAXSOURCE_OCCLUSIONROOMRATIO: + eax_defer_source_occlusion_room_ratio(eax_call); + break; + + case EAXSOURCE_OCCLUSIONDIRECTRATIO: + eax_defer_source_occlusion_direct_ratio(eax_call); + break; + + case EAXSOURCE_EXCLUSION: + eax_defer_source_exclusion(eax_call); + break; + + case EAXSOURCE_EXCLUSIONLFRATIO: + eax_defer_source_exclusion_lf_ratio(eax_call); + break; + + case EAXSOURCE_OUTSIDEVOLUMEHF: + eax_defer_source_outside_volume_hf(eax_call); + break; + + case EAXSOURCE_DOPPLERFACTOR: + eax_defer_source_doppler_factor(eax_call); + break; + + case EAXSOURCE_ROLLOFFFACTOR: + eax_defer_source_rolloff_factor(eax_call); + break; + + case EAXSOURCE_ROOMROLLOFFFACTOR: + eax_defer_source_room_rolloff_factor(eax_call); + break; + + case EAXSOURCE_AIRABSORPTIONFACTOR: + eax_defer_source_air_absorption_factor(eax_call); + break; + + case EAXSOURCE_FLAGS: + eax_defer_source_flags(eax_call); + break; + + case EAXSOURCE_SENDPARAMETERS: + eax_defer_send(eax_call); + break; + + case EAXSOURCE_ALLSENDPARAMETERS: + eax_defer_send_all(eax_call); + break; + + case EAXSOURCE_OCCLUSIONSENDPARAMETERS: + eax_defer_send_occlusion_all(eax_call); + break; + + case EAXSOURCE_EXCLUSIONSENDPARAMETERS: + eax_defer_send_exclusion_all(eax_call); + break; + + case EAXSOURCE_ACTIVEFXSLOTID: + eax_defer_active_fx_slots(eax_call); + break; + + case EAXSOURCE_MACROFXFACTOR: + eax_defer_source_macro_fx_factor(eax_call); + break; + + case EAXSOURCE_SPEAKERLEVELS: + eax_defer_source_speaker_level_all(eax_call); + break; + + case EAXSOURCE_ALL2DPARAMETERS: + eax_defer_source_2d_all(eax_call); + break; + + default: + eax_fail("Unsupported property id."); + } + + if (!eax_call.is_deferred()) + { + eax_apply_deferred(); + } +} + +const GUID& ALsource::eax_get_send_fx_slot_guid( + int eax_version, + EaxFxSlotIndexValue fx_slot_index) +{ + switch (eax_version) + { + case 4: + switch (fx_slot_index) + { + case 0: + return EAXPROPERTYID_EAX40_FXSlot0; + + case 1: + return EAXPROPERTYID_EAX40_FXSlot1; + + case 2: + return EAXPROPERTYID_EAX40_FXSlot2; + + case 3: + return EAXPROPERTYID_EAX40_FXSlot3; + + default: + eax_fail("FX slot index out of range."); + } + + case 5: + switch (fx_slot_index) + { + case 0: + return EAXPROPERTYID_EAX50_FXSlot0; + + case 1: + return EAXPROPERTYID_EAX50_FXSlot1; + + case 2: + return EAXPROPERTYID_EAX50_FXSlot2; + + case 3: + return EAXPROPERTYID_EAX50_FXSlot3; + + default: + eax_fail("FX slot index out of range."); + } + + default: + eax_fail("Unsupported EAX version."); + } +} + +void ALsource::eax_copy_send( + const EAXSOURCEALLSENDPROPERTIES& src_send, + EAXSOURCESENDPROPERTIES& dst_send) +{ + dst_send.lSend = src_send.lSend; + dst_send.lSendHF = src_send.lSendHF; +} + +void ALsource::eax_copy_send( + const EAXSOURCEALLSENDPROPERTIES& src_send, + EAXSOURCEALLSENDPROPERTIES& dst_send) +{ + dst_send = src_send; +} + +void ALsource::eax_copy_send( + const EAXSOURCEALLSENDPROPERTIES& src_send, + EAXSOURCEOCCLUSIONSENDPROPERTIES& dst_send) +{ + dst_send.lOcclusion = src_send.lOcclusion; + dst_send.flOcclusionLFRatio = src_send.flOcclusionLFRatio; + dst_send.flOcclusionRoomRatio = src_send.flOcclusionRoomRatio; + dst_send.flOcclusionDirectRatio = src_send.flOcclusionDirectRatio; +} + +void ALsource::eax_copy_send( + const EAXSOURCEALLSENDPROPERTIES& src_send, + EAXSOURCEEXCLUSIONSENDPROPERTIES& dst_send) +{ + dst_send.lExclusion = src_send.lExclusion; + dst_send.flExclusionLFRatio = src_send.flExclusionLFRatio; +} + +void ALsource::eax_api_get_source_all_v2( + const EaxEaxCall& eax_call) +{ + auto eax_2_all = EAX20BUFFERPROPERTIES{}; + eax_2_all.lDirect = eax_.source.lDirect; + eax_2_all.lDirectHF = eax_.source.lDirectHF; + eax_2_all.lRoom = eax_.source.lRoom; + eax_2_all.lRoomHF = eax_.source.lRoomHF; + eax_2_all.flRoomRolloffFactor = eax_.source.flRoomRolloffFactor; + eax_2_all.lObstruction = eax_.source.lObstruction; + eax_2_all.flObstructionLFRatio = eax_.source.flObstructionLFRatio; + eax_2_all.lOcclusion = eax_.source.lOcclusion; + eax_2_all.flOcclusionLFRatio = eax_.source.flOcclusionLFRatio; + eax_2_all.flOcclusionRoomRatio = eax_.source.flOcclusionRoomRatio; + eax_2_all.lOutsideVolumeHF = eax_.source.lOutsideVolumeHF; + eax_2_all.flAirAbsorptionFactor = eax_.source.flAirAbsorptionFactor; + eax_2_all.dwFlags = eax_.source.ulFlags; + + eax_call.set_value(eax_2_all); +} + +void ALsource::eax_api_get_source_all_v3( + const EaxEaxCall& eax_call) +{ + eax_call.set_value(static_cast(eax_.source)); +} + +void ALsource::eax_api_get_source_all_v5( + const EaxEaxCall& eax_call) +{ + eax_call.set_value(eax_.source); +} + +void ALsource::eax_api_get_source_all( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_version()) + { + case 2: + eax_api_get_source_all_v2(eax_call); + break; + + case 3: + case 4: + eax_api_get_source_all_v3(eax_call); + break; + + case 5: + eax_api_get_source_all_v5(eax_call); + break; + + default: + eax_fail("Unsupported EAX version."); + } +} + +void ALsource::eax_api_get_source_all_obstruction( + const EaxEaxCall& eax_call) +{ + static_assert( + offsetof(EAXOBSTRUCTIONPROPERTIES, flObstructionLFRatio) - offsetof(EAXOBSTRUCTIONPROPERTIES, lObstruction) == + offsetof(EAX30SOURCEPROPERTIES, flObstructionLFRatio) - offsetof(EAX30SOURCEPROPERTIES, lObstruction), + "Type size." + ); + + const auto eax_obstruction_all = *reinterpret_cast(&eax_.source.lObstruction); + + eax_call.set_value(eax_obstruction_all); +} + +void ALsource::eax_api_get_source_all_occlusion( + const EaxEaxCall& eax_call) +{ + static_assert( + offsetof(EAXOCCLUSIONPROPERTIES, flOcclusionLFRatio) - offsetof(EAXOCCLUSIONPROPERTIES, lOcclusion) == + offsetof(EAX30SOURCEPROPERTIES, flOcclusionLFRatio) - offsetof(EAX30SOURCEPROPERTIES, lOcclusion) && + + offsetof(EAXOCCLUSIONPROPERTIES, flOcclusionRoomRatio) - offsetof(EAXOCCLUSIONPROPERTIES, lOcclusion) == + offsetof(EAX30SOURCEPROPERTIES, flOcclusionRoomRatio) - offsetof(EAX30SOURCEPROPERTIES, lOcclusion) && + + offsetof(EAXOCCLUSIONPROPERTIES, flOcclusionDirectRatio) - offsetof(EAXOCCLUSIONPROPERTIES, lOcclusion) == + offsetof(EAX30SOURCEPROPERTIES, flOcclusionDirectRatio) - offsetof(EAX30SOURCEPROPERTIES, lOcclusion), + + "Type size." + ); + + const auto eax_occlusion_all = *reinterpret_cast(&eax_.source.lOcclusion); + + eax_call.set_value(eax_occlusion_all); +} + +void ALsource::eax_api_get_source_all_exclusion( + const EaxEaxCall& eax_call) +{ + static_assert( + offsetof(EAXEXCLUSIONPROPERTIES, flExclusionLFRatio) - offsetof(EAXEXCLUSIONPROPERTIES, lExclusion) == + offsetof(EAX30SOURCEPROPERTIES, flExclusionLFRatio) - offsetof(EAX30SOURCEPROPERTIES, lExclusion), + + "Type size." + ); + + const auto eax_exclusion_all = *reinterpret_cast(&eax_.source.lExclusion); + + eax_call.set_value(eax_exclusion_all); +} + +void ALsource::eax_api_get_source_active_fx_slot_id( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_version()) + { + case 4: + { + const auto& active_fx_slots = reinterpret_cast(eax_.active_fx_slots); + eax_call.set_value(active_fx_slots); + } + break; + + case 5: + { + const auto& active_fx_slots = reinterpret_cast(eax_.active_fx_slots); + eax_call.set_value(active_fx_slots); + } + break; + + default: + eax_fail("Unsupported EAX version."); + } +} + +void ALsource::eax_api_get_source_all_2d( + const EaxEaxCall& eax_call) +{ + auto eax_2d_all = EAXSOURCE2DPROPERTIES{}; + eax_2d_all.lDirect = eax_.source.lDirect; + eax_2d_all.lDirectHF = eax_.source.lDirectHF; + eax_2d_all.lRoom = eax_.source.lRoom; + eax_2d_all.lRoomHF = eax_.source.lRoomHF; + eax_2d_all.ulFlags = eax_.source.ulFlags; + + eax_call.set_value(eax_2d_all); +} + +void ALsource::eax_api_get_source_speaker_level_all( + const EaxEaxCall& eax_call) +{ + auto& all = eax_call.get_value(); + + eax_validate_source_speaker_id(all.lSpeakerID); + const auto speaker_index = static_cast(all.lSpeakerID - 1); + all.lLevel = eax_.speaker_levels[speaker_index]; +} + +void ALsource::eax_get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXSOURCE_NONE: + break; + + case EAXSOURCE_ALLPARAMETERS: + eax_api_get_source_all(eax_call); + break; + + case EAXSOURCE_OBSTRUCTIONPARAMETERS: + eax_api_get_source_all_obstruction(eax_call); + break; + + case EAXSOURCE_OCCLUSIONPARAMETERS: + eax_api_get_source_all_occlusion(eax_call); + break; + + case EAXSOURCE_EXCLUSIONPARAMETERS: + eax_api_get_source_all_exclusion(eax_call); + break; + + case EAXSOURCE_DIRECT: + eax_call.set_value(eax_.source.lDirect); + break; + + case EAXSOURCE_DIRECTHF: + eax_call.set_value(eax_.source.lDirectHF); + break; + + case EAXSOURCE_ROOM: + eax_call.set_value(eax_.source.lRoom); + break; + + case EAXSOURCE_ROOMHF: + eax_call.set_value(eax_.source.lRoomHF); + break; + + case EAXSOURCE_OBSTRUCTION: + eax_call.set_value(eax_.source.lObstruction); + break; + + case EAXSOURCE_OBSTRUCTIONLFRATIO: + eax_call.set_value(eax_.source.flObstructionLFRatio); + break; + + case EAXSOURCE_OCCLUSION: + eax_call.set_value(eax_.source.lOcclusion); + break; + + case EAXSOURCE_OCCLUSIONLFRATIO: + eax_call.set_value(eax_.source.flOcclusionLFRatio); + break; + + case EAXSOURCE_OCCLUSIONROOMRATIO: + eax_call.set_value(eax_.source.flOcclusionRoomRatio); + break; + + case EAXSOURCE_OCCLUSIONDIRECTRATIO: + eax_call.set_value(eax_.source.flOcclusionDirectRatio); + break; + + case EAXSOURCE_EXCLUSION: + eax_call.set_value(eax_.source.lExclusion); + break; + + case EAXSOURCE_EXCLUSIONLFRATIO: + eax_call.set_value(eax_.source.flExclusionLFRatio); + break; + + case EAXSOURCE_OUTSIDEVOLUMEHF: + eax_call.set_value(eax_.source.lOutsideVolumeHF); + break; + + case EAXSOURCE_DOPPLERFACTOR: + eax_call.set_value(eax_.source.flDopplerFactor); + break; + + case EAXSOURCE_ROLLOFFFACTOR: + eax_call.set_value(eax_.source.flRolloffFactor); + break; + + case EAXSOURCE_ROOMROLLOFFFACTOR: + eax_call.set_value(eax_.source.flRoomRolloffFactor); + break; + + case EAXSOURCE_AIRABSORPTIONFACTOR: + eax_call.set_value(eax_.source.flAirAbsorptionFactor); + break; + + case EAXSOURCE_FLAGS: + eax_call.set_value(eax_.source.ulFlags); + break; + + case EAXSOURCE_SENDPARAMETERS: + eax_api_get_send_properties(eax_call); + break; + + case EAXSOURCE_ALLSENDPARAMETERS: + eax_api_get_send_properties(eax_call); + break; + + case EAXSOURCE_OCCLUSIONSENDPARAMETERS: + eax_api_get_send_properties(eax_call); + break; + + case EAXSOURCE_EXCLUSIONSENDPARAMETERS: + eax_api_get_send_properties(eax_call); + break; + + case EAXSOURCE_ACTIVEFXSLOTID: + eax_api_get_source_active_fx_slot_id(eax_call); + break; + + case EAXSOURCE_MACROFXFACTOR: + eax_call.set_value(eax_.source.flMacroFXFactor); + break; + + case EAXSOURCE_SPEAKERLEVELS: + eax_api_get_source_speaker_level_all(eax_call); + break; + + case EAXSOURCE_ALL2DPARAMETERS: + eax_api_get_source_all_2d(eax_call); + break; + + default: + eax_fail("Unsupported property id."); + } +} + +void ALsource::eax_al_source_i( + ALenum param, + ALint value) +{ + SetSourceiv(this, eax_al_context_, static_cast(param), {&value, 1}); +} + +void ALsource::eax_al_source_f( + ALenum param, + ALfloat value) +{ + SetSourcefv(this, eax_al_context_, static_cast(param), {&value, 1}); +} + +void ALsource::eax_al_source_3i( + ALenum param, + ALint value1, + ALint value2, + ALint value3) +{ + const ALint values[3] = {value1, value2, value3}; + SetSourceiv(this, eax_al_context_, static_cast(param), values); +} + + +#endif // ALSOFT_EAX diff --git a/al/source.h b/al/source.h index 25ece822..41cd6187 100644 --- a/al/source.h +++ b/al/source.h @@ -21,6 +21,12 @@ #include "core/voice.h" #include "vector.h" +#if ALSOFT_EAX +#include "eax_eax_call.h" +#include "eax_fx_slot_index.h" +#include "eax_utils.h" +#endif // ALSOFT_EAX + struct ALbuffer; struct ALeffectslot; @@ -41,6 +47,77 @@ struct ALbufferQueueItem : public VoiceBufferItem { }; +#if ALSOFT_EAX +struct EaxSourceInitParam +{ + ALCcontext* al_context{}; + ALfilter* al_filter{}; +}; // EaxSourceInitParam + + +using EaxSourceSourceFilterDirtyFlagsValue = std::uint_least16_t; + +struct EaxSourceSourceFilterDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxSourceSourceFilterDirtyFlagsValue lDirect : 1; + EaxSourceSourceFilterDirtyFlagsValue lDirectHF : 1; + EaxSourceSourceFilterDirtyFlagsValue lRoom : 1; + EaxSourceSourceFilterDirtyFlagsValue lRoomHF : 1; + EaxSourceSourceFilterDirtyFlagsValue lObstruction : 1; + EaxSourceSourceFilterDirtyFlagsValue flObstructionLFRatio : 1; + EaxSourceSourceFilterDirtyFlagsValue lOcclusion : 1; + EaxSourceSourceFilterDirtyFlagsValue flOcclusionLFRatio : 1; + EaxSourceSourceFilterDirtyFlagsValue flOcclusionRoomRatio : 1; + EaxSourceSourceFilterDirtyFlagsValue flOcclusionDirectRatio : 1; + EaxSourceSourceFilterDirtyFlagsValue lExclusion : 1; + EaxSourceSourceFilterDirtyFlagsValue flExclusionLFRatio : 1; +}; // EaxSourceSourceFilterDirtyFlags + + +using EaxSourceSourceMiscDirtyFlagsValue = std::uint_least8_t; + +struct EaxSourceSourceMiscDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxSourceSourceMiscDirtyFlagsValue lOutsideVolumeHF : 1; + EaxSourceSourceMiscDirtyFlagsValue flDopplerFactor : 1; + EaxSourceSourceMiscDirtyFlagsValue flRolloffFactor : 1; + EaxSourceSourceMiscDirtyFlagsValue flRoomRolloffFactor : 1; + EaxSourceSourceMiscDirtyFlagsValue flAirAbsorptionFactor : 1; + EaxSourceSourceMiscDirtyFlagsValue ulFlags : 1; + EaxSourceSourceMiscDirtyFlagsValue flMacroFXFactor : 1; + EaxSourceSourceMiscDirtyFlagsValue speaker_levels : 1; +}; // EaxSourceSourceMiscDirtyFlags + + +using EaxSourceSendDirtyFlagsValue = std::uint_least8_t; + +struct EaxSourceSendDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxSourceSendDirtyFlagsValue lSend : 1; + EaxSourceSendDirtyFlagsValue lSendHF : 1; + EaxSourceSendDirtyFlagsValue lOcclusion : 1; + EaxSourceSendDirtyFlagsValue flOcclusionLFRatio : 1; + EaxSourceSendDirtyFlagsValue flOcclusionRoomRatio : 1; + EaxSourceSendDirtyFlagsValue flOcclusionDirectRatio : 1; + EaxSourceSendDirtyFlagsValue lExclusion : 1; + EaxSourceSendDirtyFlagsValue flExclusionLFRatio : 1; +}; // EaxSourceSendDirtyFlags + + +struct EaxSourceSendsDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxSourceSendDirtyFlags sends[EAX_MAX_FXSLOTS]; +}; // EaxSourceSendsDirtyFlags +#endif // ALSOFT_EAX + struct ALsource { /** Source properties. */ float Pitch{1.0f}; @@ -135,6 +212,618 @@ struct ALsource { ALsource& operator=(const ALsource&) = delete; DISABLE_ALLOC() + +#if ALSOFT_EAX +public: + void eax_initialize( + const EaxSourceInitParam& param) noexcept; + + void eax_uninitialize(); + + + void eax_dispatch( + const EaxEaxCall& eax_call); + + + void eax_update_filters(); + + void eax_update( + EaxContextSharedDirtyFlags dirty_flags); + + + static ALsource* eax_lookup_source( + ALCcontext& al_context, + ALuint source_id) noexcept; + + +private: + static constexpr auto eax_max_speakers = 9; + + + using EaxActiveFxSlots = std::array; + using EaxSpeakerLevels = std::array; + + + struct Eax + { + using Sends = std::array; + + EAX50ACTIVEFXSLOTS active_fx_slots{}; + EAX50SOURCEPROPERTIES source{}; + Sends sends{}; + EaxSpeakerLevels speaker_levels{}; + }; // Eax + + + bool eax_uses_primary_id_{}; + bool eax_has_active_fx_slots_{}; + bool eax_are_active_fx_slots_dirty_{}; + + ALCcontext* eax_al_context_{}; + ALfilter* eax_al_filter_{}; + + Eax eax_{}; + Eax eax_d_{}; + EaxActiveFxSlots eax_active_fx_slots_{}; + + EaxSourceSendsDirtyFlags eax_sends_dirty_flags_{}; + EaxSourceSourceFilterDirtyFlags eax_source_dirty_filter_flags_{}; + EaxSourceSourceMiscDirtyFlags eax_source_dirty_misc_flags_{}; + + + [[noreturn]] + static void eax_fail( + const char* message); + + + static void eax_validate_init_param( + const EaxSourceInitParam& param); + + void eax_copy_init_param( + const EaxSourceInitParam& param); + + + void eax_set_source_defaults(); + + void eax_set_active_fx_slots_defaults(); + + void eax_set_send_defaults( + EAXSOURCEALLSENDPROPERTIES& eax_send); + + void eax_set_sends_defaults(); + + void eax_set_speaker_levels_defaults(); + + void eax_set_defaults(); + + + static float eax_calculate_dst_occlusion_mb( + long src_occlusion_mb, + float path_ratio, + float lf_ratio) noexcept; + + EaxAlLowPassParam eax_create_direct_filter_param() const noexcept; + + EaxAlLowPassParam eax_create_room_filter_param( + const ALeffectslot& fx_slot, + const EAXSOURCEALLSENDPROPERTIES& send) const noexcept; + + void eax_set_al_filter_parameters( + const EaxAlLowPassParam& al_low_pass_param) const noexcept; + + void eax_set_fx_slots(); + + void eax_initialize_fx_slots(); + + void eax_update_direct_filter_internal(); + + void eax_update_room_filters_internal(); + + void eax_update_filters_internal(); + + void eax_update_primary_fx_slot_id(); + + + void eax_defer_active_fx_slots( + const EaxEaxCall& eax_call); + + + static const char* eax_get_exclusion_name() noexcept; + + static const char* eax_get_exclusion_lf_ratio_name() noexcept; + + + static const char* eax_get_occlusion_name() noexcept; + + static const char* eax_get_occlusion_lf_ratio_name() noexcept; + + static const char* eax_get_occlusion_direct_ratio_name() noexcept; + + static const char* eax_get_occlusion_room_ratio_name() noexcept; + + + static void eax_validate_send_receiving_fx_slot_guid( + const GUID& guidReceivingFXSlotID); + + static void eax_validate_send_send( + long lSend); + + static void eax_validate_send_send_hf( + long lSendHF); + + static void eax_validate_send_occlusion( + long lOcclusion); + + static void eax_validate_send_occlusion_lf_ratio( + float flOcclusionLFRatio); + + static void eax_validate_send_occlusion_room_ratio( + float flOcclusionRoomRatio); + + static void eax_validate_send_occlusion_direct_ratio( + float flOcclusionDirectRatio); + + static void eax_validate_send_exclusion( + long lExclusion); + + static void eax_validate_send_exclusion_lf_ratio( + float flExclusionLFRatio); + + static void eax_validate_send( + const EAXSOURCESENDPROPERTIES& all); + + static void eax_validate_send_exclusion_all( + const EAXSOURCEEXCLUSIONSENDPROPERTIES& all); + + static void eax_validate_send_occlusion_all( + const EAXSOURCEOCCLUSIONSENDPROPERTIES& all); + + static void eax_validate_send_all( + const EAXSOURCEALLSENDPROPERTIES& all); + + + static EaxFxSlotIndexValue eax_get_send_index( + const GUID& send_guid); + + + void eax_defer_send_send( + long lSend, + EaxFxSlotIndexValue index); + + void eax_defer_send_send_hf( + long lSendHF, + EaxFxSlotIndexValue index); + + void eax_defer_send_occlusion( + long lOcclusion, + EaxFxSlotIndexValue index); + + void eax_defer_send_occlusion_lf_ratio( + float flOcclusionLFRatio, + EaxFxSlotIndexValue index); + + void eax_defer_send_occlusion_room_ratio( + float flOcclusionRoomRatio, + EaxFxSlotIndexValue index); + + void eax_defer_send_occlusion_direct_ratio( + float flOcclusionDirectRatio, + EaxFxSlotIndexValue index); + + void eax_defer_send_exclusion( + long lExclusion, + EaxFxSlotIndexValue index); + + void eax_defer_send_exclusion_lf_ratio( + float flExclusionLFRatio, + EaxFxSlotIndexValue index); + + void eax_defer_send( + const EAXSOURCESENDPROPERTIES& all, + EaxFxSlotIndexValue index); + + void eax_defer_send_exclusion_all( + const EAXSOURCEEXCLUSIONSENDPROPERTIES& all, + EaxFxSlotIndexValue index); + + void eax_defer_send_occlusion_all( + const EAXSOURCEOCCLUSIONSENDPROPERTIES& all, + EaxFxSlotIndexValue index); + + void eax_defer_send_all( + const EAXSOURCEALLSENDPROPERTIES& all, + EaxFxSlotIndexValue index); + + + void eax_defer_send( + const EaxEaxCall& eax_call); + + void eax_defer_send_exclusion_all( + const EaxEaxCall& eax_call); + + void eax_defer_send_occlusion_all( + const EaxEaxCall& eax_call); + + void eax_defer_send_all( + const EaxEaxCall& eax_call); + + + static void eax_validate_source_direct( + long direct); + + static void eax_validate_source_direct_hf( + long direct_hf); + + static void eax_validate_source_room( + long room); + + static void eax_validate_source_room_hf( + long room_hf); + + static void eax_validate_source_obstruction( + long obstruction); + + static void eax_validate_source_obstruction_lf_ratio( + float obstruction_lf_ratio); + + static void eax_validate_source_occlusion( + long occlusion); + + static void eax_validate_source_occlusion_lf_ratio( + float occlusion_lf_ratio); + + static void eax_validate_source_occlusion_room_ratio( + float occlusion_room_ratio); + + static void eax_validate_source_occlusion_direct_ratio( + float occlusion_direct_ratio); + + static void eax_validate_source_exclusion( + long exclusion); + + static void eax_validate_source_exclusion_lf_ratio( + float exclusion_lf_ratio); + + static void eax_validate_source_outside_volume_hf( + long outside_volume_hf); + + static void eax_validate_source_doppler_factor( + float doppler_factor); + + static void eax_validate_source_rolloff_factor( + float rolloff_factor); + + static void eax_validate_source_room_rolloff_factor( + float room_rolloff_factor); + + static void eax_validate_source_air_absorption_factor( + float air_absorption_factor); + + static void eax_validate_source_flags( + unsigned long flags, + int eax_version); + + static void eax_validate_source_macro_fx_factor( + float macro_fx_factor); + + static void eax_validate_source_2d_all( + const EAXSOURCE2DPROPERTIES& all, + int eax_version); + + static void eax_validate_source_obstruction_all( + const EAXOBSTRUCTIONPROPERTIES& all); + + static void eax_validate_source_exclusion_all( + const EAXEXCLUSIONPROPERTIES& all); + + static void eax_validate_source_occlusion_all( + const EAXOCCLUSIONPROPERTIES& all); + + static void eax_validate_source_all( + const EAX20BUFFERPROPERTIES& all, + int eax_version); + + static void eax_validate_source_all( + const EAX30SOURCEPROPERTIES& all, + int eax_version); + + static void eax_validate_source_all( + const EAX50SOURCEPROPERTIES& all, + int eax_version); + + static void eax_validate_source_speaker_id( + long speaker_id); + + static void eax_validate_source_speaker_level( + long speaker_level); + + static void eax_validate_source_speaker_level_all( + const EAXSPEAKERLEVELPROPERTIES& all); + + + void eax_defer_source_direct( + long lDirect); + + void eax_defer_source_direct_hf( + long lDirectHF); + + void eax_defer_source_room( + long lRoom); + + void eax_defer_source_room_hf( + long lRoomHF); + + void eax_defer_source_obstruction( + long lObstruction); + + void eax_defer_source_obstruction_lf_ratio( + float flObstructionLFRatio); + + void eax_defer_source_occlusion( + long lOcclusion); + + void eax_defer_source_occlusion_lf_ratio( + float flOcclusionLFRatio); + + void eax_defer_source_occlusion_room_ratio( + float flOcclusionRoomRatio); + + void eax_defer_source_occlusion_direct_ratio( + float flOcclusionDirectRatio); + + void eax_defer_source_exclusion( + long lExclusion); + + void eax_defer_source_exclusion_lf_ratio( + float flExclusionLFRatio); + + void eax_defer_source_outside_volume_hf( + long lOutsideVolumeHF); + + void eax_defer_source_doppler_factor( + float flDopplerFactor); + + void eax_defer_source_rolloff_factor( + float flRolloffFactor); + + void eax_defer_source_room_rolloff_factor( + float flRoomRolloffFactor); + + void eax_defer_source_air_absorption_factor( + float flAirAbsorptionFactor); + + void eax_defer_source_flags( + unsigned long ulFlags); + + void eax_defer_source_macro_fx_factor( + float flMacroFXFactor); + + void eax_defer_source_2d_all( + const EAXSOURCE2DPROPERTIES& all); + + void eax_defer_source_obstruction_all( + const EAXOBSTRUCTIONPROPERTIES& all); + + void eax_defer_source_exclusion_all( + const EAXEXCLUSIONPROPERTIES& all); + + void eax_defer_source_occlusion_all( + const EAXOCCLUSIONPROPERTIES& all); + + void eax_defer_source_all( + const EAX20BUFFERPROPERTIES& all); + + void eax_defer_source_all( + const EAX30SOURCEPROPERTIES& all); + + void eax_defer_source_all( + const EAX50SOURCEPROPERTIES& all); + + void eax_defer_source_speaker_level_all( + const EAXSPEAKERLEVELPROPERTIES& all); + + + void eax_defer_source_direct( + const EaxEaxCall& eax_call); + + void eax_defer_source_direct_hf( + const EaxEaxCall& eax_call); + + void eax_defer_source_room( + const EaxEaxCall& eax_call); + + void eax_defer_source_room_hf( + const EaxEaxCall& eax_call); + + void eax_defer_source_obstruction( + const EaxEaxCall& eax_call); + + void eax_defer_source_obstruction_lf_ratio( + const EaxEaxCall& eax_call); + + void eax_defer_source_occlusion( + const EaxEaxCall& eax_call); + + void eax_defer_source_occlusion_lf_ratio( + const EaxEaxCall& eax_call); + + void eax_defer_source_occlusion_room_ratio( + const EaxEaxCall& eax_call); + + void eax_defer_source_occlusion_direct_ratio( + const EaxEaxCall& eax_call); + + void eax_defer_source_exclusion( + const EaxEaxCall& eax_call); + + void eax_defer_source_exclusion_lf_ratio( + const EaxEaxCall& eax_call); + + void eax_defer_source_outside_volume_hf( + const EaxEaxCall& eax_call); + + void eax_defer_source_doppler_factor( + const EaxEaxCall& eax_call); + + void eax_defer_source_rolloff_factor( + const EaxEaxCall& eax_call); + + void eax_defer_source_room_rolloff_factor( + const EaxEaxCall& eax_call); + + void eax_defer_source_air_absorption_factor( + const EaxEaxCall& eax_call); + + void eax_defer_source_flags( + const EaxEaxCall& eax_call); + + void eax_defer_source_macro_fx_factor( + const EaxEaxCall& eax_call); + + void eax_defer_source_2d_all( + const EaxEaxCall& eax_call); + + void eax_defer_source_obstruction_all( + const EaxEaxCall& eax_call); + + void eax_defer_source_exclusion_all( + const EaxEaxCall& eax_call); + + void eax_defer_source_occlusion_all( + const EaxEaxCall& eax_call); + + void eax_defer_source_all( + const EaxEaxCall& eax_call); + + void eax_defer_source_speaker_level_all( + const EaxEaxCall& eax_call); + + + void eax_set_outside_volume_hf(); + + void eax_set_doppler_factor(); + + void eax_set_rolloff_factor(); + + void eax_set_room_rolloff_factor(); + + void eax_set_air_absorption_factor(); + + + void eax_set_direct_hf_auto_flag(); + + void eax_set_room_auto_flag(); + + void eax_set_room_hf_auto_flag(); + + void eax_set_flags(); + + + void eax_set_macro_fx_factor(); + + void eax_set_speaker_levels(); + + + void eax_apply_deferred(); + + void eax_set( + const EaxEaxCall& eax_call); + + + static const GUID& eax_get_send_fx_slot_guid( + int eax_version, + EaxFxSlotIndexValue fx_slot_index); + + static void eax_copy_send( + const EAXSOURCEALLSENDPROPERTIES& src_send, + EAXSOURCESENDPROPERTIES& dst_send); + + static void eax_copy_send( + const EAXSOURCEALLSENDPROPERTIES& src_send, + EAXSOURCEALLSENDPROPERTIES& dst_send); + + static void eax_copy_send( + const EAXSOURCEALLSENDPROPERTIES& src_send, + EAXSOURCEOCCLUSIONSENDPROPERTIES& dst_send); + + static void eax_copy_send( + const EAXSOURCEALLSENDPROPERTIES& src_send, + EAXSOURCEEXCLUSIONSENDPROPERTIES& dst_send); + + template< + typename TException, + typename TSrcSend + > + void eax_api_get_send_properties( + const EaxEaxCall& eax_call) const + { + const auto eax_version = eax_call.get_version(); + const auto dst_sends = eax_call.get_values(); + const auto send_count = dst_sends.size(); + + for (auto fx_slot_index = EaxFxSlotIndexValue{}; fx_slot_index < send_count; ++fx_slot_index) + { + auto& dst_send = dst_sends[fx_slot_index]; + const auto& src_send = eax_.sends[fx_slot_index]; + + eax_copy_send(src_send, dst_send); + + dst_send.guidReceivingFXSlotID = eax_get_send_fx_slot_guid(eax_version, fx_slot_index); + } + } + + + void eax_api_get_source_all_v2( + const EaxEaxCall& eax_call); + + void eax_api_get_source_all_v3( + const EaxEaxCall& eax_call); + + void eax_api_get_source_all_v5( + const EaxEaxCall& eax_call); + + void eax_api_get_source_all( + const EaxEaxCall& eax_call); + + void eax_api_get_source_all_obstruction( + const EaxEaxCall& eax_call); + + void eax_api_get_source_all_occlusion( + const EaxEaxCall& eax_call); + + void eax_api_get_source_all_exclusion( + const EaxEaxCall& eax_call); + + void eax_api_get_source_active_fx_slot_id( + const EaxEaxCall& eax_call); + + void eax_api_get_source_all_2d( + const EaxEaxCall& eax_call); + + void eax_api_get_source_speaker_level_all( + const EaxEaxCall& eax_call); + + void eax_get( + const EaxEaxCall& eax_call); + + + // `alSourcei` + void eax_al_source_i( + ALenum param, + ALint value); + + // `alSourcef` + void eax_al_source_f( + ALenum param, + ALfloat value); + + // `alSource3i` + void eax_al_source_3i( + ALenum param, + ALint value1, + ALint value2, + ALint value3); +#endif // ALSOFT_EAX }; void UpdateAllSourceProps(ALCcontext *context); diff --git a/al/state.cpp b/al/state.cpp index 10c7bc74..0ec0e280 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -46,6 +46,13 @@ #include "opthelpers.h" #include "strutils.h" +#if ALSOFT_EAX +#include "alc/device.h" + +#include "eax_globals.h" +#include "eax_x_ram.h" +#endif // ALSOFT_EAX + namespace { @@ -427,6 +434,41 @@ START_API_FUNC value = static_cast(ResamplerDefault); break; +#if ALSOFT_EAX + +#define EAX_ERROR "[alGetInteger] EAX not enabled." + + case AL_EAX_RAM_SIZE: + if (eax_g_is_enabled) + { + value = eax_x_ram_max_size; + } + else + { + context->setError(AL_INVALID_VALUE, EAX_ERROR); + } + + break; + + case AL_EAX_RAM_FREE: + if (eax_g_is_enabled) + { + auto device = context->mALDevice.get(); + std::lock_guard device_lock{device->BufferLock}; + + value = device->eax_x_ram_free_size; + } + else + { + context->setError(AL_INVALID_VALUE, EAX_ERROR); + } + + break; + +#undef EAX_ERROR + +#endif // ALSOFT_EAX + default: context->setError(AL_INVALID_VALUE, "Invalid integer property 0x%04x", pname); } diff --git a/alc/alc.cpp b/alc/alc.cpp index 04dbcab3..b9f322a3 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -155,6 +155,11 @@ #include "backends/wave.h" #endif +#if ALSOFT_EAX +#include "al/eax_globals.h" +#include "al/eax_x_ram.h" +#endif // ALSOFT_EAX + FILE *gLogFile{stderr}; #ifdef _DEBUG @@ -875,6 +880,14 @@ constexpr struct { DECL(AL_SUPER_STEREO_WIDTH_SOFT), DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), + +#if ALSOFT_EAX + DECL(AL_EAX_RAM_SIZE), + DECL(AL_EAX_RAM_FREE), + DECL(AL_STORAGE_AUTOMATIC), + DECL(AL_STORAGE_HARDWARE), + DECL(AL_STORAGE_ACCESSIBLE), +#endif // ALSOFT_EAX }; #undef DECL @@ -1244,6 +1257,28 @@ void alc_initconfig(void) auto defrevopt = al::getenv("ALSOFT_DEFAULT_REVERB"); if(defrevopt || (defrevopt=ConfigValueStr(nullptr, nullptr, "default-reverb"))) LoadReverbPreset(defrevopt->c_str(), &ALCcontext::sDefaultEffect); + +#if ALSOFT_EAX + { + constexpr auto eax_block_name = "eax"; + + const auto eax_enable_opt = ConfigValueBool(nullptr, eax_block_name, "enable"); + + if (eax_enable_opt) + { + eax_g_is_enabled = *eax_enable_opt; + + if (!eax_g_is_enabled) + { + TRACE("%s\n", "EAX disabled by a configuration."); + } + } + else + { + eax_g_is_enabled = true; + } + } +#endif // ALSOFT_EAX } #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();}) @@ -2929,6 +2964,7 @@ START_API_FUNC return enm.value; } } + return 0; } END_API_FUNC @@ -3038,6 +3074,7 @@ START_API_FUNC alcSetError(nullptr, ALC_INVALID_CONTEXT); return; } + /* Hold a reference to this context so it remains valid until the ListLock * is released. */ @@ -3186,6 +3223,13 @@ START_API_FUNC device->AuxiliaryEffectSlotMax = 64; device->NumAuxSends = DEFAULT_SENDS; +#if ALSOFT_EAX + if (eax_g_is_enabled) + { + device->NumAuxSends = EAX_MAX_FXSLOTS; + } +#endif // ALSOFT_EAX + try { auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback); std::lock_guard _{ListLock}; diff --git a/alc/context.cpp b/alc/context.cpp index c2d3e351..d5fd94b2 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -29,6 +29,14 @@ #include "ringbuffer.h" #include "vecmat.h" +#if ALSOFT_EAX +#include +#include + +#include "alstring.h" +#include "al/eax_exception.h" +#include "al/eax_globals.h" +#endif // ALSOFT_EAX namespace { @@ -121,6 +129,10 @@ ALCcontext::~ALCcontext() mSourceList.clear(); mNumSources = 0; +#if ALSOFT_EAX + eax_uninitialize(); +#endif // ALSOFT_EAX + mDefaultSlot = nullptr; count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u}, [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t @@ -160,6 +172,9 @@ void ALCcontext::init() mExtensionList = alExtList; +#if ALSOFT_EAX + eax_initialize_extensions(); +#endif // ALSOFT_EAX mParams.Position = alu::Vector{0.0f, 0.0f, 0.0f, 1.0f}; mParams.Matrix = alu::Matrix::Identity(); @@ -258,3 +273,1216 @@ void ALCcontext::processUpdates() mHoldUpdates.store(false, std::memory_order_release); } } + +#if ALSOFT_EAX +namespace +{ + + +class ContextException : + public EaxException +{ +public: + explicit ContextException( + const char* message) + : + EaxException{"EAX_CONTEXT", message} + { + } +}; // ContextException + + +} // namespace + + +ALCcontext::SourceListIterator::SourceListIterator( + SourceList& sources, + SourceListIteratorBeginTag) noexcept + : + sub_list_iterator_{sources.begin()}, + sub_list_end_iterator_{sources.end()}, + sub_list_item_index_{} +{ + // Search for first non-free item. + // + while (true) + { + if (sub_list_iterator_ == sub_list_end_iterator_) + { + // End of list. + + sub_list_item_index_ = 0; + return; + } + + if ((~sub_list_iterator_->FreeMask) == 0_u64) + { + // All sub-list's items are free. + + ++sub_list_iterator_; + sub_list_item_index_ = 0; + continue; + } + + if (sub_list_item_index_ >= 64_u64) + { + // Sub-list item's index beyond the last one. + + ++sub_list_iterator_; + sub_list_item_index_ = 0; + continue; + } + + if ((sub_list_iterator_->FreeMask & (1_u64 << sub_list_item_index_)) == 0_u64) + { + // Found non-free item. + + break; + } + + sub_list_item_index_ += 1; + } +} + +ALCcontext::SourceListIterator::SourceListIterator( + SourceList& sources, + SourceListIteratorEndTag) noexcept + : + sub_list_iterator_{sources.end()}, + sub_list_end_iterator_{sources.end()}, + sub_list_item_index_{} +{ +} + +ALCcontext::SourceListIterator::SourceListIterator( + const SourceListIterator& rhs) + : + sub_list_iterator_{rhs.sub_list_iterator_}, + sub_list_end_iterator_{rhs.sub_list_end_iterator_}, + sub_list_item_index_{rhs.sub_list_item_index_} +{ +} + +ALCcontext::SourceListIterator& ALCcontext::SourceListIterator::operator++() +{ + while (true) + { + if (sub_list_iterator_ == sub_list_end_iterator_) + { + // End of list. + + sub_list_item_index_ = 0; + break; + } + + if ((~sub_list_iterator_->FreeMask) == 0_u64) + { + // All sub-list's items are free. + + ++sub_list_iterator_; + sub_list_item_index_ = 0; + continue; + } + + sub_list_item_index_ += 1; + + if (sub_list_item_index_ >= 64_u64) + { + // Sub-list item's index beyond the last one. + + ++sub_list_iterator_; + sub_list_item_index_ = 0; + continue; + } + + if ((sub_list_iterator_->FreeMask & (1_u64 << sub_list_item_index_)) == 0_u64) + { + // Found non-free item. + + break; + } + } + + return *this; +} + +ALsource& ALCcontext::SourceListIterator::operator*() noexcept +{ + assert(sub_list_iterator_ != sub_list_end_iterator_); + return (*sub_list_iterator_).Sources[sub_list_item_index_]; +} + +bool ALCcontext::SourceListIterator::operator==( + const SourceListIterator& rhs) const noexcept +{ + return + sub_list_iterator_ == rhs.sub_list_iterator_ && + sub_list_end_iterator_ == rhs.sub_list_end_iterator_ && + sub_list_item_index_ == rhs.sub_list_item_index_; +} + +bool ALCcontext::SourceListIterator::operator!=( + const SourceListIterator& rhs) const noexcept +{ + return !((*this) == rhs); +} + + +ALCcontext::SourceListEnumerator::SourceListEnumerator( + ALCcontext::SourceList& sources) noexcept + : + sources_{sources} +{ +} + +ALCcontext::SourceListIterator ALCcontext::SourceListEnumerator::begin() noexcept +{ + return SourceListIterator{sources_, SourceListIteratorBeginTag{}}; +} + +ALCcontext::SourceListIterator ALCcontext::SourceListEnumerator::end() noexcept +{ + return SourceListIterator{sources_, SourceListIteratorEndTag{}}; +} + + +bool ALCcontext::has_eax() const noexcept +{ + return eax_is_initialized_; +} + +bool ALCcontext::eax_is_capable() const noexcept +{ + return + eax_has_enough_aux_sends() && + eax_has_eax_reverb_effect(); +} + +void ALCcontext::eax_uninitialize() noexcept +{ + if (!eax_is_initialized_) + { + return; + } + + eax_is_initialized_ = true; + eax_is_tried_ = false; + + eax_fx_slots_.uninitialize(); + eax_al_filter_ = nullptr; +} + +void ALCcontext::eax_initialize_source( + ALsource& al_source) noexcept +try +{ + auto param = EaxSourceInitParam{}; + param.al_context = this; + param.al_filter = eax_al_filter_.get(); + + al_source.eax_initialize(param); +} +catch (...) +{ + eax_log_exception("Failed to initialize a source."); +} + +ALenum ALCcontext::eax_eax_set( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_value, + ALuint property_value_size) +{ + eax_initialize(); + + const auto eax_call = create_eax_call( + false, + property_set_id, + property_id, + property_source_id, + property_value, + property_value_size + ); + + switch (eax_call.get_property_set_id()) + { + case EaxEaxCallPropertySetId::context: + eax_set(eax_call); + break; + + case EaxEaxCallPropertySetId::fx_slot: + case EaxEaxCallPropertySetId::fx_slot_effect: + eax_dispatch_fx_slot(eax_call); + break; + + case EaxEaxCallPropertySetId::source: + eax_dispatch_source(eax_call); + break; + + default: + eax_fail("Unsupported property set id."); + } + + return AL_NO_ERROR; +} + +ALenum ALCcontext::eax_eax_get( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_value, + ALuint property_value_size) +{ + eax_initialize(); + + const auto eax_call = create_eax_call( + true, + property_set_id, + property_id, + property_source_id, + property_value, + property_value_size + ); + + switch (eax_call.get_property_set_id()) + { + case EaxEaxCallPropertySetId::context: + eax_get(eax_call); + break; + + case EaxEaxCallPropertySetId::fx_slot: + case EaxEaxCallPropertySetId::fx_slot_effect: + eax_dispatch_fx_slot(eax_call); + break; + + case EaxEaxCallPropertySetId::source: + eax_dispatch_source(eax_call); + break; + + default: + eax_fail("Unsupported property set id."); + } + + return AL_NO_ERROR; +} + +void ALCcontext::eax_update_filters() +{ + for (auto& source : SourceListEnumerator{mSourceList}) + { + source.eax_update_filters(); + } +} + +void ALCcontext::eax_set_last_error() noexcept +{ + eax_last_error_ = EAXERR_INVALID_OPERATION; +} + +float ALCcontext::eax_get_max_filter_gain() const noexcept +{ + return eax_max_filter_gain_; +} + +float ALCcontext::eax_get_air_absorption_factor() const noexcept +{ + return eax_air_absorption_factor_; +} + +EaxFxSlotIndex ALCcontext::eax_get_previous_primary_fx_slot_index() const noexcept +{ + return eax_previous_primary_fx_slot_index_; +} + +EaxFxSlotIndex ALCcontext::eax_get_primary_fx_slot_index() const noexcept +{ + return eax_primary_fx_slot_index_; +} + +const ALeffectslot& ALCcontext::eax_get_fx_slot( + EaxFxSlotIndexValue fx_slot_index) const +{ + return eax_fx_slots_.get(fx_slot_index); +} + +ALeffectslot& ALCcontext::eax_get_fx_slot( + EaxFxSlotIndexValue fx_slot_index) +{ + return eax_fx_slots_.get(fx_slot_index); +} + +[[noreturn]] +void ALCcontext::eax_fail( + const char* message) +{ + throw ContextException{message}; +} + +void ALCcontext::eax_initialize_extensions() +{ + if (!eax_g_is_enabled) + { + return; + } + + const auto string_max_capacity = + std::strlen(mExtensionList) + 1 + + std::strlen(eax_v2_0_ext_name) + 1 + + std::strlen(eax_v3_0_ext_name) + 1 + + std::strlen(eax_v4_0_ext_name) + 1 + + std::strlen(eax_v5_0_ext_name) + 1 + + std::strlen(eax_x_ram_ext_name) + 1 + + 0; + + eax_extension_list_.reserve(string_max_capacity); + + if (eax_is_capable()) + { + eax_extension_list_ += eax_v2_0_ext_name; + eax_extension_list_ += ' '; + + eax_extension_list_ += eax_v3_0_ext_name; + eax_extension_list_ += ' '; + + eax_extension_list_ += eax_v4_0_ext_name; + eax_extension_list_ += ' '; + + eax_extension_list_ += eax_v5_0_ext_name; + eax_extension_list_ += ' '; + } + + eax_extension_list_ += eax_x_ram_ext_name; + eax_extension_list_ += ' '; + + eax_extension_list_ += mExtensionList; + mExtensionList = eax_extension_list_.c_str(); +} + +void ALCcontext::eax_initialize() +{ + if (eax_is_initialized_) + { + return; + } + + if (eax_is_tried_) + { + eax_fail("No EAX."); + } + + eax_is_tried_ = true; + + if (!eax_g_is_enabled) + { + eax_fail("EAX disabled by a configuration."); + } + + eax_ensure_compatibility(); + eax_initialize_filter_gain(); + eax_initialize_filter(); + eax_set_defaults(); + eax_set_air_absorbtion_hf(); + eax_initialize_fx_slots(); + eax_initialize_sources(); + + eax_is_initialized_ = true; +} + +bool ALCcontext::eax_has_no_default_effect_slot() const noexcept +{ + return mDefaultSlot == nullptr; +} + +void ALCcontext::eax_ensure_no_default_effect_slot() const +{ + if (!eax_has_no_default_effect_slot()) + { + eax_fail("There is a default effect slot in the context."); + } +} + +bool ALCcontext::eax_has_enough_aux_sends() const noexcept +{ + return mALDevice->NumAuxSends >= EAX_MAX_FXSLOTS; +} + +void ALCcontext::eax_ensure_enough_aux_sends() const +{ + if (!eax_has_enough_aux_sends()) + { + eax_fail("Not enough aux sends."); + } +} + +bool ALCcontext::eax_has_eax_reverb_effect() const noexcept +{ + return !DisabledEffects[EAXREVERB_EFFECT]; +} + +void ALCcontext::eax_ensure_eax_reverb_effect() const +{ + if (!eax_has_eax_reverb_effect()) + { + eax_fail("Disabled EAX Reverb Effect."); + } +} + +void ALCcontext::eax_ensure_compatibility() +{ + eax_ensure_enough_aux_sends(); + eax_ensure_eax_reverb_effect(); +} + +void ALCcontext::eax_initialize_filter_gain() +{ + eax_max_filter_gain_ = level_mb_to_gain(GainMixMax / mGainBoost); +} + +void ALCcontext::eax_set_last_error_defaults() noexcept +{ + eax_last_error_ = EAX_OK; +} + +void ALCcontext::eax_set_speaker_config_defaults() noexcept +{ + eax_speaker_config_ = HEADPHONES; +} + +void ALCcontext::eax_set_session_defaults() noexcept +{ + eax_session_.ulEAXVersion = EAXCONTEXT_MINEAXSESSION; + eax_session_.ulMaxActiveSends = EAXCONTEXT_DEFAULTMAXACTIVESENDS; +} + +void ALCcontext::eax_set_context_defaults() noexcept +{ + eax_.context.guidPrimaryFXSlotID = EAXCONTEXT_DEFAULTPRIMARYFXSLOTID; + eax_.context.flDistanceFactor = EAXCONTEXT_DEFAULTDISTANCEFACTOR; + eax_.context.flAirAbsorptionHF = EAXCONTEXT_DEFAULTAIRABSORPTIONHF; + eax_.context.flHFReference = EAXCONTEXT_DEFAULTHFREFERENCE; +} + +void ALCcontext::eax_set_defaults() noexcept +{ + eax_set_last_error_defaults(); + eax_set_speaker_config_defaults(); + eax_set_session_defaults(); + eax_set_context_defaults(); + + eax_d_ = eax_; +} + +void ALCcontext::eax_initialize_filter() +{ + eax_al_filter_ = eax_create_al_low_pass_filter(*this); + + if (!eax_al_filter_) + { + eax_fail("Failed to make a low-pass filter."); + } +} + +void ALCcontext::eax_dispatch_fx_slot( + const EaxEaxCall& eax_call) +{ + auto& fx_slot = eax_get_fx_slot(eax_call.get_fx_slot_index()); + + if (fx_slot.eax_dispatch(eax_call)) + { + std::lock_guard source_lock{mSourceLock}; + + eax_update_filters(); + } +} + +void ALCcontext::eax_dispatch_source( + const EaxEaxCall& eax_call) +{ + const auto source_id = eax_call.get_property_al_name(); + + std::lock_guard source_lock{mSourceLock}; + + const auto source = ALsource::eax_lookup_source(*this, source_id); + + if (!source) + { + eax_fail("Source not found."); + } + + source->eax_dispatch(eax_call); +} + +void ALCcontext::eax_get_primary_fx_slot_id( + const EaxEaxCall& eax_call) +{ + eax_call.set_value(eax_.context.guidPrimaryFXSlotID); +} + +void ALCcontext::eax_get_distance_factor( + const EaxEaxCall& eax_call) +{ + eax_call.set_value(eax_.context.flDistanceFactor); +} + +void ALCcontext::eax_get_air_absorption_hf( + const EaxEaxCall& eax_call) +{ + eax_call.set_value(eax_.context.flAirAbsorptionHF); +} + +void ALCcontext::eax_get_hf_reference( + const EaxEaxCall& eax_call) +{ + eax_call.set_value(eax_.context.flHFReference); +} + +void ALCcontext::eax_get_last_error( + const EaxEaxCall& eax_call) +{ + const auto eax_last_error = eax_last_error_; + eax_last_error_ = EAX_OK; + eax_call.set_value(eax_last_error); +} + +void ALCcontext::eax_get_speaker_config( + const EaxEaxCall& eax_call) +{ + eax_call.set_value(eax_speaker_config_); +} + +void ALCcontext::eax_get_session( + const EaxEaxCall& eax_call) +{ + eax_call.set_value(eax_session_); +} + +void ALCcontext::eax_get_macro_fx_factor( + const EaxEaxCall& eax_call) +{ + eax_call.set_value(eax_.context.flMacroFXFactor); +} + +void ALCcontext::eax_get_context_all( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_version()) + { + case 4: + eax_call.set_value(static_cast(eax_.context)); + break; + + case 5: + eax_call.set_value(static_cast(eax_.context)); + break; + + default: + eax_fail("Unsupported EAX version."); + } +} + +void ALCcontext::eax_get( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXCONTEXT_NONE: + break; + + case EAXCONTEXT_ALLPARAMETERS: + eax_get_context_all(eax_call); + break; + + case EAXCONTEXT_PRIMARYFXSLOTID: + eax_get_primary_fx_slot_id(eax_call); + break; + + case EAXCONTEXT_DISTANCEFACTOR: + eax_get_distance_factor(eax_call); + break; + + case EAXCONTEXT_AIRABSORPTIONHF: + eax_get_air_absorption_hf(eax_call); + break; + + case EAXCONTEXT_HFREFERENCE: + eax_get_hf_reference(eax_call); + break; + + case EAXCONTEXT_LASTERROR: + eax_get_last_error(eax_call); + break; + + case EAXCONTEXT_SPEAKERCONFIG: + eax_get_speaker_config(eax_call); + break; + + case EAXCONTEXT_EAXSESSION: + eax_get_session(eax_call); + break; + + case EAXCONTEXT_MACROFXFACTOR: + eax_get_macro_fx_factor(eax_call); + break; + + default: + eax_fail("Unsupported property id."); + } +} + +void ALCcontext::eax_set_primary_fx_slot_id() +{ + eax_previous_primary_fx_slot_index_ = eax_primary_fx_slot_index_; + eax_primary_fx_slot_index_ = eax_.context.guidPrimaryFXSlotID; +} + +void ALCcontext::eax_set_distance_factor() +{ + eax_set_al_listener_meters_per_unit(*this, eax_.context.flDistanceFactor); +} + +void ALCcontext::eax_set_air_absorbtion_hf() +{ + eax_air_absorption_factor_ = eax_.context.flAirAbsorptionHF / EAXCONTEXT_DEFAULTAIRABSORPTIONHF; +} + +void ALCcontext::eax_set_hf_reference() +{ + // TODO +} + +void ALCcontext::eax_set_macro_fx_factor() +{ + // TODO +} + +void ALCcontext::eax_set_context() +{ + eax_set_primary_fx_slot_id(); + eax_set_distance_factor(); + eax_set_air_absorbtion_hf(); + eax_set_hf_reference(); +} + +void ALCcontext::eax_initialize_fx_slots() +{ + eax_fx_slots_.initialize(*this); + eax_previous_primary_fx_slot_index_ = eax_.context.guidPrimaryFXSlotID; + eax_primary_fx_slot_index_ = eax_.context.guidPrimaryFXSlotID; +} + +void ALCcontext::eax_initialize_sources() +{ + std::unique_lock source_lock{mSourceLock}; + + for (auto& source : SourceListEnumerator{mSourceList}) + { + eax_initialize_source(source); + } +} + +void ALCcontext::eax_update_sources() +{ + std::unique_lock source_lock{mSourceLock}; + + for (auto& source : SourceListEnumerator{mSourceList}) + { + source.eax_update(eax_context_shared_dirty_flags_); + } +} + +void ALCcontext::eax_validate_primary_fx_slot_id( + const GUID& primary_fx_slot_id) +{ + if (primary_fx_slot_id != EAX_NULL_GUID && + primary_fx_slot_id != EAXPROPERTYID_EAX40_FXSlot0 && + primary_fx_slot_id != EAXPROPERTYID_EAX50_FXSlot0 && + primary_fx_slot_id != EAXPROPERTYID_EAX40_FXSlot1 && + primary_fx_slot_id != EAXPROPERTYID_EAX50_FXSlot1 && + primary_fx_slot_id != EAXPROPERTYID_EAX40_FXSlot2 && + primary_fx_slot_id != EAXPROPERTYID_EAX50_FXSlot2 && + primary_fx_slot_id != EAXPROPERTYID_EAX40_FXSlot3 && + primary_fx_slot_id != EAXPROPERTYID_EAX50_FXSlot3) + { + eax_fail("Unsupported primary FX slot id."); + } +} + +void ALCcontext::eax_validate_distance_factor( + float distance_factor) +{ + eax_validate_range( + "Distance Factor", + distance_factor, + EAXCONTEXT_MINDISTANCEFACTOR, + EAXCONTEXT_MAXDISTANCEFACTOR); +} + +void ALCcontext::eax_validate_air_absorption_hf( + float air_absorption_hf) +{ + eax_validate_range( + "Air Absorption HF", + air_absorption_hf, + EAXCONTEXT_MINAIRABSORPTIONHF, + EAXCONTEXT_MAXAIRABSORPTIONHF); +} + +void ALCcontext::eax_validate_hf_reference( + float hf_reference) +{ + eax_validate_range( + "HF Reference", + hf_reference, + EAXCONTEXT_MINHFREFERENCE, + EAXCONTEXT_MAXHFREFERENCE); +} + +void ALCcontext::eax_validate_speaker_config( + unsigned long speaker_config) +{ + switch (speaker_config) + { + case HEADPHONES: + case SPEAKERS_2: + case SPEAKERS_4: + case SPEAKERS_5: + case SPEAKERS_6: + case SPEAKERS_7: + break; + + default: + eax_fail("Unsupported speaker configuration."); + } +} + +void ALCcontext::eax_validate_session_eax_version( + unsigned long eax_version) +{ + switch (eax_version) + { + case EAX_40: + case EAX_50: + break; + + default: + eax_fail("Unsupported session EAX version."); + } +} + +void ALCcontext::eax_validate_session_max_active_sends( + unsigned long max_active_sends) +{ + eax_validate_range( + "Max Active Sends", + max_active_sends, + EAXCONTEXT_MINMAXACTIVESENDS, + EAXCONTEXT_MAXMAXACTIVESENDS); +} + +void ALCcontext::eax_validate_session( + const EAXSESSIONPROPERTIES& eax_session) +{ + eax_validate_session_eax_version(eax_session.ulEAXVersion); + eax_validate_session_max_active_sends(eax_session.ulMaxActiveSends); +} + +void ALCcontext::eax_validate_macro_fx_factor( + float macro_fx_factor) +{ + eax_validate_range( + "Macro FX Factor", + macro_fx_factor, + EAXCONTEXT_MINMACROFXFACTOR, + EAXCONTEXT_MAXMACROFXFACTOR); +} + +void ALCcontext::eax_validate_context_all( + const EAX40CONTEXTPROPERTIES& context_all) +{ + eax_validate_primary_fx_slot_id(context_all.guidPrimaryFXSlotID); + eax_validate_distance_factor(context_all.flDistanceFactor); + eax_validate_air_absorption_hf(context_all.flAirAbsorptionHF); + eax_validate_hf_reference(context_all.flHFReference); +} + +void ALCcontext::eax_validate_context_all( + const EAX50CONTEXTPROPERTIES& context_all) +{ + eax_validate_context_all(static_cast(context_all)); + eax_validate_macro_fx_factor(context_all.flMacroFXFactor); +} + +void ALCcontext::eax_defer_primary_fx_slot_id( + const GUID& primary_fx_slot_id) +{ + eax_d_.context.guidPrimaryFXSlotID = primary_fx_slot_id; + + eax_context_dirty_flags_.guidPrimaryFXSlotID = + (eax_.context.guidPrimaryFXSlotID != eax_d_.context.guidPrimaryFXSlotID); +} + +void ALCcontext::eax_defer_distance_factor( + float distance_factor) +{ + eax_d_.context.flDistanceFactor = distance_factor; + + eax_context_dirty_flags_.flDistanceFactor = + (eax_.context.flDistanceFactor != eax_d_.context.flDistanceFactor); +} + +void ALCcontext::eax_defer_air_absorption_hf( + float air_absorption_hf) +{ + eax_d_.context.flAirAbsorptionHF = air_absorption_hf; + + eax_context_dirty_flags_.flAirAbsorptionHF = + (eax_.context.flAirAbsorptionHF != eax_d_.context.flAirAbsorptionHF); +} + +void ALCcontext::eax_defer_hf_reference( + float hf_reference) +{ + eax_d_.context.flHFReference = hf_reference; + + eax_context_dirty_flags_.flHFReference = + (eax_.context.flHFReference != eax_d_.context.flHFReference); +} + +void ALCcontext::eax_defer_macro_fx_factor( + float macro_fx_factor) +{ + eax_d_.context.flMacroFXFactor = macro_fx_factor; + + eax_context_dirty_flags_.flMacroFXFactor = + (eax_.context.flMacroFXFactor != eax_d_.context.flMacroFXFactor); +} + +void ALCcontext::eax_defer_context_all( + const EAX40CONTEXTPROPERTIES& context_all) +{ + eax_defer_primary_fx_slot_id(context_all.guidPrimaryFXSlotID); + eax_defer_distance_factor(context_all.flDistanceFactor); + eax_defer_air_absorption_hf(context_all.flAirAbsorptionHF); + eax_defer_hf_reference(context_all.flHFReference); +} + +void ALCcontext::eax_defer_context_all( + const EAX50CONTEXTPROPERTIES& context_all) +{ + eax_defer_context_all(static_cast(context_all)); + eax_defer_macro_fx_factor(context_all.flMacroFXFactor); +} + +void ALCcontext::eax_defer_context_all( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_version()) + { + case 4: + { + const auto& context_all = + eax_call.get_value(); + + eax_validate_context_all(context_all); + } + + break; + + case 5: + { + const auto& context_all = + eax_call.get_value(); + + eax_validate_context_all(context_all); + } + + break; + + default: + eax_fail("Unsupported EAX version."); + } +} + +void ALCcontext::eax_defer_primary_fx_slot_id( + const EaxEaxCall& eax_call) +{ + const auto& primary_fx_slot_id = + eax_call.get_value(); + + eax_validate_primary_fx_slot_id(primary_fx_slot_id); + eax_defer_primary_fx_slot_id(primary_fx_slot_id); +} + +void ALCcontext::eax_defer_distance_factor( + const EaxEaxCall& eax_call) +{ + const auto& distance_factor = + eax_call.get_value(); + + eax_validate_distance_factor(distance_factor); + eax_defer_distance_factor(distance_factor); +} + +void ALCcontext::eax_defer_air_absorption_hf( + const EaxEaxCall& eax_call) +{ + const auto& air_absorption_hf = + eax_call.get_value(); + + eax_validate_air_absorption_hf(air_absorption_hf); + eax_defer_air_absorption_hf(air_absorption_hf); +} + +void ALCcontext::eax_defer_hf_reference( + const EaxEaxCall& eax_call) +{ + const auto& hf_reference = + eax_call.get_value(); + + eax_validate_hf_reference(hf_reference); + eax_defer_hf_reference(hf_reference); +} + +void ALCcontext::eax_set_speaker_config( + const EaxEaxCall& eax_call) +{ + const auto speaker_config = + eax_call.get_value(); + + eax_validate_speaker_config(speaker_config); + + eax_speaker_config_ = speaker_config; +} + +void ALCcontext::eax_set_session( + const EaxEaxCall& eax_call) +{ + const auto& eax_session = + eax_call.get_value(); + + eax_validate_session(eax_session); + + eax_session_ = eax_session; +} + +void ALCcontext::eax_defer_macro_fx_factor( + const EaxEaxCall& eax_call) +{ + const auto& macro_fx_factor = + eax_call.get_value(); + + eax_validate_macro_fx_factor(macro_fx_factor); + eax_defer_macro_fx_factor(macro_fx_factor); +} + +void ALCcontext::eax_set( + const EaxEaxCall& eax_call) +{ + switch (eax_call.get_property_id()) + { + case EAXCONTEXT_NONE: + break; + + case EAXCONTEXT_ALLPARAMETERS: + eax_defer_context_all(eax_call); + break; + + case EAXCONTEXT_PRIMARYFXSLOTID: + eax_defer_primary_fx_slot_id(eax_call); + break; + + case EAXCONTEXT_DISTANCEFACTOR: + eax_defer_distance_factor(eax_call); + break; + + case EAXCONTEXT_AIRABSORPTIONHF: + eax_defer_air_absorption_hf(eax_call); + break; + + case EAXCONTEXT_HFREFERENCE: + eax_defer_hf_reference(eax_call); + break; + + case EAXCONTEXT_LASTERROR: + eax_fail("Setting last error not supported."); + + case EAXCONTEXT_SPEAKERCONFIG: + eax_set_speaker_config(eax_call); + break; + + case EAXCONTEXT_EAXSESSION: + eax_set_session(eax_call); + break; + + case EAXCONTEXT_MACROFXFACTOR: + eax_defer_macro_fx_factor(eax_call); + break; + + default: + eax_fail("Unsupported property id."); + } + + if (!eax_call.is_deferred()) + { + eax_apply_deferred(); + } +} + +void ALCcontext::eax_apply_deferred() +{ + if (eax_context_dirty_flags_ == ContextDirtyFlags{}) + { + return; + } + + eax_ = eax_d_; + + if (eax_context_dirty_flags_.guidPrimaryFXSlotID) + { + eax_context_shared_dirty_flags_.primary_fx_slot_id = true; + eax_set_primary_fx_slot_id(); + } + + if (eax_context_dirty_flags_.flDistanceFactor) + { + eax_set_distance_factor(); + } + + if (eax_context_dirty_flags_.flAirAbsorptionHF) + { + eax_context_shared_dirty_flags_.air_absorption_hf = true; + eax_set_air_absorbtion_hf(); + } + + if (eax_context_dirty_flags_.flHFReference) + { + eax_set_hf_reference(); + } + + if (eax_context_dirty_flags_.flMacroFXFactor) + { + eax_set_macro_fx_factor(); + } + + if (eax_context_shared_dirty_flags_ != EaxContextSharedDirtyFlags{}) + { + eax_update_sources(); + } + + eax_context_shared_dirty_flags_ = EaxContextSharedDirtyFlags{}; + eax_context_dirty_flags_ = ContextDirtyFlags{}; +} + + +namespace +{ + + +class EaxSetException : + public EaxException +{ +public: + explicit EaxSetException( + const char* message) + : + EaxException{"EAX_SET", message} + { + } +}; // EaxSetException + + +[[noreturn]] +void eax_fail_set( + const char* message) +{ + throw EaxSetException{message}; +} + + +class EaxGetException : + public EaxException +{ +public: + explicit EaxGetException( + const char* message) + : + EaxException{"EAX_GET", message} + { + } +}; // EaxGetException + + +[[noreturn]] +void eax_fail_get( + const char* message) +{ + throw EaxGetException{message}; +} + + +} // namespace + + +ALenum AL_APIENTRY EAXSet( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_value, + ALuint property_value_size) noexcept +try +{ + auto context = GetContextRef(); + + if (!context) + { + eax_fail_set("No current context."); + } + + std::lock_guard prop_lock{context->mPropLock}; + + return context->eax_eax_set( + property_set_id, + property_id, + property_source_id, + property_value, + property_value_size + ); +} +catch (...) +{ + eax_log_exception(__func__); + return AL_INVALID_OPERATION; +} + +ALenum AL_APIENTRY EAXGet( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_value, + ALuint property_value_size) noexcept +try +{ + auto context = GetContextRef(); + + if (!context) + { + eax_fail_get("No current context."); + } + + std::lock_guard prop_lock{context->mPropLock}; + + return context->eax_eax_get( + property_set_id, + property_id, + property_source_id, + property_value, + property_value_size + ); +} +catch (...) +{ + eax_log_exception(__func__); + return AL_INVALID_OPERATION; +} +#endif // ALSOFT_EAX diff --git a/alc/context.h b/alc/context.h index 87754235..b34807b8 100644 --- a/alc/context.h +++ b/alc/context.h @@ -19,6 +19,49 @@ #include "intrusive_ptr.h" #include "vector.h" +#if ALSOFT_EAX +#include "al/filter.h" + +#include "al/eax_eax_call.h" +#include "al/eax_fx_slot_index.h" +#include "al/eax_fx_slots.h" +#include "al/eax_utils.h" +#endif // ALSOFT_EAX + + +#if ALSOFT_EAX +using EaxContextSharedDirtyFlagsValue = std::uint_least8_t; + +struct EaxContextSharedDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + EaxContextSharedDirtyFlagsValue primary_fx_slot_id : 1; + EaxContextSharedDirtyFlagsValue air_absorption_hf : 1; +}; // EaxContextSharedDirtyFlags + + +using ContextDirtyFlagsValue = std::uint_least8_t; + +struct ContextDirtyFlags +{ + using EaxIsBitFieldStruct = bool; + + ContextDirtyFlagsValue guidPrimaryFXSlotID : 1; + ContextDirtyFlagsValue flDistanceFactor : 1; + ContextDirtyFlagsValue flAirAbsorptionHF : 1; + ContextDirtyFlagsValue flHFReference : 1; + ContextDirtyFlagsValue flMacroFXFactor : 1; +}; // ContextDirtyFlags + + +struct EaxAlIsExtensionPresentResult +{ + ALboolean is_present; + bool is_return; +}; // EaxAlIsExtensionPresentResult +#endif // ALSOFT_EAX + struct ALeffect; struct ALeffectslot; struct ALsource; @@ -162,6 +205,332 @@ public: static ALeffect sDefaultEffect; DEF_NEWDEL(ALCcontext) + +#if ALSOFT_EAX +public: + bool has_eax() const noexcept; + + bool eax_is_capable() const noexcept; + + + void eax_uninitialize() noexcept; + + void eax_initialize_source( + ALsource& al_source) noexcept; + + + ALenum eax_eax_set( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_value, + ALuint property_value_size); + + ALenum eax_eax_get( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_value, + ALuint property_value_size); + + + void eax_update_filters(); + + + void eax_set_last_error() noexcept; + + + float eax_get_max_filter_gain() const noexcept; + + float eax_get_air_absorption_factor() const noexcept; + + EaxFxSlotIndex eax_get_previous_primary_fx_slot_index() const noexcept; + + EaxFxSlotIndex eax_get_primary_fx_slot_index() const noexcept; + + const ALeffectslot& eax_get_fx_slot( + EaxFxSlotIndexValue fx_slot_index) const; + + ALeffectslot& eax_get_fx_slot( + EaxFxSlotIndexValue fx_slot_index); + + +private: + using SourceList = al::vector; + + + struct SourceListIteratorBeginTag{}; + struct SourceListIteratorEndTag{}; + + class SourceListIterator + { + public: + SourceListIterator( + SourceList& sources, + SourceListIteratorBeginTag) noexcept; + + SourceListIterator( + SourceList& sources, + SourceListIteratorEndTag) noexcept; + + SourceListIterator( + const SourceListIterator& rhs); + + SourceListIterator& operator=( + const SourceListIterator& rhs) = delete; + + SourceListIterator& operator++(); + + ALsource& operator*() noexcept; + + bool operator==( + const SourceListIterator& rhs) const noexcept; + + bool operator!=( + const SourceListIterator& rhs) const noexcept; + + + private: + SourceList::iterator sub_list_iterator_; + SourceList::iterator sub_list_end_iterator_; + std::uint64_t sub_list_item_index_; + }; // SourceListIterator + + class SourceListEnumerator + { + public: + explicit SourceListEnumerator( + SourceList& sources) noexcept; + + SourceListEnumerator( + const SourceListEnumerator& rhs) = delete; + + SourceListEnumerator& operator=( + const SourceListEnumerator& rhs) = delete; + + SourceListIterator begin() noexcept; + + SourceListIterator end() noexcept; + + + private: + SourceList& sources_; + }; // SourceListEnumerator + + + struct Eax + { + EAX50CONTEXTPROPERTIES context{}; + }; // Eax + + + bool eax_is_initialized_{}; + bool eax_is_tried_{}; + + long eax_last_error_{}; + unsigned long eax_speaker_config_{}; + + float eax_max_filter_gain_{}; + float eax_air_absorption_factor_{}; + EaxFxSlotIndex eax_previous_primary_fx_slot_index_{}; + EaxFxSlotIndex eax_primary_fx_slot_index_{}; + EaxFxSlots eax_fx_slots_{}; + + EaxContextSharedDirtyFlags eax_context_shared_dirty_flags_{}; + + EaxAlFilterUPtr eax_al_filter_{}; + Eax eax_{}; + Eax eax_d_{}; + EAXSESSIONPROPERTIES eax_session_{}; + + ContextDirtyFlags eax_context_dirty_flags_{}; + + std::string eax_extension_list_{}; + + + [[noreturn]] + static void eax_fail( + const char* message); + + + void eax_initialize_extensions(); + + void eax_initialize(); + + + bool eax_has_no_default_effect_slot() const noexcept; + + void eax_ensure_no_default_effect_slot() const; + + bool eax_has_enough_aux_sends() const noexcept; + + void eax_ensure_enough_aux_sends() const; + + bool eax_has_eax_reverb_effect() const noexcept; + + void eax_ensure_eax_reverb_effect() const; + + void eax_ensure_compatibility(); + + + void eax_initialize_filter_gain(); + + void eax_set_last_error_defaults() noexcept; + + void eax_set_speaker_config_defaults() noexcept; + + void eax_set_session_defaults() noexcept; + + void eax_set_context_defaults() noexcept; + + void eax_set_defaults() noexcept; + + void eax_initialize_filter(); + + void eax_initialize_sources(); + + + void eax_dispatch_fx_slot( + const EaxEaxCall& eax_call); + + void eax_dispatch_source( + const EaxEaxCall& eax_call); + + + void eax_get_primary_fx_slot_id( + const EaxEaxCall& eax_call); + + void eax_get_distance_factor( + const EaxEaxCall& eax_call); + + void eax_get_air_absorption_hf( + const EaxEaxCall& eax_call); + + void eax_get_hf_reference( + const EaxEaxCall& eax_call); + + void eax_get_last_error( + const EaxEaxCall& eax_call); + + void eax_get_speaker_config( + const EaxEaxCall& eax_call); + + void eax_get_session( + const EaxEaxCall& eax_call); + + void eax_get_macro_fx_factor( + const EaxEaxCall& eax_call); + + void eax_get_context_all( + const EaxEaxCall& eax_call); + + void eax_get( + const EaxEaxCall& eax_call); + + + void eax_set_primary_fx_slot_id(); + + void eax_set_distance_factor(); + + void eax_set_air_absorbtion_hf(); + + void eax_set_hf_reference(); + + void eax_set_macro_fx_factor(); + + void eax_set_context(); + + void eax_initialize_fx_slots(); + + + void eax_update_sources(); + + + void eax_validate_primary_fx_slot_id( + const GUID& primary_fx_slot_id); + + void eax_validate_distance_factor( + float distance_factor); + + void eax_validate_air_absorption_hf( + float air_absorption_hf); + + void eax_validate_hf_reference( + float hf_reference); + + void eax_validate_speaker_config( + unsigned long speaker_config); + + void eax_validate_session_eax_version( + unsigned long eax_version); + + void eax_validate_session_max_active_sends( + unsigned long max_active_sends); + + void eax_validate_session( + const EAXSESSIONPROPERTIES& eax_session); + + void eax_validate_macro_fx_factor( + float macro_fx_factor); + + void eax_validate_context_all( + const EAX40CONTEXTPROPERTIES& context_all); + + void eax_validate_context_all( + const EAX50CONTEXTPROPERTIES& context_all); + + + void eax_defer_primary_fx_slot_id( + const GUID& primary_fx_slot_id); + + void eax_defer_distance_factor( + float distance_factor); + + void eax_defer_air_absorption_hf( + float air_absorption_hf); + + void eax_defer_hf_reference( + float hf_reference); + + void eax_defer_macro_fx_factor( + float macro_fx_factor); + + void eax_defer_context_all( + const EAX40CONTEXTPROPERTIES& context_all); + + void eax_defer_context_all( + const EAX50CONTEXTPROPERTIES& context_all); + + + void eax_defer_context_all( + const EaxEaxCall& eax_call); + + void eax_defer_primary_fx_slot_id( + const EaxEaxCall& eax_call); + + void eax_defer_distance_factor( + const EaxEaxCall& eax_call); + + void eax_defer_air_absorption_hf( + const EaxEaxCall& eax_call); + + void eax_defer_hf_reference( + const EaxEaxCall& eax_call); + + void eax_set_speaker_config( + const EaxEaxCall& eax_call); + + void eax_set_session( + const EaxEaxCall& eax_call); + + void eax_defer_macro_fx_factor( + const EaxEaxCall& eax_call); + + void eax_set( + const EaxEaxCall& eax_call); + + void eax_apply_deferred(); +#endif // ALSOFT_EAX }; #define SETERR_RETURN(ctx, err, retval, ...) do { \ @@ -179,4 +548,21 @@ void UpdateContextProps(ALCcontext *context); extern bool TrapALError; + +#if ALSOFT_EAX +ALenum AL_APIENTRY EAXSet( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_value, + ALuint property_value_size) noexcept; + +ALenum AL_APIENTRY EAXGet( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_value, + ALuint property_value_size) noexcept; +#endif // ALSOFT_EAX + #endif /* ALC_CONTEXT_H */ diff --git a/alc/device.h b/alc/device.h index 4798d422..e4eb76ea 100644 --- a/alc/device.h +++ b/alc/device.h @@ -18,6 +18,10 @@ #include "intrusive_ptr.h" #include "vector.h" +#if ALSOFT_EAX +#include "al/eax_x_ram.h" +#endif // ALSOFT_EAX + struct ALbuffer; struct ALeffect; struct ALfilter; @@ -106,6 +110,10 @@ struct ALCdevice : public al::intrusive_ref, DeviceBase { std::mutex FilterLock; al::vector FilterList; +#if ALSOFT_EAX + ALsizei eax_x_ram_free_size{eax_x_ram_max_size}; +#endif // ALSOFT_EAX + ALCdevice(DeviceType type); ~ALCdevice(); diff --git a/alsoftrc.sample b/alsoftrc.sample index e2a45579..ab0345d9 100644 --- a/alsoftrc.sample +++ b/alsoftrc.sample @@ -578,3 +578,11 @@ # Creates AMB format files using first-order ambisonics instead of a standard # single- or multi-channel .wav file. #bformat = false + +## +## EAX extensions stuff +## +[eax] +##enable: +# Sets whether to enable EAX extensions or not. +#enable = true diff --git a/common/alnumeric.h b/common/alnumeric.h index c16f3e62..d72ba1e3 100644 --- a/common/alnumeric.h +++ b/common/alnumeric.h @@ -1,6 +1,10 @@ #ifndef AL_NUMERIC_H #define AL_NUMERIC_H +#if ALSOFT_EAX +#include +#endif // ALSOFT_EAX + #include #include #ifdef HAVE_INTRIN_H @@ -271,4 +275,45 @@ inline float fast_roundf(float f) noexcept #endif } +#if ALSOFT_EAX +template< + typename T +> +inline constexpr const T& clamp( + const T& value, + const T& min_value, + const T& max_value) noexcept +{ + return value < min_value ? min_value : (value > max_value ? max_value : value); +} + +// Converts level (mB) to gain. +inline float level_mb_to_gain( + float x) +{ + if (x <= -10'000.0F) + { + return 0.0F; + } + else + { + return std::pow(10.0F, x / 2'000.0F); + } +} + +// Converts gain to level (mB). +inline float gain_to_level_mb( + float x) +{ + if (x <= 0.0F) + { + return -10'000.0F; + } + else + { + return std::log10(x * 2'000.0F); + } +} +#endif // ALSOFT_EAX + #endif /* AL_NUMERIC_H */ -- cgit v1.2.3 From 816bd8ab309dc0fe9afefcc5e3f2c294d3dc60a5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 30 Jan 2022 05:42:44 -0800 Subject: Move ALSOFT_EAX definition to config.h And disable it by default for non-Windows targets --- CMakeLists.txt | 4 +--- al/auxeffectslot.cpp | 8 +++----- al/auxeffectslot.h | 6 +++--- al/buffer.cpp | 15 ++++++--------- al/buffer.h | 4 ++-- al/eax_api.cpp | 1 + al/eax_eax_call.cpp | 2 ++ al/eax_effect.cpp | 2 ++ al/eax_exception.cpp | 2 ++ al/eax_fx_slot_index.cpp | 2 ++ al/eax_fx_slots.cpp | 2 ++ al/eax_globals.cpp | 2 ++ al/eax_utils.cpp | 3 ++- al/eax_x_ram.cpp | 2 ++ al/effect.cpp | 7 +++---- al/effect.h | 9 ++++----- al/effects/autowah.cpp | 11 +++-------- al/effects/chorus.cpp | 11 +++-------- al/effects/compressor.cpp | 11 +++-------- al/effects/distortion.cpp | 11 +++-------- al/effects/echo.cpp | 11 +++-------- al/effects/effects.cpp | 9 +++++---- al/effects/effects.h | 4 ++-- al/effects/equalizer.cpp | 11 +++-------- al/effects/fshifter.cpp | 11 +++-------- al/effects/modulator.cpp | 11 +++-------- al/effects/null.cpp | 11 +++-------- al/effects/pshifter.cpp | 11 +++-------- al/effects/reverb.cpp | 11 +++-------- al/effects/vmorpher.cpp | 10 +++------- al/extension.cpp | 8 ++++---- al/filter.cpp | 4 ++-- al/filter.h | 9 ++++----- al/listener.cpp | 2 +- al/listener.h | 2 +- al/source.cpp | 15 +++++++-------- al/source.h | 13 ++++++------- al/state.cpp | 4 ++-- alc/alc.cpp | 8 ++++---- alc/context.cpp | 12 +++++------- alc/context.h | 28 +++++++++++++--------------- alc/device.h | 4 ++-- common/alnumeric.h | 46 +++++++++++++--------------------------------- config.h.in | 3 +++ 44 files changed, 149 insertions(+), 224 deletions(-) (limited to 'al/effects/distortion.cpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index 9480910b..148090c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,7 +95,7 @@ option(ALSOFT_INSTALL_EXAMPLES "Install example programs (alplay, alstream, ...) option(ALSOFT_INSTALL_UTILS "Install utility programs (openal-info, alsoft-config, ...)" ON) option(ALSOFT_UPDATE_BUILD_VERSION "Update git build version info" ON) -option(ALSOFT_EAX "Enable EAX extensions." ON) +option(ALSOFT_EAX "Enable EAX extensions." $) if(DEFINED SHARE_INSTALL_DIR) message(WARNING "SHARE_INSTALL_DIR is deprecated. Use the variables provided by the GNUInstallDirs module instead") @@ -1316,7 +1316,6 @@ target_include_directories(common PRIVATE ${OpenAL_BINARY_DIR} ${OpenAL_SOURCE_D target_compile_definitions(common PRIVATE ${CPP_DEFS}) target_compile_options(common PRIVATE ${C_FLAGS}) set_target_properties(common PROPERTIES POSITION_INDEPENDENT_CODE TRUE) -target_compile_definitions(common PRIVATE "ALSOFT_EAX=$") unset(HAS_ROUTER) @@ -1438,7 +1437,6 @@ set_target_properties(${IMPL_TARGET} PROPERTIES OUTPUT_NAME ${LIBNAME} target_compile_definitions(${IMPL_TARGET} PRIVATE AL_BUILD_LIBRARY AL_ALEXT_PROTOTYPES "ALC_API=${EXPORT_DECL}" "AL_API=${EXPORT_DECL}" ${CPP_DEFS}) -target_compile_definitions(${IMPL_TARGET} PRIVATE "ALSOFT_EAX=$") target_compile_options(${IMPL_TARGET} PRIVATE ${C_FLAGS}) if(TARGET build_version) diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 40949aa3..4382553e 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -50,7 +50,7 @@ #include "effect.h" #include "opthelpers.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "eax_exception.h" #include "eax_utils.h" #endif // ALSOFT_EAX @@ -1047,10 +1047,8 @@ EffectSlotSubList::~EffectSlotSubList() EffectSlots = nullptr; } -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { class EaxFxSlotException : public EaxException diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 54f1987d..12213df6 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -16,7 +16,7 @@ #include "intrusive_ptr.h" #include "vector.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include #include "al/effect.h" @@ -72,7 +72,7 @@ struct ALeffectslot { DEF_NEWDEL(ALeffectslot) -#if ALSOFT_EAX +#ifdef ALSOFT_EAX public: void eax_initialize( ALCcontext& al_context, @@ -258,7 +258,7 @@ private: void UpdateAllEffectSlotProps(ALCcontext *context); -#if ALSOFT_EAX +#ifdef ALSOFT_EAX class EaxAlEffectSlotDeleter { public: diff --git a/al/buffer.cpp b/al/buffer.cpp index a4967223..8a5bee25 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -56,7 +56,7 @@ #include "core/voice.h" #include "opthelpers.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "eax_globals.h" #include "eax_x_ram.h" #endif // ALSOFT_EAX @@ -417,7 +417,7 @@ ALbuffer *AllocBuffer(ALCdevice *device) void FreeBuffer(ALCdevice *device, ALbuffer *buffer) { -#if ALSOFT_EAX +#ifdef ALSOFT_EAX if (buffer->eax_x_ram_is_hardware) { const auto buffer_size = static_cast(buffer->OriginalSize); @@ -499,7 +499,7 @@ const ALchar *NameFromUserFmtType(UserFmtType type) return ""; } -#if ALSOFT_EAX +#ifdef ALSOFT_EAX bool eax_x_ram_validate_buffer( ALCdevice& al_device, ALbuffer& al_buffer) @@ -731,7 +731,7 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size, ALBuf->mLoopStart = 0; ALBuf->mLoopEnd = ALBuf->mSampleLen; -#if ALSOFT_EAX +#ifdef ALSOFT_EAX if (eax_g_is_enabled) { eax_x_ram_update_buffer(*context->mALDevice, *ALBuf); @@ -1006,8 +1006,8 @@ START_API_FUNC if UNLIKELY(!usrfmt) context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format); else -#if ALSOFT_EAX { +#ifdef ALSOFT_EAX if (eax_g_is_enabled) { const auto is_buffer_valid = eax_x_ram_validate_buffer(*device, *albuf); @@ -1021,9 +1021,7 @@ START_API_FUNC #endif // ALSOFT_EAX LoadData(context.get(), albuf, freq, static_cast(size), usrfmt->channels, usrfmt->type, static_cast(data), flags); -#if ALSOFT_EAX } -#endif // ALSOFT_EAX } } END_API_FUNC @@ -1777,7 +1775,7 @@ BufferSubList::~BufferSubList() } -#if ALSOFT_EAX +#ifdef ALSOFT_EAX ALboolean AL_APIENTRY EAXSetBufferMode( ALsizei n, const ALuint* buffers, @@ -1932,5 +1930,4 @@ START_API_FUNC } END_API_FUNC - #endif // ALSOFT_EAX diff --git a/al/buffer.h b/al/buffer.h index 0514d984..8c323bea 100644 --- a/al/buffer.h +++ b/al/buffer.h @@ -12,7 +12,7 @@ #include "core/buffer_storage.h" #include "vector.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "eax_x_ram.h" #endif // ALSOFT_EAX @@ -72,7 +72,7 @@ struct ALbuffer : public BufferStorage { DISABLE_ALLOC() -#if ALSOFT_EAX +#ifdef ALSOFT_EAX ALenum eax_x_ram_mode{AL_STORAGE_AUTOMATIC}; bool eax_x_ram_is_hardware{}; bool eax_x_ram_is_dirty{}; diff --git a/al/eax_api.cpp b/al/eax_api.cpp index 9907dd4d..391363ec 100644 --- a/al/eax_api.cpp +++ b/al/eax_api.cpp @@ -5,6 +5,7 @@ // https://github.com/id-Software/DOOM-3/tree/master/neo/openal/include // +#include "config.h" #include diff --git a/al/eax_eax_call.cpp b/al/eax_eax_call.cpp index e6967ded..e9cb2746 100644 --- a/al/eax_eax_call.cpp +++ b/al/eax_eax_call.cpp @@ -1,3 +1,5 @@ +#include "config.h" + #include "al/eax_eax_call.h" #include "al/eax_exception.h" diff --git a/al/eax_effect.cpp b/al/eax_effect.cpp index 72af94fc..9cbf4c13 100644 --- a/al/eax_effect.cpp +++ b/al/eax_effect.cpp @@ -1 +1,3 @@ +#include "config.h" + #include "eax_effect.h" diff --git a/al/eax_exception.cpp b/al/eax_exception.cpp index e3635793..c8ecf79d 100644 --- a/al/eax_exception.cpp +++ b/al/eax_exception.cpp @@ -1,3 +1,5 @@ +#include "config.h" + #include "eax_exception.h" #include diff --git a/al/eax_fx_slot_index.cpp b/al/eax_fx_slot_index.cpp index dffaef47..484c3499 100644 --- a/al/eax_fx_slot_index.cpp +++ b/al/eax_fx_slot_index.cpp @@ -1,3 +1,5 @@ +#include "config.h" + #include "eax_fx_slot_index.h" #include "eax_exception.h" diff --git a/al/eax_fx_slots.cpp b/al/eax_fx_slots.cpp index 41b18f77..63e867ec 100644 --- a/al/eax_fx_slots.cpp +++ b/al/eax_fx_slots.cpp @@ -1,3 +1,5 @@ +#include "config.h" + #include "eax_fx_slots.h" #include diff --git a/al/eax_globals.cpp b/al/eax_globals.cpp index e2f4681e..454144a9 100644 --- a/al/eax_globals.cpp +++ b/al/eax_globals.cpp @@ -1,3 +1,5 @@ +#include "config.h" + #include "eax_globals.h" diff --git a/al/eax_utils.cpp b/al/eax_utils.cpp index 9a8f04f1..67389de4 100644 --- a/al/eax_utils.cpp +++ b/al/eax_utils.cpp @@ -1,7 +1,8 @@ +#include "config.h" + #include "eax_utils.h" #include - #include #include "core/logging.h" diff --git a/al/eax_x_ram.cpp b/al/eax_x_ram.cpp index d11a03ab..ac3e7ebb 100644 --- a/al/eax_x_ram.cpp +++ b/al/eax_x_ram.cpp @@ -1 +1,3 @@ +#include "config.h" + #include "eax_x_ram.h" diff --git a/al/effect.cpp b/al/effect.cpp index 79cd7fab..e4fe95b3 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -51,7 +51,7 @@ #include "opthelpers.h" #include "vector.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include #include "eax_exception.h" @@ -751,9 +751,8 @@ void LoadReverbPreset(const char *name, ALeffect *effect) WARN("Reverb preset '%s' not found\n", name); } -#if ALSOFT_EAX -namespace -{ +#ifdef ALSOFT_EAX +namespace { class EaxAlEffectException : public EaxException diff --git a/al/effect.h b/al/effect.h index 5b5e4b03..0e4948f7 100644 --- a/al/effect.h +++ b/al/effect.h @@ -7,7 +7,7 @@ #include "al/effects/effects.h" #include "alc/effects/base.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include #include "eax_effect.h" @@ -59,7 +59,7 @@ struct ALeffect { DISABLE_ALLOC() -#if ALSOFT_EAX +#ifdef ALSOFT_EAX public: EaxEffectUPtr eax_effect{}; @@ -81,9 +81,8 @@ void InitEffect(ALeffect *effect); void LoadReverbPreset(const char *name, ALeffect *effect); -#if ALSOFT_EAX -class EaxAlEffectDeleter -{ +#ifdef ALSOFT_EAX +class EaxAlEffectDeleter { public: EaxAlEffectDeleter() noexcept = default; diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index bdd1bc09..6dbafca3 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -11,7 +11,7 @@ #include "alc/effects/base.h" #include "effects.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "alnumeric.h" #include "al/eax_exception.h" @@ -116,10 +116,8 @@ DEFINE_ALEFFECT_VTABLE(Autowah); const EffectProps AutowahEffectProps{genDefaultProps()}; -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { using EaxAutoWahEffectDirtyFlagsValue = std::uint_least8_t; @@ -566,15 +564,12 @@ bool EaxAutoWahEffect::set( return false; } - } // namespace - EaxEffectUPtr eax_create_eax_auto_wah_effect( EffectProps& al_effect_props) { return std::make_unique<::EaxAutoWahEffect>(al_effect_props); } - #endif // ALSOFT_EAX diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index ed994fbb..37651406 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -11,7 +11,7 @@ #include "core/logging.h" #include "effects.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include #include "alnumeric.h" @@ -290,10 +290,8 @@ DEFINE_ALEFFECT_VTABLE(Flanger); const EffectProps FlangerEffectProps{genDefaultFlangerProps()}; -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { void eax_set_efx_waveform( ALenum waveform, @@ -1507,15 +1505,12 @@ bool EaxFlangerEffect::set( return false; } - } // namespace - EaxEffectUPtr eax_create_eax_flanger_effect( EffectProps& al_effect_props) { return std::make_unique(al_effect_props); } - #endif // ALSOFT_EAX diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp index 868c5c1b..a4835178 100644 --- a/al/effects/compressor.cpp +++ b/al/effects/compressor.cpp @@ -7,7 +7,7 @@ #include "alc/effects/base.h" #include "effects.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "alnumeric.h" #include "al/eax_exception.h" @@ -78,10 +78,8 @@ DEFINE_ALEFFECT_VTABLE(Compressor); const EffectProps CompressorEffectProps{genDefaultProps()}; -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { using EaxCompressorEffectDirtyFlagsValue = std::uint_least8_t; @@ -330,15 +328,12 @@ bool EaxCompressorEffect::set( return false; } - } // namespace - EaxEffectUPtr eax_create_eax_compressor_effect( EffectProps& al_effect_props) { return std::make_unique(al_effect_props); } - #endif // ALSOFT_EAX diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index 062cdc54..d0c9a3c2 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -7,7 +7,7 @@ #include "alc/effects/base.h" #include "effects.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "alnumeric.h" #include "al/eax_exception.h" @@ -120,10 +120,8 @@ DEFINE_ALEFFECT_VTABLE(Distortion); const EffectProps DistortionEffectProps{genDefaultProps()}; -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { using EaxDistortionEffectDirtyFlagsValue = std::uint_least8_t; @@ -636,15 +634,12 @@ bool EaxDistortionEffect::set( return false; } - } // namespace - EaxEffectUPtr eax_create_eax_distortion_effect( EffectProps& al_effect_props) { return std::make_unique(al_effect_props); } - #endif // ALSOFT_EAX diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index 5ceb161d..7e7a38bc 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -7,7 +7,7 @@ #include "alc/effects/base.h" #include "effects.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "alnumeric.h" #include "al/eax_exception.h" @@ -117,10 +117,8 @@ DEFINE_ALEFFECT_VTABLE(Echo); const EffectProps EchoEffectProps{genDefaultProps()}; -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { using EaxEchoEffectDirtyFlagsValue = std::uint_least8_t; @@ -631,15 +629,12 @@ bool EaxEchoEffect::set( return false; } - } // namespace - EaxEffectUPtr eax_create_eax_echo_effect( EffectProps& al_effect_props) { return std::make_unique(al_effect_props); } - #endif // ALSOFT_EAX diff --git a/al/effects/effects.cpp b/al/effects/effects.cpp index 55abfdc5..ede88f91 100644 --- a/al/effects/effects.cpp +++ b/al/effects/effects.cpp @@ -1,12 +1,14 @@ -#if ALSOFT_EAX +#include "config.h" + +#ifdef ALSOFT_EAX + +#include "effects.h" #include #include "AL/efx.h" -#include "effects.h" - EaxEffectUPtr eax_create_eax_null_effect(); @@ -102,5 +104,4 @@ EaxEffectUPtr eax_create_eax_effect( #undef EAX_PREFIX } - #endif // ALSOFT_EAX diff --git a/al/effects/effects.h b/al/effects/effects.h index 6813beaa..a2ab8485 100644 --- a/al/effects/effects.h +++ b/al/effects/effects.h @@ -5,7 +5,7 @@ #include "core/except.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "al/eax_effect.h" #endif // ALSOFT_EAX @@ -85,7 +85,7 @@ extern const EffectVtable DedicatedEffectVtable; extern const EffectVtable ConvolutionEffectVtable; -#if ALSOFT_EAX +#ifdef ALSOFT_EAX EaxEffectUPtr eax_create_eax_effect( ALenum al_effect_type, EffectProps& al_effect_props); diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index c052db3e..4ff26178 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -7,7 +7,7 @@ #include "alc/effects/base.h" #include "effects.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "alnumeric.h" #include "al/eax_exception.h" @@ -175,10 +175,8 @@ DEFINE_ALEFFECT_VTABLE(Equalizer); const EffectProps EqualizerEffectProps{genDefaultProps()}; -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { using EaxEqualizerEffectDirtyFlagsValue = std::uint_least16_t; @@ -1021,15 +1019,12 @@ bool EaxEqualizerEffect::set( return false; } - } // namespace - EaxEffectUPtr eax_create_eax_equalizer_effect( EffectProps& al_effect_props) { return std::make_unique(al_effect_props); } - #endif // ALSOFT_EAX diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index aa4ddadb..74ef52d9 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -10,7 +10,7 @@ #include "aloptional.h" #include "effects.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include #include "alnumeric.h" @@ -138,10 +138,8 @@ DEFINE_ALEFFECT_VTABLE(Fshifter); const EffectProps FshifterEffectProps{genDefaultProps()}; -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { using EaxFrequencyShifterEffectDirtyFlagsValue = std::uint_least8_t; @@ -530,15 +528,12 @@ bool EaxFrequencyShifterEffect::set( return false; } - } // namespace - EaxEffectUPtr eax_create_eax_frequency_shifter_effect( EffectProps& al_effect_props) { return std::make_unique(al_effect_props); } - #endif // ALSOFT_EAX diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index 6a30dc09..c33db8c3 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -10,7 +10,7 @@ #include "aloptional.h" #include "effects.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include #include "alnumeric.h" @@ -144,10 +144,8 @@ DEFINE_ALEFFECT_VTABLE(Modulator); const EffectProps ModulatorEffectProps{genDefaultProps()}; -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { using EaxRingModulatorEffectDirtyFlagsValue = std::uint_least8_t; @@ -533,15 +531,12 @@ bool EaxRingModulatorEffect::set( return false; } - } // namespace - EaxEffectUPtr eax_create_eax_ring_modulator_effect( EffectProps& al_effect_props) { return std::make_unique(al_effect_props); } - #endif // ALSOFT_EAX diff --git a/al/effects/null.cpp b/al/effects/null.cpp index 44595208..8b68eec0 100644 --- a/al/effects/null.cpp +++ b/al/effects/null.cpp @@ -7,7 +7,7 @@ #include "alc/effects/base.h" #include "effects.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "al/eax_exception.h" #endif // ALSOFT_EAX @@ -97,10 +97,8 @@ DEFINE_ALEFFECT_VTABLE(Null); const EffectProps NullEffectProps{genDefaultProps()}; -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { class EaxNullEffect final : public EaxEffect @@ -137,14 +135,11 @@ bool EaxNullEffect::dispatch( return false; } - } // namespace - EaxEffectUPtr eax_create_eax_null_effect() { return std::make_unique(); } - #endif // ALSOFT_EAX diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp index 03f9a139..7c355be1 100644 --- a/al/effects/pshifter.cpp +++ b/al/effects/pshifter.cpp @@ -7,7 +7,7 @@ #include "alc/effects/base.h" #include "effects.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "alnumeric.h" #include "al/eax_exception.h" @@ -90,10 +90,8 @@ DEFINE_ALEFFECT_VTABLE(Pshifter); const EffectProps PshifterEffectProps{genDefaultProps()}; -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { using EaxPitchShifterEffectDirtyFlagsValue = std::uint_least8_t; @@ -408,15 +406,12 @@ bool EaxPitchShifterEffect::set( return false; } - } // namespace - EaxEffectUPtr eax_create_eax_pitch_shifter_effect( EffectProps& al_effect_props) { return std::make_unique(al_effect_props); } - #endif // ALSOFT_EAX diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index 8012450d..a8404f8b 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -9,7 +9,7 @@ #include "alc/effects/base.h" #include "effects.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include #include "alnumeric.h" @@ -564,10 +564,8 @@ DEFINE_ALEFFECT_VTABLE(StdReverb); const EffectProps StdReverbEffectProps{genDefaultStdProps()}; -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { using EaxReverbEffectDirtyFlagsValue = std::uint_least32_t; @@ -2464,15 +2462,12 @@ bool EaxReverbEffect::set( return false; } - } // namespace - EaxEffectUPtr eax_create_eax_reverb_effect( EffectProps& al_effect_props) { return std::make_unique(al_effect_props); } - #endif // ALSOFT_EAX diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index 2a9e0702..2ea2594e 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -10,7 +10,7 @@ #include "aloptional.h" #include "effects.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include #include "alnumeric.h" @@ -257,10 +257,8 @@ DEFINE_ALEFFECT_VTABLE(Vmorpher); const EffectProps VmorpherEffectProps{genDefaultProps()}; -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { using EaxVocalMorpherEffectDirtyFlagsValue = std::uint_least8_t; @@ -859,7 +857,6 @@ bool EaxVocalMorpherEffect::set( return false; } - } // namespace @@ -869,5 +866,4 @@ EaxEffectUPtr eax_create_eax_vocal_morpher_effect( return std::make_unique(al_effect_props); } - #endif // ALSOFT_EAX diff --git a/al/extension.cpp b/al/extension.cpp index 373f87a9..6d9d181a 100644 --- a/al/extension.cpp +++ b/al/extension.cpp @@ -32,7 +32,7 @@ #include "core/except.h" #include "opthelpers.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "eax_globals.h" #include "eax_x_ram.h" #endif // ALSOFT_EAX @@ -47,7 +47,7 @@ START_API_FUNC SETERR_RETURN(context, AL_INVALID_VALUE, AL_FALSE, "NULL pointer"); size_t len{strlen(extName)}; -#if ALSOFT_EAX +#ifdef ALSOFT_EAX if (al::strncasecmp(eax_v2_0_ext_name, extName, len) == 0 || al::strncasecmp(eax_v3_0_ext_name, extName, len) == 0 || al::strncasecmp(eax_v4_0_ext_name, extName, len) == 0 || @@ -86,7 +86,7 @@ AL_API ALvoid* AL_APIENTRY alGetProcAddress(const ALchar *funcName) START_API_FUNC { if(!funcName) return nullptr; -#if ALSOFT_EAX +#ifdef ALSOFT_EAX if (al::strcasecmp(funcName, eax_eax_set_func_name) == 0) { if (!eax_g_is_enabled) @@ -163,7 +163,7 @@ AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *enumName) START_API_FUNC { if(!enumName) return static_cast(0); -#if ALSOFT_EAX +#ifdef ALSOFT_EAX if (eax_g_is_enabled) { struct Descriptor diff --git a/al/filter.cpp b/al/filter.cpp index 563fb3ef..9989063b 100644 --- a/al/filter.cpp +++ b/al/filter.cpp @@ -45,7 +45,7 @@ #include "opthelpers.h" #include "vector.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "core/logging.h" #endif // ALSOFT_EAX @@ -723,7 +723,7 @@ FilterSubList::~FilterSubList() } -#if ALSOFT_EAX +#ifdef ALSOFT_EAX EaxAlFilterDeleter::EaxAlFilterDeleter( ALCcontext& context) : diff --git a/al/filter.h b/al/filter.h index 222a6917..98c32325 100644 --- a/al/filter.h +++ b/al/filter.h @@ -8,7 +8,7 @@ #include "almalloc.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include #include "eax_utils.h" @@ -54,7 +54,7 @@ struct ALfilter { DISABLE_ALLOC() -#if ALSOFT_EAX +#ifdef ALSOFT_EAX public: void eax_set_low_pass_params( ALCcontext& context, @@ -62,9 +62,8 @@ public: #endif // ALSOFT_EAX }; -#if ALSOFT_EAX -class EaxAlFilterDeleter -{ +#ifdef ALSOFT_EAX +class EaxAlFilterDeleter { public: EaxAlFilterDeleter() noexcept = default; diff --git a/al/listener.cpp b/al/listener.cpp index 1909c644..16c3f6a5 100644 --- a/al/listener.cpp +++ b/al/listener.cpp @@ -451,7 +451,7 @@ void UpdateListenerProps(ALCcontext *context) } } -#if ALSOFT_EAX +#ifdef ALSOFT_EAX // `alListenerf(AL_METERS_PER_UNIT, value)` void eax_set_al_listener_meters_per_unit( ALCcontext& al_context, diff --git a/al/listener.h b/al/listener.h index 05cd3abf..df20ee69 100644 --- a/al/listener.h +++ b/al/listener.h @@ -29,7 +29,7 @@ struct ALlistener { void UpdateListenerProps(ALCcontext *context); -#if ALSOFT_EAX +#ifdef ALSOFT_EAX // `alListenerf(AL_METERS_PER_UNIT, value)` void eax_set_al_listener_meters_per_unit( ALCcontext& al_context, diff --git a/al/source.cpp b/al/source.cpp index 3f7fa540..a306404c 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -72,7 +72,7 @@ #include "ringbuffer.h" #include "threads.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "eax_exception.h" #include "eax_globals.h" #endif // ALSOFT_EAX @@ -2419,7 +2419,7 @@ START_API_FUNC ALsource *source{AllocSource(context.get())}; sources[0] = source->id; -#if ALSOFT_EAX +#ifdef ALSOFT_EAX if (context->has_eax()) { std::unique_lock prop_lock{context->mPropLock}; @@ -2429,7 +2429,7 @@ START_API_FUNC } else { -#if ALSOFT_EAX +#ifdef ALSOFT_EAX auto eax_sources = al::vector{}; if (context->has_eax()) @@ -2444,7 +2444,7 @@ START_API_FUNC ALsource *source{AllocSource(context.get())}; ids.emplace_back(source->id); -#if ALSOFT_EAX +#ifdef ALSOFT_EAX if (context->has_eax()) { eax_sources.emplace_back(source); @@ -2453,7 +2453,7 @@ START_API_FUNC } while(--n); std::copy(ids.cbegin(), ids.cend(), sources); -#if ALSOFT_EAX +#ifdef ALSOFT_EAX if (context->has_eax()) { std::unique_lock prop_lock{context->mPropLock}; @@ -3595,7 +3595,7 @@ ALsource::ALsource() ALsource::~ALsource() { -#if ALSOFT_EAX +#ifdef ALSOFT_EAX eax_uninitialize(); #endif // ALSOFT_EAX @@ -3643,7 +3643,7 @@ SourceSubList::~SourceSubList() } -#if ALSOFT_EAX +#ifdef ALSOFT_EAX class EaxSourceException : public EaxException { @@ -6083,5 +6083,4 @@ void ALsource::eax_al_source_3i( SetSourceiv(this, eax_al_context_, static_cast(param), values); } - #endif // ALSOFT_EAX diff --git a/al/source.h b/al/source.h index 41cd6187..2fbb7b22 100644 --- a/al/source.h +++ b/al/source.h @@ -21,7 +21,7 @@ #include "core/voice.h" #include "vector.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "eax_eax_call.h" #include "eax_fx_slot_index.h" #include "eax_utils.h" @@ -47,11 +47,10 @@ struct ALbufferQueueItem : public VoiceBufferItem { }; -#if ALSOFT_EAX -struct EaxSourceInitParam -{ - ALCcontext* al_context{}; - ALfilter* al_filter{}; +#ifdef ALSOFT_EAX +struct EaxSourceInitParam { + ALCcontext* al_context{}; + ALfilter* al_filter{}; }; // EaxSourceInitParam @@ -213,7 +212,7 @@ struct ALsource { DISABLE_ALLOC() -#if ALSOFT_EAX +#ifdef ALSOFT_EAX public: void eax_initialize( const EaxSourceInitParam& param) noexcept; diff --git a/al/state.cpp b/al/state.cpp index 0ec0e280..bd62c4e3 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -46,7 +46,7 @@ #include "opthelpers.h" #include "strutils.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "alc/device.h" #include "eax_globals.h" @@ -434,7 +434,7 @@ START_API_FUNC value = static_cast(ResamplerDefault); break; -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #define EAX_ERROR "[alGetInteger] EAX not enabled." diff --git a/alc/alc.cpp b/alc/alc.cpp index b9f322a3..4effcc67 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -155,7 +155,7 @@ #include "backends/wave.h" #endif -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "al/eax_globals.h" #include "al/eax_x_ram.h" #endif // ALSOFT_EAX @@ -881,7 +881,7 @@ constexpr struct { DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), -#if ALSOFT_EAX +#ifdef ALSOFT_EAX DECL(AL_EAX_RAM_SIZE), DECL(AL_EAX_RAM_FREE), DECL(AL_STORAGE_AUTOMATIC), @@ -1258,7 +1258,7 @@ void alc_initconfig(void) if(defrevopt || (defrevopt=ConfigValueStr(nullptr, nullptr, "default-reverb"))) LoadReverbPreset(defrevopt->c_str(), &ALCcontext::sDefaultEffect); -#if ALSOFT_EAX +#ifdef ALSOFT_EAX { constexpr auto eax_block_name = "eax"; @@ -3223,7 +3223,7 @@ START_API_FUNC device->AuxiliaryEffectSlotMax = 64; device->NumAuxSends = DEFAULT_SENDS; -#if ALSOFT_EAX +#ifdef ALSOFT_EAX if (eax_g_is_enabled) { device->NumAuxSends = EAX_MAX_FXSLOTS; diff --git a/alc/context.cpp b/alc/context.cpp index d5fd94b2..33e9e7e0 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -29,7 +29,7 @@ #include "ringbuffer.h" #include "vecmat.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include #include @@ -129,7 +129,7 @@ ALCcontext::~ALCcontext() mSourceList.clear(); mNumSources = 0; -#if ALSOFT_EAX +#ifdef ALSOFT_EAX eax_uninitialize(); #endif // ALSOFT_EAX @@ -172,7 +172,7 @@ void ALCcontext::init() mExtensionList = alExtList; -#if ALSOFT_EAX +#ifdef ALSOFT_EAX eax_initialize_extensions(); #endif // ALSOFT_EAX @@ -274,10 +274,8 @@ void ALCcontext::processUpdates() } } -#if ALSOFT_EAX -namespace -{ - +#ifdef ALSOFT_EAX +namespace { class ContextException : public EaxException diff --git a/alc/context.h b/alc/context.h index b34807b8..b964d813 100644 --- a/alc/context.h +++ b/alc/context.h @@ -19,17 +19,15 @@ #include "intrusive_ptr.h" #include "vector.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "al/filter.h" #include "al/eax_eax_call.h" #include "al/eax_fx_slot_index.h" #include "al/eax_fx_slots.h" #include "al/eax_utils.h" -#endif // ALSOFT_EAX -#if ALSOFT_EAX using EaxContextSharedDirtyFlagsValue = std::uint_least8_t; struct EaxContextSharedDirtyFlags @@ -206,7 +204,7 @@ public: DEF_NEWDEL(ALCcontext) -#if ALSOFT_EAX +#ifdef ALSOFT_EAX public: bool has_eax() const noexcept; @@ -549,20 +547,20 @@ void UpdateContextProps(ALCcontext *context); extern bool TrapALError; -#if ALSOFT_EAX +#ifdef ALSOFT_EAX ALenum AL_APIENTRY EAXSet( - const GUID* property_set_id, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_value, - ALuint property_value_size) noexcept; + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_value, + ALuint property_value_size) noexcept; ALenum AL_APIENTRY EAXGet( - const GUID* property_set_id, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_value, - ALuint property_value_size) noexcept; + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_value, + ALuint property_value_size) noexcept; #endif // ALSOFT_EAX #endif /* ALC_CONTEXT_H */ diff --git a/alc/device.h b/alc/device.h index e4eb76ea..daade87a 100644 --- a/alc/device.h +++ b/alc/device.h @@ -18,7 +18,7 @@ #include "intrusive_ptr.h" #include "vector.h" -#if ALSOFT_EAX +#ifdef ALSOFT_EAX #include "al/eax_x_ram.h" #endif // ALSOFT_EAX @@ -110,7 +110,7 @@ struct ALCdevice : public al::intrusive_ref, DeviceBase { std::mutex FilterLock; al::vector FilterList; -#if ALSOFT_EAX +#ifdef ALSOFT_EAX ALsizei eax_x_ram_free_size{eax_x_ram_max_size}; #endif // ALSOFT_EAX diff --git a/common/alnumeric.h b/common/alnumeric.h index d72ba1e3..18df2689 100644 --- a/common/alnumeric.h +++ b/common/alnumeric.h @@ -1,10 +1,8 @@ #ifndef AL_NUMERIC_H #define AL_NUMERIC_H -#if ALSOFT_EAX +#include #include -#endif // ALSOFT_EAX - #include #include #ifdef HAVE_INTRIN_H @@ -275,45 +273,27 @@ inline float fast_roundf(float f) noexcept #endif } -#if ALSOFT_EAX -template< - typename T -> -inline constexpr const T& clamp( - const T& value, - const T& min_value, - const T& max_value) noexcept + +template +constexpr const T& clamp(const T& value, const T& min_value, const T& max_value) noexcept { - return value < min_value ? min_value : (value > max_value ? max_value : value); + return std::min(std::max(value, min_value), max_value); } // Converts level (mB) to gain. -inline float level_mb_to_gain( - float x) +inline float level_mb_to_gain(float x) { - if (x <= -10'000.0F) - { - return 0.0F; - } - else - { - return std::pow(10.0F, x / 2'000.0F); - } + if(x <= -10'000.0f) + return 0.0f; + return std::pow(10.0f, x / 2'000.0f); } // Converts gain to level (mB). -inline float gain_to_level_mb( - float x) +inline float gain_to_level_mb(float x) { - if (x <= 0.0F) - { - return -10'000.0F; - } - else - { - return std::log10(x * 2'000.0F); - } + if (x <= 0.0f) + return -10'000.0f; + return std::log10(x * 2'000.0f); } -#endif // ALSOFT_EAX #endif /* AL_NUMERIC_H */ diff --git a/config.h.in b/config.h.in index b06314a8..588d45a5 100644 --- a/config.h.in +++ b/config.h.in @@ -1,3 +1,6 @@ +/* Define if deprecated EAX extensions are enabled */ +#cmakedefine ALSOFT_EAX + /* Define if HRTF data is embedded in the library */ #cmakedefine ALSOFT_EMBED_HRTF_DATA -- cgit v1.2.3 From 0c507b5c621993206d94fc3776174eb96823f265 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 7 Feb 2022 10:17:13 -0800 Subject: Avoid using ALeffect to manage EaxEffect objects Effect slots can just use its EaxEffect directly. --- al/auxeffectslot.cpp | 53 ++++-------------- al/auxeffectslot.h | 16 ++---- al/eax_effect.h | 8 ++- al/eax_fx_slots.cpp | 1 - al/effect.cpp | 138 +++------------------------------------------- al/effect.h | 52 +---------------- al/effects/autowah.cpp | 16 ++---- al/effects/chorus.cpp | 31 ++++------- al/effects/compressor.cpp | 16 ++---- al/effects/distortion.cpp | 16 ++---- al/effects/echo.cpp | 16 ++---- al/effects/effects.cpp | 80 +++++++++------------------ al/effects/effects.h | 4 +- al/effects/equalizer.cpp | 16 ++---- al/effects/fshifter.cpp | 16 ++---- al/effects/modulator.cpp | 16 ++---- al/effects/null.cpp | 7 +++ al/effects/pshifter.cpp | 18 ++---- al/effects/reverb.cpp | 18 ++---- al/effects/vmorpher.cpp | 18 ++---- 20 files changed, 124 insertions(+), 432 deletions(-) (limited to 'al/effects/distortion.cpp') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index e0f2be73..5ddd2a28 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -1091,11 +1091,6 @@ void ALeffectslot::eax_initialize( eax_set_default_slots_defaults(); } -void ALeffectslot::eax_uninitialize() noexcept -{ - eax_al_effect_ = nullptr; -} - const EAX50FXSLOTPROPERTIES& ALeffectslot::eax_get_eax_fx_slot() const noexcept { return eax_eax_fx_slot_; @@ -1436,21 +1431,13 @@ bool ALeffectslot::eax_get( void ALeffectslot::eax_set_fx_slot_effect( ALenum al_effect_type) { - if (!eax_al_effect_) - { - eax_al_effect_ = eax_create_al_effect(*eax_al_context_, al_effect_type); - } - else - { - auto& device = eax_al_context_->mALDevice; - std::lock_guard effect_lock{device->EffectLock}; - - eax_al_effect_->eax_al_set_effect(al_effect_type); - } + if(!IsValidEffectType(al_effect_type)) + eax_fail("Unsupported effect."); - eax_al_effect_->eax_initialize(); + eax_effect_ = nullptr; + eax_effect_ = eax_create_eax_effect(al_effect_type); - eax_set_effect_slot_effect(*eax_al_effect_); + eax_set_effect_slot_effect(*eax_effect_); } void ALeffectslot::eax_set_fx_slot_effect() @@ -1704,35 +1691,17 @@ void ALeffectslot::eax_dispatch_effect( const EaxEaxCall& eax_call) { auto is_changed = false; - - { - std::lock_guard effect_lock{eax_al_context_->mALDevice->EffectLock}; - - if (!eax_al_effect_->eax_effect) - { - return; - } - - is_changed = eax_al_effect_->eax_effect->dispatch(eax_call); - } - - if (is_changed) - { - eax_set_effect_slot_effect(*eax_al_effect_); - } + if(eax_effect_) + is_changed = eax_effect_->dispatch(eax_call); + if(is_changed) + eax_set_effect_slot_effect(*eax_effect_); } -void ALeffectslot::eax_set_effect_slot_effect( - ALeffect& effect) +void ALeffectslot::eax_set_effect_slot_effect(EaxEffect &effect) { #define EAX_PREFIX "[EAX_SET_EFFECT_SLOT_EFFECT] " - auto& device = *eax_al_context_->mALDevice; - - std::lock_guard effect_slot_lock{eax_al_context_->mEffectSlotLock}; - std::lock_guard effect_lock{device.EffectLock}; - - const auto error = initEffect(effect.type, effect.Props, eax_al_context_); + const auto error = initEffect(effect.al_effect_type_, effect.al_effect_props_, eax_al_context_); if (error != AL_NO_ERROR) { ERR(EAX_PREFIX "%s\n", "Failed to initialize an effect."); diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 2c462cd0..8182c082 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -19,9 +19,8 @@ #ifdef ALSOFT_EAX #include -#include "al/effect.h" - #include "eax_eax_call.h" +#include "eax_effect.h" #include "eax_fx_slot_index.h" #endif // ALSOFT_EAX @@ -78,8 +77,6 @@ public: ALCcontext& al_context, EaxFxSlotIndexValue index); - void eax_uninitialize() noexcept; - const EAX50FXSLOTPROPERTIES& eax_get_eax_fx_slot() const noexcept; @@ -96,7 +93,7 @@ private: EAX50FXSLOTPROPERTIES eax_eax_fx_slot_{}; - EaxAlEffectUPtr eax_al_effect_{}; + EaxEffectUPtr eax_effect_{}; [[noreturn]] @@ -243,16 +240,13 @@ private: // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)` - void eax_set_effect_slot_effect( - ALeffect& effect); + void eax_set_effect_slot_effect(EaxEffect &effect); // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, value)` - void eax_set_effect_slot_send_auto( - bool is_send_auto); + void eax_set_effect_slot_send_auto(bool is_send_auto); // `alAuxiliaryEffectSlotf(effect_slot, AL_EFFECTSLOT_GAIN, gain)` - void eax_set_effect_slot_gain( - ALfloat gain); + void eax_set_effect_slot_gain(ALfloat gain); #endif // ALSOFT_EAX }; diff --git a/al/eax_effect.h b/al/eax_effect.h index 23dbb73e..2688ca9b 100644 --- a/al/eax_effect.h +++ b/al/eax_effect.h @@ -4,16 +4,18 @@ #include +#include "AL/al.h" +#include "core/effects/base.h" #include "eax_eax_call.h" - class EaxEffect { public: - EaxEffect() = default; - + EaxEffect(ALenum type) : al_effect_type_{type} { } virtual ~EaxEffect() = default; + const ALenum al_effect_type_; + EffectProps al_effect_props_{}; // Returns "true" if any immediated property was changed. // [[nodiscard]] diff --git a/al/eax_fx_slots.cpp b/al/eax_fx_slots.cpp index 63e867ec..f2db3ede 100644 --- a/al/eax_fx_slots.cpp +++ b/al/eax_fx_slots.cpp @@ -39,7 +39,6 @@ void EaxFxSlots::uninitialize() noexcept { for (auto& fx_slot : fx_slots_) { - fx_slot->eax_uninitialize(); fx_slot = nullptr; } } diff --git a/al/effect.cpp b/al/effect.cpp index e4fe95b3..5a74ca53 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -751,139 +751,15 @@ void LoadReverbPreset(const char *name, ALeffect *effect) WARN("Reverb preset '%s' not found\n", name); } -#ifdef ALSOFT_EAX -namespace { - -class EaxAlEffectException : - public EaxException -{ -public: - explicit EaxAlEffectException( - const char* message) - : - EaxException{"[EAX_AL_EFFECT]", message} - { - } -}; // EaxAlEffectException - - -} // namespace - - -void ALeffect::eax_initialize() -{ - eax_effect = nullptr; - eax_effect = eax_create_eax_effect(type, Props); -} - -void ALeffect::eax_al_set_effect( - ALenum al_effect_type) -{ - if (al_effect_type != AL_EFFECT_NULL) - { - auto has_effect = false; - - for (const auto &effect_item : gEffectList) - { - if (al_effect_type == effect_item.val && !DisabledEffects[effect_item.type]) - { - has_effect = true; - break; - } - } - - if (!has_effect) - { - eax_fail("Effect not available."); - } - } - - InitEffectParams(this, al_effect_type); -} - -[[noreturn]] -void ALeffect::eax_fail( - const char* message) -{ - throw EaxAlEffectException{message}; -} - -EaxAlEffectDeleter::EaxAlEffectDeleter( - ALCcontext& context) noexcept - : - context_{&context} -{ -} - -void EaxAlEffectDeleter::operator()( - ALeffect* effect) const -{ - assert(effect); - - eax_al_delete_effect(*context_, *effect); -} - -EaxAlEffectUPtr eax_create_al_effect( - ALCcontext& context, - ALenum effect_type) +bool IsValidEffectType(ALenum type) noexcept { -#define EAX_PREFIX "[EAX_MAKE_EFFECT] " + if(type == AL_EFFECT_NULL) + return true; - auto& device = *context.mALDevice; - std::lock_guard effect_lock{device.EffectLock}; - - // Allocate. - // - if (!EnsureEffects(&device, 1)) + for(const auto &effect_item : gEffectList) { - ERR(EAX_PREFIX "%s\n", "Failed to ensure."); - return nullptr; + if(type == effect_item.val && !DisabledEffects[effect_item.type]) + return true; } - - auto effect = EaxAlEffectUPtr{AllocEffect(&device), EaxAlEffectDeleter{context}}; - - if (!effect) - { - ERR(EAX_PREFIX "%s\n", "Failed to allocate."); - return nullptr; - } - - // Set the type. - // - auto is_supported = (effect_type == AL_EFFECT_NULL); - - if (!is_supported) - { - for (const auto& effect_item : gEffectList) - { - if(effect_type == effect_item.val && !DisabledEffects[effect_item.type]) - { - is_supported = true; - break; - } - } - } - - if (!is_supported) - { - ERR(EAX_PREFIX "Effect type 0x%04x not supported.\n", effect_type); - return nullptr; - } - - InitEffectParams(effect.get(), effect_type); - - return effect; - -#undef EAX_PREFIX -} - -void eax_al_delete_effect( - ALCcontext& context, - ALeffect& effect) -{ - auto& device = *context.mALDevice; - std::lock_guard effect_lock{device.EffectLock}; - - FreeEffect(&device, &effect); + return false; } -#endif // ALSOFT_EAX diff --git a/al/effect.h b/al/effect.h index 0e4948f7..a1d43313 100644 --- a/al/effect.h +++ b/al/effect.h @@ -7,12 +7,6 @@ #include "al/effects/effects.h" #include "alc/effects/base.h" -#ifdef ALSOFT_EAX -#include - -#include "eax_effect.h" -#endif // ALSOFT_EAX - enum { EAXREVERB_EFFECT = 0, @@ -57,56 +51,12 @@ struct ALeffect { ALuint id{0u}; DISABLE_ALLOC() - - -#ifdef ALSOFT_EAX -public: - EaxEffectUPtr eax_effect{}; - - - void eax_initialize(); - - void eax_al_set_effect( - ALenum al_effect_type); - - -private: - [[noreturn]] - static void eax_fail( - const char* message); -#endif // ALSOFT_EAX }; void InitEffect(ALeffect *effect); void LoadReverbPreset(const char *name, ALeffect *effect); -#ifdef ALSOFT_EAX -class EaxAlEffectDeleter { -public: - EaxAlEffectDeleter() noexcept = default; - - EaxAlEffectDeleter( - ALCcontext& context) noexcept; - - void operator()( - ALeffect* effect) const; - - -private: - ALCcontext* context_{}; -}; // EaxAlEffectDeleter - -using EaxAlEffectUPtr = std::unique_ptr; - - -EaxAlEffectUPtr eax_create_al_effect( - ALCcontext& context, - ALenum effect_type); - -void eax_al_delete_effect( - ALCcontext& context, - ALeffect& effect); -#endif // ALSOFT_EAX +bool IsValidEffectType(ALenum type) noexcept; #endif diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 6dbafca3..51f8fff6 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -136,8 +136,7 @@ class EaxAutoWahEffect final : public EaxEffect { public: - EaxAutoWahEffect( - EffectProps& al_effect_props); + EaxAutoWahEffect(); // [[nodiscard]] @@ -146,8 +145,6 @@ public: private: - EffectProps& al_effect_props_; - EAXAUTOWAHPROPERTIES eax_{}; EAXAUTOWAHPROPERTIES eax_d_{}; EaxAutoWahEffectDirtyFlags eax_dirty_flags_{}; @@ -241,10 +238,8 @@ public: }; // EaxAutoWahEffectException -EaxAutoWahEffect::EaxAutoWahEffect( - EffectProps& al_effect_props) - : - al_effect_props_{al_effect_props} +EaxAutoWahEffect::EaxAutoWahEffect() + : EaxEffect{AL_EFFECT_AUTOWAH} { set_eax_defaults(); set_efx_defaults(); @@ -566,10 +561,9 @@ bool EaxAutoWahEffect::set( } // namespace -EaxEffectUPtr eax_create_eax_auto_wah_effect( - EffectProps& al_effect_props) +EaxEffectUPtr eax_create_eax_auto_wah_effect() { - return std::make_unique<::EaxAutoWahEffect>(al_effect_props); + return std::make_unique<::EaxAutoWahEffect>(); } #endif // ALSOFT_EAX diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index 37651406..15b9d635 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -357,8 +357,7 @@ class EaxChorusEffect final : public EaxEffect { public: - EaxChorusEffect( - EffectProps& al_effect_props); + EaxChorusEffect(); // [[nodiscard]] @@ -367,7 +366,6 @@ public: private: - EffectProps& al_effect_props_; EAXCHORUSPROPERTIES eax_{}; EAXCHORUSPROPERTIES eax_d_{}; EaxChorusEffectDirtyFlags eax_dirty_flags_{}; @@ -484,10 +482,8 @@ public: }; // EaxChorusEffectException -EaxChorusEffect::EaxChorusEffect( - EffectProps& al_effect_props) - : - al_effect_props_{al_effect_props} +EaxChorusEffect::EaxChorusEffect() + : EaxEffect{AL_EFFECT_CHORUS} { set_eax_defaults(); set_efx_defaults(); @@ -917,10 +913,9 @@ bool EaxChorusEffect::set( } // namespace -EaxEffectUPtr eax_create_eax_chorus_effect( - EffectProps& al_effect_props) +EaxEffectUPtr eax_create_eax_chorus_effect() { - return std::make_unique<::EaxChorusEffect>(al_effect_props); + return std::make_unique<::EaxChorusEffect>(); } @@ -947,8 +942,7 @@ class EaxFlangerEffect final : public EaxEffect { public: - EaxFlangerEffect( - EffectProps& al_effect_props); + EaxFlangerEffect(); // [[nodiscard]] @@ -957,8 +951,6 @@ public: private: - EffectProps& al_effect_props_; - EAXFLANGERPROPERTIES eax_{}; EAXFLANGERPROPERTIES eax_d_{}; EaxFlangerEffectDirtyFlags eax_dirty_flags_{}; @@ -1075,10 +1067,8 @@ public: }; // EaxFlangerEffectException -EaxFlangerEffect::EaxFlangerEffect( - EffectProps& al_effect_props) - : - al_effect_props_{al_effect_props} +EaxFlangerEffect::EaxFlangerEffect() + : EaxEffect{AL_EFFECT_FLANGER} { set_eax_defaults(); set_efx_defaults(); @@ -1507,10 +1497,9 @@ bool EaxFlangerEffect::set( } // namespace -EaxEffectUPtr eax_create_eax_flanger_effect( - EffectProps& al_effect_props) +EaxEffectUPtr eax_create_eax_flanger_effect() { - return std::make_unique(al_effect_props); + return std::make_unique(); } #endif // ALSOFT_EAX diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp index a4835178..d4a8e9c2 100644 --- a/al/effects/compressor.cpp +++ b/al/effects/compressor.cpp @@ -95,8 +95,7 @@ class EaxCompressorEffect final : public EaxEffect { public: - EaxCompressorEffect( - EffectProps& al_effect_props); + EaxCompressorEffect(); // [[nodiscard]] @@ -105,8 +104,6 @@ public: private: - EffectProps& al_effect_props_; - EAXAGCCOMPRESSORPROPERTIES eax_{}; EAXAGCCOMPRESSORPROPERTIES eax_d_{}; EaxCompressorEffectDirtyFlags eax_dirty_flags_{}; @@ -168,10 +165,8 @@ public: }; // EaxCompressorEffectException -EaxCompressorEffect::EaxCompressorEffect( - EffectProps& al_effect_props) - : - al_effect_props_{al_effect_props} +EaxCompressorEffect::EaxCompressorEffect() + : EaxEffect{AL_EFFECT_COMPRESSOR} { set_eax_defaults(); set_efx_defaults(); @@ -330,10 +325,9 @@ bool EaxCompressorEffect::set( } // namespace -EaxEffectUPtr eax_create_eax_compressor_effect( - EffectProps& al_effect_props) +EaxEffectUPtr eax_create_eax_compressor_effect() { - return std::make_unique(al_effect_props); + return std::make_unique(); } #endif // ALSOFT_EAX diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index d0c9a3c2..4554901c 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -141,8 +141,7 @@ class EaxDistortionEffect final : public EaxEffect { public: - EaxDistortionEffect( - EffectProps& al_effect_props); + EaxDistortionEffect(); // [[nodiscard]] @@ -151,8 +150,6 @@ public: private: - EffectProps& al_effect_props_; - EAXDISTORTIONPROPERTIES eax_{}; EAXDISTORTIONPROPERTIES eax_d_{}; EaxDistortionEffectDirtyFlags eax_dirty_flags_{}; @@ -258,10 +255,8 @@ public: }; // EaxDistortionEffectException -EaxDistortionEffect::EaxDistortionEffect( - EffectProps& al_effect_props) - : - al_effect_props_{al_effect_props} +EaxDistortionEffect::EaxDistortionEffect() + : EaxEffect{AL_EFFECT_DISTORTION} { set_eax_defaults(); set_efx_defaults(); @@ -636,10 +631,9 @@ bool EaxDistortionEffect::set( } // namespace -EaxEffectUPtr eax_create_eax_distortion_effect( - EffectProps& al_effect_props) +EaxEffectUPtr eax_create_eax_distortion_effect() { - return std::make_unique(al_effect_props); + return std::make_unique(); } #endif // ALSOFT_EAX diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index 7e7a38bc..f54e4f31 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -138,8 +138,7 @@ class EaxEchoEffect final : public EaxEffect { public: - EaxEchoEffect( - EffectProps& al_effect_props); + EaxEchoEffect(); // [[nodiscard]] @@ -148,8 +147,6 @@ public: private: - EffectProps& al_effect_props_; - EAXECHOPROPERTIES eax_{}; EAXECHOPROPERTIES eax_d_{}; EaxEchoEffectDirtyFlags eax_dirty_flags_{}; @@ -253,10 +250,8 @@ public: }; // EaxEchoEffectException -EaxEchoEffect::EaxEchoEffect( - EffectProps& al_effect_props) - : - al_effect_props_{al_effect_props} +EaxEchoEffect::EaxEchoEffect() + : EaxEffect{AL_EFFECT_ECHO} { set_eax_defaults(); set_efx_defaults(); @@ -631,10 +626,9 @@ bool EaxEchoEffect::set( } // namespace -EaxEffectUPtr eax_create_eax_echo_effect( - EffectProps& al_effect_props) +EaxEffectUPtr eax_create_eax_echo_effect() { - return std::make_unique(al_effect_props); + return std::make_unique(); } #endif // ALSOFT_EAX diff --git a/al/effects/effects.cpp b/al/effects/effects.cpp index ede88f91..7be85dc0 100644 --- a/al/effects/effects.cpp +++ b/al/effects/effects.cpp @@ -11,47 +11,21 @@ EaxEffectUPtr eax_create_eax_null_effect(); - -EaxEffectUPtr eax_create_eax_chorus_effect( - EffectProps& al_effect_props); - -EaxEffectUPtr eax_create_eax_distortion_effect( - EffectProps& al_effect_props); - -EaxEffectUPtr eax_create_eax_echo_effect( - EffectProps& al_effect_props); - -EaxEffectUPtr eax_create_eax_flanger_effect( - EffectProps& al_effect_props); - -EaxEffectUPtr eax_create_eax_frequency_shifter_effect( - EffectProps& al_effect_props); - -EaxEffectUPtr eax_create_eax_vocal_morpher_effect( - EffectProps& al_effect_props); - -EaxEffectUPtr eax_create_eax_pitch_shifter_effect( - EffectProps& al_effect_props); - -EaxEffectUPtr eax_create_eax_ring_modulator_effect( - EffectProps& al_effect_props); - -EaxEffectUPtr eax_create_eax_auto_wah_effect( - EffectProps& al_effect_props); - -EaxEffectUPtr eax_create_eax_compressor_effect( - EffectProps& al_effect_props); - -EaxEffectUPtr eax_create_eax_equalizer_effect( - EffectProps& al_effect_props); - -EaxEffectUPtr eax_create_eax_reverb_effect( - EffectProps& al_effect_props); - - -EaxEffectUPtr eax_create_eax_effect( - ALenum al_effect_type, - EffectProps& al_effect_props) +EaxEffectUPtr eax_create_eax_chorus_effect(); +EaxEffectUPtr eax_create_eax_distortion_effect(); +EaxEffectUPtr eax_create_eax_echo_effect(); +EaxEffectUPtr eax_create_eax_flanger_effect(); +EaxEffectUPtr eax_create_eax_frequency_shifter_effect(); +EaxEffectUPtr eax_create_eax_vocal_morpher_effect(); +EaxEffectUPtr eax_create_eax_pitch_shifter_effect(); +EaxEffectUPtr eax_create_eax_ring_modulator_effect(); +EaxEffectUPtr eax_create_eax_auto_wah_effect(); +EaxEffectUPtr eax_create_eax_compressor_effect(); +EaxEffectUPtr eax_create_eax_equalizer_effect(); +EaxEffectUPtr eax_create_eax_reverb_effect(); + + +EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type) { #define EAX_PREFIX "[EAX_MAKE_EAX_EFFECT] " @@ -61,40 +35,40 @@ EaxEffectUPtr eax_create_eax_effect( return eax_create_eax_null_effect(); case AL_EFFECT_CHORUS: - return eax_create_eax_chorus_effect(al_effect_props); + return eax_create_eax_chorus_effect(); case AL_EFFECT_DISTORTION: - return eax_create_eax_distortion_effect(al_effect_props); + return eax_create_eax_distortion_effect(); case AL_EFFECT_ECHO: - return eax_create_eax_echo_effect(al_effect_props); + return eax_create_eax_echo_effect(); case AL_EFFECT_FLANGER: - return eax_create_eax_flanger_effect(al_effect_props); + return eax_create_eax_flanger_effect(); case AL_EFFECT_FREQUENCY_SHIFTER: - return eax_create_eax_frequency_shifter_effect(al_effect_props); + return eax_create_eax_frequency_shifter_effect(); case AL_EFFECT_VOCAL_MORPHER: - return eax_create_eax_vocal_morpher_effect(al_effect_props); + return eax_create_eax_vocal_morpher_effect(); case AL_EFFECT_PITCH_SHIFTER: - return eax_create_eax_pitch_shifter_effect(al_effect_props); + return eax_create_eax_pitch_shifter_effect(); case AL_EFFECT_RING_MODULATOR: - return eax_create_eax_ring_modulator_effect(al_effect_props); + return eax_create_eax_ring_modulator_effect(); case AL_EFFECT_AUTOWAH: - return eax_create_eax_auto_wah_effect(al_effect_props); + return eax_create_eax_auto_wah_effect(); case AL_EFFECT_COMPRESSOR: - return eax_create_eax_compressor_effect(al_effect_props); + return eax_create_eax_compressor_effect(); case AL_EFFECT_EQUALIZER: - return eax_create_eax_equalizer_effect(al_effect_props); + return eax_create_eax_equalizer_effect(); case AL_EFFECT_EAXREVERB: - return eax_create_eax_reverb_effect(al_effect_props); + return eax_create_eax_reverb_effect(); default: assert(false && "Unsupported AL effect type."); diff --git a/al/effects/effects.h b/al/effects/effects.h index a2ab8485..830e7191 100644 --- a/al/effects/effects.h +++ b/al/effects/effects.h @@ -86,9 +86,7 @@ extern const EffectVtable ConvolutionEffectVtable; #ifdef ALSOFT_EAX -EaxEffectUPtr eax_create_eax_effect( - ALenum al_effect_type, - EffectProps& al_effect_props); +EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type); #endif // ALSOFT_EAX #endif /* AL_EFFECTS_EFFECTS_H */ diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index 4ff26178..43597972 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -201,8 +201,7 @@ class EaxEqualizerEffect final : public EaxEffect { public: - EaxEqualizerEffect( - EffectProps& al_effect_props); + EaxEqualizerEffect(); // [[nodiscard]] @@ -211,8 +210,6 @@ public: private: - EffectProps& al_effect_props_; - EAXEQUALIZERPROPERTIES eax_{}; EAXEQUALIZERPROPERTIES eax_d_{}; EaxEqualizerEffectDirtyFlags eax_dirty_flags_{}; @@ -373,10 +370,8 @@ public: }; // EaxEqualizerEffectException -EaxEqualizerEffect::EaxEqualizerEffect( - EffectProps& al_effect_props) - : - al_effect_props_{al_effect_props} +EaxEqualizerEffect::EaxEqualizerEffect() + : EaxEffect{AL_EFFECT_EQUALIZER} { set_eax_defaults(); set_efx_defaults(); @@ -1021,10 +1016,9 @@ bool EaxEqualizerEffect::set( } // namespace -EaxEffectUPtr eax_create_eax_equalizer_effect( - EffectProps& al_effect_props) +EaxEffectUPtr eax_create_eax_equalizer_effect() { - return std::make_unique(al_effect_props); + return std::make_unique(); } #endif // ALSOFT_EAX diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index 74ef52d9..0100a864 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -157,8 +157,7 @@ class EaxFrequencyShifterEffect final : public EaxEffect { public: - EaxFrequencyShifterEffect( - EffectProps& al_effect_props); + EaxFrequencyShifterEffect(); // [[nodiscard]] @@ -167,8 +166,6 @@ public: private: - EffectProps& al_effect_props_; - EAXFREQUENCYSHIFTERPROPERTIES eax_{}; EAXFREQUENCYSHIFTERPROPERTIES eax_d_{}; EaxFrequencyShifterEffectDirtyFlags eax_dirty_flags_{}; @@ -252,10 +249,8 @@ public: }; // EaxFrequencyShifterEffectException -EaxFrequencyShifterEffect::EaxFrequencyShifterEffect( - EffectProps& al_effect_props) - : - al_effect_props_{al_effect_props} +EaxFrequencyShifterEffect::EaxFrequencyShifterEffect() + : EaxEffect{AL_EFFECT_FREQUENCY_SHIFTER} { set_eax_defaults(); set_efx_defaults(); @@ -530,10 +525,9 @@ bool EaxFrequencyShifterEffect::set( } // namespace -EaxEffectUPtr eax_create_eax_frequency_shifter_effect( - EffectProps& al_effect_props) +EaxEffectUPtr eax_create_eax_frequency_shifter_effect() { - return std::make_unique(al_effect_props); + return std::make_unique(); } #endif // ALSOFT_EAX diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index c33db8c3..ec7520e2 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -163,8 +163,7 @@ class EaxRingModulatorEffect final : public EaxEffect { public: - EaxRingModulatorEffect( - EffectProps& al_effect_props); + EaxRingModulatorEffect(); // [[nodiscard]] @@ -173,8 +172,6 @@ public: private: - EffectProps& al_effect_props_; - EAXRINGMODULATORPROPERTIES eax_{}; EAXRINGMODULATORPROPERTIES eax_d_{}; EaxRingModulatorEffectDirtyFlags eax_dirty_flags_{}; @@ -258,10 +255,8 @@ public: }; // EaxRingModulatorEffectException -EaxRingModulatorEffect::EaxRingModulatorEffect( - EffectProps& al_effect_props) - : - al_effect_props_{al_effect_props} +EaxRingModulatorEffect::EaxRingModulatorEffect() + : EaxEffect{AL_EFFECT_RING_MODULATOR} { set_eax_defaults(); set_efx_defaults(); @@ -533,10 +528,9 @@ bool EaxRingModulatorEffect::set( } // namespace -EaxEffectUPtr eax_create_eax_ring_modulator_effect( - EffectProps& al_effect_props) +EaxEffectUPtr eax_create_eax_ring_modulator_effect() { - return std::make_unique(al_effect_props); + return std::make_unique(); } #endif // ALSOFT_EAX diff --git a/al/effects/null.cpp b/al/effects/null.cpp index 8b68eec0..78c0a61a 100644 --- a/al/effects/null.cpp +++ b/al/effects/null.cpp @@ -104,6 +104,8 @@ class EaxNullEffect final : public EaxEffect { public: + EaxNullEffect(); + // [[nodiscard]] bool dispatch( const EaxEaxCall& eax_call) override; @@ -123,6 +125,11 @@ public: }; // EaxNullEffectException +EaxNullEffect::EaxNullEffect() + : EaxEffect{AL_EFFECT_NULL} +{ +} + // [[nodiscard]] bool EaxNullEffect::dispatch( const EaxEaxCall& eax_call) diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp index 7c355be1..6c45ab4e 100644 --- a/al/effects/pshifter.cpp +++ b/al/effects/pshifter.cpp @@ -108,18 +108,13 @@ class EaxPitchShifterEffect final : public EaxEffect { public: - EaxPitchShifterEffect( - EffectProps& al_effect_props); - + EaxPitchShifterEffect(); // [[nodiscard]] bool dispatch( const EaxEaxCall& eax_call) override; - private: - EffectProps& al_effect_props_; - EAXPITCHSHIFTERPROPERTIES eax_{}; EAXPITCHSHIFTERPROPERTIES eax_d_{}; EaxPitchShifterEffectDirtyFlags eax_dirty_flags_{}; @@ -192,10 +187,8 @@ public: }; // EaxPitchShifterEffectException -EaxPitchShifterEffect::EaxPitchShifterEffect( - EffectProps& al_effect_props) - : - al_effect_props_{al_effect_props} +EaxPitchShifterEffect::EaxPitchShifterEffect() + : EaxEffect{AL_EFFECT_PITCH_SHIFTER} { set_eax_defaults(); set_efx_defaults(); @@ -408,10 +401,9 @@ bool EaxPitchShifterEffect::set( } // namespace -EaxEffectUPtr eax_create_eax_pitch_shifter_effect( - EffectProps& al_effect_props) +EaxEffectUPtr eax_create_eax_pitch_shifter_effect() { - return std::make_unique(al_effect_props); + return std::make_unique(); } #endif // ALSOFT_EAX diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index a8404f8b..ef23f869 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -604,18 +604,13 @@ class EaxReverbEffect final : public EaxEffect { public: - EaxReverbEffect( - EffectProps& al_effect_props); - + EaxReverbEffect(); // [[nodiscard]] bool dispatch( const EaxEaxCall& eax_call) override; - private: - EffectProps& al_effect_props_; - EAXREVERBPROPERTIES eax_{}; EAXREVERBPROPERTIES eax_d_{}; EaxReverbEffectDirtyFlags eax_dirty_flags_{}; @@ -941,10 +936,8 @@ public: }; // EaxReverbEffectException -EaxReverbEffect::EaxReverbEffect( - EffectProps& al_effect_props) - : - al_effect_props_{al_effect_props} +EaxReverbEffect::EaxReverbEffect() + : EaxEffect{AL_EFFECT_EAXREVERB} { set_eax_defaults(); set_efx_defaults(); @@ -2464,10 +2457,9 @@ bool EaxReverbEffect::set( } // namespace -EaxEffectUPtr eax_create_eax_reverb_effect( - EffectProps& al_effect_props) +EaxEffectUPtr eax_create_eax_reverb_effect() { - return std::make_unique(al_effect_props); + return std::make_unique(); } #endif // ALSOFT_EAX diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index 2ea2594e..3081201c 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -279,18 +279,13 @@ class EaxVocalMorpherEffect final : public EaxEffect { public: - EaxVocalMorpherEffect( - EffectProps& al_effect_props); - + EaxVocalMorpherEffect(); // [[nodiscard]] bool dispatch( const EaxEaxCall& eax_call) override; - private: - EffectProps& al_effect_props_; - EAXVOCALMORPHERPROPERTIES eax_{}; EAXVOCALMORPHERPROPERTIES eax_d_{}; EaxVocalMorpherEffectDirtyFlags eax_dirty_flags_{}; @@ -407,10 +402,8 @@ public: }; // EaxVocalMorpherEffectException -EaxVocalMorpherEffect::EaxVocalMorpherEffect( - EffectProps& al_effect_props) - : - al_effect_props_{al_effect_props} +EaxVocalMorpherEffect::EaxVocalMorpherEffect() + : EaxEffect{AL_EFFECT_VOCAL_MORPHER} { set_eax_defaults(); set_efx_defaults(); @@ -860,10 +853,9 @@ bool EaxVocalMorpherEffect::set( } // namespace -EaxEffectUPtr eax_create_eax_vocal_morpher_effect( - EffectProps& al_effect_props) +EaxEffectUPtr eax_create_eax_vocal_morpher_effect() { - return std::make_unique(al_effect_props); + return std::make_unique(); } #endif // ALSOFT_EAX -- cgit v1.2.3 From 2492d76896f9cb991760c408bcce7b1c79049979 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 4 Mar 2022 13:19:00 -0800 Subject: Ensure deferred EAX effect properties are committed --- al/auxeffectslot.cpp | 58 ++++++++++++++++++++++++++++++----------------- al/auxeffectslot.h | 4 +++- al/eax_effect.h | 3 +++ al/eax_fx_slots.h | 6 +++++ al/effects/autowah.cpp | 5 ++-- al/effects/chorus.cpp | 10 ++++---- al/effects/compressor.cpp | 5 ++-- al/effects/distortion.cpp | 5 ++-- al/effects/echo.cpp | 4 ++-- al/effects/equalizer.cpp | 5 ++-- al/effects/fshifter.cpp | 5 ++-- al/effects/modulator.cpp | 5 ++-- al/effects/null.cpp | 8 +++++++ al/effects/pshifter.cpp | 6 ++--- al/effects/reverb.cpp | 6 ++--- al/effects/vmorpher.cpp | 6 ++--- alc/context.h | 2 ++ 17 files changed, 86 insertions(+), 57 deletions(-) (limited to 'al/effects/distortion.cpp') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 50c5cda6..bb279c88 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -1023,14 +1023,18 @@ void ALeffectslot::updateProps(ALCcontext *context) void UpdateAllEffectSlotProps(ALCcontext *context) { std::lock_guard _{context->mEffectSlotLock}; +#ifdef ALSOFT_EAX + if(context->has_eax()) + context->eax_commit_fx_slots(); +#endif for(auto &sublist : context->mEffectSlotList) { uint64_t usemask{~sublist.FreeMask}; while(usemask) { const int idx{al::countr_zero(usemask)}; - ALeffectslot *slot{sublist.EffectSlots + idx}; usemask &= ~(1_u64 << idx); + ALeffectslot *slot{sublist.EffectSlots + idx}; if(slot->mState != SlotState::Stopped && std::exchange(slot->mPropsDirty, false)) slot->updateProps(context); @@ -1676,18 +1680,28 @@ bool ALeffectslot::eax_set_fx_slot( bool ALeffectslot::eax_set( const EaxEaxCall& eax_call) { + bool ret{false}; + switch (eax_call.get_property_set_id()) { case EaxEaxCallPropertySetId::fx_slot: - return eax_set_fx_slot(eax_call); + ret = eax_set_fx_slot(eax_call); + break; case EaxEaxCallPropertySetId::fx_slot_effect: eax_dispatch_effect(eax_call); - return false; + break; default: eax_fail("Unsupported property id."); } + + if(!eax_call.is_deferred()) + { + eax_apply_deferred(); + } + + return ret; } void ALeffectslot::eax_dispatch_effect( @@ -1700,6 +1714,18 @@ void ALeffectslot::eax_dispatch_effect( eax_set_effect_slot_effect(*eax_effect_); } +void ALeffectslot::eax_apply_deferred() +{ + /* The other FXSlot properties (volume, effect, etc) aren't deferred? */ + + auto is_changed = false; + if(eax_effect_) + is_changed = eax_effect_->apply_deferred(); + if(is_changed) + eax_set_effect_slot_effect(*eax_effect_); +} + + void ALeffectslot::eax_set_effect_slot_effect(EaxEffect &effect) { #define EAX_PREFIX "[EAX_SET_EFFECT_SLOT_EFFECT] " @@ -1732,14 +1758,11 @@ void ALeffectslot::eax_set_effect_slot_effect(EaxEffect &effect) void ALeffectslot::eax_set_effect_slot_send_auto( bool is_send_auto) { - std::lock_guard effect_slot_lock{eax_al_context_->mEffectSlotLock}; - - const auto is_changed = (AuxSendAuto != is_send_auto); + if(AuxSendAuto == is_send_auto) + return; AuxSendAuto = is_send_auto; - - if (is_changed) - UpdateProps(this, eax_al_context_); + UpdateProps(this, eax_al_context_); } void ALeffectslot::eax_set_effect_slot_gain( @@ -1747,20 +1770,13 @@ void ALeffectslot::eax_set_effect_slot_gain( { #define EAX_PREFIX "[EAX_SET_EFFECT_SLOT_GAIN] " - if (gain < 0.0F || gain > 1.0F) - { - ERR(EAX_PREFIX "%s\n", "Gain out of range."); + if(gain == Gain) return; - } - - std::lock_guard effect_slot_lock{eax_al_context_->mEffectSlotLock}; + if(gain < 0.0f || gain > 1.0f) + ERR(EAX_PREFIX "Gain out of range (%f)\n", gain); - const auto is_changed = (Gain != gain); - - Gain = gain; - - if (is_changed) - UpdateProps(this, eax_al_context_); + Gain = clampf(gain, 0.0f, 1.0f); + UpdateProps(this, eax_al_context_); #undef EAX_PREFIX } diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index d845b2b4..94a61cfc 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -77,7 +77,6 @@ public: ALCcontext& al_context, EaxFxSlotIndexValue index); - const EAX50FXSLOTPROPERTIES& eax_get_eax_fx_slot() const noexcept; @@ -87,6 +86,7 @@ public: void eax_unlock_legacy() noexcept; + void eax_commit() { eax_apply_deferred(); } private: ALCcontext* eax_al_context_{}; @@ -230,6 +230,8 @@ private: bool eax_set_fx_slot( const EaxEaxCall& eax_call); + void eax_apply_deferred(); + // [[nodiscard]] bool eax_set( const EaxEaxCall& eax_call); diff --git a/al/eax_effect.h b/al/eax_effect.h index 1ce41647..6de9afcc 100644 --- a/al/eax_effect.h +++ b/al/eax_effect.h @@ -21,6 +21,9 @@ public: // [[nodiscard]] virtual bool dispatch( const EaxEaxCall& eax_call) = 0; + + // [[nodiscard]] + virtual bool apply_deferred() = 0; }; // EaxEffect diff --git a/al/eax_fx_slots.h b/al/eax_fx_slots.h index 0ebb9b7d..a104c6ab 100644 --- a/al/eax_fx_slots.h +++ b/al/eax_fx_slots.h @@ -19,6 +19,12 @@ public: void uninitialize() noexcept; + void commit() + { + for(auto& fx_slot : fx_slots_) + fx_slot->eax_commit(); + } + const ALeffectslot& get( EaxFxSlotIndex index) const; diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 51f8fff6..6fa859ba 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -143,6 +143,8 @@ public: bool dispatch( const EaxEaxCall& eax_call) override; + // [[nodiscard]] + bool apply_deferred() override; private: EAXAUTOWAHPROPERTIES eax_{}; @@ -216,9 +218,6 @@ private: void defer_all( const EaxEaxCall& eax_call); - // [[nodiscard]] - bool apply_deferred(); - // [[nodiscard]] bool set( const EaxEaxCall& eax_call); diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index 15b9d635..397b338a 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -364,6 +364,8 @@ public: bool dispatch( const EaxEaxCall& eax_call) override; + // [[nodiscard]] + bool apply_deferred() override; private: EAXCHORUSPROPERTIES eax_{}; @@ -460,9 +462,6 @@ private: const EaxEaxCall& eax_call); - // [[nodiscard]] - bool apply_deferred(); - // [[nodiscard]] bool set( const EaxEaxCall& eax_call); @@ -949,6 +948,8 @@ public: bool dispatch( const EaxEaxCall& eax_call) override; + // [[nodiscard]] + bool apply_deferred() override; private: EAXFLANGERPROPERTIES eax_{}; @@ -1045,9 +1046,6 @@ private: const EaxEaxCall& eax_call); - // [[nodiscard]] - bool apply_deferred(); - // [[nodiscard]] bool set( const EaxEaxCall& eax_call); diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp index d4a8e9c2..cd284383 100644 --- a/al/effects/compressor.cpp +++ b/al/effects/compressor.cpp @@ -102,6 +102,8 @@ public: bool dispatch( const EaxEaxCall& eax_call) override; + // [[nodiscard]] + bool apply_deferred() override; private: EAXAGCCOMPRESSORPROPERTIES eax_{}; @@ -143,9 +145,6 @@ private: const EaxEaxCall& eax_call); - // [[nodiscard]] - bool apply_deferred(); - // [[nodiscard]] bool set( const EaxEaxCall& eax_call); diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index 4554901c..0f4b6ed5 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -148,6 +148,8 @@ public: bool dispatch( const EaxEaxCall& eax_call) override; + // [[nodiscard]] + bool apply_deferred() override; private: EAXDISTORTIONPROPERTIES eax_{}; @@ -233,9 +235,6 @@ private: const EaxEaxCall& eax_call); - // [[nodiscard]] - bool apply_deferred(); - // [[nodiscard]] bool set( const EaxEaxCall& eax_call); diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index f54e4f31..b2e45091 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -145,6 +145,8 @@ public: bool dispatch( const EaxEaxCall& eax_call) override; + // [[nodiscard]] + bool apply_deferred() override; private: EAXECHOPROPERTIES eax_{}; @@ -230,8 +232,6 @@ private: const EaxEaxCall& eax_call); - bool apply_deferred(); - bool set( const EaxEaxCall& eax_call); }; // EaxEchoEffect diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index 43597972..8cd59cd1 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -208,6 +208,8 @@ public: bool dispatch( const EaxEaxCall& eax_call) override; + // [[nodiscard]] + bool apply_deferred() override; private: EAXEQUALIZERPROPERTIES eax_{}; @@ -348,9 +350,6 @@ private: const EaxEaxCall& eax_call); - // [[nodiscard]] - bool apply_deferred(); - // [[nodiscard]] bool set( const EaxEaxCall& eax_call); diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index 0100a864..8ad48ab3 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -164,6 +164,8 @@ public: bool dispatch( const EaxEaxCall& eax_call) override; + // [[nodiscard]] + bool apply_deferred() override; private: EAXFREQUENCYSHIFTERPROPERTIES eax_{}; @@ -227,9 +229,6 @@ private: const EaxEaxCall& eax_call); - // [[nodiscard]] - bool apply_deferred(); - // [[nodiscard]] bool set( const EaxEaxCall& eax_call); diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index ec7520e2..a1521d26 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -170,6 +170,8 @@ public: bool dispatch( const EaxEaxCall& eax_call) override; + // [[nodiscard]] + bool apply_deferred() override; private: EAXRINGMODULATORPROPERTIES eax_{}; @@ -233,9 +235,6 @@ private: const EaxEaxCall& eax_call); - // [[nodiscard]] - bool apply_deferred(); - // [[nodiscard]] bool set( const EaxEaxCall& eax_call); diff --git a/al/effects/null.cpp b/al/effects/null.cpp index 78c0a61a..5602280b 100644 --- a/al/effects/null.cpp +++ b/al/effects/null.cpp @@ -109,6 +109,9 @@ public: // [[nodiscard]] bool dispatch( const EaxEaxCall& eax_call) override; + + // [[nodiscard]] + bool apply_deferred() override; }; // EaxNullEffect @@ -142,6 +145,11 @@ bool EaxNullEffect::dispatch( return false; } +bool EaxNullEffect::apply_deferred() +{ + return false; +} + } // namespace EaxEffectUPtr eax_create_eax_null_effect() diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp index 6c45ab4e..a2b06078 100644 --- a/al/effects/pshifter.cpp +++ b/al/effects/pshifter.cpp @@ -114,6 +114,9 @@ public: bool dispatch( const EaxEaxCall& eax_call) override; + // [[nodiscard]] + bool apply_deferred() override; + private: EAXPITCHSHIFTERPROPERTIES eax_{}; EAXPITCHSHIFTERPROPERTIES eax_d_{}; @@ -165,9 +168,6 @@ private: const EaxEaxCall& eax_call); - // [[nodiscard]] - bool apply_deferred(); - // [[nodiscard]] bool set( const EaxEaxCall& eax_call); diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index 46fa0256..18760b5b 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -610,6 +610,9 @@ public: bool dispatch( const EaxEaxCall& eax_call) override; + // [[nodiscard]] + bool apply_deferred() override; + private: EAX_REVERBPROPERTIES eax1_{}; EAXREVERBPROPERTIES eax_{}; @@ -932,9 +935,6 @@ private: bool v1_set_all(const EaxEaxCall& eax_call); bool v1_set(const EaxEaxCall& eax_call); - // [[nodiscard]] - bool apply_deferred(); - // [[nodiscard]] bool set( const EaxEaxCall& eax_call); diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index 3081201c..15f099b1 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -285,6 +285,9 @@ public: bool dispatch( const EaxEaxCall& eax_call) override; + // [[nodiscard]] + bool apply_deferred() override; + private: EAXVOCALMORPHERPROPERTIES eax_{}; EAXVOCALMORPHERPROPERTIES eax_d_{}; @@ -380,9 +383,6 @@ private: const EaxEaxCall& eax_call); - // [[nodiscard]] - bool apply_deferred(); - // [[nodiscard]] bool set( const EaxEaxCall& eax_call); diff --git a/alc/context.h b/alc/context.h index a7bbef83..72b259e9 100644 --- a/alc/context.h +++ b/alc/context.h @@ -258,6 +258,8 @@ public: ALeffectslot& eax_get_fx_slot(EaxFxSlotIndexValue fx_slot_index) { return eax_fx_slots_.get(fx_slot_index); } + void eax_commit_fx_slots() + { eax_fx_slots_.commit(); } private: struct Eax -- cgit v1.2.3 From 2dc9cf170c08f0b7f35ec46cb17c829888e7392c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 5 Mar 2022 01:14:26 -0800 Subject: Simplify committing EAX properties Based on DirectSound's EAX behavior, committing any EAX property commits *all* deferred property changes, not just the object being changed. So applying EAX changes can be handled in one place. --- al/auxeffectslot.cpp | 28 +---- al/eax_eax_call.cpp | 22 +--- al/eax_eax_call.h | 2 - al/eax_effect.h | 6 +- al/effects/autowah.cpp | 34 ++---- al/effects/chorus.cpp | 282 +++++++++++----------------------------------- al/effects/compressor.cpp | 66 +++-------- al/effects/distortion.cpp | 129 +++++---------------- al/effects/echo.cpp | 127 +++++---------------- al/effects/equalizer.cpp | 194 ++++++++----------------------- al/effects/fshifter.cpp | 95 ++++------------ al/effects/modulator.cpp | 93 ++++----------- al/effects/null.cpp | 14 +-- al/effects/pshifter.cpp | 81 +++---------- al/effects/reverb.cpp | 51 +++------ al/effects/vmorpher.cpp | 147 ++++++------------------ al/source.cpp | 6 - alc/context.cpp | 23 +--- 18 files changed, 328 insertions(+), 1072 deletions(-) (limited to 'al/effects/distortion.cpp') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index bb279c88..a83c39f7 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -1677,16 +1677,12 @@ bool ALeffectslot::eax_set_fx_slot( } // [[nodiscard]] -bool ALeffectslot::eax_set( - const EaxEaxCall& eax_call) +bool ALeffectslot::eax_set(const EaxEaxCall& eax_call) { - bool ret{false}; - - switch (eax_call.get_property_set_id()) + switch(eax_call.get_property_set_id()) { case EaxEaxCallPropertySetId::fx_slot: - ret = eax_set_fx_slot(eax_call); - break; + return eax_set_fx_slot(eax_call); case EaxEaxCallPropertySetId::fx_slot_effect: eax_dispatch_effect(eax_call); @@ -1696,23 +1692,11 @@ bool ALeffectslot::eax_set( eax_fail("Unsupported property id."); } - if(!eax_call.is_deferred()) - { - eax_apply_deferred(); - } - - return ret; + return false; } -void ALeffectslot::eax_dispatch_effect( - const EaxEaxCall& eax_call) -{ - auto is_changed = false; - if(eax_effect_) - is_changed = eax_effect_->dispatch(eax_call); - if(is_changed) - eax_set_effect_slot_effect(*eax_effect_); -} +void ALeffectslot::eax_dispatch_effect(const EaxEaxCall& eax_call) +{ if(eax_effect_) eax_effect_->dispatch(eax_call); } void ALeffectslot::eax_apply_deferred() { diff --git a/al/eax_eax_call.cpp b/al/eax_eax_call.cpp index dfd7f7f7..914d2fbf 100644 --- a/al/eax_eax_call.cpp +++ b/al/eax_eax_call.cpp @@ -31,10 +31,9 @@ EaxEaxCall::EaxEaxCall( ALuint property_source_id, ALvoid* property_buffer, ALuint property_size) - : is_get_{is_get}, is_deferred_{(property_id&deferred_flag) != 0}, version_{0} - , property_set_id_{EaxEaxCallPropertySetId::none}, property_id_{property_id & ~deferred_flag} - , property_source_id_{property_source_id}, property_buffer_{property_buffer} - , property_size_{property_size} + : is_get_{is_get}, version_{0}, property_set_id_{EaxEaxCallPropertySetId::none} + , property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id} + , property_buffer_{property_buffer}, property_size_{property_size} { if (false) { @@ -152,17 +151,9 @@ EaxEaxCall::EaxEaxCall( fail("EAX version out of range."); } - if (is_deferred_) + if(!(property_id&deferred_flag)) { - if (version_ == 1) - { - fail("EAX1 does not support deferring."); - } - } - else - { - if (property_set_id_ != EaxEaxCallPropertySetId::fx_slot && - property_id_ != 0) + if(property_set_id_ != EaxEaxCallPropertySetId::fx_slot && property_id_ != 0) { if (!property_buffer) { @@ -176,8 +167,7 @@ EaxEaxCall::EaxEaxCall( } } - if (property_set_id_ == EaxEaxCallPropertySetId::source && - property_source_id_ == 0) + if(property_set_id_ == EaxEaxCallPropertySetId::source && property_source_id_ == 0) { fail("Null AL source id."); } diff --git a/al/eax_eax_call.h b/al/eax_eax_call.h index dd89795a..7b990d87 100644 --- a/al/eax_eax_call.h +++ b/al/eax_eax_call.h @@ -33,7 +33,6 @@ public: ALuint property_size); bool is_get() const noexcept { return is_get_; } - bool is_deferred() const noexcept { return is_deferred_; } int get_version() const noexcept { return version_; } EaxEaxCallPropertySetId get_property_set_id() const noexcept { return property_set_id_; } ALuint get_property_id() const noexcept { return property_id_; } @@ -83,7 +82,6 @@ public: private: const bool is_get_; - const bool is_deferred_; int version_; EaxFxSlotIndex fx_slot_index_; EaxEaxCallPropertySetId property_set_id_; diff --git a/al/eax_effect.h b/al/eax_effect.h index 6de9afcc..45315ca6 100644 --- a/al/eax_effect.h +++ b/al/eax_effect.h @@ -17,11 +17,9 @@ public: const ALenum al_effect_type_; EffectProps al_effect_props_{}; - // Returns "true" if any immediated property was changed. - // [[nodiscard]] - virtual bool dispatch( - const EaxEaxCall& eax_call) = 0; + virtual void dispatch(const EaxEaxCall& eax_call) = 0; + // Returns "true" if any immediated property was changed. // [[nodiscard]] virtual bool apply_deferred() = 0; }; // EaxEffect diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 6fa859ba..273ec7ae 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -139,9 +139,7 @@ public: EaxAutoWahEffect(); - // [[nodiscard]] - bool dispatch( - const EaxEaxCall& eax_call) override; + void dispatch(const EaxEaxCall& eax_call) override; // [[nodiscard]] bool apply_deferred() override; @@ -166,9 +164,7 @@ private: void set_efx_defaults(); - // [[nodiscard]] - bool get( - const EaxEaxCall& eax_call); + void get(const EaxEaxCall& eax_call); void validate_attack_time( @@ -218,9 +214,7 @@ private: void defer_all( const EaxEaxCall& eax_call); - // [[nodiscard]] - bool set( - const EaxEaxCall& eax_call); + void set(const EaxEaxCall& eax_call); }; // EaxAutoWahEffect @@ -244,11 +238,9 @@ EaxAutoWahEffect::EaxAutoWahEffect() set_efx_defaults(); } -// [[nodiscard]] -bool EaxAutoWahEffect::dispatch( - const EaxEaxCall& eax_call) +void EaxAutoWahEffect::dispatch(const EaxEaxCall& eax_call) { - return eax_call.is_get() ? get(eax_call) : set(eax_call); + eax_call.is_get() ? get(eax_call) : set(eax_call); } void EaxAutoWahEffect::set_eax_defaults() @@ -309,8 +301,7 @@ void EaxAutoWahEffect::set_efx_defaults() set_efx_peak_gain(); } -bool EaxAutoWahEffect::get( - const EaxEaxCall& eax_call) +void EaxAutoWahEffect::get(const EaxEaxCall& eax_call) { switch (eax_call.get_property_id()) { @@ -340,8 +331,6 @@ bool EaxAutoWahEffect::get( default: throw EaxAutoWahEffectException{"Unsupported property id."}; } - - return false; } void EaxAutoWahEffect::validate_attack_time( @@ -517,9 +506,7 @@ bool EaxAutoWahEffect::apply_deferred() return true; } -// [[nodiscard]] -bool EaxAutoWahEffect::set( - const EaxEaxCall& eax_call) +void EaxAutoWahEffect::set(const EaxEaxCall& eax_call) { switch (eax_call.get_property_id()) { @@ -549,13 +536,6 @@ bool EaxAutoWahEffect::set( default: throw EaxAutoWahEffectException{"Unsupported property id."}; } - - if (!eax_call.is_deferred()) - { - return apply_deferred(); - } - - return false; } } // namespace diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index 397b338a..56318095 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -359,10 +359,7 @@ class EaxChorusEffect final : public: EaxChorusEffect(); - - // [[nodiscard]] - bool dispatch( - const EaxEaxCall& eax_call) override; + void dispatch(const EaxEaxCall& eax_call) override; // [[nodiscard]] bool apply_deferred() override; @@ -372,99 +369,43 @@ private: EAXCHORUSPROPERTIES eax_d_{}; EaxChorusEffectDirtyFlags eax_dirty_flags_{}; - void set_eax_defaults() noexcept; - void set_efx_waveform(); - void set_efx_phase(); - void set_efx_rate(); - void set_efx_depth(); - void set_efx_feedback(); - void set_efx_delay(); - void set_efx_defaults(); - - // [[nodiscard]] - bool get( - const EaxEaxCall& eax_call); - - - void validate_waveform( - unsigned long ulWaveform); - - void validate_phase( - long lPhase); - - void validate_rate( - float flRate); - - void validate_depth( - float flDepth); - - void validate_feedback( - float flFeedback); - - void validate_delay( - float flDelay); - - void validate_all( - const EAXCHORUSPROPERTIES& eax_all); - - - void defer_waveform( - unsigned long ulWaveform); - - void defer_phase( - long lPhase); - - void defer_rate( - float flRate); - - void defer_depth( - float flDepth); - - void defer_feedback( - float flFeedback); - - void defer_delay( - float flDelay); - - void defer_all( - const EAXCHORUSPROPERTIES& eax_all); - - - void defer_waveform( - const EaxEaxCall& eax_call); - - void defer_phase( - const EaxEaxCall& eax_call); - - void defer_rate( - const EaxEaxCall& eax_call); - - void defer_depth( - const EaxEaxCall& eax_call); - - void defer_feedback( - const EaxEaxCall& eax_call); - - void defer_delay( - const EaxEaxCall& eax_call); - - void defer_all( - const EaxEaxCall& eax_call); - - - // [[nodiscard]] - bool set( - const EaxEaxCall& eax_call); + void get(const EaxEaxCall& eax_call); + + void validate_waveform(unsigned long ulWaveform); + void validate_phase(long lPhase); + void validate_rate(float flRate); + void validate_depth(float flDepth); + void validate_feedback(float flFeedback); + void validate_delay(float flDelay); + void validate_all(const EAXCHORUSPROPERTIES& eax_all); + + void defer_waveform(unsigned long ulWaveform); + void defer_phase(long lPhase); + void defer_rate(float flRate); + void defer_depth(float flDepth); + void defer_feedback(float flFeedback); + void defer_delay(float flDelay); + void defer_all(const EAXCHORUSPROPERTIES& eax_all); + + void defer_waveform(const EaxEaxCall& eax_call); + void defer_phase(const EaxEaxCall& eax_call); + void defer_rate(const EaxEaxCall& eax_call); + void defer_depth(const EaxEaxCall& eax_call); + void defer_feedback(const EaxEaxCall& eax_call); + void defer_delay(const EaxEaxCall& eax_call); + void defer_all(const EaxEaxCall& eax_call); + + void set(const EaxEaxCall& eax_call); }; // EaxChorusEffect @@ -488,11 +429,9 @@ EaxChorusEffect::EaxChorusEffect() set_efx_defaults(); } -// [[nodiscard]] -bool EaxChorusEffect::dispatch( - const EaxEaxCall& eax_call) +void EaxChorusEffect::dispatch(const EaxEaxCall& eax_call) { - return eax_call.is_get() ? get(eax_call) : set(eax_call); + eax_call.is_get() ? get(eax_call) : set(eax_call); } void EaxChorusEffect::set_eax_defaults() noexcept @@ -577,10 +516,9 @@ void EaxChorusEffect::set_efx_defaults() set_efx_delay(); } -bool EaxChorusEffect::get( - const EaxEaxCall& eax_call) +void EaxChorusEffect::get(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXCHORUS_NONE: break; @@ -616,8 +554,6 @@ bool EaxChorusEffect::get( default: throw EaxChorusEffectException{"Unsupported property id."}; } - - return false; } void EaxChorusEffect::validate_waveform( @@ -859,11 +795,9 @@ bool EaxChorusEffect::apply_deferred() return true; } -// [[nodiscard]] -bool EaxChorusEffect::set( - const EaxEaxCall& eax_call) +void EaxChorusEffect::set(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXCHORUS_NONE: break; @@ -899,13 +833,6 @@ bool EaxChorusEffect::set( default: throw EaxChorusEffectException{"Unsupported property id."}; } - - if (!eax_call.is_deferred()) - { - return apply_deferred(); - } - - return false; } @@ -944,9 +871,7 @@ public: EaxFlangerEffect(); - // [[nodiscard]] - bool dispatch( - const EaxEaxCall& eax_call) override; + void dispatch(const EaxEaxCall& eax_call) override; // [[nodiscard]] bool apply_deferred() override; @@ -956,99 +881,43 @@ private: EAXFLANGERPROPERTIES eax_d_{}; EaxFlangerEffectDirtyFlags eax_dirty_flags_{}; - void set_eax_defaults(); - void set_efx_waveform(); - void set_efx_phase(); - void set_efx_rate(); - void set_efx_depth(); - void set_efx_feedback(); - void set_efx_delay(); - void set_efx_defaults(); - - // [[nodiscard]] - bool get( - const EaxEaxCall& eax_call); - - - void validate_waveform( - unsigned long ulWaveform); - - void validate_phase( - long lPhase); - - void validate_rate( - float flRate); - - void validate_depth( - float flDepth); - - void validate_feedback( - float flFeedback); - - void validate_delay( - float flDelay); - - void validate_all( - const EAXFLANGERPROPERTIES& all); - - - void defer_waveform( - unsigned long ulWaveform); - - void defer_phase( - long lPhase); - - void defer_rate( - float flRate); - - void defer_depth( - float flDepth); - - void defer_feedback( - float flFeedback); - - void defer_delay( - float flDelay); - - void defer_all( - const EAXFLANGERPROPERTIES& all); - - - void defer_waveform( - const EaxEaxCall& eax_call); - - void defer_phase( - const EaxEaxCall& eax_call); - - void defer_rate( - const EaxEaxCall& eax_call); - - void defer_depth( - const EaxEaxCall& eax_call); - - void defer_feedback( - const EaxEaxCall& eax_call); - - void defer_delay( - const EaxEaxCall& eax_call); - - void defer_all( - const EaxEaxCall& eax_call); - - - // [[nodiscard]] - bool set( - const EaxEaxCall& eax_call); + void get(const EaxEaxCall& eax_call); + + void validate_waveform(unsigned long ulWaveform); + void validate_phase(long lPhase); + void validate_rate(float flRate); + void validate_depth(float flDepth); + void validate_feedback(float flFeedback); + void validate_delay(float flDelay); + void validate_all(const EAXFLANGERPROPERTIES& all); + + void defer_waveform(unsigned long ulWaveform); + void defer_phase(long lPhase); + void defer_rate(float flRate); + void defer_depth(float flDepth); + void defer_feedback(float flFeedback); + void defer_delay(float flDelay); + void defer_all(const EAXFLANGERPROPERTIES& all); + + void defer_waveform(const EaxEaxCall& eax_call); + void defer_phase(const EaxEaxCall& eax_call); + void defer_rate(const EaxEaxCall& eax_call); + void defer_depth(const EaxEaxCall& eax_call); + void defer_feedback(const EaxEaxCall& eax_call); + void defer_delay(const EaxEaxCall& eax_call); + void defer_all(const EaxEaxCall& eax_call); + + void set(const EaxEaxCall& eax_call); }; // EaxFlangerEffect @@ -1072,11 +941,9 @@ EaxFlangerEffect::EaxFlangerEffect() set_efx_defaults(); } -// [[nodiscard]] -bool EaxFlangerEffect::dispatch( - const EaxEaxCall& eax_call) +void EaxFlangerEffect::dispatch(const EaxEaxCall& eax_call) { - return eax_call.is_get() ? get(eax_call) : set(eax_call); + eax_call.is_get() ? get(eax_call) : set(eax_call); } void EaxFlangerEffect::set_eax_defaults() @@ -1161,11 +1028,9 @@ void EaxFlangerEffect::set_efx_defaults() set_efx_delay(); } -// [[nodiscard]] -bool EaxFlangerEffect::get( - const EaxEaxCall& eax_call) +void EaxFlangerEffect::get(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXFLANGER_NONE: break; @@ -1201,8 +1066,6 @@ bool EaxFlangerEffect::get( default: throw EaxFlangerEffectException{"Unsupported property id."}; } - - return false; } void EaxFlangerEffect::validate_waveform( @@ -1444,11 +1307,9 @@ bool EaxFlangerEffect::apply_deferred() return true; } -// [[nodiscard]] -bool EaxFlangerEffect::set( - const EaxEaxCall& eax_call) +void EaxFlangerEffect::set(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXFLANGER_NONE: break; @@ -1484,13 +1345,6 @@ bool EaxFlangerEffect::set( default: throw EaxFlangerEffectException{"Unsupported property id."}; } - - if (!eax_call.is_deferred()) - { - return apply_deferred(); - } - - return false; } } // namespace diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp index cd284383..bb5dfa3e 100644 --- a/al/effects/compressor.cpp +++ b/al/effects/compressor.cpp @@ -98,9 +98,7 @@ public: EaxCompressorEffect(); - // [[nodiscard]] - bool dispatch( - const EaxEaxCall& eax_call) override; + void dispatch(const EaxEaxCall& eax_call) override; // [[nodiscard]] bool apply_deferred() override; @@ -113,41 +111,21 @@ private: void set_eax_defaults(); - void set_efx_on_off(); - void set_efx_defaults(); + void get(const EaxEaxCall& eax_call); - // [[nodiscard]] - bool get( - const EaxEaxCall& eax_call); - - - void validate_on_off( - unsigned long ulOnOff); - - void validate_all( - const EAXAGCCOMPRESSORPROPERTIES& eax_all); - - - void defer_on_off( - unsigned long ulOnOff); - - void defer_all( - const EAXAGCCOMPRESSORPROPERTIES& eax_all); - - - void defer_on_off( - const EaxEaxCall& eax_call); + void validate_on_off(unsigned long ulOnOff); + void validate_all(const EAXAGCCOMPRESSORPROPERTIES& eax_all); - void defer_all( - const EaxEaxCall& eax_call); + void defer_on_off(unsigned long ulOnOff); + void defer_all(const EAXAGCCOMPRESSORPROPERTIES& eax_all); + void defer_on_off(const EaxEaxCall& eax_call); + void defer_all(const EaxEaxCall& eax_call); - // [[nodiscard]] - bool set( - const EaxEaxCall& eax_call); + void set(const EaxEaxCall& eax_call); }; // EaxCompressorEffect @@ -172,10 +150,9 @@ EaxCompressorEffect::EaxCompressorEffect() } // [[nodiscard]] -bool EaxCompressorEffect::dispatch( - const EaxEaxCall& eax_call) +void EaxCompressorEffect::dispatch(const EaxEaxCall& eax_call) { - return eax_call.is_get() ? get(eax_call) : set(eax_call); + eax_call.is_get() ? get(eax_call) : set(eax_call); } void EaxCompressorEffect::set_eax_defaults() @@ -200,11 +177,9 @@ void EaxCompressorEffect::set_efx_defaults() set_efx_on_off(); } -// [[nodiscard]] -bool EaxCompressorEffect::get( - const EaxEaxCall& eax_call) +void EaxCompressorEffect::get(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXAGCCOMPRESSOR_NONE: break; @@ -220,8 +195,6 @@ bool EaxCompressorEffect::get( default: throw EaxCompressorEffectException{"Unsupported property id."}; } - - return false; } void EaxCompressorEffect::validate_on_off( @@ -293,11 +266,9 @@ bool EaxCompressorEffect::apply_deferred() return true; } -// [[nodiscard]] -bool EaxCompressorEffect::set( - const EaxEaxCall& eax_call) +void EaxCompressorEffect::set(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXAGCCOMPRESSOR_NONE: break; @@ -313,13 +284,6 @@ bool EaxCompressorEffect::set( default: throw EaxCompressorEffectException{"Unsupported property id."}; } - - if (!eax_call.is_deferred()) - { - return apply_deferred(); - } - - return false; } } // namespace diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index 0f4b6ed5..13b1f23d 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -143,10 +143,7 @@ class EaxDistortionEffect final : public: EaxDistortionEffect(); - - // [[nodiscard]] - bool dispatch( - const EaxEaxCall& eax_call) override; + void dispatch(const EaxEaxCall& eax_call) override; // [[nodiscard]] bool apply_deferred() override; @@ -156,88 +153,39 @@ private: EAXDISTORTIONPROPERTIES eax_d_{}; EaxDistortionEffectDirtyFlags eax_dirty_flags_{}; - void set_eax_defaults(); - void set_efx_edge(); - void set_efx_gain(); - void set_efx_lowpass_cutoff(); - void set_efx_eq_center(); - void set_efx_eq_bandwidth(); - void set_efx_defaults(); - - // [[nodiscard]] - bool get( - const EaxEaxCall& eax_call); - - - void validate_edge( - float flEdge); - - void validate_gain( - long lGain); - - void validate_lowpass_cutoff( - float flLowPassCutOff); - - void validate_eq_center( - float flEQCenter); - - void validate_eq_bandwidth( - float flEQBandwidth); - - void validate_all( - const EAXDISTORTIONPROPERTIES& eax_all); - - - void defer_edge( - float flEdge); - - void defer_gain( - long lGain); - - void defer_low_pass_cutoff( - float flLowPassCutOff); - - void defer_eq_center( - float flEQCenter); - - void defer_eq_bandwidth( - float flEQBandwidth); - - void defer_all( - const EAXDISTORTIONPROPERTIES& eax_all); - - - void defer_edge( - const EaxEaxCall& eax_call); - - void defer_gain( - const EaxEaxCall& eax_call); - - void defer_low_pass_cutoff( - const EaxEaxCall& eax_call); - - void defer_eq_center( - const EaxEaxCall& eax_call); - - void defer_eq_bandwidth( - const EaxEaxCall& eax_call); - - void defer_all( - const EaxEaxCall& eax_call); - - - // [[nodiscard]] - bool set( - const EaxEaxCall& eax_call); + void get(const EaxEaxCall& eax_call); + + void validate_edge(float flEdge); + void validate_gain(long lGain); + void validate_lowpass_cutoff(float flLowPassCutOff); + void validate_eq_center(float flEQCenter); + void validate_eq_bandwidth(float flEQBandwidth); + void validate_all(const EAXDISTORTIONPROPERTIES& eax_all); + + void defer_edge(float flEdge); + void defer_gain(long lGain); + void defer_low_pass_cutoff(float flLowPassCutOff); + void defer_eq_center(float flEQCenter); + void defer_eq_bandwidth(float flEQBandwidth); + void defer_all(const EAXDISTORTIONPROPERTIES& eax_all); + + void defer_edge(const EaxEaxCall& eax_call); + void defer_gain(const EaxEaxCall& eax_call); + void defer_low_pass_cutoff(const EaxEaxCall& eax_call); + void defer_eq_center(const EaxEaxCall& eax_call); + void defer_eq_bandwidth(const EaxEaxCall& eax_call); + void defer_all(const EaxEaxCall& eax_call); + + void set(const EaxEaxCall& eax_call); }; // EaxDistortionEffect @@ -261,11 +209,9 @@ EaxDistortionEffect::EaxDistortionEffect() set_efx_defaults(); } -// [[nodiscard]] -bool EaxDistortionEffect::dispatch( - const EaxEaxCall& eax_call) +void EaxDistortionEffect::dispatch(const EaxEaxCall& eax_call) { - return eax_call.is_get() ? get(eax_call) : set(eax_call); + eax_call.is_get() ? get(eax_call) : set(eax_call); } void EaxDistortionEffect::set_eax_defaults() @@ -338,11 +284,9 @@ void EaxDistortionEffect::set_efx_defaults() set_efx_eq_bandwidth(); } -// [[nodiscard]] -bool EaxDistortionEffect::get( - const EaxEaxCall& eax_call) +void EaxDistortionEffect::get(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXDISTORTION_NONE: break; @@ -374,8 +318,6 @@ bool EaxDistortionEffect::get( default: throw EaxDistortionEffectException{"Unsupported property id."}; } - - return false; } void EaxDistortionEffect::validate_edge( @@ -583,11 +525,9 @@ bool EaxDistortionEffect::apply_deferred() return true; } -// [[nodiscard]] -bool EaxDistortionEffect::set( - const EaxEaxCall& eax_call) +void EaxDistortionEffect::set(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXDISTORTION_NONE: break; @@ -619,13 +559,6 @@ bool EaxDistortionEffect::set( default: throw EaxDistortionEffectException{"Unsupported property id."}; } - - if (!eax_call.is_deferred()) - { - return apply_deferred(); - } - - return false; } } // namespace diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index b2e45091..61adad7f 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -140,10 +140,7 @@ class EaxEchoEffect final : public: EaxEchoEffect(); - - // [[nodiscard]] - bool dispatch( - const EaxEaxCall& eax_call) override; + void dispatch(const EaxEaxCall& eax_call) override; // [[nodiscard]] bool apply_deferred() override; @@ -153,87 +150,39 @@ private: EAXECHOPROPERTIES eax_d_{}; EaxEchoEffectDirtyFlags eax_dirty_flags_{}; - void set_eax_defaults(); - void set_efx_delay(); - void set_efx_lr_delay(); - void set_efx_damping(); - void set_efx_feedback(); - void set_efx_spread(); - void set_efx_defaults(); - - // [[nodiscard]] - bool get( - const EaxEaxCall& eax_call); - - - void validate_delay( - float flDelay); - - void validate_lr_delay( - float flLRDelay); - - void validate_damping( - float flDamping); - - void validate_feedback( - float flFeedback); - - void validate_spread( - float flSpread); - - void validate_all( - const EAXECHOPROPERTIES& all); - - - void defer_delay( - float flDelay); - - void defer_lr_delay( - float flLRDelay); - - void defer_damping( - float flDamping); - - void defer_feedback( - float flFeedback); - - void defer_spread( - float flSpread); - - void defer_all( - const EAXECHOPROPERTIES& all); - - - void defer_delay( - const EaxEaxCall& eax_call); - - void defer_lr_delay( - const EaxEaxCall& eax_call); - - void defer_damping( - const EaxEaxCall& eax_call); - - void defer_feedback( - const EaxEaxCall& eax_call); - - void defer_spread( - const EaxEaxCall& eax_call); - - void defer_all( - const EaxEaxCall& eax_call); - - - bool set( - const EaxEaxCall& eax_call); + void get(const EaxEaxCall& eax_call); + + void validate_delay(float flDelay); + void validate_lr_delay(float flLRDelay); + void validate_damping(float flDamping); + void validate_feedback(float flFeedback); + void validate_spread(float flSpread); + void validate_all(const EAXECHOPROPERTIES& all); + + void defer_delay(float flDelay); + void defer_lr_delay(float flLRDelay); + void defer_damping(float flDamping); + void defer_feedback(float flFeedback); + void defer_spread(float flSpread); + void defer_all(const EAXECHOPROPERTIES& all); + + void defer_delay(const EaxEaxCall& eax_call); + void defer_lr_delay(const EaxEaxCall& eax_call); + void defer_damping(const EaxEaxCall& eax_call); + void defer_feedback(const EaxEaxCall& eax_call); + void defer_spread(const EaxEaxCall& eax_call); + void defer_all(const EaxEaxCall& eax_call); + + void set(const EaxEaxCall& eax_call); }; // EaxEchoEffect @@ -257,11 +206,10 @@ EaxEchoEffect::EaxEchoEffect() set_efx_defaults(); } -// [[nodiscard]] -bool EaxEchoEffect::dispatch( +void EaxEchoEffect::dispatch( const EaxEaxCall& eax_call) { - return eax_call.is_get() ? get(eax_call) : set(eax_call); + eax_call.is_get() ? get(eax_call) : set(eax_call); } void EaxEchoEffect::set_eax_defaults() @@ -334,11 +282,9 @@ void EaxEchoEffect::set_efx_defaults() set_efx_spread(); } -// [[nodiscard]] -bool EaxEchoEffect::get( - const EaxEaxCall& eax_call) +void EaxEchoEffect::get(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXECHO_NONE: break; @@ -370,8 +316,6 @@ bool EaxEchoEffect::get( default: throw EaxEchoEffectException{"Unsupported property id."}; } - - return false; } void EaxEchoEffect::validate_delay( @@ -579,11 +523,9 @@ bool EaxEchoEffect::apply_deferred() return true; } -// [[nodiscard]] -bool EaxEchoEffect::set( - const EaxEaxCall& eax_call) +void EaxEchoEffect::set(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXECHO_NONE: break; @@ -615,13 +557,6 @@ bool EaxEchoEffect::set( default: throw EaxEchoEffectException{"Unsupported property id."}; } - - if (!eax_call.is_deferred()) - { - return apply_deferred(); - } - - return false; } } // namespace diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index 8cd59cd1..f829328c 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -203,10 +203,7 @@ class EaxEqualizerEffect final : public: EaxEqualizerEffect(); - - // [[nodiscard]] - bool dispatch( - const EaxEaxCall& eax_call) override; + void dispatch(const EaxEaxCall& eax_call) override; // [[nodiscard]] bool apply_deferred() override; @@ -216,143 +213,59 @@ private: EAXEQUALIZERPROPERTIES eax_d_{}; EaxEqualizerEffectDirtyFlags eax_dirty_flags_{}; - void set_eax_defaults(); - void set_efx_low_gain(); - void set_efx_low_cutoff(); - void set_efx_mid1_gain(); - void set_efx_mid1_center(); - void set_efx_mid1_width(); - void set_efx_mid2_gain(); - void set_efx_mid2_center(); - void set_efx_mid2_width(); - void set_efx_high_gain(); - void set_efx_high_cutoff(); - void set_efx_defaults(); - - // [[nodiscard]] - bool get( - const EaxEaxCall& eax_call); - - - void validate_low_gain( - long lLowGain); - - void validate_low_cutoff( - float flLowCutOff); - - void validate_mid1_gain( - long lMid1Gain); - - void validate_mid1_center( - float flMid1Center); - - void validate_mid1_width( - float flMid1Width); - - void validate_mid2_gain( - long lMid2Gain); - - void validate_mid2_center( - float flMid2Center); - - void validate_mid2_width( - float flMid2Width); - - void validate_high_gain( - long lHighGain); - - void validate_high_cutoff( - float flHighCutOff); - - void validate_all( - const EAXEQUALIZERPROPERTIES& all); - - - void defer_low_gain( - long lLowGain); - - void defer_low_cutoff( - float flLowCutOff); - - void defer_mid1_gain( - long lMid1Gain); - - void defer_mid1_center( - float flMid1Center); - - void defer_mid1_width( - float flMid1Width); - - void defer_mid2_gain( - long lMid2Gain); - - void defer_mid2_center( - float flMid2Center); - - void defer_mid2_width( - float flMid2Width); - - void defer_high_gain( - long lHighGain); - - void defer_high_cutoff( - float flHighCutOff); - - void defer_all( - const EAXEQUALIZERPROPERTIES& all); - - - void defer_low_gain( - const EaxEaxCall& eax_call); - - void defer_low_cutoff( - const EaxEaxCall& eax_call); - - void defer_mid1_gain( - const EaxEaxCall& eax_call); - - void defer_mid1_center( - const EaxEaxCall& eax_call); - - void defer_mid1_width( - const EaxEaxCall& eax_call); - - void defer_mid2_gain( - const EaxEaxCall& eax_call); - - void defer_mid2_center( - const EaxEaxCall& eax_call); - - void defer_mid2_width( - const EaxEaxCall& eax_call); - - void defer_high_gain( - const EaxEaxCall& eax_call); - - void defer_high_cutoff( - const EaxEaxCall& eax_call); - - void defer_all( - const EaxEaxCall& eax_call); - - - // [[nodiscard]] - bool set( - const EaxEaxCall& eax_call); + void get(const EaxEaxCall& eax_call); + + void validate_low_gain(long lLowGain); + void validate_low_cutoff(float flLowCutOff); + void validate_mid1_gain(long lMid1Gain); + void validate_mid1_center(float flMid1Center); + void validate_mid1_width(float flMid1Width); + void validate_mid2_gain(long lMid2Gain); + void validate_mid2_center(float flMid2Center); + void validate_mid2_width(float flMid2Width); + void validate_high_gain(long lHighGain); + void validate_high_cutoff(float flHighCutOff); + void validate_all(const EAXEQUALIZERPROPERTIES& all); + + void defer_low_gain(long lLowGain); + void defer_low_cutoff(float flLowCutOff); + void defer_mid1_gain(long lMid1Gain); + void defer_mid1_center(float flMid1Center); + void defer_mid1_width(float flMid1Width); + void defer_mid2_gain(long lMid2Gain); + void defer_mid2_center(float flMid2Center); + void defer_mid2_width(float flMid2Width); + void defer_high_gain(long lHighGain); + void defer_high_cutoff(float flHighCutOff); + void defer_all(const EAXEQUALIZERPROPERTIES& all); + + void defer_low_gain(const EaxEaxCall& eax_call); + void defer_low_cutoff(const EaxEaxCall& eax_call); + void defer_mid1_gain(const EaxEaxCall& eax_call); + void defer_mid1_center(const EaxEaxCall& eax_call); + void defer_mid1_width(const EaxEaxCall& eax_call); + void defer_mid2_gain(const EaxEaxCall& eax_call); + void defer_mid2_center(const EaxEaxCall& eax_call); + void defer_mid2_width(const EaxEaxCall& eax_call); + void defer_high_gain(const EaxEaxCall& eax_call); + void defer_high_cutoff(const EaxEaxCall& eax_call); + void defer_all(const EaxEaxCall& eax_call); + + void set(const EaxEaxCall& eax_call); }; // EaxEqualizerEffect @@ -376,11 +289,9 @@ EaxEqualizerEffect::EaxEqualizerEffect() set_efx_defaults(); } -// [[nodiscard]] -bool EaxEqualizerEffect::dispatch( - const EaxEaxCall& eax_call) +void EaxEqualizerEffect::dispatch(const EaxEaxCall& eax_call) { - return eax_call.is_get() ? get(eax_call) : set(eax_call); + eax_call.is_get() ? get(eax_call) : set(eax_call); } void EaxEqualizerEffect::set_eax_defaults() @@ -513,11 +424,9 @@ void EaxEqualizerEffect::set_efx_defaults() set_efx_high_cutoff(); } -// [[nodiscard]] -bool EaxEqualizerEffect::get( - const EaxEaxCall& eax_call) +void EaxEqualizerEffect::get(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXEQUALIZER_NONE: break; @@ -569,8 +478,6 @@ bool EaxEqualizerEffect::get( default: throw EaxEqualizerEffectException{"Unsupported property id."}; } - - return false; } void EaxEqualizerEffect::validate_low_gain( @@ -948,11 +855,9 @@ bool EaxEqualizerEffect::apply_deferred() return true; } -// [[nodiscard]] -bool EaxEqualizerEffect::set( - const EaxEaxCall& eax_call) +void EaxEqualizerEffect::set(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXEQUALIZER_NONE: break; @@ -1004,13 +909,6 @@ bool EaxEqualizerEffect::set( default: throw EaxEqualizerEffectException{"Unsupported property id."}; } - - if (!eax_call.is_deferred()) - { - return apply_deferred(); - } - - return false; } } // namespace diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index 8ad48ab3..d334890b 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -159,10 +159,7 @@ class EaxFrequencyShifterEffect final : public: EaxFrequencyShifterEffect(); - - // [[nodiscard]] - bool dispatch( - const EaxEaxCall& eax_call) override; + void dispatch(const EaxEaxCall& eax_call) override; // [[nodiscard]] bool apply_deferred() override; @@ -172,66 +169,31 @@ private: EAXFREQUENCYSHIFTERPROPERTIES eax_d_{}; EaxFrequencyShifterEffectDirtyFlags eax_dirty_flags_{}; - void set_eax_defaults(); - void set_efx_frequency(); - void set_efx_left_direction(); - void set_efx_right_direction(); - void set_efx_defaults(); + void get(const EaxEaxCall& eax_call); - // [[nodiscard]] - bool get( - const EaxEaxCall& eax_call); - - - void validate_frequency( - float flFrequency); - - void validate_left_direction( - unsigned long ulLeftDirection); - - void validate_right_direction( - unsigned long ulRightDirection); - - void validate_all( - const EAXFREQUENCYSHIFTERPROPERTIES& all); - - - void defer_frequency( - float flFrequency); - - void defer_left_direction( - unsigned long ulLeftDirection); - - void defer_right_direction( - unsigned long ulRightDirection); + void validate_frequency(float flFrequency); + void validate_left_direction(unsigned long ulLeftDirection); + void validate_right_direction(unsigned long ulRightDirection); + void validate_all(const EAXFREQUENCYSHIFTERPROPERTIES& all); - void defer_all( - const EAXFREQUENCYSHIFTERPROPERTIES& all); + void defer_frequency(float flFrequency); + void defer_left_direction(unsigned long ulLeftDirection); + void defer_right_direction(unsigned long ulRightDirection); + void defer_all(const EAXFREQUENCYSHIFTERPROPERTIES& all); + void defer_frequency(const EaxEaxCall& eax_call); + void defer_left_direction(const EaxEaxCall& eax_call); + void defer_right_direction(const EaxEaxCall& eax_call); + void defer_all(const EaxEaxCall& eax_call); - void defer_frequency( - const EaxEaxCall& eax_call); - - void defer_left_direction( - const EaxEaxCall& eax_call); - - void defer_right_direction( - const EaxEaxCall& eax_call); - - void defer_all( - const EaxEaxCall& eax_call); - - - // [[nodiscard]] - bool set( - const EaxEaxCall& eax_call); + void set(const EaxEaxCall& eax_call); }; // EaxFrequencyShifterEffect @@ -255,11 +217,9 @@ EaxFrequencyShifterEffect::EaxFrequencyShifterEffect() set_efx_defaults(); } -// [[nodiscard]] -bool EaxFrequencyShifterEffect::dispatch( - const EaxEaxCall& eax_call) +void EaxFrequencyShifterEffect::dispatch(const EaxEaxCall& eax_call) { - return eax_call.is_get() ? get(eax_call) : set(eax_call); + eax_call.is_get() ? get(eax_call) : set(eax_call); } void EaxFrequencyShifterEffect::set_eax_defaults() @@ -312,11 +272,9 @@ void EaxFrequencyShifterEffect::set_efx_defaults() set_efx_right_direction(); } -// [[nodiscard]] -bool EaxFrequencyShifterEffect::get( - const EaxEaxCall& eax_call) +void EaxFrequencyShifterEffect::get(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXFREQUENCYSHIFTER_NONE: break; @@ -340,8 +298,6 @@ bool EaxFrequencyShifterEffect::get( default: throw EaxFrequencyShifterEffectException{"Unsupported property id."}; } - - return false; } void EaxFrequencyShifterEffect::validate_frequency( @@ -485,11 +441,9 @@ bool EaxFrequencyShifterEffect::apply_deferred() return true; } -// [[nodiscard]] -bool EaxFrequencyShifterEffect::set( - const EaxEaxCall& eax_call) +void EaxFrequencyShifterEffect::set(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXFREQUENCYSHIFTER_NONE: break; @@ -513,13 +467,6 @@ bool EaxFrequencyShifterEffect::set( default: throw EaxFrequencyShifterEffectException{"Unsupported property id."}; } - - if (!eax_call.is_deferred()) - { - return apply_deferred(); - } - - return false; } } // namespace diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index a1521d26..800b892d 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -165,10 +165,7 @@ class EaxRingModulatorEffect final : public: EaxRingModulatorEffect(); - - // [[nodiscard]] - bool dispatch( - const EaxEaxCall& eax_call) override; + void dispatch(const EaxEaxCall& eax_call) override; // [[nodiscard]] bool apply_deferred() override; @@ -178,66 +175,31 @@ private: EAXRINGMODULATORPROPERTIES eax_d_{}; EaxRingModulatorEffectDirtyFlags eax_dirty_flags_{}; - void set_eax_defaults(); - void set_efx_frequency(); - void set_efx_high_pass_cutoff(); - void set_efx_waveform(); - void set_efx_defaults(); + void get(const EaxEaxCall& eax_call); - // [[nodiscard]] - bool get( - const EaxEaxCall& eax_call); - - - void validate_frequency( - float flFrequency); - - void validate_high_pass_cutoff( - float flHighPassCutOff); - - void validate_waveform( - unsigned long ulWaveform); - - void validate_all( - const EAXRINGMODULATORPROPERTIES& all); - - - void defer_frequency( - float flFrequency); - - void defer_high_pass_cutoff( - float flHighPassCutOff); - - void defer_waveform( - unsigned long ulWaveform); - - void defer_all( - const EAXRINGMODULATORPROPERTIES& all); + void validate_frequency(float flFrequency); + void validate_high_pass_cutoff(float flHighPassCutOff); + void validate_waveform(unsigned long ulWaveform); + void validate_all(const EAXRINGMODULATORPROPERTIES& all); + void defer_frequency(float flFrequency); + void defer_high_pass_cutoff(float flHighPassCutOff); + void defer_waveform(unsigned long ulWaveform); + void defer_all(const EAXRINGMODULATORPROPERTIES& all); - void defer_frequency( - const EaxEaxCall& eax_call); + void defer_frequency(const EaxEaxCall& eax_call); + void defer_high_pass_cutoff(const EaxEaxCall& eax_call); + void defer_waveform(const EaxEaxCall& eax_call); + void defer_all(const EaxEaxCall& eax_call); - void defer_high_pass_cutoff( - const EaxEaxCall& eax_call); - - void defer_waveform( - const EaxEaxCall& eax_call); - - void defer_all( - const EaxEaxCall& eax_call); - - - // [[nodiscard]] - bool set( - const EaxEaxCall& eax_call); + void set(const EaxEaxCall& eax_call); }; // EaxRingModulatorEffect @@ -261,11 +223,9 @@ EaxRingModulatorEffect::EaxRingModulatorEffect() set_efx_defaults(); } -// [[nodiscard]] -bool EaxRingModulatorEffect::dispatch( - const EaxEaxCall& eax_call) +void EaxRingModulatorEffect::dispatch(const EaxEaxCall& eax_call) { - return eax_call.is_get() ? get(eax_call) : set(eax_call); + eax_call.is_get() ? get(eax_call) : set(eax_call); } void EaxRingModulatorEffect::set_eax_defaults() @@ -316,11 +276,9 @@ void EaxRingModulatorEffect::set_efx_defaults() set_efx_waveform(); } -// [[nodiscard]] -bool EaxRingModulatorEffect::get( - const EaxEaxCall& eax_call) +void EaxRingModulatorEffect::get(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXRINGMODULATOR_NONE: break; @@ -344,8 +302,6 @@ bool EaxRingModulatorEffect::get( default: throw EaxRingModulatorEffectException{"Unsupported property id."}; } - - return false; } void EaxRingModulatorEffect::validate_frequency( @@ -488,9 +444,7 @@ bool EaxRingModulatorEffect::apply_deferred() return true; } -// [[nodiscard]] -bool EaxRingModulatorEffect::set( - const EaxEaxCall& eax_call) +void EaxRingModulatorEffect::set(const EaxEaxCall& eax_call) { switch (eax_call.get_property_id()) { @@ -516,13 +470,6 @@ bool EaxRingModulatorEffect::set( default: throw EaxRingModulatorEffectException{"Unsupported property id."}; } - - if (!eax_call.is_deferred()) - { - return apply_deferred(); - } - - return false; } } // namespace diff --git a/al/effects/null.cpp b/al/effects/null.cpp index 5602280b..a0eb2247 100644 --- a/al/effects/null.cpp +++ b/al/effects/null.cpp @@ -106,9 +106,7 @@ class EaxNullEffect final : public: EaxNullEffect(); - // [[nodiscard]] - bool dispatch( - const EaxEaxCall& eax_call) override; + void dispatch(const EaxEaxCall& eax_call) override; // [[nodiscard]] bool apply_deferred() override; @@ -133,16 +131,10 @@ EaxNullEffect::EaxNullEffect() { } -// [[nodiscard]] -bool EaxNullEffect::dispatch( - const EaxEaxCall& eax_call) +void EaxNullEffect::dispatch(const EaxEaxCall& eax_call) { - if (eax_call.get_property_id() != 0) - { + if(eax_call.get_property_id() != 0) throw EaxNullEffectException{"Unsupported property id."}; - } - - return false; } bool EaxNullEffect::apply_deferred() diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp index a2b06078..1b2dcff0 100644 --- a/al/effects/pshifter.cpp +++ b/al/effects/pshifter.cpp @@ -110,9 +110,7 @@ class EaxPitchShifterEffect final : public: EaxPitchShifterEffect(); - // [[nodiscard]] - bool dispatch( - const EaxEaxCall& eax_call) override; + void dispatch(const EaxEaxCall& eax_call) override; // [[nodiscard]] bool apply_deferred() override; @@ -122,55 +120,27 @@ private: EAXPITCHSHIFTERPROPERTIES eax_d_{}; EaxPitchShifterEffectDirtyFlags eax_dirty_flags_{}; - void set_eax_defaults(); - void set_efx_coarse_tune(); - void set_efx_fine_tune(); - void set_efx_defaults(); + void get(const EaxEaxCall& eax_call); - // [[nodiscard]] - bool get( - const EaxEaxCall& eax_call); - - - void validate_coarse_tune( - long lCoarseTune); - - void validate_fine_tune( - long lFineTune); - - void validate_all( - const EAXPITCHSHIFTERPROPERTIES& all); - - - void defer_coarse_tune( - long lCoarseTune); - - void defer_fine_tune( - long lFineTune); - - void defer_all( - const EAXPITCHSHIFTERPROPERTIES& all); - + void validate_coarse_tune(long lCoarseTune); + void validate_fine_tune(long lFineTune); + void validate_all(const EAXPITCHSHIFTERPROPERTIES& all); - void defer_coarse_tune( - const EaxEaxCall& eax_call); + void defer_coarse_tune(long lCoarseTune); + void defer_fine_tune(long lFineTune); + void defer_all(const EAXPITCHSHIFTERPROPERTIES& all); - void defer_fine_tune( - const EaxEaxCall& eax_call); + void defer_coarse_tune(const EaxEaxCall& eax_call); + void defer_fine_tune(const EaxEaxCall& eax_call); + void defer_all(const EaxEaxCall& eax_call); - void defer_all( - const EaxEaxCall& eax_call); - - - // [[nodiscard]] - bool set( - const EaxEaxCall& eax_call); + void set(const EaxEaxCall& eax_call); }; // EaxPitchShifterEffect @@ -194,11 +164,9 @@ EaxPitchShifterEffect::EaxPitchShifterEffect() set_efx_defaults(); } -// [[nodiscard]] -bool EaxPitchShifterEffect::dispatch( - const EaxEaxCall& eax_call) +void EaxPitchShifterEffect::dispatch(const EaxEaxCall& eax_call) { - return eax_call.is_get() ? get(eax_call) : set(eax_call); + eax_call.is_get() ? get(eax_call) : set(eax_call); } void EaxPitchShifterEffect::set_eax_defaults() @@ -235,11 +203,9 @@ void EaxPitchShifterEffect::set_efx_defaults() set_efx_fine_tune(); } -// [[nodiscard]] -bool EaxPitchShifterEffect::get( - const EaxEaxCall& eax_call) +void EaxPitchShifterEffect::get(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXPITCHSHIFTER_NONE: break; @@ -259,8 +225,6 @@ bool EaxPitchShifterEffect::get( default: throw EaxPitchShifterEffectException{"Unsupported property id."}; } - - return false; } void EaxPitchShifterEffect::validate_coarse_tune( @@ -366,11 +330,9 @@ bool EaxPitchShifterEffect::apply_deferred() return true; } -// [[nodiscard]] -bool EaxPitchShifterEffect::set( - const EaxEaxCall& eax_call) +void EaxPitchShifterEffect::set(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXPITCHSHIFTER_NONE: break; @@ -390,13 +352,6 @@ bool EaxPitchShifterEffect::set( default: throw EaxPitchShifterEffectException{"Unsupported property id."}; } - - if (!eax_call.is_deferred()) - { - return apply_deferred(); - } - - return false; } } // namespace diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index 1d8e9183..81990686 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -616,9 +616,7 @@ class EaxReverbEffect final : public: EaxReverbEffect(); - // [[nodiscard]] - bool dispatch( - const EaxEaxCall& eax_call) override; + void dispatch(const EaxEaxCall& eax_call) override; // [[nodiscard]] bool apply_deferred() override; @@ -635,7 +633,6 @@ private: void set_eax_defaults(); - void set_efx_density_from_environment_size(); void set_efx_diffusion(); void set_efx_gain(); @@ -661,13 +658,11 @@ private: void set_efx_flags(); void set_efx_defaults(); - bool v1_get(const EaxEaxCall& eax_call) const; + void v1_get(const EaxEaxCall& eax_call) const; void get_all(const EaxEaxCall& eax_call) const; - // [[nodiscard]] - bool get(const EaxEaxCall& eax_call) const; - + void get(const EaxEaxCall& eax_call) const; static void v1_validate_environment(unsigned long environment); static void v1_validate_volume(float volume); @@ -770,8 +765,7 @@ private: void defer_flags(const EaxEaxCall& eax_call); void defer_all(const EaxEaxCall& eax_call); - // [[nodiscard]] - bool set(const EaxEaxCall& eax_call); + void set(const EaxEaxCall& eax_call); }; // EaxReverbEffect @@ -795,11 +789,9 @@ EaxReverbEffect::EaxReverbEffect() set_efx_defaults(); } -// [[nodiscard]] -bool EaxReverbEffect::dispatch( - const EaxEaxCall& eax_call) +void EaxReverbEffect::dispatch(const EaxEaxCall& eax_call) { - return eax_call.is_get() ? get(eax_call) : set(eax_call); + eax_call.is_get() ? get(eax_call) : set(eax_call); } [[noreturn]] void EaxReverbEffect::eax_fail(const char* message) @@ -1063,9 +1055,9 @@ void EaxReverbEffect::set_efx_defaults() set_efx_flags(); } -bool EaxReverbEffect::v1_get(const EaxEaxCall& eax_call) const +void EaxReverbEffect::v1_get(const EaxEaxCall& eax_call) const { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case DSPROPERTY_EAX_ALL: eax_call.set_value(eax1_); @@ -1090,8 +1082,6 @@ bool EaxReverbEffect::v1_get(const EaxEaxCall& eax_call) const default: eax_fail("Unsupported property id."); } - - return false; } void EaxReverbEffect::get_all( @@ -1121,14 +1111,11 @@ void EaxReverbEffect::get_all( } } -// [[nodiscard]] -bool EaxReverbEffect::get( - const EaxEaxCall& eax_call) const +void EaxReverbEffect::get(const EaxEaxCall& eax_call) const { - if (eax_call.get_version() == 1) - return v1_get(eax_call); - - switch (eax_call.get_property_id()) + if(eax_call.get_version() == 1) + v1_get(eax_call); + else switch(eax_call.get_property_id()) { case EAXREVERB_NONE: break; @@ -1236,8 +1223,6 @@ bool EaxReverbEffect::get( default: eax_fail("Unsupported property id."); } - - return false; } void EaxReverbEffect::v1_validate_environment(unsigned long environment) @@ -1844,7 +1829,6 @@ void EaxReverbEffect::v1_defer_environment(const EaxEaxCall& eax_call) validate_environment(environment, 1, true); const auto& reverb_preset = EAX1REVERB_PRESETS[environment]; - v1_defer_all(reverb_preset); } @@ -2398,9 +2382,7 @@ bool EaxReverbEffect::apply_deferred() return true; } -// [[nodiscard]] -bool EaxReverbEffect::set( - const EaxEaxCall& eax_call) +void EaxReverbEffect::set(const EaxEaxCall& eax_call) { if(eax_call.get_version() == 1) v1_defer(eax_call); @@ -2512,13 +2494,6 @@ bool EaxReverbEffect::set( default: eax_fail("Unsupported property id."); } - - if (!eax_call.is_deferred()) - { - return apply_deferred(); - } - - return false; } const EFXEAXREVERBPROPERTIES eax_efx_reverb_presets[EAX1_ENVIRONMENT_COUNT] = diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index 15f099b1..8c0b3adb 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -281,9 +281,7 @@ class EaxVocalMorpherEffect final : public: EaxVocalMorpherEffect(); - // [[nodiscard]] - bool dispatch( - const EaxEaxCall& eax_call) override; + void dispatch(const EaxEaxCall& eax_call) override; // [[nodiscard]] bool apply_deferred() override; @@ -293,99 +291,43 @@ private: EAXVOCALMORPHERPROPERTIES eax_d_{}; EaxVocalMorpherEffectDirtyFlags eax_dirty_flags_{}; - void set_eax_defaults(); - void set_efx_phoneme_a(); - void set_efx_phoneme_a_coarse_tuning(); - void set_efx_phoneme_b(); - void set_efx_phoneme_b_coarse_tuning(); - void set_efx_waveform(); - void set_efx_rate(); - void set_efx_defaults(); - - // [[nodiscard]] - bool get( - const EaxEaxCall& eax_call); - - - void validate_phoneme_a( - unsigned long ulPhonemeA); - - void validate_phoneme_a_coarse_tuning( - long lPhonemeACoarseTuning); - - void validate_phoneme_b( - unsigned long ulPhonemeB); - - void validate_phoneme_b_coarse_tuning( - long lPhonemeBCoarseTuning); - - void validate_waveform( - unsigned long ulWaveform); - - void validate_rate( - float flRate); - - void validate_all( - const EAXVOCALMORPHERPROPERTIES& all); - - - void defer_phoneme_a( - unsigned long ulPhonemeA); - - void defer_phoneme_a_coarse_tuning( - long lPhonemeACoarseTuning); - - void defer_phoneme_b( - unsigned long ulPhonemeB); - - void defer_phoneme_b_coarse_tuning( - long lPhonemeBCoarseTuning); - - void defer_waveform( - unsigned long ulWaveform); - - void defer_rate( - float flRate); - - void defer_all( - const EAXVOCALMORPHERPROPERTIES& all); - - - void defer_phoneme_a( - const EaxEaxCall& eax_call); - - void defer_phoneme_a_coarse_tuning( - const EaxEaxCall& eax_call); - - void defer_phoneme_b( - const EaxEaxCall& eax_call); - - void defer_phoneme_b_coarse_tuning( - const EaxEaxCall& eax_call); - - void defer_waveform( - const EaxEaxCall& eax_call); - - void defer_rate( - const EaxEaxCall& eax_call); - - void defer_all( - const EaxEaxCall& eax_call); - - - // [[nodiscard]] - bool set( - const EaxEaxCall& eax_call); + void get(const EaxEaxCall& eax_call); + + void validate_phoneme_a(unsigned long ulPhonemeA); + void validate_phoneme_a_coarse_tuning(long lPhonemeACoarseTuning); + void validate_phoneme_b(unsigned long ulPhonemeB); + void validate_phoneme_b_coarse_tuning(long lPhonemeBCoarseTuning); + void validate_waveform(unsigned long ulWaveform); + void validate_rate(float flRate); + void validate_all(const EAXVOCALMORPHERPROPERTIES& all); + + void defer_phoneme_a(unsigned long ulPhonemeA); + void defer_phoneme_a_coarse_tuning(long lPhonemeACoarseTuning); + void defer_phoneme_b(unsigned long ulPhonemeB); + void defer_phoneme_b_coarse_tuning(long lPhonemeBCoarseTuning); + void defer_waveform(unsigned long ulWaveform); + void defer_rate(float flRate); + void defer_all(const EAXVOCALMORPHERPROPERTIES& all); + + void defer_phoneme_a(const EaxEaxCall& eax_call); + void defer_phoneme_a_coarse_tuning(const EaxEaxCall& eax_call); + void defer_phoneme_b(const EaxEaxCall& eax_call); + void defer_phoneme_b_coarse_tuning(const EaxEaxCall& eax_call); + void defer_waveform(const EaxEaxCall& eax_call); + void defer_rate(const EaxEaxCall& eax_call); + void defer_all(const EaxEaxCall& eax_call); + + void set(const EaxEaxCall& eax_call); }; // EaxVocalMorpherEffect @@ -409,11 +351,9 @@ EaxVocalMorpherEffect::EaxVocalMorpherEffect() set_efx_defaults(); } -// [[nodiscard]] -bool EaxVocalMorpherEffect::dispatch( - const EaxEaxCall& eax_call) +void EaxVocalMorpherEffect::dispatch(const EaxEaxCall& eax_call) { - return eax_call.is_get() ? get(eax_call) : set(eax_call); + eax_call.is_get() ? get(eax_call) : set(eax_call); } void EaxVocalMorpherEffect::set_eax_defaults() @@ -504,11 +444,9 @@ void EaxVocalMorpherEffect::set_efx_defaults() set_efx_rate(); } -// [[nodiscard]] -bool EaxVocalMorpherEffect::get( - const EaxEaxCall& eax_call) +void EaxVocalMorpherEffect::get(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXVOCALMORPHER_NONE: break; @@ -544,8 +482,6 @@ bool EaxVocalMorpherEffect::get( default: throw EaxVocalMorpherEffectException{"Unsupported property id."}; } - - return false; } void EaxVocalMorpherEffect::validate_phoneme_a( @@ -675,10 +611,8 @@ void EaxVocalMorpherEffect::defer_all( void EaxVocalMorpherEffect::defer_phoneme_a( const EaxEaxCall& eax_call) { - const auto& phoneme_a = eax_call.get_value< - EaxVocalMorpherEffectException, - const decltype(EAXVOCALMORPHERPROPERTIES::ulPhonemeA) - >(); + const auto& phoneme_a = eax_call.get_value(); validate_phoneme_a(phoneme_a); defer_phoneme_a(phoneme_a); @@ -801,11 +735,9 @@ bool EaxVocalMorpherEffect::apply_deferred() return true; } -// [[nodiscard]] -bool EaxVocalMorpherEffect::set( - const EaxEaxCall& eax_call) +void EaxVocalMorpherEffect::set(const EaxEaxCall& eax_call) { - switch (eax_call.get_property_id()) + switch(eax_call.get_property_id()) { case EAXVOCALMORPHER_NONE: break; @@ -841,13 +773,6 @@ bool EaxVocalMorpherEffect::set( default: throw EaxVocalMorpherEffectException{"Unsupported property id."}; } - - if (!eax_call.is_deferred()) - { - return apply_deferred(); - } - - return false; } } // namespace diff --git a/al/source.cpp b/al/source.cpp index 3009edd8..3f416151 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -5681,12 +5681,6 @@ void ALsource::eax_set( default: eax_fail("Unsupported property id."); } - - if(!eax_call.is_deferred()) - { - eax_apply_deferred(); - EaxUpdateSourceVoice(this, eax_al_context_); - } } const GUID& ALsource::eax_get_send_fx_slot_guid( diff --git a/alc/context.cpp b/alc/context.cpp index 5a24a311..4b1c2a4c 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -332,11 +332,10 @@ ALenum ALCcontext::eax_eax_set( { eax_initialize(); - constexpr auto deferred_flag = 0x80000000u; const auto eax_call = create_eax_call( false, property_set_id, - property_id | (mDeferUpdates ? deferred_flag : 0u), + property_id, property_source_id, property_value, property_value_size @@ -363,6 +362,10 @@ ALenum ALCcontext::eax_eax_set( eax_fail("Unsupported property set id."); } + static constexpr auto deferred_flag = 0x80000000u; + if(!(property_id&deferred_flag) && !mDeferUpdates) + applyAllUpdates(); + return AL_NO_ERROR; } @@ -1136,22 +1139,6 @@ void ALCcontext::eax_set( default: eax_fail("Unsupported property id."); } - - if(!eax_call.is_deferred()) - { - eax_apply_deferred(); - - mHoldUpdates.store(true, std::memory_order_release); - while((mUpdateCount.load(std::memory_order_acquire)&1) != 0) { - /* busy-wait */ - } - - if(std::exchange(mPropsDirty, false)) - UpdateContextProps(this); - UpdateAllSourceProps(this); - - mHoldUpdates.store(false, std::memory_order_release); - } } void ALCcontext::eax_apply_deferred() -- cgit v1.2.3 From 65e4c20c27f2acf853e58fd4c26ebc0e3eb926c6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 16 May 2022 02:08:18 -0700 Subject: Move EAX files to their own sub-directory --- CMakeLists.txt | 36 +- al/auxeffectslot.cpp | 4 +- al/auxeffectslot.h | 6 +- al/buffer.cpp | 4 +- al/buffer.h | 2 +- al/eax/api.cpp | 1213 +++++++++++++++++++++++++++++++++++ al/eax/api.h | 1557 +++++++++++++++++++++++++++++++++++++++++++++ al/eax/eax_call.cpp | 323 ++++++++++ al/eax/eax_call.h | 117 ++++ al/eax/effect.cpp | 3 + al/eax/effect.h | 44 ++ al/eax/exception.cpp | 62 ++ al/eax/exception.h | 25 + al/eax/fx_slot_index.cpp | 71 +++ al/eax/fx_slot_index.h | 41 ++ al/eax/fx_slots.cpp | 83 +++ al/eax/fx_slots.h | 53 ++ al/eax/globals.cpp | 21 + al/eax/globals.h | 22 + al/eax/utils.cpp | 36 ++ al/eax/utils.h | 132 ++++ al/eax/x_ram.cpp | 3 + al/eax/x_ram.h | 38 ++ al/eax_api.cpp | 1213 ----------------------------------- al/eax_api.h | 1557 --------------------------------------------- al/eax_eax_call.cpp | 324 ---------- al/eax_eax_call.h | 117 ---- al/eax_effect.cpp | 3 - al/eax_effect.h | 44 -- al/eax_exception.cpp | 63 -- al/eax_exception.h | 25 - al/eax_fx_slot_index.cpp | 71 --- al/eax_fx_slot_index.h | 41 -- al/eax_fx_slots.cpp | 84 --- al/eax_fx_slots.h | 54 -- al/eax_globals.cpp | 21 - al/eax_globals.h | 22 - al/eax_utils.cpp | 36 -- al/eax_utils.h | 132 ---- al/eax_x_ram.cpp | 3 - al/eax_x_ram.h | 38 -- al/effect.cpp | 2 +- al/effects/autowah.cpp | 4 +- al/effects/chorus.cpp | 4 +- al/effects/compressor.cpp | 4 +- al/effects/distortion.cpp | 4 +- al/effects/echo.cpp | 4 +- al/effects/effects.h | 2 +- al/effects/equalizer.cpp | 4 +- al/effects/fshifter.cpp | 4 +- al/effects/modulator.cpp | 4 +- al/effects/null.cpp | 2 +- al/effects/pshifter.cpp | 4 +- al/effects/reverb.cpp | 9 +- al/effects/vmorpher.cpp | 4 +- al/source.cpp | 2 +- al/source.h | 6 +- al/state.cpp | 4 +- alc/alc.cpp | 4 +- alc/context.cpp | 4 +- alc/context.h | 8 +- alc/device.h | 2 +- 62 files changed, 3914 insertions(+), 3915 deletions(-) create mode 100644 al/eax/api.cpp create mode 100644 al/eax/api.h create mode 100644 al/eax/eax_call.cpp create mode 100644 al/eax/eax_call.h create mode 100644 al/eax/effect.cpp create mode 100644 al/eax/effect.h create mode 100644 al/eax/exception.cpp create mode 100644 al/eax/exception.h create mode 100644 al/eax/fx_slot_index.cpp create mode 100644 al/eax/fx_slot_index.h create mode 100644 al/eax/fx_slots.cpp create mode 100644 al/eax/fx_slots.h create mode 100644 al/eax/globals.cpp create mode 100644 al/eax/globals.h create mode 100644 al/eax/utils.cpp create mode 100644 al/eax/utils.h create mode 100644 al/eax/x_ram.cpp create mode 100644 al/eax/x_ram.h delete mode 100644 al/eax_api.cpp delete mode 100644 al/eax_api.h delete mode 100644 al/eax_eax_call.cpp delete mode 100644 al/eax_eax_call.h delete mode 100644 al/eax_effect.cpp delete mode 100644 al/eax_effect.h delete mode 100644 al/eax_exception.cpp delete mode 100644 al/eax_exception.h delete mode 100644 al/eax_fx_slot_index.cpp delete mode 100644 al/eax_fx_slot_index.h delete mode 100644 al/eax_fx_slots.cpp delete mode 100644 al/eax_fx_slots.h delete mode 100644 al/eax_globals.cpp delete mode 100644 al/eax_globals.h delete mode 100644 al/eax_utils.cpp delete mode 100644 al/eax_utils.h delete mode 100644 al/eax_x_ram.cpp delete mode 100644 al/eax_x_ram.h (limited to 'al/effects/distortion.cpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index b1c7ede0..52d61ff0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -798,24 +798,24 @@ set(ALC_OBJS if (ALSOFT_EAX) set(OPENAL_OBJS ${OPENAL_OBJS} - al/eax_api.cpp - al/eax_api.h - al/eax_eax_call.cpp - al/eax_eax_call.h - al/eax_effect.cpp - al/eax_effect.h - al/eax_exception.cpp - al/eax_exception.h - al/eax_fx_slot_index.cpp - al/eax_fx_slot_index.h - al/eax_fx_slots.cpp - al/eax_fx_slots.h - al/eax_globals.cpp - al/eax_globals.h - al/eax_utils.cpp - al/eax_utils.h - al/eax_x_ram.cpp - al/eax_x_ram.h + al/eax/api.cpp + al/eax/api.h + al/eax/eax_call.cpp + al/eax/eax_call.h + al/eax/effect.cpp + al/eax/effect.h + al/eax/exception.cpp + al/eax/exception.h + al/eax/fx_slot_index.cpp + al/eax/fx_slot_index.h + al/eax/fx_slots.cpp + al/eax/fx_slots.h + al/eax/globals.cpp + al/eax/globals.h + al/eax/utils.cpp + al/eax/utils.h + al/eax/x_ram.cpp + al/eax/x_ram.h ) endif () diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index c33fb149..455a1072 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -51,8 +51,8 @@ #include "opthelpers.h" #ifdef ALSOFT_EAX -#include "eax_exception.h" -#include "eax_utils.h" +#include "eax/exception.h" +#include "eax/utils.h" #endif // ALSOFT_EAX namespace { diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index ca0dcd31..5336a2a8 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -19,9 +19,9 @@ #ifdef ALSOFT_EAX #include -#include "eax_eax_call.h" -#include "eax_effect.h" -#include "eax_fx_slot_index.h" +#include "eax/eax_call.h" +#include "eax/effect.h" +#include "eax/fx_slot_index.h" #endif // ALSOFT_EAX struct ALbuffer; diff --git a/al/buffer.cpp b/al/buffer.cpp index 13407103..9b455b9c 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -57,8 +57,8 @@ #include "opthelpers.h" #ifdef ALSOFT_EAX -#include "eax_globals.h" -#include "eax_x_ram.h" +#include "eax/globals.h" +#include "eax/x_ram.h" #endif // ALSOFT_EAX diff --git a/al/buffer.h b/al/buffer.h index b3a0f0d8..7ded83bd 100644 --- a/al/buffer.h +++ b/al/buffer.h @@ -13,7 +13,7 @@ #include "vector.h" #ifdef ALSOFT_EAX -#include "eax_x_ram.h" +#include "eax/x_ram.h" #endif // ALSOFT_EAX /* User formats */ diff --git a/al/eax/api.cpp b/al/eax/api.cpp new file mode 100644 index 00000000..f859a1c4 --- /dev/null +++ b/al/eax/api.cpp @@ -0,0 +1,1213 @@ +// +// EAX API. +// +// Based on headers `eax[2-5].h` included in Doom 3 source code: +// https://github.com/id-Software/DOOM-3/tree/master/neo/openal/include +// + +#include "config.h" + +#include + +#include "api.h" + + +const GUID DSPROPSETID_EAX_ReverbProperties = +{ + 0x4A4E6FC1, + 0xC341, + 0x11D1, + {0xB7, 0x3A, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} +}; + +const GUID DSPROPSETID_EAXBUFFER_ReverbProperties = +{ + 0x4A4E6FC0, + 0xC341, + 0x11D1, + {0xB7, 0x3A, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} +}; + +const GUID DSPROPSETID_EAX20_ListenerProperties = +{ + 0x306A6A8, + 0xB224, + 0x11D2, + {0x99, 0xE5, 0x00, 0x00, 0xE8, 0xD8, 0xC7, 0x22} +}; + +const GUID DSPROPSETID_EAX20_BufferProperties = +{ + 0x306A6A7, + 0xB224, + 0x11D2, + {0x99, 0xE5, 0x00, 0x00, 0xE8, 0xD8, 0xC7, 0x22} +}; + +const GUID DSPROPSETID_EAX30_ListenerProperties = +{ + 0xA8FA6882, + 0xB476, + 0x11D3, + {0xBD, 0xB9, 0x00, 0xC0, 0xF0, 0x2D, 0xDF, 0x87} +}; + +const GUID DSPROPSETID_EAX30_BufferProperties = +{ + 0xA8FA6881, + 0xB476, + 0x11D3, + {0xBD, 0xB9, 0x00, 0xC0, 0xF0, 0x2D, 0xDF, 0x87} +}; + +const GUID EAX_NULL_GUID = +{ + 0x00000000, + 0x0000, + 0x0000, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +}; + +const GUID EAX_PrimaryFXSlotID = +{ + 0xF317866D, + 0x924C, + 0x450C, + {0x86, 0x1B, 0xE6, 0xDA, 0xA2, 0x5E, 0x7C, 0x20} +}; + +const GUID EAXPROPERTYID_EAX40_Context = +{ + 0x1D4870AD, + 0xDEF, + 0x43C0, + {0xA4, 0xC, 0x52, 0x36, 0x32, 0x29, 0x63, 0x42} +}; + +const GUID EAXPROPERTYID_EAX50_Context = +{ + 0x57E13437, + 0xB932, + 0x4AB2, + {0xB8, 0xBD, 0x52, 0x66, 0xC1, 0xA8, 0x87, 0xEE} +}; + +const GUID EAXPROPERTYID_EAX40_FXSlot0 = +{ + 0xC4D79F1E, + 0xF1AC, + 0x436B, + {0xA8, 0x1D, 0xA7, 0x38, 0xE7, 0x04, 0x54, 0x69} +}; + +const GUID EAXPROPERTYID_EAX50_FXSlot0 = +{ + 0x91F9590F, + 0xC388, + 0x407A, + {0x84, 0xB0, 0x1B, 0xAE, 0xE, 0xF7, 0x1A, 0xBC} +}; + +const GUID EAXPROPERTYID_EAX40_FXSlot1 = +{ + 0x8C00E96, + 0x74BE, + 0x4491, + {0x93, 0xAA, 0xE8, 0xAD, 0x35, 0xA4, 0x91, 0x17} +}; + +const GUID EAXPROPERTYID_EAX50_FXSlot1 = +{ + 0x8F5F7ACA, + 0x9608, + 0x4965, + {0x81, 0x37, 0x82, 0x13, 0xC7, 0xB9, 0xD9, 0xDE} +}; + +const GUID EAXPROPERTYID_EAX40_FXSlot2 = +{ + 0x1D433B88, + 0xF0F6, + 0x4637, + {0x91, 0x9F, 0x60, 0xE7, 0xE0, 0x6B, 0x5E, 0xDD} +}; + +const GUID EAXPROPERTYID_EAX50_FXSlot2 = +{ + 0x3C0F5252, + 0x9834, + 0x46F0, + {0xA1, 0xD8, 0x5B, 0x95, 0xC4, 0xA0, 0xA, 0x30} +}; + +const GUID EAXPROPERTYID_EAX40_FXSlot3 = +{ + 0xEFFF08EA, + 0xC7D8, + 0x44AB, + {0x93, 0xAD, 0x6D, 0xBD, 0x5F, 0x91, 0x00, 0x64} +}; + +const GUID EAXPROPERTYID_EAX50_FXSlot3 = +{ + 0xE2EB0EAA, + 0xE806, + 0x45E7, + {0x9F, 0x86, 0x06, 0xC1, 0x57, 0x1A, 0x6F, 0xA3} +}; + +const GUID EAXPROPERTYID_EAX40_Source = +{ + 0x1B86B823, + 0x22DF, + 0x4EAE, + {0x8B, 0x3C, 0x12, 0x78, 0xCE, 0x54, 0x42, 0x27} +}; + +const GUID EAXPROPERTYID_EAX50_Source = +{ + 0x5EDF82F0, + 0x24A7, + 0x4F38, + {0x8E, 0x64, 0x2F, 0x09, 0xCA, 0x05, 0xDE, 0xE1} +}; + +const GUID EAX_REVERB_EFFECT = +{ + 0xCF95C8F, + 0xA3CC, + 0x4849, + {0xB0, 0xB6, 0x83, 0x2E, 0xCC, 0x18, 0x22, 0xDF} +}; + +const GUID EAX_AGCCOMPRESSOR_EFFECT = +{ + 0xBFB7A01E, + 0x7825, + 0x4039, + {0x92, 0x7F, 0x03, 0xAA, 0xBD, 0xA0, 0xC5, 0x60} +}; + +const GUID EAX_AUTOWAH_EFFECT = +{ + 0xEC3130C0, + 0xAC7A, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_CHORUS_EFFECT = +{ + 0xDE6D6FE0, + 0xAC79, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_DISTORTION_EFFECT = +{ + 0x975A4CE0, + 0xAC7E, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_ECHO_EFFECT = +{ + 0xE9F1BC0, + 0xAC82, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_EQUALIZER_EFFECT = +{ + 0x65F94CE0, + 0x9793, + 0x11D3, + {0x93, 0x9D, 0x00, 0xC0, 0xF0, 0x2D, 0xD6, 0xF0} +}; + +const GUID EAX_FLANGER_EFFECT = +{ + 0xA70007C0, + 0x7D2, + 0x11D3, + {0x9B, 0x1E, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_FREQUENCYSHIFTER_EFFECT = +{ + 0xDC3E1880, + 0x9212, + 0x11D3, + {0x93, 0x9D, 0x00, 0xC0, 0xF0, 0x2D, 0xD6, 0xF0} +}; + +const GUID EAX_VOCALMORPHER_EFFECT = +{ + 0xE41CF10C, + 0x3383, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_PITCHSHIFTER_EFFECT = +{ + 0xE7905100, + 0xAFB2, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + +const GUID EAX_RINGMODULATOR_EFFECT = +{ + 0xB89FE60, + 0xAFB5, + 0x11D2, + {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} +}; + + +bool operator==( + const EAX40CONTEXTPROPERTIES& lhs, + const EAX40CONTEXTPROPERTIES& rhs) noexcept +{ + return + lhs.guidPrimaryFXSlotID == rhs.guidPrimaryFXSlotID && + lhs.flDistanceFactor == rhs.flDistanceFactor && + lhs.flAirAbsorptionHF == rhs.flAirAbsorptionHF && + lhs.flHFReference == rhs.flHFReference; +} + +bool operator==( + const EAX50CONTEXTPROPERTIES& lhs, + const EAX50CONTEXTPROPERTIES& rhs) noexcept +{ + return + static_cast(lhs) == static_cast(rhs) && + lhs.flMacroFXFactor == rhs.flMacroFXFactor; +} + + +const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX40_FXSlot0; + +bool operator==( + const EAX40FXSLOTPROPERTIES& lhs, + const EAX40FXSLOTPROPERTIES& rhs) noexcept +{ + return + lhs.guidLoadEffect == rhs.guidLoadEffect && + lhs.lVolume == rhs.lVolume && + lhs.lLock == rhs.lLock && + lhs.ulFlags == rhs.ulFlags; +} + +bool operator==( + const EAX50FXSLOTPROPERTIES& lhs, + const EAX50FXSLOTPROPERTIES& rhs) noexcept +{ + return + static_cast(lhs) == static_cast(rhs) && + lhs.lOcclusion == rhs.lOcclusion && + lhs.flOcclusionLFRatio == rhs.flOcclusionLFRatio; +} + +const EAX50ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS +{{ + EAX_NULL_GUID, + EAXPROPERTYID_EAX40_FXSlot0, +}}; + +bool operator==( + const EAX50ACTIVEFXSLOTS& lhs, + const EAX50ACTIVEFXSLOTS& rhs) noexcept +{ + return std::equal( + std::cbegin(lhs.guidActiveFXSlots), + std::cend(lhs.guidActiveFXSlots), + std::begin(rhs.guidActiveFXSlots)); +} + +bool operator!=( + const EAX50ACTIVEFXSLOTS& lhs, + const EAX50ACTIVEFXSLOTS& rhs) noexcept +{ + return !(lhs == rhs); +} + + +const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS +{{ + EAX_NULL_GUID, + EAX_PrimaryFXSlotID, + EAX_NULL_GUID, + EAX_NULL_GUID, +}}; + + +const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS +{{ + EAX_NULL_GUID, + EAX_NULL_GUID, + EAX_NULL_GUID, + EAX_NULL_GUID, +}}; + +bool operator==( + const EAXREVERBPROPERTIES& lhs, + const EAXREVERBPROPERTIES& rhs) noexcept +{ + return + lhs.ulEnvironment == rhs.ulEnvironment && + lhs.flEnvironmentSize == rhs.flEnvironmentSize && + lhs.flEnvironmentDiffusion == rhs.flEnvironmentDiffusion && + lhs.lRoom == rhs.lRoom && + lhs.lRoomHF == rhs.lRoomHF && + lhs.lRoomLF == rhs.lRoomLF && + lhs.flDecayTime == rhs.flDecayTime && + lhs.flDecayHFRatio == rhs.flDecayHFRatio && + lhs.flDecayLFRatio == rhs.flDecayLFRatio && + lhs.lReflections == rhs.lReflections && + lhs.flReflectionsDelay == rhs.flReflectionsDelay && + lhs.vReflectionsPan == rhs.vReflectionsPan && + lhs.lReverb == rhs.lReverb && + lhs.flReverbDelay == rhs.flReverbDelay && + lhs.vReverbPan == rhs.vReverbPan && + lhs.flEchoTime == rhs.flEchoTime && + lhs.flEchoDepth == rhs.flEchoDepth && + lhs.flModulationTime == rhs.flModulationTime && + lhs.flModulationDepth == rhs.flModulationDepth && + lhs.flAirAbsorptionHF == rhs.flAirAbsorptionHF && + lhs.flHFReference == rhs.flHFReference && + lhs.flLFReference == rhs.flLFReference && + lhs.flRoomRolloffFactor == rhs.flRoomRolloffFactor && + lhs.ulFlags == rhs.ulFlags; +} + +bool operator!=( + const EAXREVERBPROPERTIES& lhs, + const EAXREVERBPROPERTIES& rhs) noexcept +{ + return !(lhs == rhs); +} + + +namespace { + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_GENERIC = +{ + EAXREVERB_DEFAULTENVIRONMENT, + EAXREVERB_DEFAULTENVIRONMENTSIZE, + EAXREVERB_DEFAULTENVIRONMENTDIFFUSION, + EAXREVERB_DEFAULTROOM, + EAXREVERB_DEFAULTROOMHF, + EAXREVERB_DEFAULTROOMLF, + EAXREVERB_DEFAULTDECAYTIME, + EAXREVERB_DEFAULTDECAYHFRATIO, + EAXREVERB_DEFAULTDECAYLFRATIO, + EAXREVERB_DEFAULTREFLECTIONS, + EAXREVERB_DEFAULTREFLECTIONSDELAY, + EAXREVERB_DEFAULTREFLECTIONSPAN, + EAXREVERB_DEFAULTREVERB, + EAXREVERB_DEFAULTREVERBDELAY, + EAXREVERB_DEFAULTREVERBPAN, + EAXREVERB_DEFAULTECHOTIME, + EAXREVERB_DEFAULTECHODEPTH, + EAXREVERB_DEFAULTMODULATIONTIME, + EAXREVERB_DEFAULTMODULATIONDEPTH, + EAXREVERB_DEFAULTAIRABSORPTIONHF, + EAXREVERB_DEFAULTHFREFERENCE, + EAXREVERB_DEFAULTLFREFERENCE, + EAXREVERB_DEFAULTROOMROLLOFFFACTOR, + EAXREVERB_DEFAULTFLAGS, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_PADDEDCELL = +{ + EAX_ENVIRONMENT_PADDEDCELL, + 1.4F, + 1.0F, + -1'000L, + -6'000L, + 0L, + 0.17F, + 0.10F, + 1.0F, + -1'204L, + 0.001F, + EAXVECTOR{}, + 207L, + 0.002F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_ROOM = +{ + EAX_ENVIRONMENT_ROOM, + 1.9F, + 1.0F, + -1'000L, + -454L, + 0L, + 0.40F, + 0.83F, + 1.0F, + -1'646L, + 0.002F, + EAXVECTOR{}, + 53L, + 0.003F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_BATHROOM = +{ + EAX_ENVIRONMENT_BATHROOM, + 1.4F, + 1.0F, + -1'000L, + -1'200L, + 0L, + 1.49F, + 0.54F, + 1.0F, + -370L, + 0.007F, + EAXVECTOR{}, + 1'030L, + 0.011F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_LIVINGROOM = +{ + EAX_ENVIRONMENT_LIVINGROOM, + 2.5F, + 1.0F, + -1'000L, + -6'000L, + 0L, + 0.50F, + 0.10F, + 1.0F, + -1'376, + 0.003F, + EAXVECTOR{}, + -1'104L, + 0.004F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_STONEROOM = +{ + EAX_ENVIRONMENT_STONEROOM, + 11.6F, + 1.0F, + -1'000L, + -300L, + 0L, + 2.31F, + 0.64F, + 1.0F, + -711L, + 0.012F, + EAXVECTOR{}, + 83L, + 0.017F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_AUDITORIUM = +{ + EAX_ENVIRONMENT_AUDITORIUM, + 21.6F, + 1.0F, + -1'000L, + -476L, + 0L, + 4.32F, + 0.59F, + 1.0F, + -789L, + 0.020F, + EAXVECTOR{}, + -289L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_CONCERTHALL = +{ + EAX_ENVIRONMENT_CONCERTHALL, + 19.6F, + 1.0F, + -1'000L, + -500L, + 0L, + 3.92F, + 0.70F, + 1.0F, + -1'230L, + 0.020F, + EAXVECTOR{}, + -2L, + 0.029F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_CAVE = +{ + EAX_ENVIRONMENT_CAVE, + 14.6F, + 1.0F, + -1'000L, + 0L, + 0L, + 2.91F, + 1.30F, + 1.0F, + -602L, + 0.015F, + EAXVECTOR{}, + -302L, + 0.022F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_ARENA = +{ + EAX_ENVIRONMENT_ARENA, + 36.2F, + 1.0F, + -1'000L, + -698L, + 0L, + 7.24F, + 0.33F, + 1.0F, + -1'166L, + 0.020F, + EAXVECTOR{}, + 16L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_HANGAR = +{ + EAX_ENVIRONMENT_HANGAR, + 50.3F, + 1.0F, + -1'000L, + -1'000L, + 0L, + 10.05F, + 0.23F, + 1.0F, + -602L, + 0.020F, + EAXVECTOR{}, + 198L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_CARPETTEDHALLWAY = +{ + EAX_ENVIRONMENT_CARPETEDHALLWAY, + 1.9F, + 1.0F, + -1'000L, + -4'000L, + 0L, + 0.30F, + 0.10F, + 1.0F, + -1'831L, + 0.002F, + EAXVECTOR{}, + -1'630L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_HALLWAY = +{ + EAX_ENVIRONMENT_HALLWAY, + 1.8F, + 1.0F, + -1'000L, + -300L, + 0L, + 1.49F, + 0.59F, + 1.0F, + -1'219L, + 0.007F, + EAXVECTOR{}, + 441L, + 0.011F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_STONECORRIDOR = +{ + EAX_ENVIRONMENT_STONECORRIDOR, + 13.5F, + 1.0F, + -1'000L, + -237L, + 0L, + 2.70F, + 0.79F, + 1.0F, + -1'214L, + 0.013F, + EAXVECTOR{}, + 395L, + 0.020F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_ALLEY = +{ + EAX_ENVIRONMENT_ALLEY, + 7.5F, + 0.300F, + -1'000L, + -270L, + 0L, + 1.49F, + 0.86F, + 1.0F, + -1'204L, + 0.007F, + EAXVECTOR{}, + -4L, + 0.011F, + EAXVECTOR{}, + 0.125F, + 0.950F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_FOREST = +{ + EAX_ENVIRONMENT_FOREST, + 38.0F, + 0.300F, + -1'000L, + -3'300L, + 0L, + 1.49F, + 0.54F, + 1.0F, + -2'560L, + 0.162F, + EAXVECTOR{}, + -229L, + 0.088F, + EAXVECTOR{}, + 0.125F, + 1.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_CITY = +{ + EAX_ENVIRONMENT_CITY, + 7.5F, + 0.500F, + -1'000L, + -800L, + 0L, + 1.49F, + 0.67F, + 1.0F, + -2'273L, + 0.007F, + EAXVECTOR{}, + -1'691L, + 0.011F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_MOUNTAINS = +{ + EAX_ENVIRONMENT_MOUNTAINS, + 100.0F, + 0.270F, + -1'000L, + -2'500L, + 0L, + 1.49F, + 0.21F, + 1.0F, + -2'780L, + 0.300F, + EAXVECTOR{}, + -1'434L, + 0.100F, + EAXVECTOR{}, + 0.250F, + 1.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_QUARRY = +{ + EAX_ENVIRONMENT_QUARRY, + 17.5F, + 1.0F, + -1'000L, + -1'000L, + 0L, + 1.49F, + 0.83F, + 1.0F, + -10'000L, + 0.061F, + EAXVECTOR{}, + 500L, + 0.025F, + EAXVECTOR{}, + 0.125F, + 0.700F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_PLAIN = +{ + EAX_ENVIRONMENT_PLAIN, + 42.5F, + 0.210F, + -1'000L, + -2'000L, + 0L, + 1.49F, + 0.50F, + 1.0F, + -2'466L, + 0.179F, + EAXVECTOR{}, + -1'926L, + 0.100F, + EAXVECTOR{}, + 0.250F, + 1.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_PARKINGLOT = +{ + EAX_ENVIRONMENT_PARKINGLOT, + 8.3F, + 1.0F, + -1'000L, + 0L, + 0L, + 1.65F, + 1.50F, + 1.0F, + -1'363L, + 0.008F, + EAXVECTOR{}, + -1'153L, + 0.012F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_SEWERPIPE = +{ + EAX_ENVIRONMENT_SEWERPIPE, + 1.7F, + 0.800F, + -1'000L, + -1'000L, + 0L, + 2.81F, + 0.14F, + 1.0F, + 429L, + 0.014F, + EAXVECTOR{}, + 1'023L, + 0.021F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 0.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_UNDERWATER = +{ + EAX_ENVIRONMENT_UNDERWATER, + 1.8F, + 1.0F, + -1'000L, + -4'000L, + 0L, + 1.49F, + 0.10F, + 1.0F, + -449L, + 0.007F, + EAXVECTOR{}, + 1'700L, + 0.011F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 1.180F, + 0.348F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x3FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_DRUGGED = +{ + EAX_ENVIRONMENT_DRUGGED, + 1.9F, + 0.500F, + -1'000L, + 0L, + 0L, + 8.39F, + 1.39F, + 1.0F, + -115L, + 0.002F, + EAXVECTOR{}, + 985L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 0.250F, + 1.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_DIZZY = +{ + EAX_ENVIRONMENT_DIZZY, + 1.8F, + 0.600F, + -1'000L, + -400L, + 0L, + 17.23F, + 0.56F, + 1.0F, + -1'713L, + 0.020F, + EAXVECTOR{}, + -613L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 1.0F, + 0.810F, + 0.310F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_PSYCHOTIC = +{ + EAX_ENVIRONMENT_PSYCHOTIC, + 1.0F, + 0.500F, + -1'000L, + -151L, + 0L, + 7.56F, + 0.91F, + 1.0F, + -626L, + 0.020F, + EAXVECTOR{}, + 774L, + 0.030F, + EAXVECTOR{}, + 0.250F, + 0.0F, + 4.0F, + 1.0F, + -5.0F, + 5'000.0F, + 250.0F, + 0.0F, + 0x1FUL, +}; + +} // namespace + +const EaxReverbPresets EAXREVERB_PRESETS{{ + EAXREVERB_PRESET_GENERIC, + EAXREVERB_PRESET_PADDEDCELL, + EAXREVERB_PRESET_ROOM, + EAXREVERB_PRESET_BATHROOM, + EAXREVERB_PRESET_LIVINGROOM, + EAXREVERB_PRESET_STONEROOM, + EAXREVERB_PRESET_AUDITORIUM, + EAXREVERB_PRESET_CONCERTHALL, + EAXREVERB_PRESET_CAVE, + EAXREVERB_PRESET_ARENA, + EAXREVERB_PRESET_HANGAR, + EAXREVERB_PRESET_CARPETTEDHALLWAY, + EAXREVERB_PRESET_HALLWAY, + EAXREVERB_PRESET_STONECORRIDOR, + EAXREVERB_PRESET_ALLEY, + EAXREVERB_PRESET_FOREST, + EAXREVERB_PRESET_CITY, + EAXREVERB_PRESET_MOUNTAINS, + EAXREVERB_PRESET_QUARRY, + EAXREVERB_PRESET_PLAIN, + EAXREVERB_PRESET_PARKINGLOT, + EAXREVERB_PRESET_SEWERPIPE, + EAXREVERB_PRESET_UNDERWATER, + EAXREVERB_PRESET_DRUGGED, + EAXREVERB_PRESET_DIZZY, + EAXREVERB_PRESET_PSYCHOTIC, +}}; + +namespace { +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_GENERIC = {EAX_ENVIRONMENT_GENERIC, 0.5F, 1.493F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PADDEDCELL = {EAX_ENVIRONMENT_PADDEDCELL, 0.25F, 0.1F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ROOM = {EAX_ENVIRONMENT_ROOM, 0.417F, 0.4F, 0.666F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_BATHROOM = {EAX_ENVIRONMENT_BATHROOM, 0.653F, 1.499F, 0.166F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_LIVINGROOM = {EAX_ENVIRONMENT_LIVINGROOM, 0.208F, 0.478F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONEROOM = {EAX_ENVIRONMENT_STONEROOM, 0.5F, 2.309F, 0.888F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_AUDITORIUM = {EAX_ENVIRONMENT_AUDITORIUM, 0.403F, 4.279F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CONCERTHALL = {EAX_ENVIRONMENT_CONCERTHALL, 0.5F, 3.961F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CAVE = {EAX_ENVIRONMENT_CAVE, 0.5F, 2.886F, 1.304F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ARENA = {EAX_ENVIRONMENT_ARENA, 0.361F, 7.284F, 0.332F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HANGAR = {EAX_ENVIRONMENT_HANGAR, 0.5F, 10.0F, 0.3F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CARPETTEDHALLWAY = {EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153F, 0.259F, 2.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HALLWAY = {EAX_ENVIRONMENT_HALLWAY, 0.361F, 1.493F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONECORRIDOR = {EAX_ENVIRONMENT_STONECORRIDOR, 0.444F, 2.697F, 0.638F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ALLEY = {EAX_ENVIRONMENT_ALLEY, 0.25F, 1.752F, 0.776F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_FOREST = {EAX_ENVIRONMENT_FOREST, 0.111F, 3.145F, 0.472F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CITY = {EAX_ENVIRONMENT_CITY, 0.111F, 2.767F, 0.224F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_MOUNTAINS = {EAX_ENVIRONMENT_MOUNTAINS, 0.194F, 7.841F, 0.472F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_QUARRY = {EAX_ENVIRONMENT_QUARRY, 1.0F, 1.499F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PLAIN = {EAX_ENVIRONMENT_PLAIN, 0.097F, 2.767F, 0.224F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PARKINGLOT = {EAX_ENVIRONMENT_PARKINGLOT, 0.208F, 1.652F, 1.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_SEWERPIPE = {EAX_ENVIRONMENT_SEWERPIPE, 0.652F, 2.886F, 0.25F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_UNDERWATER = {EAX_ENVIRONMENT_UNDERWATER, 1.0F, 1.499F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DRUGGED = {EAX_ENVIRONMENT_DRUGGED, 0.875F, 8.392F, 1.388F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DIZZY = {EAX_ENVIRONMENT_DIZZY, 0.139F, 17.234F, 0.666F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PSYCHOTIC = {EAX_ENVIRONMENT_PSYCHOTIC, 0.486F, 7.563F, 0.806F}; +} // namespace + +const Eax1ReverbPresets EAX1REVERB_PRESETS{{ + EAX1REVERB_PRESET_GENERIC, + EAX1REVERB_PRESET_PADDEDCELL, + EAX1REVERB_PRESET_ROOM, + EAX1REVERB_PRESET_BATHROOM, + EAX1REVERB_PRESET_LIVINGROOM, + EAX1REVERB_PRESET_STONEROOM, + EAX1REVERB_PRESET_AUDITORIUM, + EAX1REVERB_PRESET_CONCERTHALL, + EAX1REVERB_PRESET_CAVE, + EAX1REVERB_PRESET_ARENA, + EAX1REVERB_PRESET_HANGAR, + EAX1REVERB_PRESET_CARPETTEDHALLWAY, + EAX1REVERB_PRESET_HALLWAY, + EAX1REVERB_PRESET_STONECORRIDOR, + EAX1REVERB_PRESET_ALLEY, + EAX1REVERB_PRESET_FOREST, + EAX1REVERB_PRESET_CITY, + EAX1REVERB_PRESET_MOUNTAINS, + EAX1REVERB_PRESET_QUARRY, + EAX1REVERB_PRESET_PLAIN, + EAX1REVERB_PRESET_PARKINGLOT, + EAX1REVERB_PRESET_SEWERPIPE, + EAX1REVERB_PRESET_UNDERWATER, + EAX1REVERB_PRESET_DRUGGED, + EAX1REVERB_PRESET_DIZZY, + EAX1REVERB_PRESET_PSYCHOTIC, +}}; diff --git a/al/eax/api.h b/al/eax/api.h new file mode 100644 index 00000000..d0737d1d --- /dev/null +++ b/al/eax/api.h @@ -0,0 +1,1557 @@ +#ifndef EAX_API_INCLUDED +#define EAX_API_INCLUDED + + +// +// EAX API. +// +// Based on headers `eax[2-5].h` included in Doom 3 source code: +// https://github.com/id-Software/DOOM-3/tree/master/neo/openal/include +// + + +#include +#include +#include + +#include + +#include "AL/al.h" + + +#ifndef GUID_DEFINED +#define GUID_DEFINED +typedef struct _GUID +{ + std::uint32_t Data1; + std::uint16_t Data2; + std::uint16_t Data3; + std::uint8_t Data4[8]; +} GUID; + +inline bool operator==(const GUID& lhs, const GUID& rhs) noexcept +{ + return std::memcmp(&lhs, &rhs, sizeof(GUID)) == 0; +} + +inline bool operator!=(const GUID& lhs, const GUID& rhs) noexcept +{ + return !(lhs == rhs); +} +#endif // GUID_DEFINED + + +extern const GUID DSPROPSETID_EAX_ReverbProperties; + +enum DSPROPERTY_EAX_REVERBPROPERTY : unsigned int +{ + DSPROPERTY_EAX_ALL, + DSPROPERTY_EAX_ENVIRONMENT, + DSPROPERTY_EAX_VOLUME, + DSPROPERTY_EAX_DECAYTIME, + DSPROPERTY_EAX_DAMPING, +}; // DSPROPERTY_EAX_REVERBPROPERTY + +struct EAX_REVERBPROPERTIES +{ + unsigned long environment; + float fVolume; + float fDecayTime_sec; + float fDamping; +}; // EAX_REVERBPROPERTIES + +inline bool operator==(const EAX_REVERBPROPERTIES& lhs, const EAX_REVERBPROPERTIES& rhs) noexcept +{ + return std::memcmp(&lhs, &rhs, sizeof(EAX_REVERBPROPERTIES)) == 0; +} + +extern const GUID DSPROPSETID_EAXBUFFER_ReverbProperties; + +enum DSPROPERTY_EAXBUFFER_REVERBPROPERTY : unsigned int +{ + DSPROPERTY_EAXBUFFER_ALL, + DSPROPERTY_EAXBUFFER_REVERBMIX, +}; // DSPROPERTY_EAXBUFFER_REVERBPROPERTY + +struct EAXBUFFER_REVERBPROPERTIES +{ + float fMix; +}; + +inline bool operator==(const EAXBUFFER_REVERBPROPERTIES& lhs, const EAXBUFFER_REVERBPROPERTIES& rhs) noexcept +{ + return lhs.fMix == rhs.fMix; +} + +constexpr auto EAX_BUFFER_MINREVERBMIX = 0.0F; +constexpr auto EAX_BUFFER_MAXREVERBMIX = 1.0F; +constexpr auto EAX_REVERBMIX_USEDISTANCE = -1.0F; + + +extern const GUID DSPROPSETID_EAX20_ListenerProperties; + +enum DSPROPERTY_EAX20_LISTENERPROPERTY : + unsigned int +{ + DSPROPERTY_EAX20LISTENER_NONE, + DSPROPERTY_EAX20LISTENER_ALLPARAMETERS, + DSPROPERTY_EAX20LISTENER_ROOM, + DSPROPERTY_EAX20LISTENER_ROOMHF, + DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR, + DSPROPERTY_EAX20LISTENER_DECAYTIME, + DSPROPERTY_EAX20LISTENER_DECAYHFRATIO, + DSPROPERTY_EAX20LISTENER_REFLECTIONS, + DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY, + DSPROPERTY_EAX20LISTENER_REVERB, + DSPROPERTY_EAX20LISTENER_REVERBDELAY, + DSPROPERTY_EAX20LISTENER_ENVIRONMENT, + DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE, + DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION, + DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF, + DSPROPERTY_EAX20LISTENER_FLAGS +}; // DSPROPERTY_EAX20_LISTENERPROPERTY + +struct EAX20LISTENERPROPERTIES +{ + long lRoom; // room effect level at low frequencies + long lRoomHF; // room effect high-frequency level re. low frequency level + float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + float flDecayTime; // reverberation decay time at low frequencies + float flDecayHFRatio; // high-frequency to low-frequency decay time ratio + long lReflections; // early reflections level relative to room effect + float flReflectionsDelay; // initial reflection delay time + long lReverb; // late reverberation level relative to room effect + float flReverbDelay; // late reverberation delay time relative to initial reflection + unsigned long dwEnvironment; // sets all listener properties + float flEnvironmentSize; // environment size in meters + float flEnvironmentDiffusion; // environment diffusion + float flAirAbsorptionHF; // change in level per meter at 5 kHz + unsigned long dwFlags; // modifies the behavior of properties +}; // EAX20LISTENERPROPERTIES + + +extern const GUID DSPROPSETID_EAX20_BufferProperties; + + +enum DSPROPERTY_EAX20_BUFFERPROPERTY : + unsigned int +{ + DSPROPERTY_EAX20BUFFER_NONE, + DSPROPERTY_EAX20BUFFER_ALLPARAMETERS, + DSPROPERTY_EAX20BUFFER_DIRECT, + DSPROPERTY_EAX20BUFFER_DIRECTHF, + DSPROPERTY_EAX20BUFFER_ROOM, + DSPROPERTY_EAX20BUFFER_ROOMHF, + DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR, + DSPROPERTY_EAX20BUFFER_OBSTRUCTION, + DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO, + DSPROPERTY_EAX20BUFFER_OCCLUSION, + DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO, + DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO, + DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF, + DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR, + DSPROPERTY_EAX20BUFFER_FLAGS +}; // DSPROPERTY_EAX20_BUFFERPROPERTY + + +struct EAX20BUFFERPROPERTIES +{ + long lDirect; // direct path level + long lDirectHF; // direct path level at high frequencies + long lRoom; // room effect level + long lRoomHF; // room effect level at high frequencies + float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + long lObstruction; // main obstruction control (attenuation at high frequencies) + float flObstructionLFRatio; // obstruction low-frequency level re. main control + long lOcclusion; // main occlusion control (attenuation at high frequencies) + float flOcclusionLFRatio; // occlusion low-frequency level re. main control + float flOcclusionRoomRatio; // occlusion room effect level re. main control + long lOutsideVolumeHF; // outside sound cone level at high frequencies + float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF + unsigned long dwFlags; // modifies the behavior of properties +}; // EAX20BUFFERPROPERTIES + + +extern const GUID DSPROPSETID_EAX30_ListenerProperties; + +extern const GUID DSPROPSETID_EAX30_BufferProperties; + + +constexpr auto EAX_MAX_FXSLOTS = 4; + +constexpr auto EAX40_MAX_ACTIVE_FXSLOTS = 2; +constexpr auto EAX50_MAX_ACTIVE_FXSLOTS = 4; + + +constexpr auto EAX_OK = 0L; +constexpr auto EAXERR_INVALID_OPERATION = -1L; +constexpr auto EAXERR_INVALID_VALUE = -2L; +constexpr auto EAXERR_NO_EFFECT_LOADED = -3L; +constexpr auto EAXERR_UNKNOWN_EFFECT = -4L; +constexpr auto EAXERR_INCOMPATIBLE_SOURCE_TYPE = -5L; +constexpr auto EAXERR_INCOMPATIBLE_EAX_VERSION = -6L; + + +extern const GUID EAX_NULL_GUID; + +extern const GUID EAX_PrimaryFXSlotID; + + +struct EAXVECTOR +{ + float x; + float y; + float z; +}; // EAXVECTOR + +inline bool operator==(const EAXVECTOR& lhs, const EAXVECTOR& rhs) noexcept +{ return std::memcmp(&lhs, &rhs, sizeof(EAXVECTOR)) == 0; } + +inline bool operator!=(const EAXVECTOR& lhs, const EAXVECTOR& rhs) noexcept +{ return !(lhs == rhs); } + + +extern const GUID EAXPROPERTYID_EAX40_Context; + +extern const GUID EAXPROPERTYID_EAX50_Context; + +// EAX50 +enum : + unsigned long +{ + HEADPHONES = 0, + SPEAKERS_2, + SPEAKERS_4, + SPEAKERS_5, // 5.1 speakers + SPEAKERS_6, // 6.1 speakers + SPEAKERS_7, // 7.1 speakers +}; + +// EAX50 +enum : + unsigned long +{ + EAX_40 = 5, // EAX 4.0 + EAX_50 = 6, // EAX 5.0 +}; + +constexpr auto EAXCONTEXT_MINEAXSESSION = EAX_40; +constexpr auto EAXCONTEXT_MAXEAXSESSION = EAX_50; +constexpr auto EAXCONTEXT_DEFAULTEAXSESSION = EAX_40; + +constexpr auto EAXCONTEXT_MINMAXACTIVESENDS = 2UL; +constexpr auto EAXCONTEXT_MAXMAXACTIVESENDS = 4UL; +constexpr auto EAXCONTEXT_DEFAULTMAXACTIVESENDS = 2UL; + +// EAX50 +struct EAXSESSIONPROPERTIES +{ + unsigned long ulEAXVersion; + unsigned long ulMaxActiveSends; +}; // EAXSESSIONPROPERTIES + +enum EAXCONTEXT_PROPERTY : + unsigned int +{ + EAXCONTEXT_NONE = 0, + EAXCONTEXT_ALLPARAMETERS, + EAXCONTEXT_PRIMARYFXSLOTID, + EAXCONTEXT_DISTANCEFACTOR, + EAXCONTEXT_AIRABSORPTIONHF, + EAXCONTEXT_HFREFERENCE, + EAXCONTEXT_LASTERROR, + + // EAX50 + EAXCONTEXT_SPEAKERCONFIG, + EAXCONTEXT_EAXSESSION, + EAXCONTEXT_MACROFXFACTOR, +}; // EAXCONTEXT_PROPERTY + +struct EAX40CONTEXTPROPERTIES +{ + GUID guidPrimaryFXSlotID; + float flDistanceFactor; + float flAirAbsorptionHF; + float flHFReference; +}; // EAX40CONTEXTPROPERTIES + +struct EAX50CONTEXTPROPERTIES : + public EAX40CONTEXTPROPERTIES +{ + float flMacroFXFactor; +}; // EAX40CONTEXTPROPERTIES + + +bool operator==( + const EAX40CONTEXTPROPERTIES& lhs, + const EAX40CONTEXTPROPERTIES& rhs) noexcept; + +bool operator==( + const EAX50CONTEXTPROPERTIES& lhs, + const EAX50CONTEXTPROPERTIES& rhs) noexcept; + + +constexpr auto EAXCONTEXT_MINDISTANCEFACTOR = FLT_MIN; +constexpr auto EAXCONTEXT_MAXDISTANCEFACTOR = FLT_MAX; +constexpr auto EAXCONTEXT_DEFAULTDISTANCEFACTOR = 1.0F; + +constexpr auto EAXCONTEXT_MINAIRABSORPTIONHF = -100.0F; +constexpr auto EAXCONTEXT_MAXAIRABSORPTIONHF = 0.0F; +constexpr auto EAXCONTEXT_DEFAULTAIRABSORPTIONHF = -5.0F; + +constexpr auto EAXCONTEXT_MINHFREFERENCE = 1000.0F; +constexpr auto EAXCONTEXT_MAXHFREFERENCE = 20000.0F; +constexpr auto EAXCONTEXT_DEFAULTHFREFERENCE = 5000.0F; + +constexpr auto EAXCONTEXT_MINMACROFXFACTOR = 0.0F; +constexpr auto EAXCONTEXT_MAXMACROFXFACTOR = 1.0F; +constexpr auto EAXCONTEXT_DEFAULTMACROFXFACTOR = 0.0F; + + +extern const GUID EAXPROPERTYID_EAX40_FXSlot0; + +extern const GUID EAXPROPERTYID_EAX50_FXSlot0; + +extern const GUID EAXPROPERTYID_EAX40_FXSlot1; + +extern const GUID EAXPROPERTYID_EAX50_FXSlot1; + +extern const GUID EAXPROPERTYID_EAX40_FXSlot2; + +extern const GUID EAXPROPERTYID_EAX50_FXSlot2; + +extern const GUID EAXPROPERTYID_EAX40_FXSlot3; + +extern const GUID EAXPROPERTYID_EAX50_FXSlot3; + +extern const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID; + +enum EAXFXSLOT_PROPERTY : + unsigned int +{ + EAXFXSLOT_PARAMETER = 0, + + EAXFXSLOT_NONE = 0x10000, + EAXFXSLOT_ALLPARAMETERS, + EAXFXSLOT_LOADEFFECT, + EAXFXSLOT_VOLUME, + EAXFXSLOT_LOCK, + EAXFXSLOT_FLAGS, + + // EAX50 + EAXFXSLOT_OCCLUSION, + EAXFXSLOT_OCCLUSIONLFRATIO, +}; // EAXFXSLOT_PROPERTY + +constexpr auto EAXFXSLOTFLAGS_ENVIRONMENT = 0x00000001UL; +// EAX50 +constexpr auto EAXFXSLOTFLAGS_UPMIX = 0x00000002UL; + +constexpr auto EAX40FXSLOTFLAGS_RESERVED = 0xFFFFFFFEUL; // reserved future use +constexpr auto EAX50FXSLOTFLAGS_RESERVED = 0xFFFFFFFCUL; // reserved future use + + +constexpr auto EAXFXSLOT_MINVOLUME = -10'000L; +constexpr auto EAXFXSLOT_MAXVOLUME = 0L; +constexpr auto EAXFXSLOT_DEFAULTVOLUME = 0L; + +constexpr auto EAXFXSLOT_MINLOCK = 0L; +constexpr auto EAXFXSLOT_MAXLOCK = 1L; + +enum : + long +{ + EAXFXSLOT_UNLOCKED = 0, + EAXFXSLOT_LOCKED = 1 +}; + +constexpr auto EAXFXSLOT_MINOCCLUSION = -10'000L; +constexpr auto EAXFXSLOT_MAXOCCLUSION = 0L; +constexpr auto EAXFXSLOT_DEFAULTOCCLUSION = 0L; + +constexpr auto EAXFXSLOT_MINOCCLUSIONLFRATIO = 0.0F; +constexpr auto EAXFXSLOT_MAXOCCLUSIONLFRATIO = 1.0F; +constexpr auto EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO = 0.25F; + +constexpr auto EAX40FXSLOT_DEFAULTFLAGS = EAXFXSLOTFLAGS_ENVIRONMENT; + +constexpr auto EAX50FXSLOT_DEFAULTFLAGS = + EAXFXSLOTFLAGS_ENVIRONMENT | + EAXFXSLOTFLAGS_UPMIX; // ignored for reverb; + +struct EAX40FXSLOTPROPERTIES +{ + GUID guidLoadEffect; + long lVolume; + long lLock; + unsigned long ulFlags; +}; // EAX40FXSLOTPROPERTIES + +struct EAX50FXSLOTPROPERTIES : + public EAX40FXSLOTPROPERTIES +{ + long lOcclusion; + float flOcclusionLFRatio; +}; // EAX50FXSLOTPROPERTIES + +bool operator==( + const EAX40FXSLOTPROPERTIES& lhs, + const EAX40FXSLOTPROPERTIES& rhs) noexcept; + +bool operator==( + const EAX50FXSLOTPROPERTIES& lhs, + const EAX50FXSLOTPROPERTIES& rhs) noexcept; + +extern const GUID EAXPROPERTYID_EAX40_Source; + +extern const GUID EAXPROPERTYID_EAX50_Source; + +// Source object properties +enum EAXSOURCE_PROPERTY : + unsigned int +{ + // EAX30 + + EAXSOURCE_NONE, + EAXSOURCE_ALLPARAMETERS, + EAXSOURCE_OBSTRUCTIONPARAMETERS, + EAXSOURCE_OCCLUSIONPARAMETERS, + EAXSOURCE_EXCLUSIONPARAMETERS, + EAXSOURCE_DIRECT, + EAXSOURCE_DIRECTHF, + EAXSOURCE_ROOM, + EAXSOURCE_ROOMHF, + EAXSOURCE_OBSTRUCTION, + EAXSOURCE_OBSTRUCTIONLFRATIO, + EAXSOURCE_OCCLUSION, + EAXSOURCE_OCCLUSIONLFRATIO, + EAXSOURCE_OCCLUSIONROOMRATIO, + EAXSOURCE_OCCLUSIONDIRECTRATIO, + EAXSOURCE_EXCLUSION, + EAXSOURCE_EXCLUSIONLFRATIO, + EAXSOURCE_OUTSIDEVOLUMEHF, + EAXSOURCE_DOPPLERFACTOR, + EAXSOURCE_ROLLOFFFACTOR, + EAXSOURCE_ROOMROLLOFFFACTOR, + EAXSOURCE_AIRABSORPTIONFACTOR, + EAXSOURCE_FLAGS, + + // EAX40 + + EAXSOURCE_SENDPARAMETERS, + EAXSOURCE_ALLSENDPARAMETERS, + EAXSOURCE_OCCLUSIONSENDPARAMETERS, + EAXSOURCE_EXCLUSIONSENDPARAMETERS, + EAXSOURCE_ACTIVEFXSLOTID, + + // EAX50 + + EAXSOURCE_MACROFXFACTOR, + EAXSOURCE_SPEAKERLEVELS, + EAXSOURCE_ALL2DPARAMETERS, +}; // EAXSOURCE_PROPERTY + + +constexpr auto EAXSOURCEFLAGS_DIRECTHFAUTO = 0x00000001UL; // relates to EAXSOURCE_DIRECTHF +constexpr auto EAXSOURCEFLAGS_ROOMAUTO = 0x00000002UL; // relates to EAXSOURCE_ROOM +constexpr auto EAXSOURCEFLAGS_ROOMHFAUTO = 0x00000004UL; // relates to EAXSOURCE_ROOMHF +// EAX50 +constexpr auto EAXSOURCEFLAGS_3DELEVATIONFILTER = 0x00000008UL; +// EAX50 +constexpr auto EAXSOURCEFLAGS_UPMIX = 0x00000010UL; +// EAX50 +constexpr auto EAXSOURCEFLAGS_APPLYSPEAKERLEVELS = 0x00000020UL; + +constexpr auto EAX20SOURCEFLAGS_RESERVED = 0xFFFFFFF8UL; // reserved future use +constexpr auto EAX50SOURCEFLAGS_RESERVED = 0xFFFFFFC0UL; // reserved future use + + +constexpr auto EAXSOURCE_MINSEND = -10'000L; +constexpr auto EAXSOURCE_MAXSEND = 0L; +constexpr auto EAXSOURCE_DEFAULTSEND = 0L; + +constexpr auto EAXSOURCE_MINSENDHF = -10'000L; +constexpr auto EAXSOURCE_MAXSENDHF = 0L; +constexpr auto EAXSOURCE_DEFAULTSENDHF = 0L; + +constexpr auto EAXSOURCE_MINDIRECT = -10'000L; +constexpr auto EAXSOURCE_MAXDIRECT = 1'000L; +constexpr auto EAXSOURCE_DEFAULTDIRECT = 0L; + +constexpr auto EAXSOURCE_MINDIRECTHF = -10'000L; +constexpr auto EAXSOURCE_MAXDIRECTHF = 0L; +constexpr auto EAXSOURCE_DEFAULTDIRECTHF = 0L; + +constexpr auto EAXSOURCE_MINROOM = -10'000L; +constexpr auto EAXSOURCE_MAXROOM = 1'000L; +constexpr auto EAXSOURCE_DEFAULTROOM = 0L; + +constexpr auto EAXSOURCE_MINROOMHF = -10'000L; +constexpr auto EAXSOURCE_MAXROOMHF = 0L; +constexpr auto EAXSOURCE_DEFAULTROOMHF = 0L; + +constexpr auto EAXSOURCE_MINOBSTRUCTION = -10'000L; +constexpr auto EAXSOURCE_MAXOBSTRUCTION = 0L; +constexpr auto EAXSOURCE_DEFAULTOBSTRUCTION = 0L; + +constexpr auto EAXSOURCE_MINOBSTRUCTIONLFRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXOBSTRUCTIONLFRATIO = 1.0F; +constexpr auto EAXSOURCE_DEFAULTOBSTRUCTIONLFRATIO = 0.0F; + +constexpr auto EAXSOURCE_MINOCCLUSION = -10'000L; +constexpr auto EAXSOURCE_MAXOCCLUSION = 0L; +constexpr auto EAXSOURCE_DEFAULTOCCLUSION = 0L; + +constexpr auto EAXSOURCE_MINOCCLUSIONLFRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXOCCLUSIONLFRATIO = 1.0F; +constexpr auto EAXSOURCE_DEFAULTOCCLUSIONLFRATIO = 0.25F; + +constexpr auto EAXSOURCE_MINOCCLUSIONROOMRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXOCCLUSIONROOMRATIO = 10.0F; +constexpr auto EAXSOURCE_DEFAULTOCCLUSIONROOMRATIO = 1.5F; + +constexpr auto EAXSOURCE_MINOCCLUSIONDIRECTRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXOCCLUSIONDIRECTRATIO = 10.0F; +constexpr auto EAXSOURCE_DEFAULTOCCLUSIONDIRECTRATIO = 1.0F; + +constexpr auto EAXSOURCE_MINEXCLUSION = -10'000L; +constexpr auto EAXSOURCE_MAXEXCLUSION = 0L; +constexpr auto EAXSOURCE_DEFAULTEXCLUSION = 0L; + +constexpr auto EAXSOURCE_MINEXCLUSIONLFRATIO = 0.0F; +constexpr auto EAXSOURCE_MAXEXCLUSIONLFRATIO = 1.0F; +constexpr auto EAXSOURCE_DEFAULTEXCLUSIONLFRATIO = 1.0F; + +constexpr auto EAXSOURCE_MINOUTSIDEVOLUMEHF = -10'000L; +constexpr auto EAXSOURCE_MAXOUTSIDEVOLUMEHF = 0L; +constexpr auto EAXSOURCE_DEFAULTOUTSIDEVOLUMEHF = 0L; + +constexpr auto EAXSOURCE_MINDOPPLERFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXDOPPLERFACTOR = 10.0F; +constexpr auto EAXSOURCE_DEFAULTDOPPLERFACTOR = 1.0F; + +constexpr auto EAXSOURCE_MINROLLOFFFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXROLLOFFFACTOR = 10.0F; +constexpr auto EAXSOURCE_DEFAULTROLLOFFFACTOR = 0.0F; + +constexpr auto EAXSOURCE_MINROOMROLLOFFFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXROOMROLLOFFFACTOR = 10.0F; +constexpr auto EAXSOURCE_DEFAULTROOMROLLOFFFACTOR = 0.0F; + +constexpr auto EAXSOURCE_MINAIRABSORPTIONFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXAIRABSORPTIONFACTOR = 10.0F; +constexpr auto EAXSOURCE_DEFAULTAIRABSORPTIONFACTOR = 0.0F; + +// EAX50 + +constexpr auto EAXSOURCE_MINMACROFXFACTOR = 0.0F; +constexpr auto EAXSOURCE_MAXMACROFXFACTOR = 1.0F; +constexpr auto EAXSOURCE_DEFAULTMACROFXFACTOR = 1.0F; + +// EAX50 + +constexpr auto EAXSOURCE_MINSPEAKERLEVEL = -10'000L; +constexpr auto EAXSOURCE_MAXSPEAKERLEVEL = 0L; +constexpr auto EAXSOURCE_DEFAULTSPEAKERLEVEL = -10'000L; + +constexpr auto EAXSOURCE_DEFAULTFLAGS = + EAXSOURCEFLAGS_DIRECTHFAUTO | + EAXSOURCEFLAGS_ROOMAUTO | + EAXSOURCEFLAGS_ROOMHFAUTO; + +enum : + long +{ + EAXSPEAKER_FRONT_LEFT = 1, + EAXSPEAKER_FRONT_CENTER = 2, + EAXSPEAKER_FRONT_RIGHT = 3, + EAXSPEAKER_SIDE_RIGHT = 4, + EAXSPEAKER_REAR_RIGHT = 5, + EAXSPEAKER_REAR_CENTER = 6, + EAXSPEAKER_REAR_LEFT = 7, + EAXSPEAKER_SIDE_LEFT = 8, + EAXSPEAKER_LOW_FREQUENCY = 9 +}; + +// EAXSOURCEFLAGS_DIRECTHFAUTO, EAXSOURCEFLAGS_ROOMAUTO and EAXSOURCEFLAGS_ROOMHFAUTO are ignored for 2D sources +// EAXSOURCEFLAGS_UPMIX is ignored for 3D sources +constexpr auto EAX50SOURCE_DEFAULTFLAGS = + EAXSOURCEFLAGS_DIRECTHFAUTO | + EAXSOURCEFLAGS_ROOMAUTO | + EAXSOURCEFLAGS_ROOMHFAUTO | + EAXSOURCEFLAGS_UPMIX; + +struct EAX30SOURCEPROPERTIES +{ + long lDirect; // direct path level (at low and mid frequencies) + long lDirectHF; // relative direct path level at high frequencies + long lRoom; // room effect level (at low and mid frequencies) + long lRoomHF; // relative room effect level at high frequencies + long lObstruction; // main obstruction control (attenuation at high frequencies) + float flObstructionLFRatio; // obstruction low-frequency level re. main control + long lOcclusion; // main occlusion control (attenuation at high frequencies) + float flOcclusionLFRatio; // occlusion low-frequency level re. main control + float flOcclusionRoomRatio; // relative occlusion control for room effect + float flOcclusionDirectRatio; // relative occlusion control for direct path + long lExclusion; // main exlusion control (attenuation at high frequencies) + float flExclusionLFRatio; // exclusion low-frequency level re. main control + long lOutsideVolumeHF; // outside sound cone level at high frequencies + float flDopplerFactor; // like DS3D flDopplerFactor but per source + float flRolloffFactor; // like DS3D flRolloffFactor but per source + float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + float flAirAbsorptionFactor; // multiplies EAXREVERB_AIRABSORPTIONHF + unsigned long ulFlags; // modifies the behavior of properties +}; // EAX30SOURCEPROPERTIES + +struct EAX50SOURCEPROPERTIES : + public EAX30SOURCEPROPERTIES +{ + float flMacroFXFactor; +}; // EAX50SOURCEPROPERTIES + +struct EAXSOURCEALLSENDPROPERTIES +{ + GUID guidReceivingFXSlotID; + long lSend; // send level (at low and mid frequencies) + long lSendHF; // relative send level at high frequencies + long lOcclusion; + float flOcclusionLFRatio; + float flOcclusionRoomRatio; + float flOcclusionDirectRatio; + long lExclusion; + float flExclusionLFRatio; +}; // EAXSOURCEALLSENDPROPERTIES + +struct EAXSOURCE2DPROPERTIES +{ + long lDirect; // direct path level (at low and mid frequencies) + long lDirectHF; // relative direct path level at high frequencies + long lRoom; // room effect level (at low and mid frequencies) + long lRoomHF; // relative room effect level at high frequencies + unsigned long ulFlags; // modifies the behavior of properties +}; // EAXSOURCE2DPROPERTIES + +struct EAXSPEAKERLEVELPROPERTIES +{ + long lSpeakerID; + long lLevel; +}; // EAXSPEAKERLEVELPROPERTIES + +struct EAX40ACTIVEFXSLOTS +{ + GUID guidActiveFXSlots[EAX40_MAX_ACTIVE_FXSLOTS]; +}; // EAX40ACTIVEFXSLOTS + +struct EAX50ACTIVEFXSLOTS +{ + GUID guidActiveFXSlots[EAX50_MAX_ACTIVE_FXSLOTS]; +}; // EAX50ACTIVEFXSLOTS + +bool operator==( + const EAX50ACTIVEFXSLOTS& lhs, + const EAX50ACTIVEFXSLOTS& rhs) noexcept; + +bool operator!=( + const EAX50ACTIVEFXSLOTS& lhs, + const EAX50ACTIVEFXSLOTS& rhs) noexcept; + +// Use this structure for EAXSOURCE_OBSTRUCTIONPARAMETERS property. +struct EAXOBSTRUCTIONPROPERTIES +{ + long lObstruction; + float flObstructionLFRatio; +}; // EAXOBSTRUCTIONPROPERTIES + +// Use this structure for EAXSOURCE_OCCLUSIONPARAMETERS property. +struct EAXOCCLUSIONPROPERTIES +{ + long lOcclusion; + float flOcclusionLFRatio; + float flOcclusionRoomRatio; + float flOcclusionDirectRatio; +}; // EAXOCCLUSIONPROPERTIES + +// Use this structure for EAXSOURCE_EXCLUSIONPARAMETERS property. +struct EAXEXCLUSIONPROPERTIES +{ + long lExclusion; + float flExclusionLFRatio; +}; // EAXEXCLUSIONPROPERTIES + +// Use this structure for EAXSOURCE_SENDPARAMETERS properties. +struct EAXSOURCESENDPROPERTIES +{ + GUID guidReceivingFXSlotID; + long lSend; + long lSendHF; +}; // EAXSOURCESENDPROPERTIES + +// Use this structure for EAXSOURCE_OCCLUSIONSENDPARAMETERS +struct EAXSOURCEOCCLUSIONSENDPROPERTIES +{ + GUID guidReceivingFXSlotID; + long lOcclusion; + float flOcclusionLFRatio; + float flOcclusionRoomRatio; + float flOcclusionDirectRatio; +}; // EAXSOURCEOCCLUSIONSENDPROPERTIES + +// Use this structure for EAXSOURCE_EXCLUSIONSENDPARAMETERS +struct EAXSOURCEEXCLUSIONSENDPROPERTIES +{ + GUID guidReceivingFXSlotID; + long lExclusion; + float flExclusionLFRatio; +}; // EAXSOURCEEXCLUSIONSENDPROPERTIES + +extern const EAX50ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID; + +extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID; + +extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID; + + +// EAX Reverb Effect + +extern const GUID EAX_REVERB_EFFECT; + +// Reverb effect properties +enum EAXREVERB_PROPERTY : + unsigned int +{ + EAXREVERB_NONE, + EAXREVERB_ALLPARAMETERS, + EAXREVERB_ENVIRONMENT, + EAXREVERB_ENVIRONMENTSIZE, + EAXREVERB_ENVIRONMENTDIFFUSION, + EAXREVERB_ROOM, + EAXREVERB_ROOMHF, + EAXREVERB_ROOMLF, + EAXREVERB_DECAYTIME, + EAXREVERB_DECAYHFRATIO, + EAXREVERB_DECAYLFRATIO, + EAXREVERB_REFLECTIONS, + EAXREVERB_REFLECTIONSDELAY, + EAXREVERB_REFLECTIONSPAN, + EAXREVERB_REVERB, + EAXREVERB_REVERBDELAY, + EAXREVERB_REVERBPAN, + EAXREVERB_ECHOTIME, + EAXREVERB_ECHODEPTH, + EAXREVERB_MODULATIONTIME, + EAXREVERB_MODULATIONDEPTH, + EAXREVERB_AIRABSORPTIONHF, + EAXREVERB_HFREFERENCE, + EAXREVERB_LFREFERENCE, + EAXREVERB_ROOMROLLOFFFACTOR, + EAXREVERB_FLAGS, +}; // EAXREVERB_PROPERTY + +// used by EAXREVERB_ENVIRONMENT +enum : + unsigned long +{ + EAX_ENVIRONMENT_GENERIC, + EAX_ENVIRONMENT_PADDEDCELL, + EAX_ENVIRONMENT_ROOM, + EAX_ENVIRONMENT_BATHROOM, + EAX_ENVIRONMENT_LIVINGROOM, + EAX_ENVIRONMENT_STONEROOM, + EAX_ENVIRONMENT_AUDITORIUM, + EAX_ENVIRONMENT_CONCERTHALL, + EAX_ENVIRONMENT_CAVE, + EAX_ENVIRONMENT_ARENA, + EAX_ENVIRONMENT_HANGAR, + EAX_ENVIRONMENT_CARPETEDHALLWAY, + EAX_ENVIRONMENT_HALLWAY, + EAX_ENVIRONMENT_STONECORRIDOR, + EAX_ENVIRONMENT_ALLEY, + EAX_ENVIRONMENT_FOREST, + EAX_ENVIRONMENT_CITY, + EAX_ENVIRONMENT_MOUNTAINS, + EAX_ENVIRONMENT_QUARRY, + EAX_ENVIRONMENT_PLAIN, + EAX_ENVIRONMENT_PARKINGLOT, + EAX_ENVIRONMENT_SEWERPIPE, + EAX_ENVIRONMENT_UNDERWATER, + EAX_ENVIRONMENT_DRUGGED, + EAX_ENVIRONMENT_DIZZY, + EAX_ENVIRONMENT_PSYCHOTIC, + + EAX1_ENVIRONMENT_COUNT, + + // EAX30 + EAX_ENVIRONMENT_UNDEFINED = EAX1_ENVIRONMENT_COUNT, + + EAX3_ENVIRONMENT_COUNT, +}; + + +// reverberation decay time +constexpr auto EAXREVERBFLAGS_DECAYTIMESCALE = 0x00000001UL; + +// reflection level +constexpr auto EAXREVERBFLAGS_REFLECTIONSSCALE = 0x00000002UL; + +// initial reflection delay time +constexpr auto EAXREVERBFLAGS_REFLECTIONSDELAYSCALE = 0x00000004UL; + +// reflections level +constexpr auto EAXREVERBFLAGS_REVERBSCALE = 0x00000008UL; + +// late reverberation delay time +constexpr auto EAXREVERBFLAGS_REVERBDELAYSCALE = 0x00000010UL; + +// echo time +// EAX30+ +constexpr auto EAXREVERBFLAGS_ECHOTIMESCALE = 0x00000040UL; + +// modulation time +// EAX30+ +constexpr auto EAXREVERBFLAGS_MODULATIONTIMESCALE = 0x00000080UL; + +// This flag limits high-frequency decay time according to air absorption. +constexpr auto EAXREVERBFLAGS_DECAYHFLIMIT = 0x00000020UL; + +constexpr auto EAXREVERBFLAGS_RESERVED = 0xFFFFFF00UL; // reserved future use + + +struct EAXREVERBPROPERTIES +{ + unsigned long ulEnvironment; // sets all reverb properties + float flEnvironmentSize; // environment size in meters + float flEnvironmentDiffusion; // environment diffusion + long lRoom; // room effect level (at mid frequencies) + long lRoomHF; // relative room effect level at high frequencies + long lRoomLF; // relative room effect level at low frequencies + float flDecayTime; // reverberation decay time at mid frequencies + float flDecayHFRatio; // high-frequency to mid-frequency decay time ratio + float flDecayLFRatio; // low-frequency to mid-frequency decay time ratio + long lReflections; // early reflections level relative to room effect + float flReflectionsDelay; // initial reflection delay time + EAXVECTOR vReflectionsPan; // early reflections panning vector + long lReverb; // late reverberation level relative to room effect + float flReverbDelay; // late reverberation delay time relative to initial reflection + EAXVECTOR vReverbPan; // late reverberation panning vector + float flEchoTime; // echo time + float flEchoDepth; // echo depth + float flModulationTime; // modulation time + float flModulationDepth; // modulation depth + float flAirAbsorptionHF; // change in level per meter at high frequencies + float flHFReference; // reference high frequency + float flLFReference; // reference low frequency + float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + unsigned long ulFlags; // modifies the behavior of properties +}; // EAXREVERBPROPERTIES + +bool operator==( + const EAXREVERBPROPERTIES& lhs, + const EAXREVERBPROPERTIES& rhs) noexcept; + +bool operator!=( + const EAXREVERBPROPERTIES& lhs, + const EAXREVERBPROPERTIES& rhs) noexcept; + + +constexpr auto EAXREVERB_MINENVIRONMENT = static_cast(EAX_ENVIRONMENT_GENERIC); +constexpr auto EAX1REVERB_MAXENVIRONMENT = static_cast(EAX_ENVIRONMENT_PSYCHOTIC); +constexpr auto EAX30REVERB_MAXENVIRONMENT = static_cast(EAX_ENVIRONMENT_UNDEFINED); +constexpr auto EAXREVERB_DEFAULTENVIRONMENT = static_cast(EAX_ENVIRONMENT_GENERIC); + +constexpr auto EAXREVERB_MINENVIRONMENTSIZE = 1.0F; +constexpr auto EAXREVERB_MAXENVIRONMENTSIZE = 100.0F; +constexpr auto EAXREVERB_DEFAULTENVIRONMENTSIZE = 7.5F; + +constexpr auto EAXREVERB_MINENVIRONMENTDIFFUSION = 0.0F; +constexpr auto EAXREVERB_MAXENVIRONMENTDIFFUSION = 1.0F; +constexpr auto EAXREVERB_DEFAULTENVIRONMENTDIFFUSION = 1.0F; + +constexpr auto EAXREVERB_MINROOM = -10'000L; +constexpr auto EAXREVERB_MAXROOM = 0L; +constexpr auto EAXREVERB_DEFAULTROOM = -1'000L; + +constexpr auto EAXREVERB_MINROOMHF = -10'000L; +constexpr auto EAXREVERB_MAXROOMHF = 0L; +constexpr auto EAXREVERB_DEFAULTROOMHF = -100L; + +constexpr auto EAXREVERB_MINROOMLF = -10'000L; +constexpr auto EAXREVERB_MAXROOMLF = 0L; +constexpr auto EAXREVERB_DEFAULTROOMLF = 0L; + +constexpr auto EAXREVERB_MINDECAYTIME = 0.1F; +constexpr auto EAXREVERB_MAXDECAYTIME = 20.0F; +constexpr auto EAXREVERB_DEFAULTDECAYTIME = 1.49F; + +constexpr auto EAXREVERB_MINDECAYHFRATIO = 0.1F; +constexpr auto EAXREVERB_MAXDECAYHFRATIO = 2.0F; +constexpr auto EAXREVERB_DEFAULTDECAYHFRATIO = 0.83F; + +constexpr auto EAXREVERB_MINDECAYLFRATIO = 0.1F; +constexpr auto EAXREVERB_MAXDECAYLFRATIO = 2.0F; +constexpr auto EAXREVERB_DEFAULTDECAYLFRATIO = 1.0F; + +constexpr auto EAXREVERB_MINREFLECTIONS = -10'000L; +constexpr auto EAXREVERB_MAXREFLECTIONS = 1'000L; +constexpr auto EAXREVERB_DEFAULTREFLECTIONS = -2'602L; + +constexpr auto EAXREVERB_MINREFLECTIONSDELAY = 0.0F; +constexpr auto EAXREVERB_MAXREFLECTIONSDELAY = 0.3F; +constexpr auto EAXREVERB_DEFAULTREFLECTIONSDELAY = 0.007F; + +constexpr auto EAXREVERB_DEFAULTREFLECTIONSPAN = EAXVECTOR{0.0F, 0.0F, 0.0F}; + +constexpr auto EAXREVERB_MINREVERB = -10'000L; +constexpr auto EAXREVERB_MAXREVERB = 2'000L; +constexpr auto EAXREVERB_DEFAULTREVERB = 200L; + +constexpr auto EAXREVERB_MINREVERBDELAY = 0.0F; +constexpr auto EAXREVERB_MAXREVERBDELAY = 0.1F; +constexpr auto EAXREVERB_DEFAULTREVERBDELAY = 0.011F; + +constexpr auto EAXREVERB_DEFAULTREVERBPAN = EAXVECTOR{0.0F, 0.0F, 0.0F}; + +constexpr auto EAXREVERB_MINECHOTIME = 0.075F; +constexpr auto EAXREVERB_MAXECHOTIME = 0.25F; +constexpr auto EAXREVERB_DEFAULTECHOTIME = 0.25F; + +constexpr auto EAXREVERB_MINECHODEPTH = 0.0F; +constexpr auto EAXREVERB_MAXECHODEPTH = 1.0F; +constexpr auto EAXREVERB_DEFAULTECHODEPTH = 0.0F; + +constexpr auto EAXREVERB_MINMODULATIONTIME = 0.04F; +constexpr auto EAXREVERB_MAXMODULATIONTIME = 4.0F; +constexpr auto EAXREVERB_DEFAULTMODULATIONTIME = 0.25F; + +constexpr auto EAXREVERB_MINMODULATIONDEPTH = 0.0F; +constexpr auto EAXREVERB_MAXMODULATIONDEPTH = 1.0F; +constexpr auto EAXREVERB_DEFAULTMODULATIONDEPTH = 0.0F; + +constexpr auto EAXREVERB_MINAIRABSORPTIONHF = -100.0F; +constexpr auto EAXREVERB_MAXAIRABSORPTIONHF = 0.0F; +constexpr auto EAXREVERB_DEFAULTAIRABSORPTIONHF = -5.0F; + +constexpr auto EAXREVERB_MINHFREFERENCE = 1'000.0F; +constexpr auto EAXREVERB_MAXHFREFERENCE = 20'000.0F; +constexpr auto EAXREVERB_DEFAULTHFREFERENCE = 5'000.0F; + +constexpr auto EAXREVERB_MINLFREFERENCE = 20.0F; +constexpr auto EAXREVERB_MAXLFREFERENCE = 1'000.0F; +constexpr auto EAXREVERB_DEFAULTLFREFERENCE = 250.0F; + +constexpr auto EAXREVERB_MINROOMROLLOFFFACTOR = 0.0F; +constexpr auto EAXREVERB_MAXROOMROLLOFFFACTOR = 10.0F; +constexpr auto EAXREVERB_DEFAULTROOMROLLOFFFACTOR = 0.0F; + +constexpr auto EAX1REVERB_MINVOLUME = 0.0F; +constexpr auto EAX1REVERB_MAXVOLUME = 1.0F; + +constexpr auto EAX1REVERB_MINDAMPING = 0.0F; +constexpr auto EAX1REVERB_MAXDAMPING = 2.0F; + +constexpr auto EAXREVERB_DEFAULTFLAGS = + EAXREVERBFLAGS_DECAYTIMESCALE | + EAXREVERBFLAGS_REFLECTIONSSCALE | + EAXREVERBFLAGS_REFLECTIONSDELAYSCALE | + EAXREVERBFLAGS_REVERBSCALE | + EAXREVERBFLAGS_REVERBDELAYSCALE | + EAXREVERBFLAGS_DECAYHFLIMIT; + + +using EaxReverbPresets = std::array; +extern const EaxReverbPresets EAXREVERB_PRESETS; + + +using Eax1ReverbPresets = std::array; +extern const Eax1ReverbPresets EAX1REVERB_PRESETS; + + +// AGC Compressor Effect + +extern const GUID EAX_AGCCOMPRESSOR_EFFECT; + +enum EAXAGCCOMPRESSOR_PROPERTY : + unsigned int +{ + EAXAGCCOMPRESSOR_NONE, + EAXAGCCOMPRESSOR_ALLPARAMETERS, + EAXAGCCOMPRESSOR_ONOFF, +}; // EAXAGCCOMPRESSOR_PROPERTY + +struct EAXAGCCOMPRESSORPROPERTIES +{ + unsigned long ulOnOff; // Switch Compressor on or off +}; // EAXAGCCOMPRESSORPROPERTIES + + +constexpr auto EAXAGCCOMPRESSOR_MINONOFF = 0UL; +constexpr auto EAXAGCCOMPRESSOR_MAXONOFF = 1UL; +constexpr auto EAXAGCCOMPRESSOR_DEFAULTONOFF = EAXAGCCOMPRESSOR_MAXONOFF; + + +// Autowah Effect + +extern const GUID EAX_AUTOWAH_EFFECT; + +enum EAXAUTOWAH_PROPERTY : + unsigned int +{ + EAXAUTOWAH_NONE, + EAXAUTOWAH_ALLPARAMETERS, + EAXAUTOWAH_ATTACKTIME, + EAXAUTOWAH_RELEASETIME, + EAXAUTOWAH_RESONANCE, + EAXAUTOWAH_PEAKLEVEL, +}; // EAXAUTOWAH_PROPERTY + +struct EAXAUTOWAHPROPERTIES +{ + float flAttackTime; // Attack time (seconds) + float flReleaseTime; // Release time (seconds) + long lResonance; // Resonance (mB) + long lPeakLevel; // Peak level (mB) +}; // EAXAUTOWAHPROPERTIES + + +constexpr auto EAXAUTOWAH_MINATTACKTIME = 0.0001F; +constexpr auto EAXAUTOWAH_MAXATTACKTIME = 1.0F; +constexpr auto EAXAUTOWAH_DEFAULTATTACKTIME = 0.06F; + +constexpr auto EAXAUTOWAH_MINRELEASETIME = 0.0001F; +constexpr auto EAXAUTOWAH_MAXRELEASETIME = 1.0F; +constexpr auto EAXAUTOWAH_DEFAULTRELEASETIME = 0.06F; + +constexpr auto EAXAUTOWAH_MINRESONANCE = 600L; +constexpr auto EAXAUTOWAH_MAXRESONANCE = 6000L; +constexpr auto EAXAUTOWAH_DEFAULTRESONANCE = 6000L; + +constexpr auto EAXAUTOWAH_MINPEAKLEVEL = -9000L; +constexpr auto EAXAUTOWAH_MAXPEAKLEVEL = 9000L; +constexpr auto EAXAUTOWAH_DEFAULTPEAKLEVEL = 2100L; + + +// Chorus Effect + +extern const GUID EAX_CHORUS_EFFECT; + + +enum EAXCHORUS_PROPERTY : + unsigned int +{ + EAXCHORUS_NONE, + EAXCHORUS_ALLPARAMETERS, + EAXCHORUS_WAVEFORM, + EAXCHORUS_PHASE, + EAXCHORUS_RATE, + EAXCHORUS_DEPTH, + EAXCHORUS_FEEDBACK, + EAXCHORUS_DELAY, +}; // EAXCHORUS_PROPERTY + +enum : + unsigned long +{ + EAX_CHORUS_SINUSOID, + EAX_CHORUS_TRIANGLE, +}; + +struct EAXCHORUSPROPERTIES +{ + unsigned long ulWaveform; // Waveform selector - see enum above + long lPhase; // Phase (Degrees) + float flRate; // Rate (Hz) + float flDepth; // Depth (0 to 1) + float flFeedback; // Feedback (-1 to 1) + float flDelay; // Delay (seconds) +}; // EAXCHORUSPROPERTIES + + +constexpr auto EAXCHORUS_MINWAVEFORM = 0UL; +constexpr auto EAXCHORUS_MAXWAVEFORM = 1UL; +constexpr auto EAXCHORUS_DEFAULTWAVEFORM = 1UL; + +constexpr auto EAXCHORUS_MINPHASE = -180L; +constexpr auto EAXCHORUS_MAXPHASE = 180L; +constexpr auto EAXCHORUS_DEFAULTPHASE = 90L; + +constexpr auto EAXCHORUS_MINRATE = 0.0F; +constexpr auto EAXCHORUS_MAXRATE = 10.0F; +constexpr auto EAXCHORUS_DEFAULTRATE = 1.1F; + +constexpr auto EAXCHORUS_MINDEPTH = 0.0F; +constexpr auto EAXCHORUS_MAXDEPTH = 1.0F; +constexpr auto EAXCHORUS_DEFAULTDEPTH = 0.1F; + +constexpr auto EAXCHORUS_MINFEEDBACK = -1.0F; +constexpr auto EAXCHORUS_MAXFEEDBACK = 1.0F; +constexpr auto EAXCHORUS_DEFAULTFEEDBACK = 0.25F; + +constexpr auto EAXCHORUS_MINDELAY = 0.0002F; +constexpr auto EAXCHORUS_MAXDELAY = 0.016F; +constexpr auto EAXCHORUS_DEFAULTDELAY = 0.016F; + + +// Distortion Effect + +extern const GUID EAX_DISTORTION_EFFECT; + +enum EAXDISTORTION_PROPERTY : + unsigned int +{ + EAXDISTORTION_NONE, + EAXDISTORTION_ALLPARAMETERS, + EAXDISTORTION_EDGE, + EAXDISTORTION_GAIN, + EAXDISTORTION_LOWPASSCUTOFF, + EAXDISTORTION_EQCENTER, + EAXDISTORTION_EQBANDWIDTH, +}; // EAXDISTORTION_PROPERTY + + +struct EAXDISTORTIONPROPERTIES +{ + float flEdge; // Controls the shape of the distortion (0 to 1) + long lGain; // Controls the post distortion gain (mB) + float flLowPassCutOff; // Controls the cut-off of the filter pre-distortion (Hz) + float flEQCenter; // Controls the center frequency of the EQ post-distortion (Hz) + float flEQBandwidth; // Controls the bandwidth of the EQ post-distortion (Hz) +}; // EAXDISTORTIONPROPERTIES + + +constexpr auto EAXDISTORTION_MINEDGE = 0.0F; +constexpr auto EAXDISTORTION_MAXEDGE = 1.0F; +constexpr auto EAXDISTORTION_DEFAULTEDGE = 0.2F; + +constexpr auto EAXDISTORTION_MINGAIN = -6000L; +constexpr auto EAXDISTORTION_MAXGAIN = 0L; +constexpr auto EAXDISTORTION_DEFAULTGAIN = -2600L; + +constexpr auto EAXDISTORTION_MINLOWPASSCUTOFF = 80.0F; +constexpr auto EAXDISTORTION_MAXLOWPASSCUTOFF = 24000.0F; +constexpr auto EAXDISTORTION_DEFAULTLOWPASSCUTOFF = 8000.0F; + +constexpr auto EAXDISTORTION_MINEQCENTER = 80.0F; +constexpr auto EAXDISTORTION_MAXEQCENTER = 24000.0F; +constexpr auto EAXDISTORTION_DEFAULTEQCENTER = 3600.0F; + +constexpr auto EAXDISTORTION_MINEQBANDWIDTH = 80.0F; +constexpr auto EAXDISTORTION_MAXEQBANDWIDTH = 24000.0F; +constexpr auto EAXDISTORTION_DEFAULTEQBANDWIDTH = 3600.0F; + + +// Echo Effect + +extern const GUID EAX_ECHO_EFFECT; + + +enum EAXECHO_PROPERTY : + unsigned int +{ + EAXECHO_NONE, + EAXECHO_ALLPARAMETERS, + EAXECHO_DELAY, + EAXECHO_LRDELAY, + EAXECHO_DAMPING, + EAXECHO_FEEDBACK, + EAXECHO_SPREAD, +}; // EAXECHO_PROPERTY + + +struct EAXECHOPROPERTIES +{ + float flDelay; // Controls the initial delay time (seconds) + float flLRDelay; // Controls the delay time between the first and second taps (seconds) + float flDamping; // Controls a low-pass filter that dampens the echoes (0 to 1) + float flFeedback; // Controls the duration of echo repetition (0 to 1) + float flSpread; // Controls the left-right spread of the echoes +}; // EAXECHOPROPERTIES + + +constexpr auto EAXECHO_MINDAMPING = 0.0F; +constexpr auto EAXECHO_MAXDAMPING = 0.99F; +constexpr auto EAXECHO_DEFAULTDAMPING = 0.5F; + +constexpr auto EAXECHO_MINDELAY = 0.002F; +constexpr auto EAXECHO_MAXDELAY = 0.207F; +constexpr auto EAXECHO_DEFAULTDELAY = 0.1F; + +constexpr auto EAXECHO_MINLRDELAY = 0.0F; +constexpr auto EAXECHO_MAXLRDELAY = 0.404F; +constexpr auto EAXECHO_DEFAULTLRDELAY = 0.1F; + +constexpr auto EAXECHO_MINFEEDBACK = 0.0F; +constexpr auto EAXECHO_MAXFEEDBACK = 1.0F; +constexpr auto EAXECHO_DEFAULTFEEDBACK = 0.5F; + +constexpr auto EAXECHO_MINSPREAD = -1.0F; +constexpr auto EAXECHO_MAXSPREAD = 1.0F; +constexpr auto EAXECHO_DEFAULTSPREAD = -1.0F; + + +// Equalizer Effect + +extern const GUID EAX_EQUALIZER_EFFECT; + + +enum EAXEQUALIZER_PROPERTY : + unsigned int +{ + EAXEQUALIZER_NONE, + EAXEQUALIZER_ALLPARAMETERS, + EAXEQUALIZER_LOWGAIN, + EAXEQUALIZER_LOWCUTOFF, + EAXEQUALIZER_MID1GAIN, + EAXEQUALIZER_MID1CENTER, + EAXEQUALIZER_MID1WIDTH, + EAXEQUALIZER_MID2GAIN, + EAXEQUALIZER_MID2CENTER, + EAXEQUALIZER_MID2WIDTH, + EAXEQUALIZER_HIGHGAIN, + EAXEQUALIZER_HIGHCUTOFF, +}; // EAXEQUALIZER_PROPERTY + + +struct EAXEQUALIZERPROPERTIES +{ + long lLowGain; // (mB) + float flLowCutOff; // (Hz) + long lMid1Gain; // (mB) + float flMid1Center; // (Hz) + float flMid1Width; // (octaves) + long lMid2Gain; // (mB) + float flMid2Center; // (Hz) + float flMid2Width; // (octaves) + long lHighGain; // (mB) + float flHighCutOff; // (Hz) +}; // EAXEQUALIZERPROPERTIES + + +constexpr auto EAXEQUALIZER_MINLOWGAIN = -1800L; +constexpr auto EAXEQUALIZER_MAXLOWGAIN = 1800L; +constexpr auto EAXEQUALIZER_DEFAULTLOWGAIN = 0L; + +constexpr auto EAXEQUALIZER_MINLOWCUTOFF = 50.0F; +constexpr auto EAXEQUALIZER_MAXLOWCUTOFF = 800.0F; +constexpr auto EAXEQUALIZER_DEFAULTLOWCUTOFF = 200.0F; + +constexpr auto EAXEQUALIZER_MINMID1GAIN = -1800L; +constexpr auto EAXEQUALIZER_MAXMID1GAIN = 1800L; +constexpr auto EAXEQUALIZER_DEFAULTMID1GAIN = 0L; + +constexpr auto EAXEQUALIZER_MINMID1CENTER = 200.0F; +constexpr auto EAXEQUALIZER_MAXMID1CENTER = 3000.0F; +constexpr auto EAXEQUALIZER_DEFAULTMID1CENTER = 500.0F; + +constexpr auto EAXEQUALIZER_MINMID1WIDTH = 0.01F; +constexpr auto EAXEQUALIZER_MAXMID1WIDTH = 1.0F; +constexpr auto EAXEQUALIZER_DEFAULTMID1WIDTH = 1.0F; + +constexpr auto EAXEQUALIZER_MINMID2GAIN = -1800L; +constexpr auto EAXEQUALIZER_MAXMID2GAIN = 1800L; +constexpr auto EAXEQUALIZER_DEFAULTMID2GAIN = 0L; + +constexpr auto EAXEQUALIZER_MINMID2CENTER = 1000.0F; +constexpr auto EAXEQUALIZER_MAXMID2CENTER = 8000.0F; +constexpr auto EAXEQUALIZER_DEFAULTMID2CENTER = 3000.0F; + +constexpr auto EAXEQUALIZER_MINMID2WIDTH = 0.01F; +constexpr auto EAXEQUALIZER_MAXMID2WIDTH = 1.0F; +constexpr auto EAXEQUALIZER_DEFAULTMID2WIDTH = 1.0F; + +constexpr auto EAXEQUALIZER_MINHIGHGAIN = -1800L; +constexpr auto EAXEQUALIZER_MAXHIGHGAIN = 1800L; +constexpr auto EAXEQUALIZER_DEFAULTHIGHGAIN = 0L; + +constexpr auto EAXEQUALIZER_MINHIGHCUTOFF = 4000.0F; +constexpr auto EAXEQUALIZER_MAXHIGHCUTOFF = 16000.0F; +constexpr auto EAXEQUALIZER_DEFAULTHIGHCUTOFF = 6000.0F; + + +// Flanger Effect + +extern const GUID EAX_FLANGER_EFFECT; + +enum EAXFLANGER_PROPERTY : + unsigned int +{ + EAXFLANGER_NONE, + EAXFLANGER_ALLPARAMETERS, + EAXFLANGER_WAVEFORM, + EAXFLANGER_PHASE, + EAXFLANGER_RATE, + EAXFLANGER_DEPTH, + EAXFLANGER_FEEDBACK, + EAXFLANGER_DELAY, +}; // EAXFLANGER_PROPERTY + +enum : + unsigned long +{ + EAX_FLANGER_SINUSOID, + EAX_FLANGER_TRIANGLE, +}; + +struct EAXFLANGERPROPERTIES +{ + unsigned long ulWaveform; // Waveform selector - see enum above + long lPhase; // Phase (Degrees) + float flRate; // Rate (Hz) + float flDepth; // Depth (0 to 1) + float flFeedback; // Feedback (0 to 1) + float flDelay; // Delay (seconds) +}; // EAXFLANGERPROPERTIES + + +constexpr auto EAXFLANGER_MINWAVEFORM = 0UL; +constexpr auto EAXFLANGER_MAXWAVEFORM = 1UL; +constexpr auto EAXFLANGER_DEFAULTWAVEFORM = 1UL; + +constexpr auto EAXFLANGER_MINPHASE = -180L; +constexpr auto EAXFLANGER_MAXPHASE = 180L; +constexpr auto EAXFLANGER_DEFAULTPHASE = 0L; + +constexpr auto EAXFLANGER_MINRATE = 0.0F; +constexpr auto EAXFLANGER_MAXRATE = 10.0F; +constexpr auto EAXFLANGER_DEFAULTRATE = 0.27F; + +constexpr auto EAXFLANGER_MINDEPTH = 0.0F; +constexpr auto EAXFLANGER_MAXDEPTH = 1.0F; +constexpr auto EAXFLANGER_DEFAULTDEPTH = 1.0F; + +constexpr auto EAXFLANGER_MINFEEDBACK = -1.0F; +constexpr auto EAXFLANGER_MAXFEEDBACK = 1.0F; +constexpr auto EAXFLANGER_DEFAULTFEEDBACK = -0.5F; + +constexpr auto EAXFLANGER_MINDELAY = 0.0002F; +constexpr auto EAXFLANGER_MAXDELAY = 0.004F; +constexpr auto EAXFLANGER_DEFAULTDELAY = 0.002F; + + +// Frequency Shifter Effect + +extern const GUID EAX_FREQUENCYSHIFTER_EFFECT; + +enum EAXFREQUENCYSHIFTER_PROPERTY : + unsigned int +{ + EAXFREQUENCYSHIFTER_NONE, + EAXFREQUENCYSHIFTER_ALLPARAMETERS, + EAXFREQUENCYSHIFTER_FREQUENCY, + EAXFREQUENCYSHIFTER_LEFTDIRECTION, + EAXFREQUENCYSHIFTER_RIGHTDIRECTION, +}; // EAXFREQUENCYSHIFTER_PROPERTY + +enum : + unsigned long +{ + EAX_FREQUENCYSHIFTER_DOWN, + EAX_FREQUENCYSHIFTER_UP, + EAX_FREQUENCYSHIFTER_OFF +}; + +struct EAXFREQUENCYSHIFTERPROPERTIES +{ + float flFrequency; // (Hz) + unsigned long ulLeftDirection; // see enum above + unsigned long ulRightDirection; // see enum above +}; // EAXFREQUENCYSHIFTERPROPERTIES + + +constexpr auto EAXFREQUENCYSHIFTER_MINFREQUENCY = 0.0F; +constexpr auto EAXFREQUENCYSHIFTER_MAXFREQUENCY = 24000.0F; +constexpr auto EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY = EAXFREQUENCYSHIFTER_MINFREQUENCY; + +constexpr auto EAXFREQUENCYSHIFTER_MINLEFTDIRECTION = 0UL; +constexpr auto EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION = 2UL; +constexpr auto EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION = EAXFREQUENCYSHIFTER_MINLEFTDIRECTION; + +constexpr auto EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION = 0UL; +constexpr auto EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION = 2UL; +constexpr auto EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION = EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION; + + +// Vocal Morpher Effect + +extern const GUID EAX_VOCALMORPHER_EFFECT; + +enum EAXVOCALMORPHER_PROPERTY : + unsigned int +{ + EAXVOCALMORPHER_NONE, + EAXVOCALMORPHER_ALLPARAMETERS, + EAXVOCALMORPHER_PHONEMEA, + EAXVOCALMORPHER_PHONEMEACOARSETUNING, + EAXVOCALMORPHER_PHONEMEB, + EAXVOCALMORPHER_PHONEMEBCOARSETUNING, + EAXVOCALMORPHER_WAVEFORM, + EAXVOCALMORPHER_RATE, +}; // EAXVOCALMORPHER_PROPERTY + +enum : + unsigned long +{ + A, + E, + I, + O, + U, + AA, + AE, + AH, + AO, + EH, + ER, + IH, + IY, + UH, + UW, + B, + D, + F, + G, + J, + K, + L, + M, + N, + P, + R, + S, + T, + V, + Z, +}; + +enum : + unsigned long +{ + EAX_VOCALMORPHER_SINUSOID, + EAX_VOCALMORPHER_TRIANGLE, + EAX_VOCALMORPHER_SAWTOOTH +}; + +// Use this structure for EAXVOCALMORPHER_ALLPARAMETERS +struct EAXVOCALMORPHERPROPERTIES +{ + unsigned long ulPhonemeA; // see enum above + long lPhonemeACoarseTuning; // (semitones) + unsigned long ulPhonemeB; // see enum above + long lPhonemeBCoarseTuning; // (semitones) + unsigned long ulWaveform; // Waveform selector - see enum above + float flRate; // (Hz) +}; // EAXVOCALMORPHERPROPERTIES + + +constexpr auto EAXVOCALMORPHER_MINPHONEMEA = 0UL; +constexpr auto EAXVOCALMORPHER_MAXPHONEMEA = 29UL; +constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEA = EAXVOCALMORPHER_MINPHONEMEA; + +constexpr auto EAXVOCALMORPHER_MINPHONEMEACOARSETUNING = -24L; +constexpr auto EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING = 24L; +constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING = 0L; + +constexpr auto EAXVOCALMORPHER_MINPHONEMEB = 0UL; +constexpr auto EAXVOCALMORPHER_MAXPHONEMEB = 29UL; +constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEB = 10UL; + +constexpr auto EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING = -24L; +constexpr auto EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING = 24L; +constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING = 0L; + +constexpr auto EAXVOCALMORPHER_MINWAVEFORM = 0UL; +constexpr auto EAXVOCALMORPHER_MAXWAVEFORM = 2UL; +constexpr auto EAXVOCALMORPHER_DEFAULTWAVEFORM = EAXVOCALMORPHER_MINWAVEFORM; + +constexpr auto EAXVOCALMORPHER_MINRATE = 0.0F; +constexpr auto EAXVOCALMORPHER_MAXRATE = 10.0F; +constexpr auto EAXVOCALMORPHER_DEFAULTRATE = 1.41F; + + +// Pitch Shifter Effect + +extern const GUID EAX_PITCHSHIFTER_EFFECT; + +enum EAXPITCHSHIFTER_PROPERTY : + unsigned int +{ + EAXPITCHSHIFTER_NONE, + EAXPITCHSHIFTER_ALLPARAMETERS, + EAXPITCHSHIFTER_COARSETUNE, + EAXPITCHSHIFTER_FINETUNE, +}; // EAXPITCHSHIFTER_PROPERTY + +struct EAXPITCHSHIFTERPROPERTIES +{ + long lCoarseTune; // Amount of pitch shift (semitones) + long lFineTune; // Amount of pitch shift (cents) +}; // EAXPITCHSHIFTERPROPERTIES + + +constexpr auto EAXPITCHSHIFTER_MINCOARSETUNE = -12L; +constexpr auto EAXPITCHSHIFTER_MAXCOARSETUNE = 12L; +constexpr auto EAXPITCHSHIFTER_DEFAULTCOARSETUNE = 12L; + +constexpr auto EAXPITCHSHIFTER_MINFINETUNE = -50L; +constexpr auto EAXPITCHSHIFTER_MAXFINETUNE = 50L; +constexpr auto EAXPITCHSHIFTER_DEFAULTFINETUNE = 0L; + + +// Ring Modulator Effect + +extern const GUID EAX_RINGMODULATOR_EFFECT; + +enum EAXRINGMODULATOR_PROPERTY : + unsigned int +{ + EAXRINGMODULATOR_NONE, + EAXRINGMODULATOR_ALLPARAMETERS, + EAXRINGMODULATOR_FREQUENCY, + EAXRINGMODULATOR_HIGHPASSCUTOFF, + EAXRINGMODULATOR_WAVEFORM, +}; // EAXRINGMODULATOR_PROPERTY + +enum : + unsigned long +{ + EAX_RINGMODULATOR_SINUSOID, + EAX_RINGMODULATOR_SAWTOOTH, + EAX_RINGMODULATOR_SQUARE, +}; + +// Use this structure for EAXRINGMODULATOR_ALLPARAMETERS +struct EAXRINGMODULATORPROPERTIES +{ + float flFrequency; // Frequency of modulation (Hz) + float flHighPassCutOff; // Cut-off frequency of high-pass filter (Hz) + unsigned long ulWaveform; // Waveform selector - see enum above +}; // EAXRINGMODULATORPROPERTIES + + +constexpr auto EAXRINGMODULATOR_MINFREQUENCY = 0.0F; +constexpr auto EAXRINGMODULATOR_MAXFREQUENCY = 8000.0F; +constexpr auto EAXRINGMODULATOR_DEFAULTFREQUENCY = 440.0F; + +constexpr auto EAXRINGMODULATOR_MINHIGHPASSCUTOFF = 0.0F; +constexpr auto EAXRINGMODULATOR_MAXHIGHPASSCUTOFF = 24000.0F; +constexpr auto EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF = 800.0F; + +constexpr auto EAXRINGMODULATOR_MINWAVEFORM = 0UL; +constexpr auto EAXRINGMODULATOR_MAXWAVEFORM = 2UL; +constexpr auto EAXRINGMODULATOR_DEFAULTWAVEFORM = EAXRINGMODULATOR_MINWAVEFORM; + + +using LPEAXSET = ALenum(AL_APIENTRY*)( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + +using LPEAXGET = ALenum(AL_APIENTRY*)( + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + + +#endif // !EAX_API_INCLUDED diff --git a/al/eax/eax_call.cpp b/al/eax/eax_call.cpp new file mode 100644 index 00000000..19565852 --- /dev/null +++ b/al/eax/eax_call.cpp @@ -0,0 +1,323 @@ +#include "config.h" + +#include "eax_call.h" +#include "exception.h" + + +namespace { + +constexpr auto deferred_flag = 0x80000000U; + +class EaxEaxCallException : + public EaxException +{ +public: + explicit EaxEaxCallException( + const char* message) + : + EaxException{"EAX_EAX_CALL", message} + { + } +}; // EaxEaxCallException + +} // namespace + + +EaxEaxCall::EaxEaxCall( + bool is_get, + const GUID& property_set_guid, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size) + : is_get_{is_get}, version_{0}, property_set_id_{EaxEaxCallPropertySetId::none} + , property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id} + , property_buffer_{property_buffer}, property_size_{property_size} +{ + if (false) + { + } + else if (property_set_guid == EAXPROPERTYID_EAX40_Context) + { + version_ = 4; + property_set_id_ = EaxEaxCallPropertySetId::context; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_Context) + { + version_ = 5; + property_set_id_ = EaxEaxCallPropertySetId::context; + } + else if (property_set_guid == DSPROPSETID_EAX20_ListenerProperties) + { + version_ = 2; + fx_slot_index_ = 0u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; + property_id_ = convert_eax_v2_0_listener_property_id(property_id_); + } + else if (property_set_guid == DSPROPSETID_EAX30_ListenerProperties) + { + version_ = 3; + fx_slot_index_ = 0u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot0) + { + version_ = 4; + fx_slot_index_ = 0u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot0) + { + version_ = 5; + fx_slot_index_ = 0u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot1) + { + version_ = 4; + fx_slot_index_ = 1u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot1) + { + version_ = 5; + fx_slot_index_ = 1u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot2) + { + version_ = 4; + fx_slot_index_ = 2u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot2) + { + version_ = 5; + fx_slot_index_ = 2u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot3) + { + version_ = 4; + fx_slot_index_ = 3u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot3) + { + version_ = 5; + fx_slot_index_ = 3u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == DSPROPSETID_EAX20_BufferProperties) + { + version_ = 2; + property_set_id_ = EaxEaxCallPropertySetId::source; + property_id_ = convert_eax_v2_0_buffer_property_id(property_id_); + } + else if (property_set_guid == DSPROPSETID_EAX30_BufferProperties) + { + version_ = 3; + property_set_id_ = EaxEaxCallPropertySetId::source; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_Source) + { + version_ = 4; + property_set_id_ = EaxEaxCallPropertySetId::source; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_Source) + { + version_ = 5; + property_set_id_ = EaxEaxCallPropertySetId::source; + } + else if (property_set_guid == DSPROPSETID_EAX_ReverbProperties) + { + version_ = 1; + fx_slot_index_ = 0u; + property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid == DSPROPSETID_EAXBUFFER_ReverbProperties) + { + version_ = 1; + property_set_id_ = EaxEaxCallPropertySetId::source; + } + else + { + fail("Unsupported property set id."); + } + + if (version_ < 1 || version_ > 5) + { + fail("EAX version out of range."); + } + + if(!(property_id&deferred_flag)) + { + if(property_set_id_ != EaxEaxCallPropertySetId::fx_slot && property_id_ != 0) + { + if (!property_buffer) + { + fail("Null property buffer."); + } + + if (property_size == 0) + { + fail("Empty property."); + } + } + } + + if(property_set_id_ == EaxEaxCallPropertySetId::source && property_source_id_ == 0) + { + fail("Null AL source id."); + } + + if (property_set_id_ == EaxEaxCallPropertySetId::fx_slot) + { + if (property_id_ < EAXFXSLOT_NONE) + { + property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; + } + } +} + +[[noreturn]] +void EaxEaxCall::fail( + const char* message) +{ + throw EaxEaxCallException{message}; +} + +ALuint EaxEaxCall::convert_eax_v2_0_listener_property_id( + ALuint property_id) +{ + switch (property_id) + { + case DSPROPERTY_EAX20LISTENER_NONE: + return EAXREVERB_NONE; + + case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: + return EAXREVERB_ALLPARAMETERS; + + case DSPROPERTY_EAX20LISTENER_ROOM: + return EAXREVERB_ROOM; + + case DSPROPERTY_EAX20LISTENER_ROOMHF: + return EAXREVERB_ROOMHF; + + case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: + return EAXREVERB_ROOMROLLOFFFACTOR; + + case DSPROPERTY_EAX20LISTENER_DECAYTIME: + return EAXREVERB_DECAYTIME; + + case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: + return EAXREVERB_DECAYHFRATIO; + + case DSPROPERTY_EAX20LISTENER_REFLECTIONS: + return EAXREVERB_REFLECTIONS; + + case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: + return EAXREVERB_REFLECTIONSDELAY; + + case DSPROPERTY_EAX20LISTENER_REVERB: + return EAXREVERB_REVERB; + + case DSPROPERTY_EAX20LISTENER_REVERBDELAY: + return EAXREVERB_REVERBDELAY; + + case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: + return EAXREVERB_ENVIRONMENT; + + case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE: + return EAXREVERB_ENVIRONMENTSIZE; + + case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION: + return EAXREVERB_ENVIRONMENTDIFFUSION; + + case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: + return EAXREVERB_AIRABSORPTIONHF; + + case DSPROPERTY_EAX20LISTENER_FLAGS: + return EAXREVERB_FLAGS; + + default: + fail("Unsupported EAX 2.0 listener property id."); + } +} + +ALuint EaxEaxCall::convert_eax_v2_0_buffer_property_id( + ALuint property_id) +{ + switch (property_id) + { + case DSPROPERTY_EAX20BUFFER_NONE: + return EAXSOURCE_NONE; + + case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS: + return EAXSOURCE_ALLPARAMETERS; + + case DSPROPERTY_EAX20BUFFER_DIRECT: + return EAXSOURCE_DIRECT; + + case DSPROPERTY_EAX20BUFFER_DIRECTHF: + return EAXSOURCE_DIRECTHF; + + case DSPROPERTY_EAX20BUFFER_ROOM: + return EAXSOURCE_ROOM; + + case DSPROPERTY_EAX20BUFFER_ROOMHF: + return EAXSOURCE_ROOMHF; + + case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR: + return EAXSOURCE_ROOMROLLOFFFACTOR; + + case DSPROPERTY_EAX20BUFFER_OBSTRUCTION: + return EAXSOURCE_OBSTRUCTION; + + case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO: + return EAXSOURCE_OBSTRUCTIONLFRATIO; + + case DSPROPERTY_EAX20BUFFER_OCCLUSION: + return EAXSOURCE_OCCLUSION; + + case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO: + return EAXSOURCE_OCCLUSIONLFRATIO; + + case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO: + return EAXSOURCE_OCCLUSIONROOMRATIO; + + case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF: + return EAXSOURCE_OUTSIDEVOLUMEHF; + + case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR: + return EAXSOURCE_AIRABSORPTIONFACTOR; + + case DSPROPERTY_EAX20BUFFER_FLAGS: + return EAXSOURCE_FLAGS; + + default: + fail("Unsupported EAX 2.0 buffer property id."); + } +} + + +EaxEaxCall create_eax_call( + bool is_get, + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size) +{ + if(!property_set_id) + throw EaxEaxCallException{"Null property set ID."}; + + return EaxEaxCall{ + is_get, + *property_set_id, + property_id, + property_source_id, + property_buffer, + property_size + }; +} diff --git a/al/eax/eax_call.h b/al/eax/eax_call.h new file mode 100644 index 00000000..2c90bdc3 --- /dev/null +++ b/al/eax/eax_call.h @@ -0,0 +1,117 @@ +#ifndef EAX_EAX_CALL_INCLUDED +#define EAX_EAX_CALL_INCLUDED + + +#include "AL/al.h" + +#include "alspan.h" + +#include "api.h" +#include "fx_slot_index.h" + + +enum class EaxEaxCallPropertySetId +{ + none, + + context, + fx_slot, + source, + fx_slot_effect, +}; // EaxEaxCallPropertySetId + + +class EaxEaxCall +{ +public: + EaxEaxCall( + bool is_get, + const GUID& property_set_guid, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + + bool is_get() const noexcept { return is_get_; } + int get_version() const noexcept { return version_; } + EaxEaxCallPropertySetId get_property_set_id() const noexcept { return property_set_id_; } + ALuint get_property_id() const noexcept { return property_id_; } + ALuint get_property_al_name() const noexcept { return property_source_id_; } + EaxFxSlotIndex get_fx_slot_index() const noexcept { return fx_slot_index_; } + + template< + typename TException, + typename TValue + > + TValue& get_value() const + { + if (property_size_ < static_cast(sizeof(TValue))) + { + throw TException{"Property buffer too small."}; + } + + return *static_cast(property_buffer_); + } + + template< + typename TException, + typename TValue + > + al::span get_values() const + { + if (property_size_ < static_cast(sizeof(TValue))) + { + throw TException{"Property buffer too small."}; + } + + const auto count = property_size_ / sizeof(TValue); + + return al::span{static_cast(property_buffer_), count}; + } + + template< + typename TException, + typename TValue + > + void set_value( + const TValue& value) const + { + get_value() = value; + } + + +private: + const bool is_get_; + int version_; + EaxFxSlotIndex fx_slot_index_; + EaxEaxCallPropertySetId property_set_id_; + + ALuint property_id_; + const ALuint property_source_id_; + ALvoid*const property_buffer_; + const ALuint property_size_; + + + [[noreturn]] + static void fail( + const char* message); + + + static ALuint convert_eax_v2_0_listener_property_id( + ALuint property_id); + + static ALuint convert_eax_v2_0_buffer_property_id( + ALuint property_id); +}; // EaxEaxCall + + +EaxEaxCall create_eax_call( + bool is_get, + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + + +#endif // !EAX_EAX_CALL_INCLUDED diff --git a/al/eax/effect.cpp b/al/eax/effect.cpp new file mode 100644 index 00000000..4e8faa73 --- /dev/null +++ b/al/eax/effect.cpp @@ -0,0 +1,3 @@ +#include "config.h" + +#include "effect.h" diff --git a/al/eax/effect.h b/al/eax/effect.h new file mode 100644 index 00000000..9c9fdef4 --- /dev/null +++ b/al/eax/effect.h @@ -0,0 +1,44 @@ +#ifndef EAX_EFFECT_INCLUDED +#define EAX_EFFECT_INCLUDED + + +#include + +#include "AL/al.h" +#include "core/effects/base.h" +#include "eax_call.h" + +class EaxEffect +{ +public: + EaxEffect(ALenum type) : al_effect_type_{type} { } + virtual ~EaxEffect() = default; + + const ALenum al_effect_type_; + EffectProps al_effect_props_{}; + + virtual void dispatch(const EaxEaxCall& eax_call) = 0; + + // Returns "true" if any immediated property was changed. + // [[nodiscard]] + virtual bool apply_deferred() = 0; +}; // EaxEffect + + +using EaxEffectUPtr = std::unique_ptr; + +EaxEffectUPtr eax_create_eax_null_effect(); +EaxEffectUPtr eax_create_eax_chorus_effect(); +EaxEffectUPtr eax_create_eax_distortion_effect(); +EaxEffectUPtr eax_create_eax_echo_effect(); +EaxEffectUPtr eax_create_eax_flanger_effect(); +EaxEffectUPtr eax_create_eax_frequency_shifter_effect(); +EaxEffectUPtr eax_create_eax_vocal_morpher_effect(); +EaxEffectUPtr eax_create_eax_pitch_shifter_effect(); +EaxEffectUPtr eax_create_eax_ring_modulator_effect(); +EaxEffectUPtr eax_create_eax_auto_wah_effect(); +EaxEffectUPtr eax_create_eax_compressor_effect(); +EaxEffectUPtr eax_create_eax_equalizer_effect(); +EaxEffectUPtr eax_create_eax_reverb_effect(); + +#endif // !EAX_EFFECT_INCLUDED diff --git a/al/eax/exception.cpp b/al/eax/exception.cpp new file mode 100644 index 00000000..3b319648 --- /dev/null +++ b/al/eax/exception.cpp @@ -0,0 +1,62 @@ +#include "config.h" + +#include "exception.h" + +#include +#include + + +EaxException::EaxException( + const char* context, + const char* message) + : + std::runtime_error{make_message(context, message)} +{ +} + +std::string EaxException::make_message( + const char* context, + const char* message) +{ + const auto context_size = (context ? std::string::traits_type::length(context) : 0); + const auto has_contex = (context_size > 0); + + const auto message_size = (message ? std::string::traits_type::length(message) : 0); + const auto has_message = (message_size > 0); + + if (!has_contex && !has_message) + { + return std::string{}; + } + + static constexpr char left_prefix[] = "["; + const auto left_prefix_size = std::string::traits_type::length(left_prefix); + + static constexpr char right_prefix[] = "] "; + const auto right_prefix_size = std::string::traits_type::length(right_prefix); + + const auto what_size = + ( + has_contex ? + left_prefix_size + context_size + right_prefix_size : + 0) + + message_size + + 1; + + auto what = std::string{}; + what.reserve(what_size); + + if (has_contex) + { + what.append(left_prefix, left_prefix_size); + what.append(context, context_size); + what.append(right_prefix, right_prefix_size); + } + + if (has_message) + { + what.append(message, message_size); + } + + return what; +} diff --git a/al/eax/exception.h b/al/eax/exception.h new file mode 100644 index 00000000..9a7acf71 --- /dev/null +++ b/al/eax/exception.h @@ -0,0 +1,25 @@ +#ifndef EAX_EXCEPTION_INCLUDED +#define EAX_EXCEPTION_INCLUDED + + +#include +#include + + +class EaxException : + public std::runtime_error +{ +public: + EaxException( + const char* context, + const char* message); + + +private: + static std::string make_message( + const char* context, + const char* message); +}; // EaxException + + +#endif // !EAX_EXCEPTION_INCLUDED diff --git a/al/eax/fx_slot_index.cpp b/al/eax/fx_slot_index.cpp new file mode 100644 index 00000000..28b11882 --- /dev/null +++ b/al/eax/fx_slot_index.cpp @@ -0,0 +1,71 @@ +#include "config.h" + +#include "fx_slot_index.h" + +#include "exception.h" + + +namespace +{ + + +class EaxFxSlotIndexException : + public EaxException +{ +public: + explicit EaxFxSlotIndexException( + const char* message) + : + EaxException{"EAX_FX_SLOT_INDEX", message} + { + } +}; // EaxFxSlotIndexException + + +} // namespace + + +void EaxFxSlotIndex::set(EaxFxSlotIndexValue index) +{ + if(index >= EaxFxSlotIndexValue{EAX_MAX_FXSLOTS}) + fail("Index out of range."); + + emplace(index); +} + +void EaxFxSlotIndex::set(const GUID &guid) +{ + if (false) + { + } + else if (guid == EAX_NULL_GUID) + { + reset(); + } + else if (guid == EAXPROPERTYID_EAX40_FXSlot0 || guid == EAXPROPERTYID_EAX50_FXSlot0) + { + emplace(0u); + } + else if (guid == EAXPROPERTYID_EAX40_FXSlot1 || guid == EAXPROPERTYID_EAX50_FXSlot1) + { + emplace(1u); + } + else if (guid == EAXPROPERTYID_EAX40_FXSlot2 || guid == EAXPROPERTYID_EAX50_FXSlot2) + { + emplace(2u); + } + else if (guid == EAXPROPERTYID_EAX40_FXSlot3 || guid == EAXPROPERTYID_EAX50_FXSlot3) + { + emplace(3u); + } + else + { + fail("Unsupported GUID."); + } +} + +[[noreturn]] +void EaxFxSlotIndex::fail(const char* message) +{ + throw EaxFxSlotIndexException{message}; +} diff --git a/al/eax/fx_slot_index.h b/al/eax/fx_slot_index.h new file mode 100644 index 00000000..63dba037 --- /dev/null +++ b/al/eax/fx_slot_index.h @@ -0,0 +1,41 @@ +#ifndef EAX_FX_SLOT_INDEX_INCLUDED +#define EAX_FX_SLOT_INDEX_INCLUDED + + +#include + +#include "aloptional.h" +#include "api.h" + + +using EaxFxSlotIndexValue = std::size_t; + +class EaxFxSlotIndex : public al::optional +{ +public: + using al::optional::optional; + + EaxFxSlotIndex& operator=(const EaxFxSlotIndexValue &value) { set(value); return *this; } + EaxFxSlotIndex& operator=(const GUID &guid) { set(guid); return *this; } + + void set(EaxFxSlotIndexValue index); + void set(const GUID& guid); + +private: + [[noreturn]] + static void fail(const char *message); +}; // EaxFxSlotIndex + +inline bool operator==(const EaxFxSlotIndex& lhs, const EaxFxSlotIndex& rhs) noexcept +{ + if(lhs.has_value() != rhs.has_value()) + return false; + if(lhs.has_value()) + return *lhs == *rhs; + return true; +} + +inline bool operator!=(const EaxFxSlotIndex& lhs, const EaxFxSlotIndex& rhs) noexcept +{ return !(lhs == rhs); } + +#endif // !EAX_FX_SLOT_INDEX_INCLUDED diff --git a/al/eax/fx_slots.cpp b/al/eax/fx_slots.cpp new file mode 100644 index 00000000..5897e951 --- /dev/null +++ b/al/eax/fx_slots.cpp @@ -0,0 +1,83 @@ +#include "config.h" + +#include "fx_slots.h" + +#include + +#include "api.h" +#include "exception.h" + + +namespace +{ + + +class EaxFxSlotsException : + public EaxException +{ +public: + explicit EaxFxSlotsException( + const char* message) + : + EaxException{"EAX_FX_SLOTS", message} + { + } +}; // EaxFxSlotsException + + +} // namespace + + +void EaxFxSlots::initialize( + ALCcontext& al_context) +{ + initialize_fx_slots(al_context); +} + +void EaxFxSlots::uninitialize() noexcept +{ + for (auto& fx_slot : fx_slots_) + { + fx_slot = nullptr; + } +} + +const ALeffectslot& EaxFxSlots::get(EaxFxSlotIndex index) const +{ + if(!index.has_value()) + fail("Empty index."); + return *fx_slots_[index.value()]; +} + +ALeffectslot& EaxFxSlots::get(EaxFxSlotIndex index) +{ + if(!index.has_value()) + fail("Empty index."); + return *fx_slots_[index.value()]; +} + +void EaxFxSlots::unlock_legacy() noexcept +{ + fx_slots_[0]->eax_unlock_legacy(); + fx_slots_[1]->eax_unlock_legacy(); +} + +[[noreturn]] +void EaxFxSlots::fail( + const char* message) +{ + throw EaxFxSlotsException{message}; +} + +void EaxFxSlots::initialize_fx_slots( + ALCcontext& al_context) +{ + auto fx_slot_index = EaxFxSlotIndexValue{}; + + for (auto& fx_slot : fx_slots_) + { + fx_slot = eax_create_al_effect_slot(al_context); + fx_slot->eax_initialize(al_context, fx_slot_index); + fx_slot_index += 1; + } +} diff --git a/al/eax/fx_slots.h b/al/eax/fx_slots.h new file mode 100644 index 00000000..49cabd75 --- /dev/null +++ b/al/eax/fx_slots.h @@ -0,0 +1,53 @@ +#ifndef EAX_FX_SLOTS_INCLUDED +#define EAX_FX_SLOTS_INCLUDED + + +#include + +#include "al/auxeffectslot.h" + +#include "api.h" +#include "fx_slot_index.h" + + +class EaxFxSlots +{ +public: + void initialize( + ALCcontext& al_context); + + void uninitialize() noexcept; + + void commit() + { + for(auto& fx_slot : fx_slots_) + fx_slot->eax_commit(); + } + + + const ALeffectslot& get( + EaxFxSlotIndex index) const; + + ALeffectslot& get( + EaxFxSlotIndex index); + + void unlock_legacy() noexcept; + + +private: + using Items = std::array; + + + Items fx_slots_{}; + + + [[noreturn]] + static void fail( + const char* message); + + void initialize_fx_slots( + ALCcontext& al_context); +}; // EaxFxSlots + + +#endif // !EAX_FX_SLOTS_INCLUDED diff --git a/al/eax/globals.cpp b/al/eax/globals.cpp new file mode 100644 index 00000000..80e9dbfe --- /dev/null +++ b/al/eax/globals.cpp @@ -0,0 +1,21 @@ +#include "config.h" + +#include "globals.h" + + +bool eax_g_is_enabled = true; + + +const char eax1_ext_name[] = "EAX"; +const char eax2_ext_name[] = "EAX2.0"; +const char eax3_ext_name[] = "EAX3.0"; +const char eax4_ext_name[] = "EAX4.0"; +const char eax5_ext_name[] = "EAX5.0"; + +const char eax_x_ram_ext_name[] = "EAX-RAM"; + +const char eax_eax_set_func_name[] = "EAXSet"; +const char eax_eax_get_func_name[] = "EAXGet"; + +const char eax_eax_set_buffer_mode_func_name[] = "EAXSetBufferMode"; +const char eax_eax_get_buffer_mode_func_name[] = "EAXGetBufferMode"; diff --git a/al/eax/globals.h b/al/eax/globals.h new file mode 100644 index 00000000..1b4d63b8 --- /dev/null +++ b/al/eax/globals.h @@ -0,0 +1,22 @@ +#ifndef EAX_GLOBALS_INCLUDED +#define EAX_GLOBALS_INCLUDED + + +extern bool eax_g_is_enabled; + + +extern const char eax1_ext_name[]; +extern const char eax2_ext_name[]; +extern const char eax3_ext_name[]; +extern const char eax4_ext_name[]; +extern const char eax5_ext_name[]; + +extern const char eax_x_ram_ext_name[]; + +extern const char eax_eax_set_func_name[]; +extern const char eax_eax_get_func_name[]; + +extern const char eax_eax_set_buffer_mode_func_name[]; +extern const char eax_eax_get_buffer_mode_func_name[]; + +#endif // !EAX_GLOBALS_INCLUDED diff --git a/al/eax/utils.cpp b/al/eax/utils.cpp new file mode 100644 index 00000000..9fa2871d --- /dev/null +++ b/al/eax/utils.cpp @@ -0,0 +1,36 @@ +#include "config.h" + +#include "utils.h" + +#include +#include + +#include "core/logging.h" + + +void eax_log_exception( + const char* message) noexcept +{ + const auto exception_ptr = std::current_exception(); + + assert(exception_ptr); + + if (message) + { + ERR("%s\n", message); + } + + try + { + std::rethrow_exception(exception_ptr); + } + catch (const std::exception& ex) + { + const auto ex_message = ex.what(); + ERR("%s\n", ex_message); + } + catch (...) + { + ERR("%s\n", "Generic exception."); + } +} diff --git a/al/eax/utils.h b/al/eax/utils.h new file mode 100644 index 00000000..d3d4a196 --- /dev/null +++ b/al/eax/utils.h @@ -0,0 +1,132 @@ +#ifndef EAX_UTILS_INCLUDED +#define EAX_UTILS_INCLUDED + +#include +#include +#include +#include + + +struct EaxAlLowPassParam +{ + float gain; + float gain_hf; +}; // EaxAlLowPassParam + + +void eax_log_exception( + const char* message = nullptr) noexcept; + + +template< + typename TException, + typename TValue +> +void eax_validate_range( + const char* value_name, + const TValue& value, + const TValue& min_value, + const TValue& max_value) +{ + if (value >= min_value && value <= max_value) + { + return; + } + + const auto message = + std::string{value_name} + + " out of range (value: " + + std::to_string(value) + "; min: " + + std::to_string(min_value) + "; max: " + + std::to_string(max_value) + ")."; + + throw TException{message.c_str()}; +} + + +namespace detail +{ + + +template< + typename T +> +struct EaxIsBitFieldStruct +{ +private: + using yes = std::true_type; + using no = std::false_type; + + template< + typename U + > + static auto test(int) -> decltype(std::declval(), yes{}); + + template< + typename + > + static no test(...); + + +public: + static constexpr auto value = std::is_same(0)), yes>::value; +}; // EaxIsBitFieldStruct + + +template< + typename T, + typename TValue +> +inline bool eax_bit_fields_are_equal( + const T& lhs, + const T& rhs) noexcept +{ + static_assert(sizeof(T) == sizeof(TValue), "Invalid type size."); + + return reinterpret_cast(lhs) == reinterpret_cast(rhs); +} + + +} // namespace detail + + +template< + typename T, + std::enable_if_t::value, int> = 0 +> +inline bool operator==( + const T& lhs, + const T& rhs) noexcept +{ + using Value = std::conditional_t< + sizeof(T) == 1, + std::uint8_t, + std::conditional_t< + sizeof(T) == 2, + std::uint16_t, + std::conditional_t< + sizeof(T) == 4, + std::uint32_t, + void + > + > + >; + + static_assert(!std::is_same::value, "Unsupported type."); + + return detail::eax_bit_fields_are_equal(lhs, rhs); +} + +template< + typename T, + std::enable_if_t::value, int> = 0 +> +inline bool operator!=( + const T& lhs, + const T& rhs) noexcept +{ + return !(lhs == rhs); +} + + +#endif // !EAX_UTILS_INCLUDED diff --git a/al/eax/x_ram.cpp b/al/eax/x_ram.cpp new file mode 100644 index 00000000..7332c82e --- /dev/null +++ b/al/eax/x_ram.cpp @@ -0,0 +1,3 @@ +#include "config.h" + +#include "x_ram.h" diff --git a/al/eax/x_ram.h b/al/eax/x_ram.h new file mode 100644 index 00000000..438b9916 --- /dev/null +++ b/al/eax/x_ram.h @@ -0,0 +1,38 @@ +#ifndef EAX_X_RAM_INCLUDED +#define EAX_X_RAM_INCLUDED + + +#include "AL/al.h" + + +constexpr auto eax_x_ram_min_size = ALsizei{}; +constexpr auto eax_x_ram_max_size = ALsizei{64 * 1'024 * 1'024}; + + +constexpr auto AL_EAX_RAM_SIZE = ALenum{0x202201}; +constexpr auto AL_EAX_RAM_FREE = ALenum{0x202202}; + +constexpr auto AL_STORAGE_AUTOMATIC = ALenum{0x202203}; +constexpr auto AL_STORAGE_HARDWARE = ALenum{0x202204}; +constexpr auto AL_STORAGE_ACCESSIBLE = ALenum{0x202205}; + + +constexpr auto AL_EAX_RAM_SIZE_NAME = "AL_EAX_RAM_SIZE"; +constexpr auto AL_EAX_RAM_FREE_NAME = "AL_EAX_RAM_FREE"; + +constexpr auto AL_STORAGE_AUTOMATIC_NAME = "AL_STORAGE_AUTOMATIC"; +constexpr auto AL_STORAGE_HARDWARE_NAME = "AL_STORAGE_HARDWARE"; +constexpr auto AL_STORAGE_ACCESSIBLE_NAME = "AL_STORAGE_ACCESSIBLE"; + + +ALboolean AL_APIENTRY EAXSetBufferMode( + ALsizei n, + const ALuint* buffers, + ALint value); + +ALenum AL_APIENTRY EAXGetBufferMode( + ALuint buffer, + ALint* pReserved); + + +#endif // !EAX_X_RAM_INCLUDED diff --git a/al/eax_api.cpp b/al/eax_api.cpp deleted file mode 100644 index 6b1f7fcf..00000000 --- a/al/eax_api.cpp +++ /dev/null @@ -1,1213 +0,0 @@ -// -// EAX API. -// -// Based on headers `eax[2-5].h` included in Doom 3 source code: -// https://github.com/id-Software/DOOM-3/tree/master/neo/openal/include -// - -#include "config.h" - -#include - -#include "al/eax_api.h" - - -const GUID DSPROPSETID_EAX_ReverbProperties = -{ - 0x4A4E6FC1, - 0xC341, - 0x11D1, - {0xB7, 0x3A, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} -}; - -const GUID DSPROPSETID_EAXBUFFER_ReverbProperties = -{ - 0x4A4E6FC0, - 0xC341, - 0x11D1, - {0xB7, 0x3A, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} -}; - -const GUID DSPROPSETID_EAX20_ListenerProperties = -{ - 0x306A6A8, - 0xB224, - 0x11D2, - {0x99, 0xE5, 0x00, 0x00, 0xE8, 0xD8, 0xC7, 0x22} -}; - -const GUID DSPROPSETID_EAX20_BufferProperties = -{ - 0x306A6A7, - 0xB224, - 0x11D2, - {0x99, 0xE5, 0x00, 0x00, 0xE8, 0xD8, 0xC7, 0x22} -}; - -const GUID DSPROPSETID_EAX30_ListenerProperties = -{ - 0xA8FA6882, - 0xB476, - 0x11D3, - {0xBD, 0xB9, 0x00, 0xC0, 0xF0, 0x2D, 0xDF, 0x87} -}; - -const GUID DSPROPSETID_EAX30_BufferProperties = -{ - 0xA8FA6881, - 0xB476, - 0x11D3, - {0xBD, 0xB9, 0x00, 0xC0, 0xF0, 0x2D, 0xDF, 0x87} -}; - -const GUID EAX_NULL_GUID = -{ - 0x00000000, - 0x0000, - 0x0000, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} -}; - -const GUID EAX_PrimaryFXSlotID = -{ - 0xF317866D, - 0x924C, - 0x450C, - {0x86, 0x1B, 0xE6, 0xDA, 0xA2, 0x5E, 0x7C, 0x20} -}; - -const GUID EAXPROPERTYID_EAX40_Context = -{ - 0x1D4870AD, - 0xDEF, - 0x43C0, - {0xA4, 0xC, 0x52, 0x36, 0x32, 0x29, 0x63, 0x42} -}; - -const GUID EAXPROPERTYID_EAX50_Context = -{ - 0x57E13437, - 0xB932, - 0x4AB2, - {0xB8, 0xBD, 0x52, 0x66, 0xC1, 0xA8, 0x87, 0xEE} -}; - -const GUID EAXPROPERTYID_EAX40_FXSlot0 = -{ - 0xC4D79F1E, - 0xF1AC, - 0x436B, - {0xA8, 0x1D, 0xA7, 0x38, 0xE7, 0x04, 0x54, 0x69} -}; - -const GUID EAXPROPERTYID_EAX50_FXSlot0 = -{ - 0x91F9590F, - 0xC388, - 0x407A, - {0x84, 0xB0, 0x1B, 0xAE, 0xE, 0xF7, 0x1A, 0xBC} -}; - -const GUID EAXPROPERTYID_EAX40_FXSlot1 = -{ - 0x8C00E96, - 0x74BE, - 0x4491, - {0x93, 0xAA, 0xE8, 0xAD, 0x35, 0xA4, 0x91, 0x17} -}; - -const GUID EAXPROPERTYID_EAX50_FXSlot1 = -{ - 0x8F5F7ACA, - 0x9608, - 0x4965, - {0x81, 0x37, 0x82, 0x13, 0xC7, 0xB9, 0xD9, 0xDE} -}; - -const GUID EAXPROPERTYID_EAX40_FXSlot2 = -{ - 0x1D433B88, - 0xF0F6, - 0x4637, - {0x91, 0x9F, 0x60, 0xE7, 0xE0, 0x6B, 0x5E, 0xDD} -}; - -const GUID EAXPROPERTYID_EAX50_FXSlot2 = -{ - 0x3C0F5252, - 0x9834, - 0x46F0, - {0xA1, 0xD8, 0x5B, 0x95, 0xC4, 0xA0, 0xA, 0x30} -}; - -const GUID EAXPROPERTYID_EAX40_FXSlot3 = -{ - 0xEFFF08EA, - 0xC7D8, - 0x44AB, - {0x93, 0xAD, 0x6D, 0xBD, 0x5F, 0x91, 0x00, 0x64} -}; - -const GUID EAXPROPERTYID_EAX50_FXSlot3 = -{ - 0xE2EB0EAA, - 0xE806, - 0x45E7, - {0x9F, 0x86, 0x06, 0xC1, 0x57, 0x1A, 0x6F, 0xA3} -}; - -const GUID EAXPROPERTYID_EAX40_Source = -{ - 0x1B86B823, - 0x22DF, - 0x4EAE, - {0x8B, 0x3C, 0x12, 0x78, 0xCE, 0x54, 0x42, 0x27} -}; - -const GUID EAXPROPERTYID_EAX50_Source = -{ - 0x5EDF82F0, - 0x24A7, - 0x4F38, - {0x8E, 0x64, 0x2F, 0x09, 0xCA, 0x05, 0xDE, 0xE1} -}; - -const GUID EAX_REVERB_EFFECT = -{ - 0xCF95C8F, - 0xA3CC, - 0x4849, - {0xB0, 0xB6, 0x83, 0x2E, 0xCC, 0x18, 0x22, 0xDF} -}; - -const GUID EAX_AGCCOMPRESSOR_EFFECT = -{ - 0xBFB7A01E, - 0x7825, - 0x4039, - {0x92, 0x7F, 0x03, 0xAA, 0xBD, 0xA0, 0xC5, 0x60} -}; - -const GUID EAX_AUTOWAH_EFFECT = -{ - 0xEC3130C0, - 0xAC7A, - 0x11D2, - {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} -}; - -const GUID EAX_CHORUS_EFFECT = -{ - 0xDE6D6FE0, - 0xAC79, - 0x11D2, - {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} -}; - -const GUID EAX_DISTORTION_EFFECT = -{ - 0x975A4CE0, - 0xAC7E, - 0x11D2, - {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} -}; - -const GUID EAX_ECHO_EFFECT = -{ - 0xE9F1BC0, - 0xAC82, - 0x11D2, - {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} -}; - -const GUID EAX_EQUALIZER_EFFECT = -{ - 0x65F94CE0, - 0x9793, - 0x11D3, - {0x93, 0x9D, 0x00, 0xC0, 0xF0, 0x2D, 0xD6, 0xF0} -}; - -const GUID EAX_FLANGER_EFFECT = -{ - 0xA70007C0, - 0x7D2, - 0x11D3, - {0x9B, 0x1E, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} -}; - -const GUID EAX_FREQUENCYSHIFTER_EFFECT = -{ - 0xDC3E1880, - 0x9212, - 0x11D3, - {0x93, 0x9D, 0x00, 0xC0, 0xF0, 0x2D, 0xD6, 0xF0} -}; - -const GUID EAX_VOCALMORPHER_EFFECT = -{ - 0xE41CF10C, - 0x3383, - 0x11D2, - {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} -}; - -const GUID EAX_PITCHSHIFTER_EFFECT = -{ - 0xE7905100, - 0xAFB2, - 0x11D2, - {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} -}; - -const GUID EAX_RINGMODULATOR_EFFECT = -{ - 0xB89FE60, - 0xAFB5, - 0x11D2, - {0x88, 0xDD, 0x00, 0xA0, 0x24, 0xD1, 0x3C, 0xE1} -}; - - -bool operator==( - const EAX40CONTEXTPROPERTIES& lhs, - const EAX40CONTEXTPROPERTIES& rhs) noexcept -{ - return - lhs.guidPrimaryFXSlotID == rhs.guidPrimaryFXSlotID && - lhs.flDistanceFactor == rhs.flDistanceFactor && - lhs.flAirAbsorptionHF == rhs.flAirAbsorptionHF && - lhs.flHFReference == rhs.flHFReference; -} - -bool operator==( - const EAX50CONTEXTPROPERTIES& lhs, - const EAX50CONTEXTPROPERTIES& rhs) noexcept -{ - return - static_cast(lhs) == static_cast(rhs) && - lhs.flMacroFXFactor == rhs.flMacroFXFactor; -} - - -const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX40_FXSlot0; - -bool operator==( - const EAX40FXSLOTPROPERTIES& lhs, - const EAX40FXSLOTPROPERTIES& rhs) noexcept -{ - return - lhs.guidLoadEffect == rhs.guidLoadEffect && - lhs.lVolume == rhs.lVolume && - lhs.lLock == rhs.lLock && - lhs.ulFlags == rhs.ulFlags; -} - -bool operator==( - const EAX50FXSLOTPROPERTIES& lhs, - const EAX50FXSLOTPROPERTIES& rhs) noexcept -{ - return - static_cast(lhs) == static_cast(rhs) && - lhs.lOcclusion == rhs.lOcclusion && - lhs.flOcclusionLFRatio == rhs.flOcclusionLFRatio; -} - -const EAX50ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS -{{ - EAX_NULL_GUID, - EAXPROPERTYID_EAX40_FXSlot0, -}}; - -bool operator==( - const EAX50ACTIVEFXSLOTS& lhs, - const EAX50ACTIVEFXSLOTS& rhs) noexcept -{ - return std::equal( - std::cbegin(lhs.guidActiveFXSlots), - std::cend(lhs.guidActiveFXSlots), - std::begin(rhs.guidActiveFXSlots)); -} - -bool operator!=( - const EAX50ACTIVEFXSLOTS& lhs, - const EAX50ACTIVEFXSLOTS& rhs) noexcept -{ - return !(lhs == rhs); -} - - -const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS -{{ - EAX_NULL_GUID, - EAX_PrimaryFXSlotID, - EAX_NULL_GUID, - EAX_NULL_GUID, -}}; - - -const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS -{{ - EAX_NULL_GUID, - EAX_NULL_GUID, - EAX_NULL_GUID, - EAX_NULL_GUID, -}}; - -bool operator==( - const EAXREVERBPROPERTIES& lhs, - const EAXREVERBPROPERTIES& rhs) noexcept -{ - return - lhs.ulEnvironment == rhs.ulEnvironment && - lhs.flEnvironmentSize == rhs.flEnvironmentSize && - lhs.flEnvironmentDiffusion == rhs.flEnvironmentDiffusion && - lhs.lRoom == rhs.lRoom && - lhs.lRoomHF == rhs.lRoomHF && - lhs.lRoomLF == rhs.lRoomLF && - lhs.flDecayTime == rhs.flDecayTime && - lhs.flDecayHFRatio == rhs.flDecayHFRatio && - lhs.flDecayLFRatio == rhs.flDecayLFRatio && - lhs.lReflections == rhs.lReflections && - lhs.flReflectionsDelay == rhs.flReflectionsDelay && - lhs.vReflectionsPan == rhs.vReflectionsPan && - lhs.lReverb == rhs.lReverb && - lhs.flReverbDelay == rhs.flReverbDelay && - lhs.vReverbPan == rhs.vReverbPan && - lhs.flEchoTime == rhs.flEchoTime && - lhs.flEchoDepth == rhs.flEchoDepth && - lhs.flModulationTime == rhs.flModulationTime && - lhs.flModulationDepth == rhs.flModulationDepth && - lhs.flAirAbsorptionHF == rhs.flAirAbsorptionHF && - lhs.flHFReference == rhs.flHFReference && - lhs.flLFReference == rhs.flLFReference && - lhs.flRoomRolloffFactor == rhs.flRoomRolloffFactor && - lhs.ulFlags == rhs.ulFlags; -} - -bool operator!=( - const EAXREVERBPROPERTIES& lhs, - const EAXREVERBPROPERTIES& rhs) noexcept -{ - return !(lhs == rhs); -} - - -namespace { - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_GENERIC = -{ - EAXREVERB_DEFAULTENVIRONMENT, - EAXREVERB_DEFAULTENVIRONMENTSIZE, - EAXREVERB_DEFAULTENVIRONMENTDIFFUSION, - EAXREVERB_DEFAULTROOM, - EAXREVERB_DEFAULTROOMHF, - EAXREVERB_DEFAULTROOMLF, - EAXREVERB_DEFAULTDECAYTIME, - EAXREVERB_DEFAULTDECAYHFRATIO, - EAXREVERB_DEFAULTDECAYLFRATIO, - EAXREVERB_DEFAULTREFLECTIONS, - EAXREVERB_DEFAULTREFLECTIONSDELAY, - EAXREVERB_DEFAULTREFLECTIONSPAN, - EAXREVERB_DEFAULTREVERB, - EAXREVERB_DEFAULTREVERBDELAY, - EAXREVERB_DEFAULTREVERBPAN, - EAXREVERB_DEFAULTECHOTIME, - EAXREVERB_DEFAULTECHODEPTH, - EAXREVERB_DEFAULTMODULATIONTIME, - EAXREVERB_DEFAULTMODULATIONDEPTH, - EAXREVERB_DEFAULTAIRABSORPTIONHF, - EAXREVERB_DEFAULTHFREFERENCE, - EAXREVERB_DEFAULTLFREFERENCE, - EAXREVERB_DEFAULTROOMROLLOFFFACTOR, - EAXREVERB_DEFAULTFLAGS, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_PADDEDCELL = -{ - EAX_ENVIRONMENT_PADDEDCELL, - 1.4F, - 1.0F, - -1'000L, - -6'000L, - 0L, - 0.17F, - 0.10F, - 1.0F, - -1'204L, - 0.001F, - EAXVECTOR{}, - 207L, - 0.002F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_ROOM = -{ - EAX_ENVIRONMENT_ROOM, - 1.9F, - 1.0F, - -1'000L, - -454L, - 0L, - 0.40F, - 0.83F, - 1.0F, - -1'646L, - 0.002F, - EAXVECTOR{}, - 53L, - 0.003F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_BATHROOM = -{ - EAX_ENVIRONMENT_BATHROOM, - 1.4F, - 1.0F, - -1'000L, - -1'200L, - 0L, - 1.49F, - 0.54F, - 1.0F, - -370L, - 0.007F, - EAXVECTOR{}, - 1'030L, - 0.011F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_LIVINGROOM = -{ - EAX_ENVIRONMENT_LIVINGROOM, - 2.5F, - 1.0F, - -1'000L, - -6'000L, - 0L, - 0.50F, - 0.10F, - 1.0F, - -1'376, - 0.003F, - EAXVECTOR{}, - -1'104L, - 0.004F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_STONEROOM = -{ - EAX_ENVIRONMENT_STONEROOM, - 11.6F, - 1.0F, - -1'000L, - -300L, - 0L, - 2.31F, - 0.64F, - 1.0F, - -711L, - 0.012F, - EAXVECTOR{}, - 83L, - 0.017F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_AUDITORIUM = -{ - EAX_ENVIRONMENT_AUDITORIUM, - 21.6F, - 1.0F, - -1'000L, - -476L, - 0L, - 4.32F, - 0.59F, - 1.0F, - -789L, - 0.020F, - EAXVECTOR{}, - -289L, - 0.030F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_CONCERTHALL = -{ - EAX_ENVIRONMENT_CONCERTHALL, - 19.6F, - 1.0F, - -1'000L, - -500L, - 0L, - 3.92F, - 0.70F, - 1.0F, - -1'230L, - 0.020F, - EAXVECTOR{}, - -2L, - 0.029F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_CAVE = -{ - EAX_ENVIRONMENT_CAVE, - 14.6F, - 1.0F, - -1'000L, - 0L, - 0L, - 2.91F, - 1.30F, - 1.0F, - -602L, - 0.015F, - EAXVECTOR{}, - -302L, - 0.022F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x1FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_ARENA = -{ - EAX_ENVIRONMENT_ARENA, - 36.2F, - 1.0F, - -1'000L, - -698L, - 0L, - 7.24F, - 0.33F, - 1.0F, - -1'166L, - 0.020F, - EAXVECTOR{}, - 16L, - 0.030F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_HANGAR = -{ - EAX_ENVIRONMENT_HANGAR, - 50.3F, - 1.0F, - -1'000L, - -1'000L, - 0L, - 10.05F, - 0.23F, - 1.0F, - -602L, - 0.020F, - EAXVECTOR{}, - 198L, - 0.030F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_CARPETTEDHALLWAY = -{ - EAX_ENVIRONMENT_CARPETEDHALLWAY, - 1.9F, - 1.0F, - -1'000L, - -4'000L, - 0L, - 0.30F, - 0.10F, - 1.0F, - -1'831L, - 0.002F, - EAXVECTOR{}, - -1'630L, - 0.030F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_HALLWAY = -{ - EAX_ENVIRONMENT_HALLWAY, - 1.8F, - 1.0F, - -1'000L, - -300L, - 0L, - 1.49F, - 0.59F, - 1.0F, - -1'219L, - 0.007F, - EAXVECTOR{}, - 441L, - 0.011F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_STONECORRIDOR = -{ - EAX_ENVIRONMENT_STONECORRIDOR, - 13.5F, - 1.0F, - -1'000L, - -237L, - 0L, - 2.70F, - 0.79F, - 1.0F, - -1'214L, - 0.013F, - EAXVECTOR{}, - 395L, - 0.020F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_ALLEY = -{ - EAX_ENVIRONMENT_ALLEY, - 7.5F, - 0.300F, - -1'000L, - -270L, - 0L, - 1.49F, - 0.86F, - 1.0F, - -1'204L, - 0.007F, - EAXVECTOR{}, - -4L, - 0.011F, - EAXVECTOR{}, - 0.125F, - 0.950F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_FOREST = -{ - EAX_ENVIRONMENT_FOREST, - 38.0F, - 0.300F, - -1'000L, - -3'300L, - 0L, - 1.49F, - 0.54F, - 1.0F, - -2'560L, - 0.162F, - EAXVECTOR{}, - -229L, - 0.088F, - EAXVECTOR{}, - 0.125F, - 1.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_CITY = -{ - EAX_ENVIRONMENT_CITY, - 7.5F, - 0.500F, - -1'000L, - -800L, - 0L, - 1.49F, - 0.67F, - 1.0F, - -2'273L, - 0.007F, - EAXVECTOR{}, - -1'691L, - 0.011F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_MOUNTAINS = -{ - EAX_ENVIRONMENT_MOUNTAINS, - 100.0F, - 0.270F, - -1'000L, - -2'500L, - 0L, - 1.49F, - 0.21F, - 1.0F, - -2'780L, - 0.300F, - EAXVECTOR{}, - -1'434L, - 0.100F, - EAXVECTOR{}, - 0.250F, - 1.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x1FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_QUARRY = -{ - EAX_ENVIRONMENT_QUARRY, - 17.5F, - 1.0F, - -1'000L, - -1'000L, - 0L, - 1.49F, - 0.83F, - 1.0F, - -10'000L, - 0.061F, - EAXVECTOR{}, - 500L, - 0.025F, - EAXVECTOR{}, - 0.125F, - 0.700F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_PLAIN = -{ - EAX_ENVIRONMENT_PLAIN, - 42.5F, - 0.210F, - -1'000L, - -2'000L, - 0L, - 1.49F, - 0.50F, - 1.0F, - -2'466L, - 0.179F, - EAXVECTOR{}, - -1'926L, - 0.100F, - EAXVECTOR{}, - 0.250F, - 1.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_PARKINGLOT = -{ - EAX_ENVIRONMENT_PARKINGLOT, - 8.3F, - 1.0F, - -1'000L, - 0L, - 0L, - 1.65F, - 1.50F, - 1.0F, - -1'363L, - 0.008F, - EAXVECTOR{}, - -1'153L, - 0.012F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x1FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_SEWERPIPE = -{ - EAX_ENVIRONMENT_SEWERPIPE, - 1.7F, - 0.800F, - -1'000L, - -1'000L, - 0L, - 2.81F, - 0.14F, - 1.0F, - 429L, - 0.014F, - EAXVECTOR{}, - 1'023L, - 0.021F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 0.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_UNDERWATER = -{ - EAX_ENVIRONMENT_UNDERWATER, - 1.8F, - 1.0F, - -1'000L, - -4'000L, - 0L, - 1.49F, - 0.10F, - 1.0F, - -449L, - 0.007F, - EAXVECTOR{}, - 1'700L, - 0.011F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 1.180F, - 0.348F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x3FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_DRUGGED = -{ - EAX_ENVIRONMENT_DRUGGED, - 1.9F, - 0.500F, - -1'000L, - 0L, - 0L, - 8.39F, - 1.39F, - 1.0F, - -115L, - 0.002F, - EAXVECTOR{}, - 985L, - 0.030F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 0.250F, - 1.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x1FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_DIZZY = -{ - EAX_ENVIRONMENT_DIZZY, - 1.8F, - 0.600F, - -1'000L, - -400L, - 0L, - 17.23F, - 0.56F, - 1.0F, - -1'713L, - 0.020F, - EAXVECTOR{}, - -613L, - 0.030F, - EAXVECTOR{}, - 0.250F, - 1.0F, - 0.810F, - 0.310F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x1FUL, -}; - -constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_PSYCHOTIC = -{ - EAX_ENVIRONMENT_PSYCHOTIC, - 1.0F, - 0.500F, - -1'000L, - -151L, - 0L, - 7.56F, - 0.91F, - 1.0F, - -626L, - 0.020F, - EAXVECTOR{}, - 774L, - 0.030F, - EAXVECTOR{}, - 0.250F, - 0.0F, - 4.0F, - 1.0F, - -5.0F, - 5'000.0F, - 250.0F, - 0.0F, - 0x1FUL, -}; - -} // namespace - -const EaxReverbPresets EAXREVERB_PRESETS{{ - EAXREVERB_PRESET_GENERIC, - EAXREVERB_PRESET_PADDEDCELL, - EAXREVERB_PRESET_ROOM, - EAXREVERB_PRESET_BATHROOM, - EAXREVERB_PRESET_LIVINGROOM, - EAXREVERB_PRESET_STONEROOM, - EAXREVERB_PRESET_AUDITORIUM, - EAXREVERB_PRESET_CONCERTHALL, - EAXREVERB_PRESET_CAVE, - EAXREVERB_PRESET_ARENA, - EAXREVERB_PRESET_HANGAR, - EAXREVERB_PRESET_CARPETTEDHALLWAY, - EAXREVERB_PRESET_HALLWAY, - EAXREVERB_PRESET_STONECORRIDOR, - EAXREVERB_PRESET_ALLEY, - EAXREVERB_PRESET_FOREST, - EAXREVERB_PRESET_CITY, - EAXREVERB_PRESET_MOUNTAINS, - EAXREVERB_PRESET_QUARRY, - EAXREVERB_PRESET_PLAIN, - EAXREVERB_PRESET_PARKINGLOT, - EAXREVERB_PRESET_SEWERPIPE, - EAXREVERB_PRESET_UNDERWATER, - EAXREVERB_PRESET_DRUGGED, - EAXREVERB_PRESET_DIZZY, - EAXREVERB_PRESET_PSYCHOTIC, -}}; - -namespace { -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_GENERIC = {EAX_ENVIRONMENT_GENERIC, 0.5F, 1.493F, 0.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PADDEDCELL = {EAX_ENVIRONMENT_PADDEDCELL, 0.25F, 0.1F, 0.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ROOM = {EAX_ENVIRONMENT_ROOM, 0.417F, 0.4F, 0.666F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_BATHROOM = {EAX_ENVIRONMENT_BATHROOM, 0.653F, 1.499F, 0.166F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_LIVINGROOM = {EAX_ENVIRONMENT_LIVINGROOM, 0.208F, 0.478F, 0.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONEROOM = {EAX_ENVIRONMENT_STONEROOM, 0.5F, 2.309F, 0.888F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_AUDITORIUM = {EAX_ENVIRONMENT_AUDITORIUM, 0.403F, 4.279F, 0.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CONCERTHALL = {EAX_ENVIRONMENT_CONCERTHALL, 0.5F, 3.961F, 0.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CAVE = {EAX_ENVIRONMENT_CAVE, 0.5F, 2.886F, 1.304F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ARENA = {EAX_ENVIRONMENT_ARENA, 0.361F, 7.284F, 0.332F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HANGAR = {EAX_ENVIRONMENT_HANGAR, 0.5F, 10.0F, 0.3F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CARPETTEDHALLWAY = {EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153F, 0.259F, 2.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HALLWAY = {EAX_ENVIRONMENT_HALLWAY, 0.361F, 1.493F, 0.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONECORRIDOR = {EAX_ENVIRONMENT_STONECORRIDOR, 0.444F, 2.697F, 0.638F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ALLEY = {EAX_ENVIRONMENT_ALLEY, 0.25F, 1.752F, 0.776F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_FOREST = {EAX_ENVIRONMENT_FOREST, 0.111F, 3.145F, 0.472F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CITY = {EAX_ENVIRONMENT_CITY, 0.111F, 2.767F, 0.224F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_MOUNTAINS = {EAX_ENVIRONMENT_MOUNTAINS, 0.194F, 7.841F, 0.472F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_QUARRY = {EAX_ENVIRONMENT_QUARRY, 1.0F, 1.499F, 0.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PLAIN = {EAX_ENVIRONMENT_PLAIN, 0.097F, 2.767F, 0.224F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PARKINGLOT = {EAX_ENVIRONMENT_PARKINGLOT, 0.208F, 1.652F, 1.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_SEWERPIPE = {EAX_ENVIRONMENT_SEWERPIPE, 0.652F, 2.886F, 0.25F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_UNDERWATER = {EAX_ENVIRONMENT_UNDERWATER, 1.0F, 1.499F, 0.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DRUGGED = {EAX_ENVIRONMENT_DRUGGED, 0.875F, 8.392F, 1.388F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DIZZY = {EAX_ENVIRONMENT_DIZZY, 0.139F, 17.234F, 0.666F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PSYCHOTIC = {EAX_ENVIRONMENT_PSYCHOTIC, 0.486F, 7.563F, 0.806F}; -} // namespace - -const Eax1ReverbPresets EAX1REVERB_PRESETS{{ - EAX1REVERB_PRESET_GENERIC, - EAX1REVERB_PRESET_PADDEDCELL, - EAX1REVERB_PRESET_ROOM, - EAX1REVERB_PRESET_BATHROOM, - EAX1REVERB_PRESET_LIVINGROOM, - EAX1REVERB_PRESET_STONEROOM, - EAX1REVERB_PRESET_AUDITORIUM, - EAX1REVERB_PRESET_CONCERTHALL, - EAX1REVERB_PRESET_CAVE, - EAX1REVERB_PRESET_ARENA, - EAX1REVERB_PRESET_HANGAR, - EAX1REVERB_PRESET_CARPETTEDHALLWAY, - EAX1REVERB_PRESET_HALLWAY, - EAX1REVERB_PRESET_STONECORRIDOR, - EAX1REVERB_PRESET_ALLEY, - EAX1REVERB_PRESET_FOREST, - EAX1REVERB_PRESET_CITY, - EAX1REVERB_PRESET_MOUNTAINS, - EAX1REVERB_PRESET_QUARRY, - EAX1REVERB_PRESET_PLAIN, - EAX1REVERB_PRESET_PARKINGLOT, - EAX1REVERB_PRESET_SEWERPIPE, - EAX1REVERB_PRESET_UNDERWATER, - EAX1REVERB_PRESET_DRUGGED, - EAX1REVERB_PRESET_DIZZY, - EAX1REVERB_PRESET_PSYCHOTIC, -}}; diff --git a/al/eax_api.h b/al/eax_api.h deleted file mode 100644 index d0737d1d..00000000 --- a/al/eax_api.h +++ /dev/null @@ -1,1557 +0,0 @@ -#ifndef EAX_API_INCLUDED -#define EAX_API_INCLUDED - - -// -// EAX API. -// -// Based on headers `eax[2-5].h` included in Doom 3 source code: -// https://github.com/id-Software/DOOM-3/tree/master/neo/openal/include -// - - -#include -#include -#include - -#include - -#include "AL/al.h" - - -#ifndef GUID_DEFINED -#define GUID_DEFINED -typedef struct _GUID -{ - std::uint32_t Data1; - std::uint16_t Data2; - std::uint16_t Data3; - std::uint8_t Data4[8]; -} GUID; - -inline bool operator==(const GUID& lhs, const GUID& rhs) noexcept -{ - return std::memcmp(&lhs, &rhs, sizeof(GUID)) == 0; -} - -inline bool operator!=(const GUID& lhs, const GUID& rhs) noexcept -{ - return !(lhs == rhs); -} -#endif // GUID_DEFINED - - -extern const GUID DSPROPSETID_EAX_ReverbProperties; - -enum DSPROPERTY_EAX_REVERBPROPERTY : unsigned int -{ - DSPROPERTY_EAX_ALL, - DSPROPERTY_EAX_ENVIRONMENT, - DSPROPERTY_EAX_VOLUME, - DSPROPERTY_EAX_DECAYTIME, - DSPROPERTY_EAX_DAMPING, -}; // DSPROPERTY_EAX_REVERBPROPERTY - -struct EAX_REVERBPROPERTIES -{ - unsigned long environment; - float fVolume; - float fDecayTime_sec; - float fDamping; -}; // EAX_REVERBPROPERTIES - -inline bool operator==(const EAX_REVERBPROPERTIES& lhs, const EAX_REVERBPROPERTIES& rhs) noexcept -{ - return std::memcmp(&lhs, &rhs, sizeof(EAX_REVERBPROPERTIES)) == 0; -} - -extern const GUID DSPROPSETID_EAXBUFFER_ReverbProperties; - -enum DSPROPERTY_EAXBUFFER_REVERBPROPERTY : unsigned int -{ - DSPROPERTY_EAXBUFFER_ALL, - DSPROPERTY_EAXBUFFER_REVERBMIX, -}; // DSPROPERTY_EAXBUFFER_REVERBPROPERTY - -struct EAXBUFFER_REVERBPROPERTIES -{ - float fMix; -}; - -inline bool operator==(const EAXBUFFER_REVERBPROPERTIES& lhs, const EAXBUFFER_REVERBPROPERTIES& rhs) noexcept -{ - return lhs.fMix == rhs.fMix; -} - -constexpr auto EAX_BUFFER_MINREVERBMIX = 0.0F; -constexpr auto EAX_BUFFER_MAXREVERBMIX = 1.0F; -constexpr auto EAX_REVERBMIX_USEDISTANCE = -1.0F; - - -extern const GUID DSPROPSETID_EAX20_ListenerProperties; - -enum DSPROPERTY_EAX20_LISTENERPROPERTY : - unsigned int -{ - DSPROPERTY_EAX20LISTENER_NONE, - DSPROPERTY_EAX20LISTENER_ALLPARAMETERS, - DSPROPERTY_EAX20LISTENER_ROOM, - DSPROPERTY_EAX20LISTENER_ROOMHF, - DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAX20LISTENER_DECAYTIME, - DSPROPERTY_EAX20LISTENER_DECAYHFRATIO, - DSPROPERTY_EAX20LISTENER_REFLECTIONS, - DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY, - DSPROPERTY_EAX20LISTENER_REVERB, - DSPROPERTY_EAX20LISTENER_REVERBDELAY, - DSPROPERTY_EAX20LISTENER_ENVIRONMENT, - DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE, - DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION, - DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF, - DSPROPERTY_EAX20LISTENER_FLAGS -}; // DSPROPERTY_EAX20_LISTENERPROPERTY - -struct EAX20LISTENERPROPERTIES -{ - long lRoom; // room effect level at low frequencies - long lRoomHF; // room effect high-frequency level re. low frequency level - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - float flDecayTime; // reverberation decay time at low frequencies - float flDecayHFRatio; // high-frequency to low-frequency decay time ratio - long lReflections; // early reflections level relative to room effect - float flReflectionsDelay; // initial reflection delay time - long lReverb; // late reverberation level relative to room effect - float flReverbDelay; // late reverberation delay time relative to initial reflection - unsigned long dwEnvironment; // sets all listener properties - float flEnvironmentSize; // environment size in meters - float flEnvironmentDiffusion; // environment diffusion - float flAirAbsorptionHF; // change in level per meter at 5 kHz - unsigned long dwFlags; // modifies the behavior of properties -}; // EAX20LISTENERPROPERTIES - - -extern const GUID DSPROPSETID_EAX20_BufferProperties; - - -enum DSPROPERTY_EAX20_BUFFERPROPERTY : - unsigned int -{ - DSPROPERTY_EAX20BUFFER_NONE, - DSPROPERTY_EAX20BUFFER_ALLPARAMETERS, - DSPROPERTY_EAX20BUFFER_DIRECT, - DSPROPERTY_EAX20BUFFER_DIRECTHF, - DSPROPERTY_EAX20BUFFER_ROOM, - DSPROPERTY_EAX20BUFFER_ROOMHF, - DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAX20BUFFER_OBSTRUCTION, - DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO, - DSPROPERTY_EAX20BUFFER_OCCLUSION, - DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO, - DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO, - DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF, - DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR, - DSPROPERTY_EAX20BUFFER_FLAGS -}; // DSPROPERTY_EAX20_BUFFERPROPERTY - - -struct EAX20BUFFERPROPERTIES -{ - long lDirect; // direct path level - long lDirectHF; // direct path level at high frequencies - long lRoom; // room effect level - long lRoomHF; // room effect level at high frequencies - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - long lObstruction; // main obstruction control (attenuation at high frequencies) - float flObstructionLFRatio; // obstruction low-frequency level re. main control - long lOcclusion; // main occlusion control (attenuation at high frequencies) - float flOcclusionLFRatio; // occlusion low-frequency level re. main control - float flOcclusionRoomRatio; // occlusion room effect level re. main control - long lOutsideVolumeHF; // outside sound cone level at high frequencies - float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF - unsigned long dwFlags; // modifies the behavior of properties -}; // EAX20BUFFERPROPERTIES - - -extern const GUID DSPROPSETID_EAX30_ListenerProperties; - -extern const GUID DSPROPSETID_EAX30_BufferProperties; - - -constexpr auto EAX_MAX_FXSLOTS = 4; - -constexpr auto EAX40_MAX_ACTIVE_FXSLOTS = 2; -constexpr auto EAX50_MAX_ACTIVE_FXSLOTS = 4; - - -constexpr auto EAX_OK = 0L; -constexpr auto EAXERR_INVALID_OPERATION = -1L; -constexpr auto EAXERR_INVALID_VALUE = -2L; -constexpr auto EAXERR_NO_EFFECT_LOADED = -3L; -constexpr auto EAXERR_UNKNOWN_EFFECT = -4L; -constexpr auto EAXERR_INCOMPATIBLE_SOURCE_TYPE = -5L; -constexpr auto EAXERR_INCOMPATIBLE_EAX_VERSION = -6L; - - -extern const GUID EAX_NULL_GUID; - -extern const GUID EAX_PrimaryFXSlotID; - - -struct EAXVECTOR -{ - float x; - float y; - float z; -}; // EAXVECTOR - -inline bool operator==(const EAXVECTOR& lhs, const EAXVECTOR& rhs) noexcept -{ return std::memcmp(&lhs, &rhs, sizeof(EAXVECTOR)) == 0; } - -inline bool operator!=(const EAXVECTOR& lhs, const EAXVECTOR& rhs) noexcept -{ return !(lhs == rhs); } - - -extern const GUID EAXPROPERTYID_EAX40_Context; - -extern const GUID EAXPROPERTYID_EAX50_Context; - -// EAX50 -enum : - unsigned long -{ - HEADPHONES = 0, - SPEAKERS_2, - SPEAKERS_4, - SPEAKERS_5, // 5.1 speakers - SPEAKERS_6, // 6.1 speakers - SPEAKERS_7, // 7.1 speakers -}; - -// EAX50 -enum : - unsigned long -{ - EAX_40 = 5, // EAX 4.0 - EAX_50 = 6, // EAX 5.0 -}; - -constexpr auto EAXCONTEXT_MINEAXSESSION = EAX_40; -constexpr auto EAXCONTEXT_MAXEAXSESSION = EAX_50; -constexpr auto EAXCONTEXT_DEFAULTEAXSESSION = EAX_40; - -constexpr auto EAXCONTEXT_MINMAXACTIVESENDS = 2UL; -constexpr auto EAXCONTEXT_MAXMAXACTIVESENDS = 4UL; -constexpr auto EAXCONTEXT_DEFAULTMAXACTIVESENDS = 2UL; - -// EAX50 -struct EAXSESSIONPROPERTIES -{ - unsigned long ulEAXVersion; - unsigned long ulMaxActiveSends; -}; // EAXSESSIONPROPERTIES - -enum EAXCONTEXT_PROPERTY : - unsigned int -{ - EAXCONTEXT_NONE = 0, - EAXCONTEXT_ALLPARAMETERS, - EAXCONTEXT_PRIMARYFXSLOTID, - EAXCONTEXT_DISTANCEFACTOR, - EAXCONTEXT_AIRABSORPTIONHF, - EAXCONTEXT_HFREFERENCE, - EAXCONTEXT_LASTERROR, - - // EAX50 - EAXCONTEXT_SPEAKERCONFIG, - EAXCONTEXT_EAXSESSION, - EAXCONTEXT_MACROFXFACTOR, -}; // EAXCONTEXT_PROPERTY - -struct EAX40CONTEXTPROPERTIES -{ - GUID guidPrimaryFXSlotID; - float flDistanceFactor; - float flAirAbsorptionHF; - float flHFReference; -}; // EAX40CONTEXTPROPERTIES - -struct EAX50CONTEXTPROPERTIES : - public EAX40CONTEXTPROPERTIES -{ - float flMacroFXFactor; -}; // EAX40CONTEXTPROPERTIES - - -bool operator==( - const EAX40CONTEXTPROPERTIES& lhs, - const EAX40CONTEXTPROPERTIES& rhs) noexcept; - -bool operator==( - const EAX50CONTEXTPROPERTIES& lhs, - const EAX50CONTEXTPROPERTIES& rhs) noexcept; - - -constexpr auto EAXCONTEXT_MINDISTANCEFACTOR = FLT_MIN; -constexpr auto EAXCONTEXT_MAXDISTANCEFACTOR = FLT_MAX; -constexpr auto EAXCONTEXT_DEFAULTDISTANCEFACTOR = 1.0F; - -constexpr auto EAXCONTEXT_MINAIRABSORPTIONHF = -100.0F; -constexpr auto EAXCONTEXT_MAXAIRABSORPTIONHF = 0.0F; -constexpr auto EAXCONTEXT_DEFAULTAIRABSORPTIONHF = -5.0F; - -constexpr auto EAXCONTEXT_MINHFREFERENCE = 1000.0F; -constexpr auto EAXCONTEXT_MAXHFREFERENCE = 20000.0F; -constexpr auto EAXCONTEXT_DEFAULTHFREFERENCE = 5000.0F; - -constexpr auto EAXCONTEXT_MINMACROFXFACTOR = 0.0F; -constexpr auto EAXCONTEXT_MAXMACROFXFACTOR = 1.0F; -constexpr auto EAXCONTEXT_DEFAULTMACROFXFACTOR = 0.0F; - - -extern const GUID EAXPROPERTYID_EAX40_FXSlot0; - -extern const GUID EAXPROPERTYID_EAX50_FXSlot0; - -extern const GUID EAXPROPERTYID_EAX40_FXSlot1; - -extern const GUID EAXPROPERTYID_EAX50_FXSlot1; - -extern const GUID EAXPROPERTYID_EAX40_FXSlot2; - -extern const GUID EAXPROPERTYID_EAX50_FXSlot2; - -extern const GUID EAXPROPERTYID_EAX40_FXSlot3; - -extern const GUID EAXPROPERTYID_EAX50_FXSlot3; - -extern const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID; - -enum EAXFXSLOT_PROPERTY : - unsigned int -{ - EAXFXSLOT_PARAMETER = 0, - - EAXFXSLOT_NONE = 0x10000, - EAXFXSLOT_ALLPARAMETERS, - EAXFXSLOT_LOADEFFECT, - EAXFXSLOT_VOLUME, - EAXFXSLOT_LOCK, - EAXFXSLOT_FLAGS, - - // EAX50 - EAXFXSLOT_OCCLUSION, - EAXFXSLOT_OCCLUSIONLFRATIO, -}; // EAXFXSLOT_PROPERTY - -constexpr auto EAXFXSLOTFLAGS_ENVIRONMENT = 0x00000001UL; -// EAX50 -constexpr auto EAXFXSLOTFLAGS_UPMIX = 0x00000002UL; - -constexpr auto EAX40FXSLOTFLAGS_RESERVED = 0xFFFFFFFEUL; // reserved future use -constexpr auto EAX50FXSLOTFLAGS_RESERVED = 0xFFFFFFFCUL; // reserved future use - - -constexpr auto EAXFXSLOT_MINVOLUME = -10'000L; -constexpr auto EAXFXSLOT_MAXVOLUME = 0L; -constexpr auto EAXFXSLOT_DEFAULTVOLUME = 0L; - -constexpr auto EAXFXSLOT_MINLOCK = 0L; -constexpr auto EAXFXSLOT_MAXLOCK = 1L; - -enum : - long -{ - EAXFXSLOT_UNLOCKED = 0, - EAXFXSLOT_LOCKED = 1 -}; - -constexpr auto EAXFXSLOT_MINOCCLUSION = -10'000L; -constexpr auto EAXFXSLOT_MAXOCCLUSION = 0L; -constexpr auto EAXFXSLOT_DEFAULTOCCLUSION = 0L; - -constexpr auto EAXFXSLOT_MINOCCLUSIONLFRATIO = 0.0F; -constexpr auto EAXFXSLOT_MAXOCCLUSIONLFRATIO = 1.0F; -constexpr auto EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO = 0.25F; - -constexpr auto EAX40FXSLOT_DEFAULTFLAGS = EAXFXSLOTFLAGS_ENVIRONMENT; - -constexpr auto EAX50FXSLOT_DEFAULTFLAGS = - EAXFXSLOTFLAGS_ENVIRONMENT | - EAXFXSLOTFLAGS_UPMIX; // ignored for reverb; - -struct EAX40FXSLOTPROPERTIES -{ - GUID guidLoadEffect; - long lVolume; - long lLock; - unsigned long ulFlags; -}; // EAX40FXSLOTPROPERTIES - -struct EAX50FXSLOTPROPERTIES : - public EAX40FXSLOTPROPERTIES -{ - long lOcclusion; - float flOcclusionLFRatio; -}; // EAX50FXSLOTPROPERTIES - -bool operator==( - const EAX40FXSLOTPROPERTIES& lhs, - const EAX40FXSLOTPROPERTIES& rhs) noexcept; - -bool operator==( - const EAX50FXSLOTPROPERTIES& lhs, - const EAX50FXSLOTPROPERTIES& rhs) noexcept; - -extern const GUID EAXPROPERTYID_EAX40_Source; - -extern const GUID EAXPROPERTYID_EAX50_Source; - -// Source object properties -enum EAXSOURCE_PROPERTY : - unsigned int -{ - // EAX30 - - EAXSOURCE_NONE, - EAXSOURCE_ALLPARAMETERS, - EAXSOURCE_OBSTRUCTIONPARAMETERS, - EAXSOURCE_OCCLUSIONPARAMETERS, - EAXSOURCE_EXCLUSIONPARAMETERS, - EAXSOURCE_DIRECT, - EAXSOURCE_DIRECTHF, - EAXSOURCE_ROOM, - EAXSOURCE_ROOMHF, - EAXSOURCE_OBSTRUCTION, - EAXSOURCE_OBSTRUCTIONLFRATIO, - EAXSOURCE_OCCLUSION, - EAXSOURCE_OCCLUSIONLFRATIO, - EAXSOURCE_OCCLUSIONROOMRATIO, - EAXSOURCE_OCCLUSIONDIRECTRATIO, - EAXSOURCE_EXCLUSION, - EAXSOURCE_EXCLUSIONLFRATIO, - EAXSOURCE_OUTSIDEVOLUMEHF, - EAXSOURCE_DOPPLERFACTOR, - EAXSOURCE_ROLLOFFFACTOR, - EAXSOURCE_ROOMROLLOFFFACTOR, - EAXSOURCE_AIRABSORPTIONFACTOR, - EAXSOURCE_FLAGS, - - // EAX40 - - EAXSOURCE_SENDPARAMETERS, - EAXSOURCE_ALLSENDPARAMETERS, - EAXSOURCE_OCCLUSIONSENDPARAMETERS, - EAXSOURCE_EXCLUSIONSENDPARAMETERS, - EAXSOURCE_ACTIVEFXSLOTID, - - // EAX50 - - EAXSOURCE_MACROFXFACTOR, - EAXSOURCE_SPEAKERLEVELS, - EAXSOURCE_ALL2DPARAMETERS, -}; // EAXSOURCE_PROPERTY - - -constexpr auto EAXSOURCEFLAGS_DIRECTHFAUTO = 0x00000001UL; // relates to EAXSOURCE_DIRECTHF -constexpr auto EAXSOURCEFLAGS_ROOMAUTO = 0x00000002UL; // relates to EAXSOURCE_ROOM -constexpr auto EAXSOURCEFLAGS_ROOMHFAUTO = 0x00000004UL; // relates to EAXSOURCE_ROOMHF -// EAX50 -constexpr auto EAXSOURCEFLAGS_3DELEVATIONFILTER = 0x00000008UL; -// EAX50 -constexpr auto EAXSOURCEFLAGS_UPMIX = 0x00000010UL; -// EAX50 -constexpr auto EAXSOURCEFLAGS_APPLYSPEAKERLEVELS = 0x00000020UL; - -constexpr auto EAX20SOURCEFLAGS_RESERVED = 0xFFFFFFF8UL; // reserved future use -constexpr auto EAX50SOURCEFLAGS_RESERVED = 0xFFFFFFC0UL; // reserved future use - - -constexpr auto EAXSOURCE_MINSEND = -10'000L; -constexpr auto EAXSOURCE_MAXSEND = 0L; -constexpr auto EAXSOURCE_DEFAULTSEND = 0L; - -constexpr auto EAXSOURCE_MINSENDHF = -10'000L; -constexpr auto EAXSOURCE_MAXSENDHF = 0L; -constexpr auto EAXSOURCE_DEFAULTSENDHF = 0L; - -constexpr auto EAXSOURCE_MINDIRECT = -10'000L; -constexpr auto EAXSOURCE_MAXDIRECT = 1'000L; -constexpr auto EAXSOURCE_DEFAULTDIRECT = 0L; - -constexpr auto EAXSOURCE_MINDIRECTHF = -10'000L; -constexpr auto EAXSOURCE_MAXDIRECTHF = 0L; -constexpr auto EAXSOURCE_DEFAULTDIRECTHF = 0L; - -constexpr auto EAXSOURCE_MINROOM = -10'000L; -constexpr auto EAXSOURCE_MAXROOM = 1'000L; -constexpr auto EAXSOURCE_DEFAULTROOM = 0L; - -constexpr auto EAXSOURCE_MINROOMHF = -10'000L; -constexpr auto EAXSOURCE_MAXROOMHF = 0L; -constexpr auto EAXSOURCE_DEFAULTROOMHF = 0L; - -constexpr auto EAXSOURCE_MINOBSTRUCTION = -10'000L; -constexpr auto EAXSOURCE_MAXOBSTRUCTION = 0L; -constexpr auto EAXSOURCE_DEFAULTOBSTRUCTION = 0L; - -constexpr auto EAXSOURCE_MINOBSTRUCTIONLFRATIO = 0.0F; -constexpr auto EAXSOURCE_MAXOBSTRUCTIONLFRATIO = 1.0F; -constexpr auto EAXSOURCE_DEFAULTOBSTRUCTIONLFRATIO = 0.0F; - -constexpr auto EAXSOURCE_MINOCCLUSION = -10'000L; -constexpr auto EAXSOURCE_MAXOCCLUSION = 0L; -constexpr auto EAXSOURCE_DEFAULTOCCLUSION = 0L; - -constexpr auto EAXSOURCE_MINOCCLUSIONLFRATIO = 0.0F; -constexpr auto EAXSOURCE_MAXOCCLUSIONLFRATIO = 1.0F; -constexpr auto EAXSOURCE_DEFAULTOCCLUSIONLFRATIO = 0.25F; - -constexpr auto EAXSOURCE_MINOCCLUSIONROOMRATIO = 0.0F; -constexpr auto EAXSOURCE_MAXOCCLUSIONROOMRATIO = 10.0F; -constexpr auto EAXSOURCE_DEFAULTOCCLUSIONROOMRATIO = 1.5F; - -constexpr auto EAXSOURCE_MINOCCLUSIONDIRECTRATIO = 0.0F; -constexpr auto EAXSOURCE_MAXOCCLUSIONDIRECTRATIO = 10.0F; -constexpr auto EAXSOURCE_DEFAULTOCCLUSIONDIRECTRATIO = 1.0F; - -constexpr auto EAXSOURCE_MINEXCLUSION = -10'000L; -constexpr auto EAXSOURCE_MAXEXCLUSION = 0L; -constexpr auto EAXSOURCE_DEFAULTEXCLUSION = 0L; - -constexpr auto EAXSOURCE_MINEXCLUSIONLFRATIO = 0.0F; -constexpr auto EAXSOURCE_MAXEXCLUSIONLFRATIO = 1.0F; -constexpr auto EAXSOURCE_DEFAULTEXCLUSIONLFRATIO = 1.0F; - -constexpr auto EAXSOURCE_MINOUTSIDEVOLUMEHF = -10'000L; -constexpr auto EAXSOURCE_MAXOUTSIDEVOLUMEHF = 0L; -constexpr auto EAXSOURCE_DEFAULTOUTSIDEVOLUMEHF = 0L; - -constexpr auto EAXSOURCE_MINDOPPLERFACTOR = 0.0F; -constexpr auto EAXSOURCE_MAXDOPPLERFACTOR = 10.0F; -constexpr auto EAXSOURCE_DEFAULTDOPPLERFACTOR = 1.0F; - -constexpr auto EAXSOURCE_MINROLLOFFFACTOR = 0.0F; -constexpr auto EAXSOURCE_MAXROLLOFFFACTOR = 10.0F; -constexpr auto EAXSOURCE_DEFAULTROLLOFFFACTOR = 0.0F; - -constexpr auto EAXSOURCE_MINROOMROLLOFFFACTOR = 0.0F; -constexpr auto EAXSOURCE_MAXROOMROLLOFFFACTOR = 10.0F; -constexpr auto EAXSOURCE_DEFAULTROOMROLLOFFFACTOR = 0.0F; - -constexpr auto EAXSOURCE_MINAIRABSORPTIONFACTOR = 0.0F; -constexpr auto EAXSOURCE_MAXAIRABSORPTIONFACTOR = 10.0F; -constexpr auto EAXSOURCE_DEFAULTAIRABSORPTIONFACTOR = 0.0F; - -// EAX50 - -constexpr auto EAXSOURCE_MINMACROFXFACTOR = 0.0F; -constexpr auto EAXSOURCE_MAXMACROFXFACTOR = 1.0F; -constexpr auto EAXSOURCE_DEFAULTMACROFXFACTOR = 1.0F; - -// EAX50 - -constexpr auto EAXSOURCE_MINSPEAKERLEVEL = -10'000L; -constexpr auto EAXSOURCE_MAXSPEAKERLEVEL = 0L; -constexpr auto EAXSOURCE_DEFAULTSPEAKERLEVEL = -10'000L; - -constexpr auto EAXSOURCE_DEFAULTFLAGS = - EAXSOURCEFLAGS_DIRECTHFAUTO | - EAXSOURCEFLAGS_ROOMAUTO | - EAXSOURCEFLAGS_ROOMHFAUTO; - -enum : - long -{ - EAXSPEAKER_FRONT_LEFT = 1, - EAXSPEAKER_FRONT_CENTER = 2, - EAXSPEAKER_FRONT_RIGHT = 3, - EAXSPEAKER_SIDE_RIGHT = 4, - EAXSPEAKER_REAR_RIGHT = 5, - EAXSPEAKER_REAR_CENTER = 6, - EAXSPEAKER_REAR_LEFT = 7, - EAXSPEAKER_SIDE_LEFT = 8, - EAXSPEAKER_LOW_FREQUENCY = 9 -}; - -// EAXSOURCEFLAGS_DIRECTHFAUTO, EAXSOURCEFLAGS_ROOMAUTO and EAXSOURCEFLAGS_ROOMHFAUTO are ignored for 2D sources -// EAXSOURCEFLAGS_UPMIX is ignored for 3D sources -constexpr auto EAX50SOURCE_DEFAULTFLAGS = - EAXSOURCEFLAGS_DIRECTHFAUTO | - EAXSOURCEFLAGS_ROOMAUTO | - EAXSOURCEFLAGS_ROOMHFAUTO | - EAXSOURCEFLAGS_UPMIX; - -struct EAX30SOURCEPROPERTIES -{ - long lDirect; // direct path level (at low and mid frequencies) - long lDirectHF; // relative direct path level at high frequencies - long lRoom; // room effect level (at low and mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lObstruction; // main obstruction control (attenuation at high frequencies) - float flObstructionLFRatio; // obstruction low-frequency level re. main control - long lOcclusion; // main occlusion control (attenuation at high frequencies) - float flOcclusionLFRatio; // occlusion low-frequency level re. main control - float flOcclusionRoomRatio; // relative occlusion control for room effect - float flOcclusionDirectRatio; // relative occlusion control for direct path - long lExclusion; // main exlusion control (attenuation at high frequencies) - float flExclusionLFRatio; // exclusion low-frequency level re. main control - long lOutsideVolumeHF; // outside sound cone level at high frequencies - float flDopplerFactor; // like DS3D flDopplerFactor but per source - float flRolloffFactor; // like DS3D flRolloffFactor but per source - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - float flAirAbsorptionFactor; // multiplies EAXREVERB_AIRABSORPTIONHF - unsigned long ulFlags; // modifies the behavior of properties -}; // EAX30SOURCEPROPERTIES - -struct EAX50SOURCEPROPERTIES : - public EAX30SOURCEPROPERTIES -{ - float flMacroFXFactor; -}; // EAX50SOURCEPROPERTIES - -struct EAXSOURCEALLSENDPROPERTIES -{ - GUID guidReceivingFXSlotID; - long lSend; // send level (at low and mid frequencies) - long lSendHF; // relative send level at high frequencies - long lOcclusion; - float flOcclusionLFRatio; - float flOcclusionRoomRatio; - float flOcclusionDirectRatio; - long lExclusion; - float flExclusionLFRatio; -}; // EAXSOURCEALLSENDPROPERTIES - -struct EAXSOURCE2DPROPERTIES -{ - long lDirect; // direct path level (at low and mid frequencies) - long lDirectHF; // relative direct path level at high frequencies - long lRoom; // room effect level (at low and mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - unsigned long ulFlags; // modifies the behavior of properties -}; // EAXSOURCE2DPROPERTIES - -struct EAXSPEAKERLEVELPROPERTIES -{ - long lSpeakerID; - long lLevel; -}; // EAXSPEAKERLEVELPROPERTIES - -struct EAX40ACTIVEFXSLOTS -{ - GUID guidActiveFXSlots[EAX40_MAX_ACTIVE_FXSLOTS]; -}; // EAX40ACTIVEFXSLOTS - -struct EAX50ACTIVEFXSLOTS -{ - GUID guidActiveFXSlots[EAX50_MAX_ACTIVE_FXSLOTS]; -}; // EAX50ACTIVEFXSLOTS - -bool operator==( - const EAX50ACTIVEFXSLOTS& lhs, - const EAX50ACTIVEFXSLOTS& rhs) noexcept; - -bool operator!=( - const EAX50ACTIVEFXSLOTS& lhs, - const EAX50ACTIVEFXSLOTS& rhs) noexcept; - -// Use this structure for EAXSOURCE_OBSTRUCTIONPARAMETERS property. -struct EAXOBSTRUCTIONPROPERTIES -{ - long lObstruction; - float flObstructionLFRatio; -}; // EAXOBSTRUCTIONPROPERTIES - -// Use this structure for EAXSOURCE_OCCLUSIONPARAMETERS property. -struct EAXOCCLUSIONPROPERTIES -{ - long lOcclusion; - float flOcclusionLFRatio; - float flOcclusionRoomRatio; - float flOcclusionDirectRatio; -}; // EAXOCCLUSIONPROPERTIES - -// Use this structure for EAXSOURCE_EXCLUSIONPARAMETERS property. -struct EAXEXCLUSIONPROPERTIES -{ - long lExclusion; - float flExclusionLFRatio; -}; // EAXEXCLUSIONPROPERTIES - -// Use this structure for EAXSOURCE_SENDPARAMETERS properties. -struct EAXSOURCESENDPROPERTIES -{ - GUID guidReceivingFXSlotID; - long lSend; - long lSendHF; -}; // EAXSOURCESENDPROPERTIES - -// Use this structure for EAXSOURCE_OCCLUSIONSENDPARAMETERS -struct EAXSOURCEOCCLUSIONSENDPROPERTIES -{ - GUID guidReceivingFXSlotID; - long lOcclusion; - float flOcclusionLFRatio; - float flOcclusionRoomRatio; - float flOcclusionDirectRatio; -}; // EAXSOURCEOCCLUSIONSENDPROPERTIES - -// Use this structure for EAXSOURCE_EXCLUSIONSENDPARAMETERS -struct EAXSOURCEEXCLUSIONSENDPROPERTIES -{ - GUID guidReceivingFXSlotID; - long lExclusion; - float flExclusionLFRatio; -}; // EAXSOURCEEXCLUSIONSENDPROPERTIES - -extern const EAX50ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID; - -extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID; - -extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID; - - -// EAX Reverb Effect - -extern const GUID EAX_REVERB_EFFECT; - -// Reverb effect properties -enum EAXREVERB_PROPERTY : - unsigned int -{ - EAXREVERB_NONE, - EAXREVERB_ALLPARAMETERS, - EAXREVERB_ENVIRONMENT, - EAXREVERB_ENVIRONMENTSIZE, - EAXREVERB_ENVIRONMENTDIFFUSION, - EAXREVERB_ROOM, - EAXREVERB_ROOMHF, - EAXREVERB_ROOMLF, - EAXREVERB_DECAYTIME, - EAXREVERB_DECAYHFRATIO, - EAXREVERB_DECAYLFRATIO, - EAXREVERB_REFLECTIONS, - EAXREVERB_REFLECTIONSDELAY, - EAXREVERB_REFLECTIONSPAN, - EAXREVERB_REVERB, - EAXREVERB_REVERBDELAY, - EAXREVERB_REVERBPAN, - EAXREVERB_ECHOTIME, - EAXREVERB_ECHODEPTH, - EAXREVERB_MODULATIONTIME, - EAXREVERB_MODULATIONDEPTH, - EAXREVERB_AIRABSORPTIONHF, - EAXREVERB_HFREFERENCE, - EAXREVERB_LFREFERENCE, - EAXREVERB_ROOMROLLOFFFACTOR, - EAXREVERB_FLAGS, -}; // EAXREVERB_PROPERTY - -// used by EAXREVERB_ENVIRONMENT -enum : - unsigned long -{ - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX1_ENVIRONMENT_COUNT, - - // EAX30 - EAX_ENVIRONMENT_UNDEFINED = EAX1_ENVIRONMENT_COUNT, - - EAX3_ENVIRONMENT_COUNT, -}; - - -// reverberation decay time -constexpr auto EAXREVERBFLAGS_DECAYTIMESCALE = 0x00000001UL; - -// reflection level -constexpr auto EAXREVERBFLAGS_REFLECTIONSSCALE = 0x00000002UL; - -// initial reflection delay time -constexpr auto EAXREVERBFLAGS_REFLECTIONSDELAYSCALE = 0x00000004UL; - -// reflections level -constexpr auto EAXREVERBFLAGS_REVERBSCALE = 0x00000008UL; - -// late reverberation delay time -constexpr auto EAXREVERBFLAGS_REVERBDELAYSCALE = 0x00000010UL; - -// echo time -// EAX30+ -constexpr auto EAXREVERBFLAGS_ECHOTIMESCALE = 0x00000040UL; - -// modulation time -// EAX30+ -constexpr auto EAXREVERBFLAGS_MODULATIONTIMESCALE = 0x00000080UL; - -// This flag limits high-frequency decay time according to air absorption. -constexpr auto EAXREVERBFLAGS_DECAYHFLIMIT = 0x00000020UL; - -constexpr auto EAXREVERBFLAGS_RESERVED = 0xFFFFFF00UL; // reserved future use - - -struct EAXREVERBPROPERTIES -{ - unsigned long ulEnvironment; // sets all reverb properties - float flEnvironmentSize; // environment size in meters - float flEnvironmentDiffusion; // environment diffusion - long lRoom; // room effect level (at mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lRoomLF; // relative room effect level at low frequencies - float flDecayTime; // reverberation decay time at mid frequencies - float flDecayHFRatio; // high-frequency to mid-frequency decay time ratio - float flDecayLFRatio; // low-frequency to mid-frequency decay time ratio - long lReflections; // early reflections level relative to room effect - float flReflectionsDelay; // initial reflection delay time - EAXVECTOR vReflectionsPan; // early reflections panning vector - long lReverb; // late reverberation level relative to room effect - float flReverbDelay; // late reverberation delay time relative to initial reflection - EAXVECTOR vReverbPan; // late reverberation panning vector - float flEchoTime; // echo time - float flEchoDepth; // echo depth - float flModulationTime; // modulation time - float flModulationDepth; // modulation depth - float flAirAbsorptionHF; // change in level per meter at high frequencies - float flHFReference; // reference high frequency - float flLFReference; // reference low frequency - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - unsigned long ulFlags; // modifies the behavior of properties -}; // EAXREVERBPROPERTIES - -bool operator==( - const EAXREVERBPROPERTIES& lhs, - const EAXREVERBPROPERTIES& rhs) noexcept; - -bool operator!=( - const EAXREVERBPROPERTIES& lhs, - const EAXREVERBPROPERTIES& rhs) noexcept; - - -constexpr auto EAXREVERB_MINENVIRONMENT = static_cast(EAX_ENVIRONMENT_GENERIC); -constexpr auto EAX1REVERB_MAXENVIRONMENT = static_cast(EAX_ENVIRONMENT_PSYCHOTIC); -constexpr auto EAX30REVERB_MAXENVIRONMENT = static_cast(EAX_ENVIRONMENT_UNDEFINED); -constexpr auto EAXREVERB_DEFAULTENVIRONMENT = static_cast(EAX_ENVIRONMENT_GENERIC); - -constexpr auto EAXREVERB_MINENVIRONMENTSIZE = 1.0F; -constexpr auto EAXREVERB_MAXENVIRONMENTSIZE = 100.0F; -constexpr auto EAXREVERB_DEFAULTENVIRONMENTSIZE = 7.5F; - -constexpr auto EAXREVERB_MINENVIRONMENTDIFFUSION = 0.0F; -constexpr auto EAXREVERB_MAXENVIRONMENTDIFFUSION = 1.0F; -constexpr auto EAXREVERB_DEFAULTENVIRONMENTDIFFUSION = 1.0F; - -constexpr auto EAXREVERB_MINROOM = -10'000L; -constexpr auto EAXREVERB_MAXROOM = 0L; -constexpr auto EAXREVERB_DEFAULTROOM = -1'000L; - -constexpr auto EAXREVERB_MINROOMHF = -10'000L; -constexpr auto EAXREVERB_MAXROOMHF = 0L; -constexpr auto EAXREVERB_DEFAULTROOMHF = -100L; - -constexpr auto EAXREVERB_MINROOMLF = -10'000L; -constexpr auto EAXREVERB_MAXROOMLF = 0L; -constexpr auto EAXREVERB_DEFAULTROOMLF = 0L; - -constexpr auto EAXREVERB_MINDECAYTIME = 0.1F; -constexpr auto EAXREVERB_MAXDECAYTIME = 20.0F; -constexpr auto EAXREVERB_DEFAULTDECAYTIME = 1.49F; - -constexpr auto EAXREVERB_MINDECAYHFRATIO = 0.1F; -constexpr auto EAXREVERB_MAXDECAYHFRATIO = 2.0F; -constexpr auto EAXREVERB_DEFAULTDECAYHFRATIO = 0.83F; - -constexpr auto EAXREVERB_MINDECAYLFRATIO = 0.1F; -constexpr auto EAXREVERB_MAXDECAYLFRATIO = 2.0F; -constexpr auto EAXREVERB_DEFAULTDECAYLFRATIO = 1.0F; - -constexpr auto EAXREVERB_MINREFLECTIONS = -10'000L; -constexpr auto EAXREVERB_MAXREFLECTIONS = 1'000L; -constexpr auto EAXREVERB_DEFAULTREFLECTIONS = -2'602L; - -constexpr auto EAXREVERB_MINREFLECTIONSDELAY = 0.0F; -constexpr auto EAXREVERB_MAXREFLECTIONSDELAY = 0.3F; -constexpr auto EAXREVERB_DEFAULTREFLECTIONSDELAY = 0.007F; - -constexpr auto EAXREVERB_DEFAULTREFLECTIONSPAN = EAXVECTOR{0.0F, 0.0F, 0.0F}; - -constexpr auto EAXREVERB_MINREVERB = -10'000L; -constexpr auto EAXREVERB_MAXREVERB = 2'000L; -constexpr auto EAXREVERB_DEFAULTREVERB = 200L; - -constexpr auto EAXREVERB_MINREVERBDELAY = 0.0F; -constexpr auto EAXREVERB_MAXREVERBDELAY = 0.1F; -constexpr auto EAXREVERB_DEFAULTREVERBDELAY = 0.011F; - -constexpr auto EAXREVERB_DEFAULTREVERBPAN = EAXVECTOR{0.0F, 0.0F, 0.0F}; - -constexpr auto EAXREVERB_MINECHOTIME = 0.075F; -constexpr auto EAXREVERB_MAXECHOTIME = 0.25F; -constexpr auto EAXREVERB_DEFAULTECHOTIME = 0.25F; - -constexpr auto EAXREVERB_MINECHODEPTH = 0.0F; -constexpr auto EAXREVERB_MAXECHODEPTH = 1.0F; -constexpr auto EAXREVERB_DEFAULTECHODEPTH = 0.0F; - -constexpr auto EAXREVERB_MINMODULATIONTIME = 0.04F; -constexpr auto EAXREVERB_MAXMODULATIONTIME = 4.0F; -constexpr auto EAXREVERB_DEFAULTMODULATIONTIME = 0.25F; - -constexpr auto EAXREVERB_MINMODULATIONDEPTH = 0.0F; -constexpr auto EAXREVERB_MAXMODULATIONDEPTH = 1.0F; -constexpr auto EAXREVERB_DEFAULTMODULATIONDEPTH = 0.0F; - -constexpr auto EAXREVERB_MINAIRABSORPTIONHF = -100.0F; -constexpr auto EAXREVERB_MAXAIRABSORPTIONHF = 0.0F; -constexpr auto EAXREVERB_DEFAULTAIRABSORPTIONHF = -5.0F; - -constexpr auto EAXREVERB_MINHFREFERENCE = 1'000.0F; -constexpr auto EAXREVERB_MAXHFREFERENCE = 20'000.0F; -constexpr auto EAXREVERB_DEFAULTHFREFERENCE = 5'000.0F; - -constexpr auto EAXREVERB_MINLFREFERENCE = 20.0F; -constexpr auto EAXREVERB_MAXLFREFERENCE = 1'000.0F; -constexpr auto EAXREVERB_DEFAULTLFREFERENCE = 250.0F; - -constexpr auto EAXREVERB_MINROOMROLLOFFFACTOR = 0.0F; -constexpr auto EAXREVERB_MAXROOMROLLOFFFACTOR = 10.0F; -constexpr auto EAXREVERB_DEFAULTROOMROLLOFFFACTOR = 0.0F; - -constexpr auto EAX1REVERB_MINVOLUME = 0.0F; -constexpr auto EAX1REVERB_MAXVOLUME = 1.0F; - -constexpr auto EAX1REVERB_MINDAMPING = 0.0F; -constexpr auto EAX1REVERB_MAXDAMPING = 2.0F; - -constexpr auto EAXREVERB_DEFAULTFLAGS = - EAXREVERBFLAGS_DECAYTIMESCALE | - EAXREVERBFLAGS_REFLECTIONSSCALE | - EAXREVERBFLAGS_REFLECTIONSDELAYSCALE | - EAXREVERBFLAGS_REVERBSCALE | - EAXREVERBFLAGS_REVERBDELAYSCALE | - EAXREVERBFLAGS_DECAYHFLIMIT; - - -using EaxReverbPresets = std::array; -extern const EaxReverbPresets EAXREVERB_PRESETS; - - -using Eax1ReverbPresets = std::array; -extern const Eax1ReverbPresets EAX1REVERB_PRESETS; - - -// AGC Compressor Effect - -extern const GUID EAX_AGCCOMPRESSOR_EFFECT; - -enum EAXAGCCOMPRESSOR_PROPERTY : - unsigned int -{ - EAXAGCCOMPRESSOR_NONE, - EAXAGCCOMPRESSOR_ALLPARAMETERS, - EAXAGCCOMPRESSOR_ONOFF, -}; // EAXAGCCOMPRESSOR_PROPERTY - -struct EAXAGCCOMPRESSORPROPERTIES -{ - unsigned long ulOnOff; // Switch Compressor on or off -}; // EAXAGCCOMPRESSORPROPERTIES - - -constexpr auto EAXAGCCOMPRESSOR_MINONOFF = 0UL; -constexpr auto EAXAGCCOMPRESSOR_MAXONOFF = 1UL; -constexpr auto EAXAGCCOMPRESSOR_DEFAULTONOFF = EAXAGCCOMPRESSOR_MAXONOFF; - - -// Autowah Effect - -extern const GUID EAX_AUTOWAH_EFFECT; - -enum EAXAUTOWAH_PROPERTY : - unsigned int -{ - EAXAUTOWAH_NONE, - EAXAUTOWAH_ALLPARAMETERS, - EAXAUTOWAH_ATTACKTIME, - EAXAUTOWAH_RELEASETIME, - EAXAUTOWAH_RESONANCE, - EAXAUTOWAH_PEAKLEVEL, -}; // EAXAUTOWAH_PROPERTY - -struct EAXAUTOWAHPROPERTIES -{ - float flAttackTime; // Attack time (seconds) - float flReleaseTime; // Release time (seconds) - long lResonance; // Resonance (mB) - long lPeakLevel; // Peak level (mB) -}; // EAXAUTOWAHPROPERTIES - - -constexpr auto EAXAUTOWAH_MINATTACKTIME = 0.0001F; -constexpr auto EAXAUTOWAH_MAXATTACKTIME = 1.0F; -constexpr auto EAXAUTOWAH_DEFAULTATTACKTIME = 0.06F; - -constexpr auto EAXAUTOWAH_MINRELEASETIME = 0.0001F; -constexpr auto EAXAUTOWAH_MAXRELEASETIME = 1.0F; -constexpr auto EAXAUTOWAH_DEFAULTRELEASETIME = 0.06F; - -constexpr auto EAXAUTOWAH_MINRESONANCE = 600L; -constexpr auto EAXAUTOWAH_MAXRESONANCE = 6000L; -constexpr auto EAXAUTOWAH_DEFAULTRESONANCE = 6000L; - -constexpr auto EAXAUTOWAH_MINPEAKLEVEL = -9000L; -constexpr auto EAXAUTOWAH_MAXPEAKLEVEL = 9000L; -constexpr auto EAXAUTOWAH_DEFAULTPEAKLEVEL = 2100L; - - -// Chorus Effect - -extern const GUID EAX_CHORUS_EFFECT; - - -enum EAXCHORUS_PROPERTY : - unsigned int -{ - EAXCHORUS_NONE, - EAXCHORUS_ALLPARAMETERS, - EAXCHORUS_WAVEFORM, - EAXCHORUS_PHASE, - EAXCHORUS_RATE, - EAXCHORUS_DEPTH, - EAXCHORUS_FEEDBACK, - EAXCHORUS_DELAY, -}; // EAXCHORUS_PROPERTY - -enum : - unsigned long -{ - EAX_CHORUS_SINUSOID, - EAX_CHORUS_TRIANGLE, -}; - -struct EAXCHORUSPROPERTIES -{ - unsigned long ulWaveform; // Waveform selector - see enum above - long lPhase; // Phase (Degrees) - float flRate; // Rate (Hz) - float flDepth; // Depth (0 to 1) - float flFeedback; // Feedback (-1 to 1) - float flDelay; // Delay (seconds) -}; // EAXCHORUSPROPERTIES - - -constexpr auto EAXCHORUS_MINWAVEFORM = 0UL; -constexpr auto EAXCHORUS_MAXWAVEFORM = 1UL; -constexpr auto EAXCHORUS_DEFAULTWAVEFORM = 1UL; - -constexpr auto EAXCHORUS_MINPHASE = -180L; -constexpr auto EAXCHORUS_MAXPHASE = 180L; -constexpr auto EAXCHORUS_DEFAULTPHASE = 90L; - -constexpr auto EAXCHORUS_MINRATE = 0.0F; -constexpr auto EAXCHORUS_MAXRATE = 10.0F; -constexpr auto EAXCHORUS_DEFAULTRATE = 1.1F; - -constexpr auto EAXCHORUS_MINDEPTH = 0.0F; -constexpr auto EAXCHORUS_MAXDEPTH = 1.0F; -constexpr auto EAXCHORUS_DEFAULTDEPTH = 0.1F; - -constexpr auto EAXCHORUS_MINFEEDBACK = -1.0F; -constexpr auto EAXCHORUS_MAXFEEDBACK = 1.0F; -constexpr auto EAXCHORUS_DEFAULTFEEDBACK = 0.25F; - -constexpr auto EAXCHORUS_MINDELAY = 0.0002F; -constexpr auto EAXCHORUS_MAXDELAY = 0.016F; -constexpr auto EAXCHORUS_DEFAULTDELAY = 0.016F; - - -// Distortion Effect - -extern const GUID EAX_DISTORTION_EFFECT; - -enum EAXDISTORTION_PROPERTY : - unsigned int -{ - EAXDISTORTION_NONE, - EAXDISTORTION_ALLPARAMETERS, - EAXDISTORTION_EDGE, - EAXDISTORTION_GAIN, - EAXDISTORTION_LOWPASSCUTOFF, - EAXDISTORTION_EQCENTER, - EAXDISTORTION_EQBANDWIDTH, -}; // EAXDISTORTION_PROPERTY - - -struct EAXDISTORTIONPROPERTIES -{ - float flEdge; // Controls the shape of the distortion (0 to 1) - long lGain; // Controls the post distortion gain (mB) - float flLowPassCutOff; // Controls the cut-off of the filter pre-distortion (Hz) - float flEQCenter; // Controls the center frequency of the EQ post-distortion (Hz) - float flEQBandwidth; // Controls the bandwidth of the EQ post-distortion (Hz) -}; // EAXDISTORTIONPROPERTIES - - -constexpr auto EAXDISTORTION_MINEDGE = 0.0F; -constexpr auto EAXDISTORTION_MAXEDGE = 1.0F; -constexpr auto EAXDISTORTION_DEFAULTEDGE = 0.2F; - -constexpr auto EAXDISTORTION_MINGAIN = -6000L; -constexpr auto EAXDISTORTION_MAXGAIN = 0L; -constexpr auto EAXDISTORTION_DEFAULTGAIN = -2600L; - -constexpr auto EAXDISTORTION_MINLOWPASSCUTOFF = 80.0F; -constexpr auto EAXDISTORTION_MAXLOWPASSCUTOFF = 24000.0F; -constexpr auto EAXDISTORTION_DEFAULTLOWPASSCUTOFF = 8000.0F; - -constexpr auto EAXDISTORTION_MINEQCENTER = 80.0F; -constexpr auto EAXDISTORTION_MAXEQCENTER = 24000.0F; -constexpr auto EAXDISTORTION_DEFAULTEQCENTER = 3600.0F; - -constexpr auto EAXDISTORTION_MINEQBANDWIDTH = 80.0F; -constexpr auto EAXDISTORTION_MAXEQBANDWIDTH = 24000.0F; -constexpr auto EAXDISTORTION_DEFAULTEQBANDWIDTH = 3600.0F; - - -// Echo Effect - -extern const GUID EAX_ECHO_EFFECT; - - -enum EAXECHO_PROPERTY : - unsigned int -{ - EAXECHO_NONE, - EAXECHO_ALLPARAMETERS, - EAXECHO_DELAY, - EAXECHO_LRDELAY, - EAXECHO_DAMPING, - EAXECHO_FEEDBACK, - EAXECHO_SPREAD, -}; // EAXECHO_PROPERTY - - -struct EAXECHOPROPERTIES -{ - float flDelay; // Controls the initial delay time (seconds) - float flLRDelay; // Controls the delay time between the first and second taps (seconds) - float flDamping; // Controls a low-pass filter that dampens the echoes (0 to 1) - float flFeedback; // Controls the duration of echo repetition (0 to 1) - float flSpread; // Controls the left-right spread of the echoes -}; // EAXECHOPROPERTIES - - -constexpr auto EAXECHO_MINDAMPING = 0.0F; -constexpr auto EAXECHO_MAXDAMPING = 0.99F; -constexpr auto EAXECHO_DEFAULTDAMPING = 0.5F; - -constexpr auto EAXECHO_MINDELAY = 0.002F; -constexpr auto EAXECHO_MAXDELAY = 0.207F; -constexpr auto EAXECHO_DEFAULTDELAY = 0.1F; - -constexpr auto EAXECHO_MINLRDELAY = 0.0F; -constexpr auto EAXECHO_MAXLRDELAY = 0.404F; -constexpr auto EAXECHO_DEFAULTLRDELAY = 0.1F; - -constexpr auto EAXECHO_MINFEEDBACK = 0.0F; -constexpr auto EAXECHO_MAXFEEDBACK = 1.0F; -constexpr auto EAXECHO_DEFAULTFEEDBACK = 0.5F; - -constexpr auto EAXECHO_MINSPREAD = -1.0F; -constexpr auto EAXECHO_MAXSPREAD = 1.0F; -constexpr auto EAXECHO_DEFAULTSPREAD = -1.0F; - - -// Equalizer Effect - -extern const GUID EAX_EQUALIZER_EFFECT; - - -enum EAXEQUALIZER_PROPERTY : - unsigned int -{ - EAXEQUALIZER_NONE, - EAXEQUALIZER_ALLPARAMETERS, - EAXEQUALIZER_LOWGAIN, - EAXEQUALIZER_LOWCUTOFF, - EAXEQUALIZER_MID1GAIN, - EAXEQUALIZER_MID1CENTER, - EAXEQUALIZER_MID1WIDTH, - EAXEQUALIZER_MID2GAIN, - EAXEQUALIZER_MID2CENTER, - EAXEQUALIZER_MID2WIDTH, - EAXEQUALIZER_HIGHGAIN, - EAXEQUALIZER_HIGHCUTOFF, -}; // EAXEQUALIZER_PROPERTY - - -struct EAXEQUALIZERPROPERTIES -{ - long lLowGain; // (mB) - float flLowCutOff; // (Hz) - long lMid1Gain; // (mB) - float flMid1Center; // (Hz) - float flMid1Width; // (octaves) - long lMid2Gain; // (mB) - float flMid2Center; // (Hz) - float flMid2Width; // (octaves) - long lHighGain; // (mB) - float flHighCutOff; // (Hz) -}; // EAXEQUALIZERPROPERTIES - - -constexpr auto EAXEQUALIZER_MINLOWGAIN = -1800L; -constexpr auto EAXEQUALIZER_MAXLOWGAIN = 1800L; -constexpr auto EAXEQUALIZER_DEFAULTLOWGAIN = 0L; - -constexpr auto EAXEQUALIZER_MINLOWCUTOFF = 50.0F; -constexpr auto EAXEQUALIZER_MAXLOWCUTOFF = 800.0F; -constexpr auto EAXEQUALIZER_DEFAULTLOWCUTOFF = 200.0F; - -constexpr auto EAXEQUALIZER_MINMID1GAIN = -1800L; -constexpr auto EAXEQUALIZER_MAXMID1GAIN = 1800L; -constexpr auto EAXEQUALIZER_DEFAULTMID1GAIN = 0L; - -constexpr auto EAXEQUALIZER_MINMID1CENTER = 200.0F; -constexpr auto EAXEQUALIZER_MAXMID1CENTER = 3000.0F; -constexpr auto EAXEQUALIZER_DEFAULTMID1CENTER = 500.0F; - -constexpr auto EAXEQUALIZER_MINMID1WIDTH = 0.01F; -constexpr auto EAXEQUALIZER_MAXMID1WIDTH = 1.0F; -constexpr auto EAXEQUALIZER_DEFAULTMID1WIDTH = 1.0F; - -constexpr auto EAXEQUALIZER_MINMID2GAIN = -1800L; -constexpr auto EAXEQUALIZER_MAXMID2GAIN = 1800L; -constexpr auto EAXEQUALIZER_DEFAULTMID2GAIN = 0L; - -constexpr auto EAXEQUALIZER_MINMID2CENTER = 1000.0F; -constexpr auto EAXEQUALIZER_MAXMID2CENTER = 8000.0F; -constexpr auto EAXEQUALIZER_DEFAULTMID2CENTER = 3000.0F; - -constexpr auto EAXEQUALIZER_MINMID2WIDTH = 0.01F; -constexpr auto EAXEQUALIZER_MAXMID2WIDTH = 1.0F; -constexpr auto EAXEQUALIZER_DEFAULTMID2WIDTH = 1.0F; - -constexpr auto EAXEQUALIZER_MINHIGHGAIN = -1800L; -constexpr auto EAXEQUALIZER_MAXHIGHGAIN = 1800L; -constexpr auto EAXEQUALIZER_DEFAULTHIGHGAIN = 0L; - -constexpr auto EAXEQUALIZER_MINHIGHCUTOFF = 4000.0F; -constexpr auto EAXEQUALIZER_MAXHIGHCUTOFF = 16000.0F; -constexpr auto EAXEQUALIZER_DEFAULTHIGHCUTOFF = 6000.0F; - - -// Flanger Effect - -extern const GUID EAX_FLANGER_EFFECT; - -enum EAXFLANGER_PROPERTY : - unsigned int -{ - EAXFLANGER_NONE, - EAXFLANGER_ALLPARAMETERS, - EAXFLANGER_WAVEFORM, - EAXFLANGER_PHASE, - EAXFLANGER_RATE, - EAXFLANGER_DEPTH, - EAXFLANGER_FEEDBACK, - EAXFLANGER_DELAY, -}; // EAXFLANGER_PROPERTY - -enum : - unsigned long -{ - EAX_FLANGER_SINUSOID, - EAX_FLANGER_TRIANGLE, -}; - -struct EAXFLANGERPROPERTIES -{ - unsigned long ulWaveform; // Waveform selector - see enum above - long lPhase; // Phase (Degrees) - float flRate; // Rate (Hz) - float flDepth; // Depth (0 to 1) - float flFeedback; // Feedback (0 to 1) - float flDelay; // Delay (seconds) -}; // EAXFLANGERPROPERTIES - - -constexpr auto EAXFLANGER_MINWAVEFORM = 0UL; -constexpr auto EAXFLANGER_MAXWAVEFORM = 1UL; -constexpr auto EAXFLANGER_DEFAULTWAVEFORM = 1UL; - -constexpr auto EAXFLANGER_MINPHASE = -180L; -constexpr auto EAXFLANGER_MAXPHASE = 180L; -constexpr auto EAXFLANGER_DEFAULTPHASE = 0L; - -constexpr auto EAXFLANGER_MINRATE = 0.0F; -constexpr auto EAXFLANGER_MAXRATE = 10.0F; -constexpr auto EAXFLANGER_DEFAULTRATE = 0.27F; - -constexpr auto EAXFLANGER_MINDEPTH = 0.0F; -constexpr auto EAXFLANGER_MAXDEPTH = 1.0F; -constexpr auto EAXFLANGER_DEFAULTDEPTH = 1.0F; - -constexpr auto EAXFLANGER_MINFEEDBACK = -1.0F; -constexpr auto EAXFLANGER_MAXFEEDBACK = 1.0F; -constexpr auto EAXFLANGER_DEFAULTFEEDBACK = -0.5F; - -constexpr auto EAXFLANGER_MINDELAY = 0.0002F; -constexpr auto EAXFLANGER_MAXDELAY = 0.004F; -constexpr auto EAXFLANGER_DEFAULTDELAY = 0.002F; - - -// Frequency Shifter Effect - -extern const GUID EAX_FREQUENCYSHIFTER_EFFECT; - -enum EAXFREQUENCYSHIFTER_PROPERTY : - unsigned int -{ - EAXFREQUENCYSHIFTER_NONE, - EAXFREQUENCYSHIFTER_ALLPARAMETERS, - EAXFREQUENCYSHIFTER_FREQUENCY, - EAXFREQUENCYSHIFTER_LEFTDIRECTION, - EAXFREQUENCYSHIFTER_RIGHTDIRECTION, -}; // EAXFREQUENCYSHIFTER_PROPERTY - -enum : - unsigned long -{ - EAX_FREQUENCYSHIFTER_DOWN, - EAX_FREQUENCYSHIFTER_UP, - EAX_FREQUENCYSHIFTER_OFF -}; - -struct EAXFREQUENCYSHIFTERPROPERTIES -{ - float flFrequency; // (Hz) - unsigned long ulLeftDirection; // see enum above - unsigned long ulRightDirection; // see enum above -}; // EAXFREQUENCYSHIFTERPROPERTIES - - -constexpr auto EAXFREQUENCYSHIFTER_MINFREQUENCY = 0.0F; -constexpr auto EAXFREQUENCYSHIFTER_MAXFREQUENCY = 24000.0F; -constexpr auto EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY = EAXFREQUENCYSHIFTER_MINFREQUENCY; - -constexpr auto EAXFREQUENCYSHIFTER_MINLEFTDIRECTION = 0UL; -constexpr auto EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION = 2UL; -constexpr auto EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION = EAXFREQUENCYSHIFTER_MINLEFTDIRECTION; - -constexpr auto EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION = 0UL; -constexpr auto EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION = 2UL; -constexpr auto EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION = EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION; - - -// Vocal Morpher Effect - -extern const GUID EAX_VOCALMORPHER_EFFECT; - -enum EAXVOCALMORPHER_PROPERTY : - unsigned int -{ - EAXVOCALMORPHER_NONE, - EAXVOCALMORPHER_ALLPARAMETERS, - EAXVOCALMORPHER_PHONEMEA, - EAXVOCALMORPHER_PHONEMEACOARSETUNING, - EAXVOCALMORPHER_PHONEMEB, - EAXVOCALMORPHER_PHONEMEBCOARSETUNING, - EAXVOCALMORPHER_WAVEFORM, - EAXVOCALMORPHER_RATE, -}; // EAXVOCALMORPHER_PROPERTY - -enum : - unsigned long -{ - A, - E, - I, - O, - U, - AA, - AE, - AH, - AO, - EH, - ER, - IH, - IY, - UH, - UW, - B, - D, - F, - G, - J, - K, - L, - M, - N, - P, - R, - S, - T, - V, - Z, -}; - -enum : - unsigned long -{ - EAX_VOCALMORPHER_SINUSOID, - EAX_VOCALMORPHER_TRIANGLE, - EAX_VOCALMORPHER_SAWTOOTH -}; - -// Use this structure for EAXVOCALMORPHER_ALLPARAMETERS -struct EAXVOCALMORPHERPROPERTIES -{ - unsigned long ulPhonemeA; // see enum above - long lPhonemeACoarseTuning; // (semitones) - unsigned long ulPhonemeB; // see enum above - long lPhonemeBCoarseTuning; // (semitones) - unsigned long ulWaveform; // Waveform selector - see enum above - float flRate; // (Hz) -}; // EAXVOCALMORPHERPROPERTIES - - -constexpr auto EAXVOCALMORPHER_MINPHONEMEA = 0UL; -constexpr auto EAXVOCALMORPHER_MAXPHONEMEA = 29UL; -constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEA = EAXVOCALMORPHER_MINPHONEMEA; - -constexpr auto EAXVOCALMORPHER_MINPHONEMEACOARSETUNING = -24L; -constexpr auto EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING = 24L; -constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING = 0L; - -constexpr auto EAXVOCALMORPHER_MINPHONEMEB = 0UL; -constexpr auto EAXVOCALMORPHER_MAXPHONEMEB = 29UL; -constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEB = 10UL; - -constexpr auto EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING = -24L; -constexpr auto EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING = 24L; -constexpr auto EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING = 0L; - -constexpr auto EAXVOCALMORPHER_MINWAVEFORM = 0UL; -constexpr auto EAXVOCALMORPHER_MAXWAVEFORM = 2UL; -constexpr auto EAXVOCALMORPHER_DEFAULTWAVEFORM = EAXVOCALMORPHER_MINWAVEFORM; - -constexpr auto EAXVOCALMORPHER_MINRATE = 0.0F; -constexpr auto EAXVOCALMORPHER_MAXRATE = 10.0F; -constexpr auto EAXVOCALMORPHER_DEFAULTRATE = 1.41F; - - -// Pitch Shifter Effect - -extern const GUID EAX_PITCHSHIFTER_EFFECT; - -enum EAXPITCHSHIFTER_PROPERTY : - unsigned int -{ - EAXPITCHSHIFTER_NONE, - EAXPITCHSHIFTER_ALLPARAMETERS, - EAXPITCHSHIFTER_COARSETUNE, - EAXPITCHSHIFTER_FINETUNE, -}; // EAXPITCHSHIFTER_PROPERTY - -struct EAXPITCHSHIFTERPROPERTIES -{ - long lCoarseTune; // Amount of pitch shift (semitones) - long lFineTune; // Amount of pitch shift (cents) -}; // EAXPITCHSHIFTERPROPERTIES - - -constexpr auto EAXPITCHSHIFTER_MINCOARSETUNE = -12L; -constexpr auto EAXPITCHSHIFTER_MAXCOARSETUNE = 12L; -constexpr auto EAXPITCHSHIFTER_DEFAULTCOARSETUNE = 12L; - -constexpr auto EAXPITCHSHIFTER_MINFINETUNE = -50L; -constexpr auto EAXPITCHSHIFTER_MAXFINETUNE = 50L; -constexpr auto EAXPITCHSHIFTER_DEFAULTFINETUNE = 0L; - - -// Ring Modulator Effect - -extern const GUID EAX_RINGMODULATOR_EFFECT; - -enum EAXRINGMODULATOR_PROPERTY : - unsigned int -{ - EAXRINGMODULATOR_NONE, - EAXRINGMODULATOR_ALLPARAMETERS, - EAXRINGMODULATOR_FREQUENCY, - EAXRINGMODULATOR_HIGHPASSCUTOFF, - EAXRINGMODULATOR_WAVEFORM, -}; // EAXRINGMODULATOR_PROPERTY - -enum : - unsigned long -{ - EAX_RINGMODULATOR_SINUSOID, - EAX_RINGMODULATOR_SAWTOOTH, - EAX_RINGMODULATOR_SQUARE, -}; - -// Use this structure for EAXRINGMODULATOR_ALLPARAMETERS -struct EAXRINGMODULATORPROPERTIES -{ - float flFrequency; // Frequency of modulation (Hz) - float flHighPassCutOff; // Cut-off frequency of high-pass filter (Hz) - unsigned long ulWaveform; // Waveform selector - see enum above -}; // EAXRINGMODULATORPROPERTIES - - -constexpr auto EAXRINGMODULATOR_MINFREQUENCY = 0.0F; -constexpr auto EAXRINGMODULATOR_MAXFREQUENCY = 8000.0F; -constexpr auto EAXRINGMODULATOR_DEFAULTFREQUENCY = 440.0F; - -constexpr auto EAXRINGMODULATOR_MINHIGHPASSCUTOFF = 0.0F; -constexpr auto EAXRINGMODULATOR_MAXHIGHPASSCUTOFF = 24000.0F; -constexpr auto EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF = 800.0F; - -constexpr auto EAXRINGMODULATOR_MINWAVEFORM = 0UL; -constexpr auto EAXRINGMODULATOR_MAXWAVEFORM = 2UL; -constexpr auto EAXRINGMODULATOR_DEFAULTWAVEFORM = EAXRINGMODULATOR_MINWAVEFORM; - - -using LPEAXSET = ALenum(AL_APIENTRY*)( - const GUID* property_set_id, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_buffer, - ALuint property_size); - -using LPEAXGET = ALenum(AL_APIENTRY*)( - const GUID* property_set_id, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_buffer, - ALuint property_size); - - -#endif // !EAX_API_INCLUDED diff --git a/al/eax_eax_call.cpp b/al/eax_eax_call.cpp deleted file mode 100644 index 914d2fbf..00000000 --- a/al/eax_eax_call.cpp +++ /dev/null @@ -1,324 +0,0 @@ -#include "config.h" - -#include "al/eax_eax_call.h" - -#include "al/eax_exception.h" - - -namespace { - -constexpr auto deferred_flag = 0x80000000U; - -class EaxEaxCallException : - public EaxException -{ -public: - explicit EaxEaxCallException( - const char* message) - : - EaxException{"EAX_EAX_CALL", message} - { - } -}; // EaxEaxCallException - -} // namespace - - -EaxEaxCall::EaxEaxCall( - bool is_get, - const GUID& property_set_guid, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_buffer, - ALuint property_size) - : is_get_{is_get}, version_{0}, property_set_id_{EaxEaxCallPropertySetId::none} - , property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id} - , property_buffer_{property_buffer}, property_size_{property_size} -{ - if (false) - { - } - else if (property_set_guid == EAXPROPERTYID_EAX40_Context) - { - version_ = 4; - property_set_id_ = EaxEaxCallPropertySetId::context; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_Context) - { - version_ = 5; - property_set_id_ = EaxEaxCallPropertySetId::context; - } - else if (property_set_guid == DSPROPSETID_EAX20_ListenerProperties) - { - version_ = 2; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; - property_id_ = convert_eax_v2_0_listener_property_id(property_id_); - } - else if (property_set_guid == DSPROPSETID_EAX30_ListenerProperties) - { - version_ = 3; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot0) - { - version_ = 4; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot0) - { - version_ = 5; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot1) - { - version_ = 4; - fx_slot_index_ = 1u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot1) - { - version_ = 5; - fx_slot_index_ = 1u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot2) - { - version_ = 4; - fx_slot_index_ = 2u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot2) - { - version_ = 5; - fx_slot_index_ = 2u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot3) - { - version_ = 4; - fx_slot_index_ = 3u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot3) - { - version_ = 5; - fx_slot_index_ = 3u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == DSPROPSETID_EAX20_BufferProperties) - { - version_ = 2; - property_set_id_ = EaxEaxCallPropertySetId::source; - property_id_ = convert_eax_v2_0_buffer_property_id(property_id_); - } - else if (property_set_guid == DSPROPSETID_EAX30_BufferProperties) - { - version_ = 3; - property_set_id_ = EaxEaxCallPropertySetId::source; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_Source) - { - version_ = 4; - property_set_id_ = EaxEaxCallPropertySetId::source; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_Source) - { - version_ = 5; - property_set_id_ = EaxEaxCallPropertySetId::source; - } - else if (property_set_guid == DSPROPSETID_EAX_ReverbProperties) - { - version_ = 1; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; - } - else if (property_set_guid == DSPROPSETID_EAXBUFFER_ReverbProperties) - { - version_ = 1; - property_set_id_ = EaxEaxCallPropertySetId::source; - } - else - { - fail("Unsupported property set id."); - } - - if (version_ < 1 || version_ > 5) - { - fail("EAX version out of range."); - } - - if(!(property_id&deferred_flag)) - { - if(property_set_id_ != EaxEaxCallPropertySetId::fx_slot && property_id_ != 0) - { - if (!property_buffer) - { - fail("Null property buffer."); - } - - if (property_size == 0) - { - fail("Empty property."); - } - } - } - - if(property_set_id_ == EaxEaxCallPropertySetId::source && property_source_id_ == 0) - { - fail("Null AL source id."); - } - - if (property_set_id_ == EaxEaxCallPropertySetId::fx_slot) - { - if (property_id_ < EAXFXSLOT_NONE) - { - property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; - } - } -} - -[[noreturn]] -void EaxEaxCall::fail( - const char* message) -{ - throw EaxEaxCallException{message}; -} - -ALuint EaxEaxCall::convert_eax_v2_0_listener_property_id( - ALuint property_id) -{ - switch (property_id) - { - case DSPROPERTY_EAX20LISTENER_NONE: - return EAXREVERB_NONE; - - case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: - return EAXREVERB_ALLPARAMETERS; - - case DSPROPERTY_EAX20LISTENER_ROOM: - return EAXREVERB_ROOM; - - case DSPROPERTY_EAX20LISTENER_ROOMHF: - return EAXREVERB_ROOMHF; - - case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: - return EAXREVERB_ROOMROLLOFFFACTOR; - - case DSPROPERTY_EAX20LISTENER_DECAYTIME: - return EAXREVERB_DECAYTIME; - - case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: - return EAXREVERB_DECAYHFRATIO; - - case DSPROPERTY_EAX20LISTENER_REFLECTIONS: - return EAXREVERB_REFLECTIONS; - - case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: - return EAXREVERB_REFLECTIONSDELAY; - - case DSPROPERTY_EAX20LISTENER_REVERB: - return EAXREVERB_REVERB; - - case DSPROPERTY_EAX20LISTENER_REVERBDELAY: - return EAXREVERB_REVERBDELAY; - - case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: - return EAXREVERB_ENVIRONMENT; - - case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE: - return EAXREVERB_ENVIRONMENTSIZE; - - case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION: - return EAXREVERB_ENVIRONMENTDIFFUSION; - - case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: - return EAXREVERB_AIRABSORPTIONHF; - - case DSPROPERTY_EAX20LISTENER_FLAGS: - return EAXREVERB_FLAGS; - - default: - fail("Unsupported EAX 2.0 listener property id."); - } -} - -ALuint EaxEaxCall::convert_eax_v2_0_buffer_property_id( - ALuint property_id) -{ - switch (property_id) - { - case DSPROPERTY_EAX20BUFFER_NONE: - return EAXSOURCE_NONE; - - case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS: - return EAXSOURCE_ALLPARAMETERS; - - case DSPROPERTY_EAX20BUFFER_DIRECT: - return EAXSOURCE_DIRECT; - - case DSPROPERTY_EAX20BUFFER_DIRECTHF: - return EAXSOURCE_DIRECTHF; - - case DSPROPERTY_EAX20BUFFER_ROOM: - return EAXSOURCE_ROOM; - - case DSPROPERTY_EAX20BUFFER_ROOMHF: - return EAXSOURCE_ROOMHF; - - case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR: - return EAXSOURCE_ROOMROLLOFFFACTOR; - - case DSPROPERTY_EAX20BUFFER_OBSTRUCTION: - return EAXSOURCE_OBSTRUCTION; - - case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO: - return EAXSOURCE_OBSTRUCTIONLFRATIO; - - case DSPROPERTY_EAX20BUFFER_OCCLUSION: - return EAXSOURCE_OCCLUSION; - - case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO: - return EAXSOURCE_OCCLUSIONLFRATIO; - - case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO: - return EAXSOURCE_OCCLUSIONROOMRATIO; - - case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF: - return EAXSOURCE_OUTSIDEVOLUMEHF; - - case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR: - return EAXSOURCE_AIRABSORPTIONFACTOR; - - case DSPROPERTY_EAX20BUFFER_FLAGS: - return EAXSOURCE_FLAGS; - - default: - fail("Unsupported EAX 2.0 buffer property id."); - } -} - - -EaxEaxCall create_eax_call( - bool is_get, - const GUID* property_set_id, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_buffer, - ALuint property_size) -{ - if(!property_set_id) - throw EaxEaxCallException{"Null property set ID."}; - - return EaxEaxCall{ - is_get, - *property_set_id, - property_id, - property_source_id, - property_buffer, - property_size - }; -} diff --git a/al/eax_eax_call.h b/al/eax_eax_call.h deleted file mode 100644 index 7b990d87..00000000 --- a/al/eax_eax_call.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef EAX_EAX_CALL_INCLUDED -#define EAX_EAX_CALL_INCLUDED - - -#include "AL/al.h" - -#include "alspan.h" - -#include "eax_api.h" -#include "eax_fx_slot_index.h" - - -enum class EaxEaxCallPropertySetId -{ - none, - - context, - fx_slot, - source, - fx_slot_effect, -}; // EaxEaxCallPropertySetId - - -class EaxEaxCall -{ -public: - EaxEaxCall( - bool is_get, - const GUID& property_set_guid, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_buffer, - ALuint property_size); - - bool is_get() const noexcept { return is_get_; } - int get_version() const noexcept { return version_; } - EaxEaxCallPropertySetId get_property_set_id() const noexcept { return property_set_id_; } - ALuint get_property_id() const noexcept { return property_id_; } - ALuint get_property_al_name() const noexcept { return property_source_id_; } - EaxFxSlotIndex get_fx_slot_index() const noexcept { return fx_slot_index_; } - - template< - typename TException, - typename TValue - > - TValue& get_value() const - { - if (property_size_ < static_cast(sizeof(TValue))) - { - throw TException{"Property buffer too small."}; - } - - return *static_cast(property_buffer_); - } - - template< - typename TException, - typename TValue - > - al::span get_values() const - { - if (property_size_ < static_cast(sizeof(TValue))) - { - throw TException{"Property buffer too small."}; - } - - const auto count = property_size_ / sizeof(TValue); - - return al::span{static_cast(property_buffer_), count}; - } - - template< - typename TException, - typename TValue - > - void set_value( - const TValue& value) const - { - get_value() = value; - } - - -private: - const bool is_get_; - int version_; - EaxFxSlotIndex fx_slot_index_; - EaxEaxCallPropertySetId property_set_id_; - - ALuint property_id_; - const ALuint property_source_id_; - ALvoid*const property_buffer_; - const ALuint property_size_; - - - [[noreturn]] - static void fail( - const char* message); - - - static ALuint convert_eax_v2_0_listener_property_id( - ALuint property_id); - - static ALuint convert_eax_v2_0_buffer_property_id( - ALuint property_id); -}; // EaxEaxCall - - -EaxEaxCall create_eax_call( - bool is_get, - const GUID* property_set_id, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_buffer, - ALuint property_size); - - -#endif // !EAX_EAX_CALL_INCLUDED diff --git a/al/eax_effect.cpp b/al/eax_effect.cpp deleted file mode 100644 index 9cbf4c13..00000000 --- a/al/eax_effect.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "config.h" - -#include "eax_effect.h" diff --git a/al/eax_effect.h b/al/eax_effect.h deleted file mode 100644 index 45315ca6..00000000 --- a/al/eax_effect.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef EAX_EFFECT_INCLUDED -#define EAX_EFFECT_INCLUDED - - -#include - -#include "AL/al.h" -#include "core/effects/base.h" -#include "eax_eax_call.h" - -class EaxEffect -{ -public: - EaxEffect(ALenum type) : al_effect_type_{type} { } - virtual ~EaxEffect() = default; - - const ALenum al_effect_type_; - EffectProps al_effect_props_{}; - - virtual void dispatch(const EaxEaxCall& eax_call) = 0; - - // Returns "true" if any immediated property was changed. - // [[nodiscard]] - virtual bool apply_deferred() = 0; -}; // EaxEffect - - -using EaxEffectUPtr = std::unique_ptr; - -EaxEffectUPtr eax_create_eax_null_effect(); -EaxEffectUPtr eax_create_eax_chorus_effect(); -EaxEffectUPtr eax_create_eax_distortion_effect(); -EaxEffectUPtr eax_create_eax_echo_effect(); -EaxEffectUPtr eax_create_eax_flanger_effect(); -EaxEffectUPtr eax_create_eax_frequency_shifter_effect(); -EaxEffectUPtr eax_create_eax_vocal_morpher_effect(); -EaxEffectUPtr eax_create_eax_pitch_shifter_effect(); -EaxEffectUPtr eax_create_eax_ring_modulator_effect(); -EaxEffectUPtr eax_create_eax_auto_wah_effect(); -EaxEffectUPtr eax_create_eax_compressor_effect(); -EaxEffectUPtr eax_create_eax_equalizer_effect(); -EaxEffectUPtr eax_create_eax_reverb_effect(); - -#endif // !EAX_EFFECT_INCLUDED diff --git a/al/eax_exception.cpp b/al/eax_exception.cpp deleted file mode 100644 index fdeecaaa..00000000 --- a/al/eax_exception.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "config.h" - -#include "eax_exception.h" - -#include - -#include - - -EaxException::EaxException( - const char* context, - const char* message) - : - std::runtime_error{make_message(context, message)} -{ -} - -std::string EaxException::make_message( - const char* context, - const char* message) -{ - const auto context_size = (context ? std::string::traits_type::length(context) : 0); - const auto has_contex = (context_size > 0); - - const auto message_size = (message ? std::string::traits_type::length(message) : 0); - const auto has_message = (message_size > 0); - - if (!has_contex && !has_message) - { - return std::string{}; - } - - static constexpr char left_prefix[] = "["; - const auto left_prefix_size = std::string::traits_type::length(left_prefix); - - static constexpr char right_prefix[] = "] "; - const auto right_prefix_size = std::string::traits_type::length(right_prefix); - - const auto what_size = - ( - has_contex ? - left_prefix_size + context_size + right_prefix_size : - 0) + - message_size + - 1; - - auto what = std::string{}; - what.reserve(what_size); - - if (has_contex) - { - what.append(left_prefix, left_prefix_size); - what.append(context, context_size); - what.append(right_prefix, right_prefix_size); - } - - if (has_message) - { - what.append(message, message_size); - } - - return what; -} diff --git a/al/eax_exception.h b/al/eax_exception.h deleted file mode 100644 index 9a7acf71..00000000 --- a/al/eax_exception.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef EAX_EXCEPTION_INCLUDED -#define EAX_EXCEPTION_INCLUDED - - -#include -#include - - -class EaxException : - public std::runtime_error -{ -public: - EaxException( - const char* context, - const char* message); - - -private: - static std::string make_message( - const char* context, - const char* message); -}; // EaxException - - -#endif // !EAX_EXCEPTION_INCLUDED diff --git a/al/eax_fx_slot_index.cpp b/al/eax_fx_slot_index.cpp deleted file mode 100644 index 9aa695ad..00000000 --- a/al/eax_fx_slot_index.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "config.h" - -#include "eax_fx_slot_index.h" - -#include "eax_exception.h" - - -namespace -{ - - -class EaxFxSlotIndexException : - public EaxException -{ -public: - explicit EaxFxSlotIndexException( - const char* message) - : - EaxException{"EAX_FX_SLOT_INDEX", message} - { - } -}; // EaxFxSlotIndexException - - -} // namespace - - -void EaxFxSlotIndex::set(EaxFxSlotIndexValue index) -{ - if(index >= EaxFxSlotIndexValue{EAX_MAX_FXSLOTS}) - fail("Index out of range."); - - emplace(index); -} - -void EaxFxSlotIndex::set(const GUID &guid) -{ - if (false) - { - } - else if (guid == EAX_NULL_GUID) - { - reset(); - } - else if (guid == EAXPROPERTYID_EAX40_FXSlot0 || guid == EAXPROPERTYID_EAX50_FXSlot0) - { - emplace(0u); - } - else if (guid == EAXPROPERTYID_EAX40_FXSlot1 || guid == EAXPROPERTYID_EAX50_FXSlot1) - { - emplace(1u); - } - else if (guid == EAXPROPERTYID_EAX40_FXSlot2 || guid == EAXPROPERTYID_EAX50_FXSlot2) - { - emplace(2u); - } - else if (guid == EAXPROPERTYID_EAX40_FXSlot3 || guid == EAXPROPERTYID_EAX50_FXSlot3) - { - emplace(3u); - } - else - { - fail("Unsupported GUID."); - } -} - -[[noreturn]] -void EaxFxSlotIndex::fail(const char* message) -{ - throw EaxFxSlotIndexException{message}; -} diff --git a/al/eax_fx_slot_index.h b/al/eax_fx_slot_index.h deleted file mode 100644 index e1e5475a..00000000 --- a/al/eax_fx_slot_index.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef EAX_FX_SLOT_INDEX_INCLUDED -#define EAX_FX_SLOT_INDEX_INCLUDED - - -#include - -#include "aloptional.h" -#include "eax_api.h" - - -using EaxFxSlotIndexValue = std::size_t; - -class EaxFxSlotIndex : public al::optional -{ -public: - using al::optional::optional; - - EaxFxSlotIndex& operator=(const EaxFxSlotIndexValue &value) { set(value); return *this; } - EaxFxSlotIndex& operator=(const GUID &guid) { set(guid); return *this; } - - void set(EaxFxSlotIndexValue index); - void set(const GUID& guid); - -private: - [[noreturn]] - static void fail(const char *message); -}; // EaxFxSlotIndex - -inline bool operator==(const EaxFxSlotIndex& lhs, const EaxFxSlotIndex& rhs) noexcept -{ - if(lhs.has_value() != rhs.has_value()) - return false; - if(lhs.has_value()) - return *lhs == *rhs; - return true; -} - -inline bool operator!=(const EaxFxSlotIndex& lhs, const EaxFxSlotIndex& rhs) noexcept -{ return !(lhs == rhs); } - -#endif // !EAX_FX_SLOT_INDEX_INCLUDED diff --git a/al/eax_fx_slots.cpp b/al/eax_fx_slots.cpp deleted file mode 100644 index 3a27dabd..00000000 --- a/al/eax_fx_slots.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "config.h" - -#include "eax_fx_slots.h" - -#include - -#include "eax_exception.h" - -#include "eax_api.h" - - -namespace -{ - - -class EaxFxSlotsException : - public EaxException -{ -public: - explicit EaxFxSlotsException( - const char* message) - : - EaxException{"EAX_FX_SLOTS", message} - { - } -}; // EaxFxSlotsException - - -} // namespace - - -void EaxFxSlots::initialize( - ALCcontext& al_context) -{ - initialize_fx_slots(al_context); -} - -void EaxFxSlots::uninitialize() noexcept -{ - for (auto& fx_slot : fx_slots_) - { - fx_slot = nullptr; - } -} - -const ALeffectslot& EaxFxSlots::get(EaxFxSlotIndex index) const -{ - if(!index.has_value()) - fail("Empty index."); - return *fx_slots_[index.value()]; -} - -ALeffectslot& EaxFxSlots::get(EaxFxSlotIndex index) -{ - if(!index.has_value()) - fail("Empty index."); - return *fx_slots_[index.value()]; -} - -void EaxFxSlots::unlock_legacy() noexcept -{ - fx_slots_[0]->eax_unlock_legacy(); - fx_slots_[1]->eax_unlock_legacy(); -} - -[[noreturn]] -void EaxFxSlots::fail( - const char* message) -{ - throw EaxFxSlotsException{message}; -} - -void EaxFxSlots::initialize_fx_slots( - ALCcontext& al_context) -{ - auto fx_slot_index = EaxFxSlotIndexValue{}; - - for (auto& fx_slot : fx_slots_) - { - fx_slot = eax_create_al_effect_slot(al_context); - fx_slot->eax_initialize(al_context, fx_slot_index); - fx_slot_index += 1; - } -} diff --git a/al/eax_fx_slots.h b/al/eax_fx_slots.h deleted file mode 100644 index a104c6ab..00000000 --- a/al/eax_fx_slots.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef EAX_FX_SLOTS_INCLUDED -#define EAX_FX_SLOTS_INCLUDED - - -#include - -#include "al/auxeffectslot.h" - -#include "eax_api.h" - -#include "eax_fx_slot_index.h" - - -class EaxFxSlots -{ -public: - void initialize( - ALCcontext& al_context); - - void uninitialize() noexcept; - - void commit() - { - for(auto& fx_slot : fx_slots_) - fx_slot->eax_commit(); - } - - - const ALeffectslot& get( - EaxFxSlotIndex index) const; - - ALeffectslot& get( - EaxFxSlotIndex index); - - void unlock_legacy() noexcept; - - -private: - using Items = std::array; - - - Items fx_slots_{}; - - - [[noreturn]] - static void fail( - const char* message); - - void initialize_fx_slots( - ALCcontext& al_context); -}; // EaxFxSlots - - -#endif // !EAX_FX_SLOTS_INCLUDED diff --git a/al/eax_globals.cpp b/al/eax_globals.cpp deleted file mode 100644 index 07909459..00000000 --- a/al/eax_globals.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "config.h" - -#include "eax_globals.h" - - -bool eax_g_is_enabled = true; - - -const char eax1_ext_name[] = "EAX"; -const char eax2_ext_name[] = "EAX2.0"; -const char eax3_ext_name[] = "EAX3.0"; -const char eax4_ext_name[] = "EAX4.0"; -const char eax5_ext_name[] = "EAX5.0"; - -const char eax_x_ram_ext_name[] = "EAX-RAM"; - -const char eax_eax_set_func_name[] = "EAXSet"; -const char eax_eax_get_func_name[] = "EAXGet"; - -const char eax_eax_set_buffer_mode_func_name[] = "EAXSetBufferMode"; -const char eax_eax_get_buffer_mode_func_name[] = "EAXGetBufferMode"; diff --git a/al/eax_globals.h b/al/eax_globals.h deleted file mode 100644 index 1b4d63b8..00000000 --- a/al/eax_globals.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef EAX_GLOBALS_INCLUDED -#define EAX_GLOBALS_INCLUDED - - -extern bool eax_g_is_enabled; - - -extern const char eax1_ext_name[]; -extern const char eax2_ext_name[]; -extern const char eax3_ext_name[]; -extern const char eax4_ext_name[]; -extern const char eax5_ext_name[]; - -extern const char eax_x_ram_ext_name[]; - -extern const char eax_eax_set_func_name[]; -extern const char eax_eax_get_func_name[]; - -extern const char eax_eax_set_buffer_mode_func_name[]; -extern const char eax_eax_get_buffer_mode_func_name[]; - -#endif // !EAX_GLOBALS_INCLUDED diff --git a/al/eax_utils.cpp b/al/eax_utils.cpp deleted file mode 100644 index 67389de4..00000000 --- a/al/eax_utils.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "config.h" - -#include "eax_utils.h" - -#include -#include - -#include "core/logging.h" - - -void eax_log_exception( - const char* message) noexcept -{ - const auto exception_ptr = std::current_exception(); - - assert(exception_ptr); - - if (message) - { - ERR("%s\n", message); - } - - try - { - std::rethrow_exception(exception_ptr); - } - catch (const std::exception& ex) - { - const auto ex_message = ex.what(); - ERR("%s\n", ex_message); - } - catch (...) - { - ERR("%s\n", "Generic exception."); - } -} diff --git a/al/eax_utils.h b/al/eax_utils.h deleted file mode 100644 index d3d4a196..00000000 --- a/al/eax_utils.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef EAX_UTILS_INCLUDED -#define EAX_UTILS_INCLUDED - -#include -#include -#include -#include - - -struct EaxAlLowPassParam -{ - float gain; - float gain_hf; -}; // EaxAlLowPassParam - - -void eax_log_exception( - const char* message = nullptr) noexcept; - - -template< - typename TException, - typename TValue -> -void eax_validate_range( - const char* value_name, - const TValue& value, - const TValue& min_value, - const TValue& max_value) -{ - if (value >= min_value && value <= max_value) - { - return; - } - - const auto message = - std::string{value_name} + - " out of range (value: " + - std::to_string(value) + "; min: " + - std::to_string(min_value) + "; max: " + - std::to_string(max_value) + ")."; - - throw TException{message.c_str()}; -} - - -namespace detail -{ - - -template< - typename T -> -struct EaxIsBitFieldStruct -{ -private: - using yes = std::true_type; - using no = std::false_type; - - template< - typename U - > - static auto test(int) -> decltype(std::declval(), yes{}); - - template< - typename - > - static no test(...); - - -public: - static constexpr auto value = std::is_same(0)), yes>::value; -}; // EaxIsBitFieldStruct - - -template< - typename T, - typename TValue -> -inline bool eax_bit_fields_are_equal( - const T& lhs, - const T& rhs) noexcept -{ - static_assert(sizeof(T) == sizeof(TValue), "Invalid type size."); - - return reinterpret_cast(lhs) == reinterpret_cast(rhs); -} - - -} // namespace detail - - -template< - typename T, - std::enable_if_t::value, int> = 0 -> -inline bool operator==( - const T& lhs, - const T& rhs) noexcept -{ - using Value = std::conditional_t< - sizeof(T) == 1, - std::uint8_t, - std::conditional_t< - sizeof(T) == 2, - std::uint16_t, - std::conditional_t< - sizeof(T) == 4, - std::uint32_t, - void - > - > - >; - - static_assert(!std::is_same::value, "Unsupported type."); - - return detail::eax_bit_fields_are_equal(lhs, rhs); -} - -template< - typename T, - std::enable_if_t::value, int> = 0 -> -inline bool operator!=( - const T& lhs, - const T& rhs) noexcept -{ - return !(lhs == rhs); -} - - -#endif // !EAX_UTILS_INCLUDED diff --git a/al/eax_x_ram.cpp b/al/eax_x_ram.cpp deleted file mode 100644 index ac3e7ebb..00000000 --- a/al/eax_x_ram.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "config.h" - -#include "eax_x_ram.h" diff --git a/al/eax_x_ram.h b/al/eax_x_ram.h deleted file mode 100644 index 438b9916..00000000 --- a/al/eax_x_ram.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef EAX_X_RAM_INCLUDED -#define EAX_X_RAM_INCLUDED - - -#include "AL/al.h" - - -constexpr auto eax_x_ram_min_size = ALsizei{}; -constexpr auto eax_x_ram_max_size = ALsizei{64 * 1'024 * 1'024}; - - -constexpr auto AL_EAX_RAM_SIZE = ALenum{0x202201}; -constexpr auto AL_EAX_RAM_FREE = ALenum{0x202202}; - -constexpr auto AL_STORAGE_AUTOMATIC = ALenum{0x202203}; -constexpr auto AL_STORAGE_HARDWARE = ALenum{0x202204}; -constexpr auto AL_STORAGE_ACCESSIBLE = ALenum{0x202205}; - - -constexpr auto AL_EAX_RAM_SIZE_NAME = "AL_EAX_RAM_SIZE"; -constexpr auto AL_EAX_RAM_FREE_NAME = "AL_EAX_RAM_FREE"; - -constexpr auto AL_STORAGE_AUTOMATIC_NAME = "AL_STORAGE_AUTOMATIC"; -constexpr auto AL_STORAGE_HARDWARE_NAME = "AL_STORAGE_HARDWARE"; -constexpr auto AL_STORAGE_ACCESSIBLE_NAME = "AL_STORAGE_ACCESSIBLE"; - - -ALboolean AL_APIENTRY EAXSetBufferMode( - ALsizei n, - const ALuint* buffers, - ALint value); - -ALenum AL_APIENTRY EAXGetBufferMode( - ALuint buffer, - ALint* pReserved); - - -#endif // !EAX_X_RAM_INCLUDED diff --git a/al/effect.cpp b/al/effect.cpp index 5a74ca53..90a4dfde 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -54,7 +54,7 @@ #ifdef ALSOFT_EAX #include -#include "eax_exception.h" +#include "eax/exception.h" #endif // ALSOFT_EAX const EffectList gEffectList[16]{ diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 273ec7ae..23f43305 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -14,8 +14,8 @@ #ifdef ALSOFT_EAX #include "alnumeric.h" -#include "al/eax_exception.h" -#include "al/eax_utils.h" +#include "al/eax/exception.h" +#include "al/eax/utils.h" #endif // ALSOFT_EAX diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index 56318095..b612a6c1 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -16,8 +16,8 @@ #include "alnumeric.h" -#include "al/eax_exception.h" -#include "al/eax_utils.h" +#include "al/eax/exception.h" +#include "al/eax/utils.h" #endif // ALSOFT_EAX diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp index bb5dfa3e..a18609ca 100644 --- a/al/effects/compressor.cpp +++ b/al/effects/compressor.cpp @@ -10,8 +10,8 @@ #ifdef ALSOFT_EAX #include "alnumeric.h" -#include "al/eax_exception.h" -#include "al/eax_utils.h" +#include "al/eax/exception.h" +#include "al/eax/utils.h" #endif // ALSOFT_EAX diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index 13b1f23d..441b89a0 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -10,8 +10,8 @@ #ifdef ALSOFT_EAX #include "alnumeric.h" -#include "al/eax_exception.h" -#include "al/eax_utils.h" +#include "al/eax/exception.h" +#include "al/eax/utils.h" #endif // ALSOFT_EAX diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index 61adad7f..56849b9d 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -10,8 +10,8 @@ #ifdef ALSOFT_EAX #include "alnumeric.h" -#include "al/eax_exception.h" -#include "al/eax_utils.h" +#include "al/eax/exception.h" +#include "al/eax/utils.h" #endif // ALSOFT_EAX diff --git a/al/effects/effects.h b/al/effects/effects.h index 830e7191..f8b97eeb 100644 --- a/al/effects/effects.h +++ b/al/effects/effects.h @@ -6,7 +6,7 @@ #include "core/except.h" #ifdef ALSOFT_EAX -#include "al/eax_effect.h" +#include "al/eax/effect.h" #endif // ALSOFT_EAX union EffectProps; diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index f829328c..ccc00f67 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -10,8 +10,8 @@ #ifdef ALSOFT_EAX #include "alnumeric.h" -#include "al/eax_exception.h" -#include "al/eax_utils.h" +#include "al/eax/exception.h" +#include "al/eax/utils.h" #endif // ALSOFT_EAX diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index d334890b..1ca97ecb 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -15,8 +15,8 @@ #include "alnumeric.h" -#include "al/eax_exception.h" -#include "al/eax_utils.h" +#include "al/eax/exception.h" +#include "al/eax/utils.h" #endif // ALSOFT_EAX diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index 800b892d..082597cd 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -15,8 +15,8 @@ #include "alnumeric.h" -#include "al/eax_exception.h" -#include "al/eax_utils.h" +#include "al/eax/exception.h" +#include "al/eax/utils.h" #endif // ALSOFT_EAX diff --git a/al/effects/null.cpp b/al/effects/null.cpp index a0eb2247..0ec387d4 100644 --- a/al/effects/null.cpp +++ b/al/effects/null.cpp @@ -8,7 +8,7 @@ #include "effects.h" #ifdef ALSOFT_EAX -#include "al/eax_exception.h" +#include "al/eax/exception.h" #endif // ALSOFT_EAX diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp index 1b2dcff0..cb81d831 100644 --- a/al/effects/pshifter.cpp +++ b/al/effects/pshifter.cpp @@ -10,8 +10,8 @@ #ifdef ALSOFT_EAX #include "alnumeric.h" -#include "al/eax_exception.h" -#include "al/eax_utils.h" +#include "al/eax/exception.h" +#include "al/eax/utils.h" #endif // ALSOFT_EAX diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index 197ea500..4184eda0 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -11,10 +11,13 @@ #ifdef ALSOFT_EAX #include -#include "alnumeric.h" + #include "AL/efx-presets.h" -#include "al/eax_exception.h" -#include "al/eax_utils.h" + +#include "alnumeric.h" + +#include "al/eax/exception.h" +#include "al/eax/utils.h" #endif // ALSOFT_EAX diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index 8c0b3adb..da513015 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -15,8 +15,8 @@ #include "alnumeric.h" -#include "al/eax_exception.h" -#include "al/eax_utils.h" +#include "al/eax/exception.h" +#include "al/eax/utils.h" #endif // ALSOFT_EAX diff --git a/al/source.cpp b/al/source.cpp index d2ccfe08..604d4566 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -73,7 +73,7 @@ #include "threads.h" #ifdef ALSOFT_EAX -#include "eax_exception.h" +#include "eax/exception.h" #endif // ALSOFT_EAX namespace { diff --git a/al/source.h b/al/source.h index 6db6bfa7..6fc1c1d4 100644 --- a/al/source.h +++ b/al/source.h @@ -22,9 +22,9 @@ #include "vector.h" #ifdef ALSOFT_EAX -#include "eax_eax_call.h" -#include "eax_fx_slot_index.h" -#include "eax_utils.h" +#include "eax/eax_call.h" +#include "eax/fx_slot_index.h" +#include "eax/utils.h" #endif // ALSOFT_EAX struct ALbuffer; diff --git a/al/state.cpp b/al/state.cpp index 1a07f624..f41016d6 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -49,8 +49,8 @@ #ifdef ALSOFT_EAX #include "alc/device.h" -#include "eax_globals.h" -#include "eax_x_ram.h" +#include "eax/globals.h" +#include "eax/x_ram.h" #endif // ALSOFT_EAX diff --git a/alc/alc.cpp b/alc/alc.cpp index 686b794e..3fa0d353 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -156,8 +156,8 @@ #endif #ifdef ALSOFT_EAX -#include "al/eax_globals.h" -#include "al/eax_x_ram.h" +#include "al/eax/globals.h" +#include "al/eax/x_ram.h" #endif // ALSOFT_EAX diff --git a/alc/context.cpp b/alc/context.cpp index 34da3784..5fe03e78 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -34,8 +34,8 @@ #include #include "alstring.h" -#include "al/eax_exception.h" -#include "al/eax_globals.h" +#include "al/eax/exception.h" +#include "al/eax/globals.h" #endif // ALSOFT_EAX namespace { diff --git a/alc/context.h b/alc/context.h index 72b259e9..b3f1ea09 100644 --- a/alc/context.h +++ b/alc/context.h @@ -20,10 +20,10 @@ #include "vector.h" #ifdef ALSOFT_EAX -#include "al/eax_eax_call.h" -#include "al/eax_fx_slot_index.h" -#include "al/eax_fx_slots.h" -#include "al/eax_utils.h" +#include "al/eax/eax_call.h" +#include "al/eax/fx_slot_index.h" +#include "al/eax/fx_slots.h" +#include "al/eax/utils.h" using EaxContextSharedDirtyFlagsValue = std::uint_least8_t; diff --git a/alc/device.h b/alc/device.h index 434d4d8f..ef50f53e 100644 --- a/alc/device.h +++ b/alc/device.h @@ -20,7 +20,7 @@ #include "vector.h" #ifdef ALSOFT_EAX -#include "al/eax_x_ram.h" +#include "al/eax/x_ram.h" #endif // ALSOFT_EAX struct ALbuffer; -- cgit v1.2.3 From 074dbef2e3129e9f7ee4895c44721c2a0a4b045b Mon Sep 17 00:00:00 2001 From: "Boris I. Bendovsky" Date: Tue, 24 May 2022 12:19:14 +0300 Subject: [EAX] Add separate effect state for each version (#705) * [EAX] Add separate effect state for each version * [EAX] Don't use EAX call as data member --- CMakeLists.txt | 6 +- al/auxeffectslot.cpp | 194 ++-- al/auxeffectslot.h | 99 +- al/eax/api.cpp | 621 ++++++++++- al/eax/api.h | 114 +- al/eax/call.cpp | 212 ++++ al/eax/call.h | 92 ++ al/eax/eax_call.cpp | 323 ------ al/eax/eax_call.h | 117 -- al/eax/effect.cpp | 3 - al/eax/effect.h | 165 ++- al/eax/fx_slots.cpp | 6 +- al/eax/fx_slots.h | 3 + al/eax/x_ram.cpp | 3 - al/effects/autowah.cpp | 482 +++----- al/effects/chorus.cpp | 1399 +++++++---------------- al/effects/compressor.cpp | 230 ++-- al/effects/distortion.cpp | 510 +++------ al/effects/echo.cpp | 511 +++------ al/effects/effects.cpp | 26 +- al/effects/effects.h | 3 +- al/effects/equalizer.cpp | 862 +++++---------- al/effects/fshifter.cpp | 359 ++---- al/effects/modulator.cpp | 365 ++---- al/effects/null.cpp | 36 +- al/effects/pshifter.cpp | 301 ++--- al/effects/reverb.cpp | 2696 ++++++++++++++++++--------------------------- al/effects/vmorpher.cpp | 552 +++------- al/source.cpp | 363 +++--- al/source.h | 103 +- alc/context.cpp | 214 ++-- alc/context.h | 68 +- 32 files changed, 4299 insertions(+), 6739 deletions(-) create mode 100644 al/eax/call.cpp create mode 100644 al/eax/call.h delete mode 100644 al/eax/eax_call.cpp delete mode 100644 al/eax/eax_call.h delete mode 100644 al/eax/effect.cpp delete mode 100644 al/eax/x_ram.cpp (limited to 'al/effects/distortion.cpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index 52d61ff0..4a3ce192 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -800,9 +800,8 @@ if (ALSOFT_EAX) ${OPENAL_OBJS} al/eax/api.cpp al/eax/api.h - al/eax/eax_call.cpp - al/eax/eax_call.h - al/eax/effect.cpp + al/eax/call.cpp + al/eax/call.h al/eax/effect.h al/eax/exception.cpp al/eax/exception.h @@ -814,7 +813,6 @@ if (ALSOFT_EAX) al/eax/globals.h al/eax/utils.cpp al/eax/utils.h - al/eax/x_ram.cpp al/eax/x_ram.h ) endif () diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 455a1072..d37168e7 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -1076,6 +1076,7 @@ public: void ALeffectslot::eax_initialize( + const EaxCall& call, ALCcontext& al_context, EaxFxSlotIndexValue index) { @@ -1090,7 +1091,7 @@ void ALeffectslot::eax_initialize( eax_initialize_eax(); eax_initialize_lock(); - eax_initialize_effects(); + eax_initialize_effects(call); } const EAX50FXSLOTPROPERTIES& ALeffectslot::eax_get_eax_fx_slot() const noexcept @@ -1104,8 +1105,7 @@ void ALeffectslot::eax_ensure_is_unlocked() const eax_fail("Locked."); } -void ALeffectslot::eax_validate_fx_slot_effect( - const GUID& eax_effect_id) +void ALeffectslot::eax_validate_fx_slot_effect(const GUID& eax_effect_id) { eax_ensure_is_unlocked(); @@ -1127,8 +1127,7 @@ void ALeffectslot::eax_validate_fx_slot_effect( } } -void ALeffectslot::eax_validate_fx_slot_volume( - long eax_volume) +void ALeffectslot::eax_validate_fx_slot_volume(long eax_volume) { eax_validate_range( "Volume", @@ -1137,8 +1136,7 @@ void ALeffectslot::eax_validate_fx_slot_volume( EAXFXSLOT_MAXVOLUME); } -void ALeffectslot::eax_validate_fx_slot_lock( - long eax_lock) +void ALeffectslot::eax_validate_fx_slot_lock(long eax_lock) { eax_ensure_is_unlocked(); @@ -1149,19 +1147,16 @@ void ALeffectslot::eax_validate_fx_slot_lock( EAXFXSLOT_MAXLOCK); } -void ALeffectslot::eax_validate_fx_slot_flags( - unsigned long eax_flags, - int eax_version) +void ALeffectslot::eax_validate_fx_slot_flags(const EaxCall& call, unsigned long eax_flags) { eax_validate_range( "Flags", eax_flags, 0UL, - ~(eax_version == 4 ? EAX40FXSLOTFLAGS_RESERVED : EAX50FXSLOTFLAGS_RESERVED)); + ~(call.get_version() == 4 ? EAX40FXSLOTFLAGS_RESERVED : EAX50FXSLOTFLAGS_RESERVED)); } -void ALeffectslot::eax_validate_fx_slot_occlusion( - long eax_occlusion) +void ALeffectslot::eax_validate_fx_slot_occlusion(long eax_occlusion) { eax_validate_range( "Occlusion", @@ -1170,8 +1165,7 @@ void ALeffectslot::eax_validate_fx_slot_occlusion( EAXFXSLOT_MAXOCCLUSION); } -void ALeffectslot::eax_validate_fx_slot_occlusion_lf_ratio( - float eax_occlusion_lf_ratio) +void ALeffectslot::eax_validate_fx_slot_occlusion_lf_ratio(float eax_occlusion_lf_ratio) { eax_validate_range( "Occlusion LF Ratio", @@ -1180,28 +1174,22 @@ void ALeffectslot::eax_validate_fx_slot_occlusion_lf_ratio( EAXFXSLOT_MAXOCCLUSIONLFRATIO); } -void ALeffectslot::eax_validate_fx_slot_all( - const EAX40FXSLOTPROPERTIES& fx_slot, - int eax_version) +void ALeffectslot::eax_validate_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& fx_slot) { eax_validate_fx_slot_effect(fx_slot.guidLoadEffect); eax_validate_fx_slot_volume(fx_slot.lVolume); eax_validate_fx_slot_lock(fx_slot.lLock); - eax_validate_fx_slot_flags(fx_slot.ulFlags, eax_version); + eax_validate_fx_slot_flags(call, fx_slot.ulFlags); } -void ALeffectslot::eax_validate_fx_slot_all( - const EAX50FXSLOTPROPERTIES& fx_slot, - int eax_version) +void ALeffectslot::eax_validate_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& fx_slot) { - eax_validate_fx_slot_all(static_cast(fx_slot), eax_version); - + eax_validate_fx_slot_all(call, static_cast(fx_slot)); eax_validate_fx_slot_occlusion(fx_slot.lOcclusion); eax_validate_fx_slot_occlusion_lf_ratio(fx_slot.flOcclusionLFRatio); } -void ALeffectslot::eax_set_fx_slot_effect( - const GUID& eax_effect_id) +void ALeffectslot::eax_set_fx_slot_effect(const EaxCall& call, const GUID& eax_effect_id) { if (eax_eax_fx_slot_.guidLoadEffect == eax_effect_id) { @@ -1210,7 +1198,7 @@ void ALeffectslot::eax_set_fx_slot_effect( eax_eax_fx_slot_.guidLoadEffect = eax_effect_id; - eax_set_fx_slot_effect(); + eax_set_fx_slot_effect(call); } void ALeffectslot::eax_set_fx_slot_volume( @@ -1278,20 +1266,18 @@ bool ALeffectslot::eax_set_fx_slot_occlusion_lf_ratio( return true; } -void ALeffectslot::eax_set_fx_slot_all( - const EAX40FXSLOTPROPERTIES& eax_fx_slot) +void ALeffectslot::eax_set_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& eax_fx_slot) { - eax_set_fx_slot_effect(eax_fx_slot.guidLoadEffect); + eax_set_fx_slot_effect(call, eax_fx_slot.guidLoadEffect); eax_set_fx_slot_volume(eax_fx_slot.lVolume); eax_set_fx_slot_lock(eax_fx_slot.lLock); eax_set_fx_slot_flags(eax_fx_slot.ulFlags); } // [[nodiscard]] -bool ALeffectslot::eax_set_fx_slot_all( - const EAX50FXSLOTPROPERTIES& eax_fx_slot) +bool ALeffectslot::eax_set_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& eax_fx_slot) { - eax_set_fx_slot_all(static_cast(eax_fx_slot)); + eax_set_fx_slot_all(call, static_cast(eax_fx_slot)); const auto is_occlusion_modified = eax_set_fx_slot_occlusion(eax_fx_slot.lOcclusion); const auto is_occlusion_lf_ratio_modified = eax_set_fx_slot_occlusion_lf_ratio(eax_fx_slot.flOcclusionLFRatio); @@ -1348,22 +1334,21 @@ void ALeffectslot::eax_initialize_lock() eax_is_locked_ = (eax_fx_slot_index_ < 2); } -void ALeffectslot::eax_initialize_effects() +void ALeffectslot::eax_initialize_effects(const EaxCall& call) { - eax_set_fx_slot_effect(); + eax_set_fx_slot_effect(call); } -void ALeffectslot::eax_get_fx_slot_all( - const EaxEaxCall& eax_call) const +void ALeffectslot::eax_get_fx_slot_all(const EaxCall& call) const { - switch (eax_call.get_version()) + switch (call.get_version()) { case 4: - eax_call.set_value(eax_eax_fx_slot_); + call.set_value(eax_eax_fx_slot_); break; case 5: - eax_call.set_value(eax_eax_fx_slot_); + call.set_value(eax_eax_fx_slot_); break; default: @@ -1371,37 +1356,36 @@ void ALeffectslot::eax_get_fx_slot_all( } } -void ALeffectslot::eax_get_fx_slot( - const EaxEaxCall& eax_call) const +void ALeffectslot::eax_get_fx_slot(const EaxCall& call) const { - switch (eax_call.get_property_id()) + switch (call.get_property_id()) { case EAXFXSLOT_ALLPARAMETERS: - eax_get_fx_slot_all(eax_call); + eax_get_fx_slot_all(call); break; case EAXFXSLOT_LOADEFFECT: - eax_call.set_value(eax_eax_fx_slot_.guidLoadEffect); + call.set_value(eax_eax_fx_slot_.guidLoadEffect); break; case EAXFXSLOT_VOLUME: - eax_call.set_value(eax_eax_fx_slot_.lVolume); + call.set_value(eax_eax_fx_slot_.lVolume); break; case EAXFXSLOT_LOCK: - eax_call.set_value(eax_eax_fx_slot_.lLock); + call.set_value(eax_eax_fx_slot_.lLock); break; case EAXFXSLOT_FLAGS: - eax_call.set_value(eax_eax_fx_slot_.ulFlags); + call.set_value(eax_eax_fx_slot_.ulFlags); break; case EAXFXSLOT_OCCLUSION: - eax_call.set_value(eax_eax_fx_slot_.lOcclusion); + call.set_value(eax_eax_fx_slot_.lOcclusion); break; case EAXFXSLOT_OCCLUSIONLFRATIO: - eax_call.set_value(eax_eax_fx_slot_.flOcclusionLFRatio); + call.set_value(eax_eax_fx_slot_.flOcclusionLFRatio); break; default: @@ -1410,17 +1394,16 @@ void ALeffectslot::eax_get_fx_slot( } // [[nodiscard]] -bool ALeffectslot::eax_get( - const EaxEaxCall& eax_call) +bool ALeffectslot::eax_get(const EaxCall& call) { - switch (eax_call.get_property_set_id()) + switch (call.get_property_set_id()) { - case EaxEaxCallPropertySetId::fx_slot: - eax_get_fx_slot(eax_call); + case EaxCallPropertySetId::fx_slot: + eax_get_fx_slot(call); break; - case EaxEaxCallPropertySetId::fx_slot_effect: - eax_dispatch_effect(eax_call); + case EaxCallPropertySetId::fx_slot_effect: + eax_dispatch_effect(call); break; default: @@ -1430,19 +1413,18 @@ bool ALeffectslot::eax_get( return false; } -void ALeffectslot::eax_set_fx_slot_effect( - ALenum al_effect_type) +void ALeffectslot::eax_set_fx_slot_effect(const EaxCall& call, ALenum al_effect_type) { if(!IsValidEffectType(al_effect_type)) eax_fail("Unsupported effect."); eax_effect_ = nullptr; - eax_effect_ = eax_create_eax_effect(al_effect_type); + eax_effect_ = eax_create_eax_effect(al_effect_type, call); eax_set_effect_slot_effect(*eax_effect_); } -void ALeffectslot::eax_set_fx_slot_effect() +void ALeffectslot::eax_set_fx_slot_effect(const EaxCall& call) { auto al_effect_type = ALenum{}; @@ -1506,7 +1488,7 @@ void ALeffectslot::eax_set_fx_slot_effect() eax_fail("Unsupported effect."); } - eax_set_fx_slot_effect(al_effect_type); + eax_set_fx_slot_effect(call, al_effect_type); } void ALeffectslot::eax_set_efx_effect_slot_gain() @@ -1535,52 +1517,47 @@ void ALeffectslot::eax_set_fx_slot_flags() eax_set_effect_slot_send_auto(); } -void ALeffectslot::eax_set_fx_slot_effect( - const EaxEaxCall& eax_call) +void ALeffectslot::eax_defer_fx_slot_effect(const EaxCall& call) { const auto& eax_effect_id = - eax_call.get_value(); + call.get_value(); eax_validate_fx_slot_effect(eax_effect_id); - eax_set_fx_slot_effect(eax_effect_id); + eax_set_fx_slot_effect(call, eax_effect_id); } -void ALeffectslot::eax_set_fx_slot_volume( - const EaxEaxCall& eax_call) +void ALeffectslot::eax_defer_fx_slot_volume(const EaxCall& call) { const auto& eax_volume = - eax_call.get_value(); + call.get_value(); eax_validate_fx_slot_volume(eax_volume); eax_set_fx_slot_volume(eax_volume); } -void ALeffectslot::eax_set_fx_slot_lock( - const EaxEaxCall& eax_call) +void ALeffectslot::eax_defer_fx_slot_lock(const EaxCall& call) { const auto& eax_lock = - eax_call.get_value(); + call.get_value(); eax_validate_fx_slot_lock(eax_lock); eax_set_fx_slot_lock(eax_lock); } -void ALeffectslot::eax_set_fx_slot_flags( - const EaxEaxCall& eax_call) +void ALeffectslot::eax_defer_fx_slot_flags(const EaxCall& call) { const auto& eax_flags = - eax_call.get_value(); + call.get_value(); - eax_validate_fx_slot_flags(eax_flags, eax_call.get_version()); + eax_validate_fx_slot_flags(call, eax_flags); eax_set_fx_slot_flags(eax_flags); } // [[nodiscard]] -bool ALeffectslot::eax_set_fx_slot_occlusion( - const EaxEaxCall& eax_call) +bool ALeffectslot::eax_defer_fx_slot_occlusion(const EaxCall& call) { const auto& eax_occlusion = - eax_call.get_value(); + call.get_value(); eax_validate_fx_slot_occlusion(eax_occlusion); @@ -1588,11 +1565,10 @@ bool ALeffectslot::eax_set_fx_slot_occlusion( } // [[nodiscard]] -bool ALeffectslot::eax_set_fx_slot_occlusion_lf_ratio( - const EaxEaxCall& eax_call) +bool ALeffectslot::eax_defer_fx_slot_occlusion_lf_ratio(const EaxCall& call) { const auto& eax_occlusion_lf_ratio = - eax_call.get_value(); + call.get_value(); eax_validate_fx_slot_occlusion_lf_ratio(eax_occlusion_lf_ratio); @@ -1600,18 +1576,17 @@ bool ALeffectslot::eax_set_fx_slot_occlusion_lf_ratio( } // [[nodiscard]] -bool ALeffectslot::eax_set_fx_slot_all( - const EaxEaxCall& eax_call) +bool ALeffectslot::eax_defer_fx_slot_all(const EaxCall& call) { - switch (eax_call.get_version()) + switch (call.get_version()) { case 4: { const auto& eax_all = - eax_call.get_value(); + call.get_value(); - eax_validate_fx_slot_all(eax_all, eax_call.get_version()); - eax_set_fx_slot_all(eax_all); + eax_validate_fx_slot_all(call, eax_all); + eax_set_fx_slot_all(call, eax_all); return false; } @@ -1619,10 +1594,10 @@ bool ALeffectslot::eax_set_fx_slot_all( case 5: { const auto& eax_all = - eax_call.get_value(); + call.get_value(); - eax_validate_fx_slot_all(eax_all, eax_call.get_version()); - return eax_set_fx_slot_all(eax_all); + eax_validate_fx_slot_all(call, eax_all); + return eax_set_fx_slot_all(call, eax_all); } default: @@ -1630,38 +1605,37 @@ bool ALeffectslot::eax_set_fx_slot_all( } } -bool ALeffectslot::eax_set_fx_slot( - const EaxEaxCall& eax_call) +bool ALeffectslot::eax_set_fx_slot(const EaxCall& call) { - switch (eax_call.get_property_id()) + switch (call.get_property_id()) { case EAXFXSLOT_NONE: return false; case EAXFXSLOT_ALLPARAMETERS: - return eax_set_fx_slot_all(eax_call); + return eax_defer_fx_slot_all(call); case EAXFXSLOT_LOADEFFECT: - eax_set_fx_slot_effect(eax_call); + eax_defer_fx_slot_effect(call); return false; case EAXFXSLOT_VOLUME: - eax_set_fx_slot_volume(eax_call); + eax_defer_fx_slot_volume(call); return false; case EAXFXSLOT_LOCK: - eax_set_fx_slot_lock(eax_call); + eax_defer_fx_slot_lock(call); return false; case EAXFXSLOT_FLAGS: - eax_set_fx_slot_flags(eax_call); + eax_defer_fx_slot_flags(call); return false; case EAXFXSLOT_OCCLUSION: - return eax_set_fx_slot_occlusion(eax_call); + return eax_defer_fx_slot_occlusion(call); case EAXFXSLOT_OCCLUSIONLFRATIO: - return eax_set_fx_slot_occlusion_lf_ratio(eax_call); + return eax_defer_fx_slot_occlusion_lf_ratio(call); default: @@ -1670,15 +1644,15 @@ bool ALeffectslot::eax_set_fx_slot( } // [[nodiscard]] -bool ALeffectslot::eax_set(const EaxEaxCall& eax_call) +bool ALeffectslot::eax_set(const EaxCall& call) { - switch(eax_call.get_property_set_id()) + switch(call.get_property_set_id()) { - case EaxEaxCallPropertySetId::fx_slot: - return eax_set_fx_slot(eax_call); + case EaxCallPropertySetId::fx_slot: + return eax_set_fx_slot(call); - case EaxEaxCallPropertySetId::fx_slot_effect: - eax_dispatch_effect(eax_call); + case EaxCallPropertySetId::fx_slot_effect: + eax_dispatch_effect(call); break; default: @@ -1688,8 +1662,8 @@ bool ALeffectslot::eax_set(const EaxEaxCall& eax_call) return false; } -void ALeffectslot::eax_dispatch_effect(const EaxEaxCall& eax_call) -{ if(eax_effect_) eax_effect_->dispatch(eax_call); } +void ALeffectslot::eax_dispatch_effect(const EaxCall& call) +{ if(eax_effect_) eax_effect_->dispatch(call); } void ALeffectslot::eax_apply_deferred() { @@ -1697,7 +1671,7 @@ void ALeffectslot::eax_apply_deferred() auto is_changed = false; if(eax_effect_) - is_changed = eax_effect_->apply_deferred(); + is_changed = eax_effect_->commit(); if(is_changed) eax_set_effect_slot_effect(*eax_effect_); } diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 5336a2a8..83711372 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -18,8 +18,7 @@ #ifdef ALSOFT_EAX #include - -#include "eax/eax_call.h" +#include "eax/call.h" #include "eax/effect.h" #include "eax/fx_slot_index.h" #endif // ALSOFT_EAX @@ -74,6 +73,7 @@ struct ALeffectslot { #ifdef ALSOFT_EAX public: void eax_initialize( + const EaxCall& call, ALCcontext& al_context, EaxFxSlotIndexValue index); @@ -81,8 +81,8 @@ public: // [[nodiscard]] - bool eax_dispatch(const EaxEaxCall& eax_call) - { return eax_call.is_get() ? eax_get(eax_call) : eax_set(eax_call); } + bool eax_dispatch(const EaxCall& call) + { return call.is_get() ? eax_get(call) : eax_set(call); } void eax_unlock_legacy() noexcept; @@ -115,24 +115,20 @@ private: void eax_initialize_lock(); - void eax_initialize_effects(); + void eax_initialize_effects(const EaxCall& call); - void eax_get_fx_slot_all( - const EaxEaxCall& eax_call) const; + void eax_get_fx_slot_all(const EaxCall& call) const; - void eax_get_fx_slot( - const EaxEaxCall& eax_call) const; + void eax_get_fx_slot(const EaxCall& call) const; // [[nodiscard]] - bool eax_get( - const EaxEaxCall& eax_call); + bool eax_get(const EaxCall& call); - void eax_set_fx_slot_effect( - ALenum effect_type); + void eax_set_fx_slot_effect(const EaxCall& call, ALenum effect_type); - void eax_set_fx_slot_effect(); + void eax_set_fx_slot_effect(const EaxCall& call); void eax_set_efx_effect_slot_gain(); @@ -147,37 +143,16 @@ private: void eax_ensure_is_unlocked() const; + void eax_validate_fx_slot_effect(const GUID& eax_effect_id); + void eax_validate_fx_slot_volume(long eax_volume); + void eax_validate_fx_slot_lock(long eax_lock); + void eax_validate_fx_slot_flags(const EaxCall& call, unsigned long eax_flags); + void eax_validate_fx_slot_occlusion(long eax_occlusion); + void eax_validate_fx_slot_occlusion_lf_ratio(float eax_occlusion_lf_ratio); + void eax_validate_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& fx_slot); + void eax_validate_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& fx_slot); - void eax_validate_fx_slot_effect( - const GUID& eax_effect_id); - - void eax_validate_fx_slot_volume( - long eax_volume); - - void eax_validate_fx_slot_lock( - long eax_lock); - - void eax_validate_fx_slot_flags( - unsigned long eax_flags, - int eax_version); - - void eax_validate_fx_slot_occlusion( - long eax_occlusion); - - void eax_validate_fx_slot_occlusion_lf_ratio( - float eax_occlusion_lf_ratio); - - void eax_validate_fx_slot_all( - const EAX40FXSLOTPROPERTIES& fx_slot, - int eax_version); - - void eax_validate_fx_slot_all( - const EAX50FXSLOTPROPERTIES& fx_slot, - int eax_version); - - - void eax_set_fx_slot_effect( - const GUID& eax_effect_id); + void eax_set_fx_slot_effect(const EaxCall& call, const GUID& eax_effect_id); void eax_set_fx_slot_volume( long eax_volume); @@ -196,50 +171,38 @@ private: bool eax_set_fx_slot_occlusion_lf_ratio( float eax_occlusion_lf_ratio); - void eax_set_fx_slot_all( - const EAX40FXSLOTPROPERTIES& eax_fx_slot); + void eax_set_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& eax_fx_slot); // [[nodiscard]] - bool eax_set_fx_slot_all( - const EAX50FXSLOTPROPERTIES& eax_fx_slot); + bool eax_set_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& eax_fx_slot); - void eax_set_fx_slot_effect( - const EaxEaxCall& eax_call); + void eax_defer_fx_slot_effect(const EaxCall& call); - void eax_set_fx_slot_volume( - const EaxEaxCall& eax_call); + void eax_defer_fx_slot_volume(const EaxCall& call); - void eax_set_fx_slot_lock( - const EaxEaxCall& eax_call); + void eax_defer_fx_slot_lock(const EaxCall& call); - void eax_set_fx_slot_flags( - const EaxEaxCall& eax_call); + void eax_defer_fx_slot_flags(const EaxCall& call); // [[nodiscard]] - bool eax_set_fx_slot_occlusion( - const EaxEaxCall& eax_call); + bool eax_defer_fx_slot_occlusion(const EaxCall& call); // [[nodiscard]] - bool eax_set_fx_slot_occlusion_lf_ratio( - const EaxEaxCall& eax_call); + bool eax_defer_fx_slot_occlusion_lf_ratio(const EaxCall& call); // [[nodiscard]] - bool eax_set_fx_slot_all( - const EaxEaxCall& eax_call); + bool eax_defer_fx_slot_all(const EaxCall& call); - bool eax_set_fx_slot( - const EaxEaxCall& eax_call); + bool eax_set_fx_slot(const EaxCall& call); void eax_apply_deferred(); // [[nodiscard]] - bool eax_set( - const EaxEaxCall& eax_call); + bool eax_set(const EaxCall& call); - void eax_dispatch_effect( - const EaxEaxCall& eax_call); + void eax_dispatch_effect(const EaxCall& call); // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)` diff --git a/al/eax/api.cpp b/al/eax/api.cpp index f859a1c4..34ba554f 100644 --- a/al/eax/api.cpp +++ b/al/eax/api.cpp @@ -393,6 +393,569 @@ bool operator!=( } +// EAX1 ===================================================================== + +namespace { +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_GENERIC = {EAX_ENVIRONMENT_GENERIC, 0.5F, 1.493F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PADDEDCELL = {EAX_ENVIRONMENT_PADDEDCELL, 0.25F, 0.1F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ROOM = {EAX_ENVIRONMENT_ROOM, 0.417F, 0.4F, 0.666F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_BATHROOM = {EAX_ENVIRONMENT_BATHROOM, 0.653F, 1.499F, 0.166F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_LIVINGROOM = {EAX_ENVIRONMENT_LIVINGROOM, 0.208F, 0.478F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONEROOM = {EAX_ENVIRONMENT_STONEROOM, 0.5F, 2.309F, 0.888F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_AUDITORIUM = {EAX_ENVIRONMENT_AUDITORIUM, 0.403F, 4.279F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CONCERTHALL = {EAX_ENVIRONMENT_CONCERTHALL, 0.5F, 3.961F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CAVE = {EAX_ENVIRONMENT_CAVE, 0.5F, 2.886F, 1.304F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ARENA = {EAX_ENVIRONMENT_ARENA, 0.361F, 7.284F, 0.332F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HANGAR = {EAX_ENVIRONMENT_HANGAR, 0.5F, 10.0F, 0.3F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CARPETTEDHALLWAY = {EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153F, 0.259F, 2.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HALLWAY = {EAX_ENVIRONMENT_HALLWAY, 0.361F, 1.493F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONECORRIDOR = {EAX_ENVIRONMENT_STONECORRIDOR, 0.444F, 2.697F, 0.638F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ALLEY = {EAX_ENVIRONMENT_ALLEY, 0.25F, 1.752F, 0.776F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_FOREST = {EAX_ENVIRONMENT_FOREST, 0.111F, 3.145F, 0.472F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CITY = {EAX_ENVIRONMENT_CITY, 0.111F, 2.767F, 0.224F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_MOUNTAINS = {EAX_ENVIRONMENT_MOUNTAINS, 0.194F, 7.841F, 0.472F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_QUARRY = {EAX_ENVIRONMENT_QUARRY, 1.0F, 1.499F, 0.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PLAIN = {EAX_ENVIRONMENT_PLAIN, 0.097F, 2.767F, 0.224F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PARKINGLOT = {EAX_ENVIRONMENT_PARKINGLOT, 0.208F, 1.652F, 1.5F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_SEWERPIPE = {EAX_ENVIRONMENT_SEWERPIPE, 0.652F, 2.886F, 0.25F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_UNDERWATER = {EAX_ENVIRONMENT_UNDERWATER, 1.0F, 1.499F, 0.0F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DRUGGED = {EAX_ENVIRONMENT_DRUGGED, 0.875F, 8.392F, 1.388F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DIZZY = {EAX_ENVIRONMENT_DIZZY, 0.139F, 17.234F, 0.666F}; +constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PSYCHOTIC = {EAX_ENVIRONMENT_PSYCHOTIC, 0.486F, 7.563F, 0.806F}; +} // namespace + +const Eax1ReverbPresets EAX1REVERB_PRESETS{{ + EAX1REVERB_PRESET_GENERIC, + EAX1REVERB_PRESET_PADDEDCELL, + EAX1REVERB_PRESET_ROOM, + EAX1REVERB_PRESET_BATHROOM, + EAX1REVERB_PRESET_LIVINGROOM, + EAX1REVERB_PRESET_STONEROOM, + EAX1REVERB_PRESET_AUDITORIUM, + EAX1REVERB_PRESET_CONCERTHALL, + EAX1REVERB_PRESET_CAVE, + EAX1REVERB_PRESET_ARENA, + EAX1REVERB_PRESET_HANGAR, + EAX1REVERB_PRESET_CARPETTEDHALLWAY, + EAX1REVERB_PRESET_HALLWAY, + EAX1REVERB_PRESET_STONECORRIDOR, + EAX1REVERB_PRESET_ALLEY, + EAX1REVERB_PRESET_FOREST, + EAX1REVERB_PRESET_CITY, + EAX1REVERB_PRESET_MOUNTAINS, + EAX1REVERB_PRESET_QUARRY, + EAX1REVERB_PRESET_PLAIN, + EAX1REVERB_PRESET_PARKINGLOT, + EAX1REVERB_PRESET_SEWERPIPE, + EAX1REVERB_PRESET_UNDERWATER, + EAX1REVERB_PRESET_DRUGGED, + EAX1REVERB_PRESET_DIZZY, + EAX1REVERB_PRESET_PSYCHOTIC, +}}; + +// EAX2 ===================================================================== + +namespace { + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_GENERIC{ + EAX2LISTENER_DEFAULTROOM, + EAX2LISTENER_DEFAULTROOMHF, + EAX2LISTENER_DEFAULTROOMROLLOFFFACTOR, + EAX2LISTENER_DEFAULTDECAYTIME, + EAX2LISTENER_DEFAULTDECAYHFRATIO, + EAX2LISTENER_DEFAULTREFLECTIONS, + EAX2LISTENER_DEFAULTREFLECTIONSDELAY, + EAX2LISTENER_DEFAULTREVERB, + EAX2LISTENER_DEFAULTREVERBDELAY, + EAX2LISTENER_DEFAULTENVIRONMENT, + EAX2LISTENER_DEFAULTENVIRONMENTSIZE, + EAX2LISTENER_DEFAULTENVIRONMENTDIFFUSION, + EAX2LISTENER_DEFAULTAIRABSORPTIONHF, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_PADDEDCELL{ + -1'000L, + -6'000L, + 0.0F, + 0.17F, + 0.1F, + -1'204L, + 0.001F, + 207L, + 0.002F, + EAX2_ENVIRONMENT_PADDEDCELL, + 1.4F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_ROOM{ + -1'000L, + -454L, + 0.0F, + 0.4F, + 0.83F, + -1'646L, + 0.002F, + 53L, + 0.003F, + EAX2_ENVIRONMENT_ROOM, + 1.9F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_BATHROOM{ + -1'000L, + -1'200L, + 0.0F, + 1.49F, + 0.54F, + -370L, + 0.007F, + 1'030L, + 0.011F, + EAX2_ENVIRONMENT_BATHROOM, + 1.4F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_LIVINGROOM{ + -1'000L, + -6'000L, + 0.0F, + 0.5F, + 0.1F, + -1'376L, + 0.003F, + -1'104L, + 0.004F, + EAX2_ENVIRONMENT_LIVINGROOM, + 2.5F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_STONEROOM{ + -1'000L, + -300L, + 0.0F, + 2.31F, + 0.64F, + -711L, + 0.012F, + 83L, + 0.017F, + EAX2_ENVIRONMENT_STONEROOM, + 11.6F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_AUDITORIUM{ + -1'000L, + -476L, + 0.0F, + 4.32F, + 0.59F, + -789L, + 0.02F, + -289L, + 0.03F, + EAX2_ENVIRONMENT_AUDITORIUM, + 21.6F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_CONCERTHALL{ + -1'000L, + -500L, + 0.0F, + 3.92F, + 0.7F, + -1'230L, + 0.02F, + -2L, + 0.029F, + EAX2_ENVIRONMENT_CONCERTHALL, + 19.6F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_CAVE{ + -1'000L, + 0L, + 0.0F, + 2.91F, + 1.3F, + -602L, + 0.015F, + -302L, + 0.022F, + EAX2_ENVIRONMENT_CAVE, + 14.6F, + 1.0F, + -5.0F, + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_ARENA{ + -1'000L, + -698L, + 0.0F, + 7.24F, + 0.33F, + -1'166L, + 0.02F, + 16L, + 0.03F, + EAX2_ENVIRONMENT_ARENA, + 36.2F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_HANGAR{ + -1'000L, + -1'000L, + 0.0F, + 10.05F, + 0.23F, + -602L, + 0.02F, + 198L, + 0.03F, + EAX2_ENVIRONMENT_HANGAR, + 50.3F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_CARPETTEDHALLWAY{ + -1'000L, + -4'000L, + 0.0F, + 0.3F, + 0.1F, + -1'831L, + 0.002F, + -1'630L, + 0.03F, + EAX2_ENVIRONMENT_CARPETEDHALLWAY, + 1.9F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_HALLWAY{ + -1'000L, + -300L, + 0.0F, + 1.49F, + 0.59F, + -1'219L, + 0.007F, + 441L, + 0.011F, + EAX2_ENVIRONMENT_HALLWAY, + 1.8F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_STONECORRIDOR{ + -1'000L, + -237L, + 0.0F, + 2.7F, + 0.79F, + -1'214L, + 0.013F, + 395L, + 0.02F, + EAX2_ENVIRONMENT_STONECORRIDOR, + 13.5F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_ALLEY{ + -1'000L, + -270L, + 0.0F, + 1.49F, + 0.86F, + -1'204L, + 0.007F, + -4L, + 0.011F, + EAX2_ENVIRONMENT_ALLEY, + 7.5F, + 0.3F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_FOREST{ + -1'000L, + -3'300L, + 0.0F, + 1.49F, + 0.54F, + -2'560L, + 0.162F, + -229L, + 0.088F, + EAX2_ENVIRONMENT_FOREST, + 38.0F, + 0.3F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_CITY{ + -1'000L, + -800L, + 0.0F, + 1.49F, + 0.67F, + -2'273L, + 0.007F, + -1'691L, + 0.011F, + EAX2_ENVIRONMENT_CITY, + 7.5F, + 0.5F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_MOUNTAINS{ + -1'000L, + -2'500L, + 0.0F, + 1.49F, + 0.21F, + -2'780L, + 0.3F, + -1'434L, + 0.1F, + EAX2_ENVIRONMENT_MOUNTAINS, + 100.0F, + 0.27F, + -5.0F, + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_QUARRY{ + -1'000L, + -1'000L, + 0.0F, + 1.49F, + 0.83F, + -10'000L, + 0.061F, + 500L, + 0.025F, + EAX2_ENVIRONMENT_QUARRY, + 17.5F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_PLAIN{ + -1'000L, + -2'000L, + 0.0F, + 1.49F, + 0.5F, + -2'466L, + 0.179F, + -1'926L, + 0.1F, + EAX2_ENVIRONMENT_PLAIN, + 42.5F, + 0.21F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_PARKINGLOT{ + -1'000L, + 0L, + 0.0F, + 1.65F, + 1.5F, + -1'363L, + 0.008F, + -1'153L, + 0.012F, + EAX2_ENVIRONMENT_PARKINGLOT, + 8.3F, + 1.0F, + -5.0F, + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_SEWERPIPE{ + -1'000L, + -1'000L, + 0.0F, + 2.81F, + 0.14F, + 429L, + 0.014F, + 1'023L, + 0.021F, + EAX2_ENVIRONMENT_SEWERPIPE, + 1.7F, + 0.8F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_UNDERWATER{ + -1'000L, + -4'000L, + 0.0F, + 1.49F, + 0.1F, + -449L, + 0.007F, + 1'700L, + 0.011F, + EAX2_ENVIRONMENT_UNDERWATER, + 1.8F, + 1.0F, + -5.0F, + EAX2LISTENER_DEFAULTFLAGS, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_DRUGGED{ + -1'000L, + 0L, + 0.0F, + 8.39F, + 1.39F, + -115L, + 0.002F, + 985L, + 0.03F, + EAX2_ENVIRONMENT_DRUGGED, + 1.9F, + 0.5F, + -5.0F, + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_DIZZY{ + -1'000L, + -400L, + 0.0F, + 17.23F, + 0.56F, + -1'713L, + 0.02F, + -613L, + 0.03F, + EAX2_ENVIRONMENT_DIZZY, + 1.8F, + 0.6F, + -5.0F, + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE, +}; + +constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_PSYCHOTIC{ + -1'000L, + -151L, + 0.0F, + 7.56F, + 0.91F, + -626L, + 0.02F, + 774L, + 0.03F, + EAX2_ENVIRONMENT_PSYCHOTIC, + 1.0F, + 0.5F, + -5.0F, + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE, +}; + +} // namespace + +const Eax2ReverbPresets EAX2REVERB_PRESETS{ + EAX2REVERB_PRESET_GENERIC, + EAX2REVERB_PRESET_PADDEDCELL, + EAX2REVERB_PRESET_ROOM, + EAX2REVERB_PRESET_BATHROOM, + EAX2REVERB_PRESET_LIVINGROOM, + EAX2REVERB_PRESET_STONEROOM, + EAX2REVERB_PRESET_AUDITORIUM, + EAX2REVERB_PRESET_CONCERTHALL, + EAX2REVERB_PRESET_CAVE, + EAX2REVERB_PRESET_ARENA, + EAX2REVERB_PRESET_HANGAR, + EAX2REVERB_PRESET_CARPETTEDHALLWAY, + EAX2REVERB_PRESET_HALLWAY, + EAX2REVERB_PRESET_STONECORRIDOR, + EAX2REVERB_PRESET_ALLEY, + EAX2REVERB_PRESET_FOREST, + EAX2REVERB_PRESET_CITY, + EAX2REVERB_PRESET_MOUNTAINS, + EAX2REVERB_PRESET_QUARRY, + EAX2REVERB_PRESET_PLAIN, + EAX2REVERB_PRESET_PARKINGLOT, + EAX2REVERB_PRESET_SEWERPIPE, + EAX2REVERB_PRESET_UNDERWATER, + EAX2REVERB_PRESET_DRUGGED, + EAX2REVERB_PRESET_DIZZY, + EAX2REVERB_PRESET_PSYCHOTIC, +}; + +// EAX3+ ==================================================================== + namespace { constexpr EAXREVERBPROPERTIES EAXREVERB_PRESET_GENERIC = @@ -1153,61 +1716,3 @@ const EaxReverbPresets EAXREVERB_PRESETS{{ EAXREVERB_PRESET_DIZZY, EAXREVERB_PRESET_PSYCHOTIC, }}; - -namespace { -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_GENERIC = {EAX_ENVIRONMENT_GENERIC, 0.5F, 1.493F, 0.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PADDEDCELL = {EAX_ENVIRONMENT_PADDEDCELL, 0.25F, 0.1F, 0.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ROOM = {EAX_ENVIRONMENT_ROOM, 0.417F, 0.4F, 0.666F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_BATHROOM = {EAX_ENVIRONMENT_BATHROOM, 0.653F, 1.499F, 0.166F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_LIVINGROOM = {EAX_ENVIRONMENT_LIVINGROOM, 0.208F, 0.478F, 0.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONEROOM = {EAX_ENVIRONMENT_STONEROOM, 0.5F, 2.309F, 0.888F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_AUDITORIUM = {EAX_ENVIRONMENT_AUDITORIUM, 0.403F, 4.279F, 0.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CONCERTHALL = {EAX_ENVIRONMENT_CONCERTHALL, 0.5F, 3.961F, 0.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CAVE = {EAX_ENVIRONMENT_CAVE, 0.5F, 2.886F, 1.304F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ARENA = {EAX_ENVIRONMENT_ARENA, 0.361F, 7.284F, 0.332F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HANGAR = {EAX_ENVIRONMENT_HANGAR, 0.5F, 10.0F, 0.3F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CARPETTEDHALLWAY = {EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153F, 0.259F, 2.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HALLWAY = {EAX_ENVIRONMENT_HALLWAY, 0.361F, 1.493F, 0.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONECORRIDOR = {EAX_ENVIRONMENT_STONECORRIDOR, 0.444F, 2.697F, 0.638F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ALLEY = {EAX_ENVIRONMENT_ALLEY, 0.25F, 1.752F, 0.776F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_FOREST = {EAX_ENVIRONMENT_FOREST, 0.111F, 3.145F, 0.472F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CITY = {EAX_ENVIRONMENT_CITY, 0.111F, 2.767F, 0.224F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_MOUNTAINS = {EAX_ENVIRONMENT_MOUNTAINS, 0.194F, 7.841F, 0.472F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_QUARRY = {EAX_ENVIRONMENT_QUARRY, 1.0F, 1.499F, 0.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PLAIN = {EAX_ENVIRONMENT_PLAIN, 0.097F, 2.767F, 0.224F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PARKINGLOT = {EAX_ENVIRONMENT_PARKINGLOT, 0.208F, 1.652F, 1.5F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_SEWERPIPE = {EAX_ENVIRONMENT_SEWERPIPE, 0.652F, 2.886F, 0.25F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_UNDERWATER = {EAX_ENVIRONMENT_UNDERWATER, 1.0F, 1.499F, 0.0F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DRUGGED = {EAX_ENVIRONMENT_DRUGGED, 0.875F, 8.392F, 1.388F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DIZZY = {EAX_ENVIRONMENT_DIZZY, 0.139F, 17.234F, 0.666F}; -constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PSYCHOTIC = {EAX_ENVIRONMENT_PSYCHOTIC, 0.486F, 7.563F, 0.806F}; -} // namespace - -const Eax1ReverbPresets EAX1REVERB_PRESETS{{ - EAX1REVERB_PRESET_GENERIC, - EAX1REVERB_PRESET_PADDEDCELL, - EAX1REVERB_PRESET_ROOM, - EAX1REVERB_PRESET_BATHROOM, - EAX1REVERB_PRESET_LIVINGROOM, - EAX1REVERB_PRESET_STONEROOM, - EAX1REVERB_PRESET_AUDITORIUM, - EAX1REVERB_PRESET_CONCERTHALL, - EAX1REVERB_PRESET_CAVE, - EAX1REVERB_PRESET_ARENA, - EAX1REVERB_PRESET_HANGAR, - EAX1REVERB_PRESET_CARPETTEDHALLWAY, - EAX1REVERB_PRESET_HALLWAY, - EAX1REVERB_PRESET_STONECORRIDOR, - EAX1REVERB_PRESET_ALLEY, - EAX1REVERB_PRESET_FOREST, - EAX1REVERB_PRESET_CITY, - EAX1REVERB_PRESET_MOUNTAINS, - EAX1REVERB_PRESET_QUARRY, - EAX1REVERB_PRESET_PLAIN, - EAX1REVERB_PRESET_PARKINGLOT, - EAX1REVERB_PRESET_SEWERPIPE, - EAX1REVERB_PRESET_UNDERWATER, - EAX1REVERB_PRESET_DRUGGED, - EAX1REVERB_PRESET_DIZZY, - EAX1REVERB_PRESET_PSYCHOTIC, -}}; diff --git a/al/eax/api.h b/al/eax/api.h index d0737d1d..f4419ddb 100644 --- a/al/eax/api.h +++ b/al/eax/api.h @@ -129,6 +129,110 @@ struct EAX20LISTENERPROPERTIES unsigned long dwFlags; // modifies the behavior of properties }; // EAX20LISTENERPROPERTIES +inline bool operator==(const EAX20LISTENERPROPERTIES& lhs, const EAX20LISTENERPROPERTIES& rhs) noexcept +{ + return std::memcmp(&lhs, &rhs, sizeof(EAX20LISTENERPROPERTIES)) == 0; +} + +enum : unsigned long +{ + EAX2_ENVIRONMENT_GENERIC, + EAX2_ENVIRONMENT_PADDEDCELL, + EAX2_ENVIRONMENT_ROOM, + EAX2_ENVIRONMENT_BATHROOM, + EAX2_ENVIRONMENT_LIVINGROOM, + EAX2_ENVIRONMENT_STONEROOM, + EAX2_ENVIRONMENT_AUDITORIUM, + EAX2_ENVIRONMENT_CONCERTHALL, + EAX2_ENVIRONMENT_CAVE, + EAX2_ENVIRONMENT_ARENA, + EAX2_ENVIRONMENT_HANGAR, + EAX2_ENVIRONMENT_CARPETEDHALLWAY, + EAX2_ENVIRONMENT_HALLWAY, + EAX2_ENVIRONMENT_STONECORRIDOR, + EAX2_ENVIRONMENT_ALLEY, + EAX2_ENVIRONMENT_FOREST, + EAX2_ENVIRONMENT_CITY, + EAX2_ENVIRONMENT_MOUNTAINS, + EAX2_ENVIRONMENT_QUARRY, + EAX2_ENVIRONMENT_PLAIN, + EAX2_ENVIRONMENT_PARKINGLOT, + EAX2_ENVIRONMENT_SEWERPIPE, + EAX2_ENVIRONMENT_UNDERWATER, + EAX2_ENVIRONMENT_DRUGGED, + EAX2_ENVIRONMENT_DIZZY, + EAX2_ENVIRONMENT_PSYCHOTIC, + + EAX2_ENVIRONMENT_COUNT, +}; + +constexpr auto EAX2LISTENERFLAGS_DECAYTIMESCALE = 0x00000001UL; +constexpr auto EAX2LISTENERFLAGS_REFLECTIONSSCALE = 0x00000002UL; +constexpr auto EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE = 0x00000004UL; +constexpr auto EAX2LISTENERFLAGS_REVERBSCALE = 0x00000008UL; +constexpr auto EAX2LISTENERFLAGS_REVERBDELAYSCALE = 0x00000010UL; +constexpr auto EAX2LISTENERFLAGS_DECAYHFLIMIT = 0x00000020UL; +constexpr auto EAX2LISTENERFLAGS_RESERVED = 0xFFFFFFC0UL; + +constexpr auto EAX2LISTENER_MINROOM = -10'000L; +constexpr auto EAX2LISTENER_MAXROOM = 0L; +constexpr auto EAX2LISTENER_DEFAULTROOM = -1'000L; + +constexpr auto EAX2LISTENER_MINROOMHF = -10'000L; +constexpr auto EAX2LISTENER_MAXROOMHF = 0L; +constexpr auto EAX2LISTENER_DEFAULTROOMHF = -100L; + +constexpr auto EAX2LISTENER_MINROOMROLLOFFFACTOR = 0.0F; +constexpr auto EAX2LISTENER_MAXROOMROLLOFFFACTOR = 10.0F; +constexpr auto EAX2LISTENER_DEFAULTROOMROLLOFFFACTOR = 0.0F; + +constexpr auto EAX2LISTENER_MINDECAYTIME = 0.1F; +constexpr auto EAX2LISTENER_MAXDECAYTIME = 20.0F; +constexpr auto EAX2LISTENER_DEFAULTDECAYTIME = 1.49F; + +constexpr auto EAX2LISTENER_MINDECAYHFRATIO = 0.1F; +constexpr auto EAX2LISTENER_MAXDECAYHFRATIO = 2.0F; +constexpr auto EAX2LISTENER_DEFAULTDECAYHFRATIO = 0.83F; + +constexpr auto EAX2LISTENER_MINREFLECTIONS = -10'000L; +constexpr auto EAX2LISTENER_MAXREFLECTIONS = 1'000L; +constexpr auto EAX2LISTENER_DEFAULTREFLECTIONS = -2'602L; + +constexpr auto EAX2LISTENER_MINREFLECTIONSDELAY = 0.0F; +constexpr auto EAX2LISTENER_MAXREFLECTIONSDELAY = 0.3F; +constexpr auto EAX2LISTENER_DEFAULTREFLECTIONSDELAY = 0.007F; + +constexpr auto EAX2LISTENER_MINREVERB = -10'000L; +constexpr auto EAX2LISTENER_MAXREVERB = 2'000L; +constexpr auto EAX2LISTENER_DEFAULTREVERB = 200L; + +constexpr auto EAX2LISTENER_MINREVERBDELAY = 0.0F; +constexpr auto EAX2LISTENER_MAXREVERBDELAY = 0.1F; +constexpr auto EAX2LISTENER_DEFAULTREVERBDELAY = 0.011F; + +constexpr auto EAX2LISTENER_MINENVIRONMENT = 0UL; +constexpr auto EAX2LISTENER_MAXENVIRONMENT = EAX2_ENVIRONMENT_COUNT - 1; +constexpr auto EAX2LISTENER_DEFAULTENVIRONMENT = EAX2_ENVIRONMENT_GENERIC; + +constexpr auto EAX2LISTENER_MINENVIRONMENTSIZE = 1.0F; +constexpr auto EAX2LISTENER_MAXENVIRONMENTSIZE = 100.0F; +constexpr auto EAX2LISTENER_DEFAULTENVIRONMENTSIZE = 7.5F; + +constexpr auto EAX2LISTENER_MINENVIRONMENTDIFFUSION = 0.0F; +constexpr auto EAX2LISTENER_MAXENVIRONMENTDIFFUSION = 1.0F; +constexpr auto EAX2LISTENER_DEFAULTENVIRONMENTDIFFUSION = 1.0F; + +constexpr auto EAX2LISTENER_MINAIRABSORPTIONHF = -100.0F; +constexpr auto EAX2LISTENER_MAXAIRABSORPTIONHF = 0.0F; +constexpr auto EAX2LISTENER_DEFAULTAIRABSORPTIONHF = -5.0F; + +constexpr auto EAX2LISTENER_DEFAULTFLAGS = + EAX2LISTENERFLAGS_DECAYTIMESCALE | + EAX2LISTENERFLAGS_REFLECTIONSSCALE | + EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE | + EAX2LISTENERFLAGS_REVERBSCALE | + EAX2LISTENERFLAGS_REVERBDELAYSCALE | + EAX2LISTENERFLAGS_DECAYHFLIMIT; extern const GUID DSPROPSETID_EAX20_BufferProperties; @@ -957,13 +1061,15 @@ constexpr auto EAXREVERB_DEFAULTFLAGS = EAXREVERBFLAGS_DECAYHFLIMIT; -using EaxReverbPresets = std::array; -extern const EaxReverbPresets EAXREVERB_PRESETS; - - using Eax1ReverbPresets = std::array; extern const Eax1ReverbPresets EAX1REVERB_PRESETS; +using Eax2ReverbPresets = std::array; +extern const Eax2ReverbPresets EAX2REVERB_PRESETS; + +using EaxReverbPresets = std::array; +extern const EaxReverbPresets EAXREVERB_PRESETS; + // AGC Compressor Effect diff --git a/al/eax/call.cpp b/al/eax/call.cpp new file mode 100644 index 00000000..1fd05968 --- /dev/null +++ b/al/eax/call.cpp @@ -0,0 +1,212 @@ +#include "config.h" +#include "call.h" +#include "exception.h" + +namespace { + +constexpr auto deferred_flag = 0x80000000U; + +class EaxCallException : public EaxException { +public: + explicit EaxCallException(const char* message) + : EaxException{"EAX_CALL", message} + {} +}; // EaxCallException + +} // namespace + +EaxCall::EaxCall( + EaxCallType type, + const GUID& property_set_guid, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size) + : type_{type}, version_{0}, property_set_id_{EaxCallPropertySetId::none} + , property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id} + , property_buffer_{property_buffer}, property_size_{property_size} +{ + switch (type_) + { + case EaxCallType::get: + case EaxCallType::set: + break; + + default: + fail("Invalid type."); + } + + if (false) + { + } + else if (property_set_guid == EAXPROPERTYID_EAX40_Context) + { + version_ = 4; + property_set_id_ = EaxCallPropertySetId::context; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_Context) + { + version_ = 5; + property_set_id_ = EaxCallPropertySetId::context; + } + else if (property_set_guid == DSPROPSETID_EAX20_ListenerProperties) + { + version_ = 2; + fx_slot_index_ = 0u; + property_set_id_ = EaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid == DSPROPSETID_EAX30_ListenerProperties) + { + version_ = 3; + fx_slot_index_ = 0u; + property_set_id_ = EaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot0) + { + version_ = 4; + fx_slot_index_ = 0u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot0) + { + version_ = 5; + fx_slot_index_ = 0u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot1) + { + version_ = 4; + fx_slot_index_ = 1u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot1) + { + version_ = 5; + fx_slot_index_ = 1u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot2) + { + version_ = 4; + fx_slot_index_ = 2u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot2) + { + version_ = 5; + fx_slot_index_ = 2u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot3) + { + version_ = 4; + fx_slot_index_ = 3u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot3) + { + version_ = 5; + fx_slot_index_ = 3u; + property_set_id_ = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == DSPROPSETID_EAX20_BufferProperties) + { + version_ = 2; + property_set_id_ = EaxCallPropertySetId::source; + } + else if (property_set_guid == DSPROPSETID_EAX30_BufferProperties) + { + version_ = 3; + property_set_id_ = EaxCallPropertySetId::source; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_Source) + { + version_ = 4; + property_set_id_ = EaxCallPropertySetId::source; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_Source) + { + version_ = 5; + property_set_id_ = EaxCallPropertySetId::source; + } + else if (property_set_guid == DSPROPSETID_EAX_ReverbProperties) + { + version_ = 1; + fx_slot_index_ = 0u; + property_set_id_ = EaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid == DSPROPSETID_EAXBUFFER_ReverbProperties) + { + version_ = 1; + property_set_id_ = EaxCallPropertySetId::source; + } + else + { + fail("Unsupported property set id."); + } + + if (version_ < 1 || version_ > 5) + { + fail("EAX version out of range."); + } + + if(!(property_id&deferred_flag)) + { + if(property_set_id_ != EaxCallPropertySetId::fx_slot && property_id_ != 0) + { + if (property_buffer == nullptr) + { + fail("Null property buffer."); + } + + if (property_size == 0) + { + fail("Empty property."); + } + } + } + + if(property_set_id_ == EaxCallPropertySetId::source && property_source_id_ == 0) + { + fail("Null AL source id."); + } + + if (property_set_id_ == EaxCallPropertySetId::fx_slot) + { + if (property_id_ < EAXFXSLOT_NONE) + { + property_set_id_ = EaxCallPropertySetId::fx_slot_effect; + } + } +} + +[[noreturn]] void EaxCall::fail(const char* message) +{ + throw EaxCallException{message}; +} + +[[noreturn]] void EaxCall::fail_too_small() +{ + fail("Property buffer too small."); +} + +EaxCall create_eax_call( + EaxCallType type, + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size) +{ + if(!property_set_id) + throw EaxCallException{"Null property set ID."}; + + return EaxCall{ + type, + *property_set_id, + property_id, + property_source_id, + property_buffer, + property_size + }; +} diff --git a/al/eax/call.h b/al/eax/call.h new file mode 100644 index 00000000..d491d6f9 --- /dev/null +++ b/al/eax/call.h @@ -0,0 +1,92 @@ +#ifndef EAX_EAX_CALL_INCLUDED +#define EAX_EAX_CALL_INCLUDED + +#include "AL/al.h" +#include "alspan.h" +#include "api.h" +#include "fx_slot_index.h" + +enum class EaxCallType { + none, + get, + set, +}; // EaxCallType + +enum class EaxCallPropertySetId { + none, + context, + fx_slot, + source, + fx_slot_effect, +}; // EaxCallPropertySetId + +class EaxCall { +public: + EaxCall( + EaxCallType type, + const GUID& property_set_guid, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + + bool is_get() const noexcept { return type_ == EaxCallType::get; } + int get_version() const noexcept { return version_; } + EaxCallPropertySetId get_property_set_id() const noexcept { return property_set_id_; } + ALuint get_property_id() const noexcept { return property_id_; } + ALuint get_property_al_name() const noexcept { return property_source_id_; } + EaxFxSlotIndex get_fx_slot_index() const noexcept { return fx_slot_index_; } + + template + TValue& get_value() const + { + if (property_size_ < static_cast(sizeof(TValue))) + { + fail_too_small(); + } + + return *static_cast(property_buffer_); + } + + template + al::span get_values() const + { + if (property_size_ < static_cast(sizeof(TValue))) + { + fail_too_small(); + } + + const auto count = property_size_ / sizeof(TValue); + return al::span{static_cast(property_buffer_), count}; + } + + template + void set_value(const TValue& value) const + { + get_value() = value; + } + +private: + EaxCallType type_; + int version_; + EaxFxSlotIndex fx_slot_index_; + EaxCallPropertySetId property_set_id_; + + ALuint property_id_; + ALuint property_source_id_; + ALvoid*property_buffer_; + ALuint property_size_; + + [[noreturn]] static void fail(const char* message); + [[noreturn]] static void fail_too_small(); +}; // EaxCall + +EaxCall create_eax_call( + EaxCallType type, + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size); + +#endif // !EAX_EAX_CALL_INCLUDED diff --git a/al/eax/eax_call.cpp b/al/eax/eax_call.cpp deleted file mode 100644 index 19565852..00000000 --- a/al/eax/eax_call.cpp +++ /dev/null @@ -1,323 +0,0 @@ -#include "config.h" - -#include "eax_call.h" -#include "exception.h" - - -namespace { - -constexpr auto deferred_flag = 0x80000000U; - -class EaxEaxCallException : - public EaxException -{ -public: - explicit EaxEaxCallException( - const char* message) - : - EaxException{"EAX_EAX_CALL", message} - { - } -}; // EaxEaxCallException - -} // namespace - - -EaxEaxCall::EaxEaxCall( - bool is_get, - const GUID& property_set_guid, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_buffer, - ALuint property_size) - : is_get_{is_get}, version_{0}, property_set_id_{EaxEaxCallPropertySetId::none} - , property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id} - , property_buffer_{property_buffer}, property_size_{property_size} -{ - if (false) - { - } - else if (property_set_guid == EAXPROPERTYID_EAX40_Context) - { - version_ = 4; - property_set_id_ = EaxEaxCallPropertySetId::context; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_Context) - { - version_ = 5; - property_set_id_ = EaxEaxCallPropertySetId::context; - } - else if (property_set_guid == DSPROPSETID_EAX20_ListenerProperties) - { - version_ = 2; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; - property_id_ = convert_eax_v2_0_listener_property_id(property_id_); - } - else if (property_set_guid == DSPROPSETID_EAX30_ListenerProperties) - { - version_ = 3; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot0) - { - version_ = 4; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot0) - { - version_ = 5; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot1) - { - version_ = 4; - fx_slot_index_ = 1u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot1) - { - version_ = 5; - fx_slot_index_ = 1u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot2) - { - version_ = 4; - fx_slot_index_ = 2u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot2) - { - version_ = 5; - fx_slot_index_ = 2u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot3) - { - version_ = 4; - fx_slot_index_ = 3u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot3) - { - version_ = 5; - fx_slot_index_ = 3u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot; - } - else if (property_set_guid == DSPROPSETID_EAX20_BufferProperties) - { - version_ = 2; - property_set_id_ = EaxEaxCallPropertySetId::source; - property_id_ = convert_eax_v2_0_buffer_property_id(property_id_); - } - else if (property_set_guid == DSPROPSETID_EAX30_BufferProperties) - { - version_ = 3; - property_set_id_ = EaxEaxCallPropertySetId::source; - } - else if (property_set_guid == EAXPROPERTYID_EAX40_Source) - { - version_ = 4; - property_set_id_ = EaxEaxCallPropertySetId::source; - } - else if (property_set_guid == EAXPROPERTYID_EAX50_Source) - { - version_ = 5; - property_set_id_ = EaxEaxCallPropertySetId::source; - } - else if (property_set_guid == DSPROPSETID_EAX_ReverbProperties) - { - version_ = 1; - fx_slot_index_ = 0u; - property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; - } - else if (property_set_guid == DSPROPSETID_EAXBUFFER_ReverbProperties) - { - version_ = 1; - property_set_id_ = EaxEaxCallPropertySetId::source; - } - else - { - fail("Unsupported property set id."); - } - - if (version_ < 1 || version_ > 5) - { - fail("EAX version out of range."); - } - - if(!(property_id&deferred_flag)) - { - if(property_set_id_ != EaxEaxCallPropertySetId::fx_slot && property_id_ != 0) - { - if (!property_buffer) - { - fail("Null property buffer."); - } - - if (property_size == 0) - { - fail("Empty property."); - } - } - } - - if(property_set_id_ == EaxEaxCallPropertySetId::source && property_source_id_ == 0) - { - fail("Null AL source id."); - } - - if (property_set_id_ == EaxEaxCallPropertySetId::fx_slot) - { - if (property_id_ < EAXFXSLOT_NONE) - { - property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect; - } - } -} - -[[noreturn]] -void EaxEaxCall::fail( - const char* message) -{ - throw EaxEaxCallException{message}; -} - -ALuint EaxEaxCall::convert_eax_v2_0_listener_property_id( - ALuint property_id) -{ - switch (property_id) - { - case DSPROPERTY_EAX20LISTENER_NONE: - return EAXREVERB_NONE; - - case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: - return EAXREVERB_ALLPARAMETERS; - - case DSPROPERTY_EAX20LISTENER_ROOM: - return EAXREVERB_ROOM; - - case DSPROPERTY_EAX20LISTENER_ROOMHF: - return EAXREVERB_ROOMHF; - - case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: - return EAXREVERB_ROOMROLLOFFFACTOR; - - case DSPROPERTY_EAX20LISTENER_DECAYTIME: - return EAXREVERB_DECAYTIME; - - case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: - return EAXREVERB_DECAYHFRATIO; - - case DSPROPERTY_EAX20LISTENER_REFLECTIONS: - return EAXREVERB_REFLECTIONS; - - case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: - return EAXREVERB_REFLECTIONSDELAY; - - case DSPROPERTY_EAX20LISTENER_REVERB: - return EAXREVERB_REVERB; - - case DSPROPERTY_EAX20LISTENER_REVERBDELAY: - return EAXREVERB_REVERBDELAY; - - case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: - return EAXREVERB_ENVIRONMENT; - - case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE: - return EAXREVERB_ENVIRONMENTSIZE; - - case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION: - return EAXREVERB_ENVIRONMENTDIFFUSION; - - case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: - return EAXREVERB_AIRABSORPTIONHF; - - case DSPROPERTY_EAX20LISTENER_FLAGS: - return EAXREVERB_FLAGS; - - default: - fail("Unsupported EAX 2.0 listener property id."); - } -} - -ALuint EaxEaxCall::convert_eax_v2_0_buffer_property_id( - ALuint property_id) -{ - switch (property_id) - { - case DSPROPERTY_EAX20BUFFER_NONE: - return EAXSOURCE_NONE; - - case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS: - return EAXSOURCE_ALLPARAMETERS; - - case DSPROPERTY_EAX20BUFFER_DIRECT: - return EAXSOURCE_DIRECT; - - case DSPROPERTY_EAX20BUFFER_DIRECTHF: - return EAXSOURCE_DIRECTHF; - - case DSPROPERTY_EAX20BUFFER_ROOM: - return EAXSOURCE_ROOM; - - case DSPROPERTY_EAX20BUFFER_ROOMHF: - return EAXSOURCE_ROOMHF; - - case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR: - return EAXSOURCE_ROOMROLLOFFFACTOR; - - case DSPROPERTY_EAX20BUFFER_OBSTRUCTION: - return EAXSOURCE_OBSTRUCTION; - - case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO: - return EAXSOURCE_OBSTRUCTIONLFRATIO; - - case DSPROPERTY_EAX20BUFFER_OCCLUSION: - return EAXSOURCE_OCCLUSION; - - case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO: - return EAXSOURCE_OCCLUSIONLFRATIO; - - case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO: - return EAXSOURCE_OCCLUSIONROOMRATIO; - - case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF: - return EAXSOURCE_OUTSIDEVOLUMEHF; - - case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR: - return EAXSOURCE_AIRABSORPTIONFACTOR; - - case DSPROPERTY_EAX20BUFFER_FLAGS: - return EAXSOURCE_FLAGS; - - default: - fail("Unsupported EAX 2.0 buffer property id."); - } -} - - -EaxEaxCall create_eax_call( - bool is_get, - const GUID* property_set_id, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_buffer, - ALuint property_size) -{ - if(!property_set_id) - throw EaxEaxCallException{"Null property set ID."}; - - return EaxEaxCall{ - is_get, - *property_set_id, - property_id, - property_source_id, - property_buffer, - property_size - }; -} diff --git a/al/eax/eax_call.h b/al/eax/eax_call.h deleted file mode 100644 index 2c90bdc3..00000000 --- a/al/eax/eax_call.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef EAX_EAX_CALL_INCLUDED -#define EAX_EAX_CALL_INCLUDED - - -#include "AL/al.h" - -#include "alspan.h" - -#include "api.h" -#include "fx_slot_index.h" - - -enum class EaxEaxCallPropertySetId -{ - none, - - context, - fx_slot, - source, - fx_slot_effect, -}; // EaxEaxCallPropertySetId - - -class EaxEaxCall -{ -public: - EaxEaxCall( - bool is_get, - const GUID& property_set_guid, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_buffer, - ALuint property_size); - - bool is_get() const noexcept { return is_get_; } - int get_version() const noexcept { return version_; } - EaxEaxCallPropertySetId get_property_set_id() const noexcept { return property_set_id_; } - ALuint get_property_id() const noexcept { return property_id_; } - ALuint get_property_al_name() const noexcept { return property_source_id_; } - EaxFxSlotIndex get_fx_slot_index() const noexcept { return fx_slot_index_; } - - template< - typename TException, - typename TValue - > - TValue& get_value() const - { - if (property_size_ < static_cast(sizeof(TValue))) - { - throw TException{"Property buffer too small."}; - } - - return *static_cast(property_buffer_); - } - - template< - typename TException, - typename TValue - > - al::span get_values() const - { - if (property_size_ < static_cast(sizeof(TValue))) - { - throw TException{"Property buffer too small."}; - } - - const auto count = property_size_ / sizeof(TValue); - - return al::span{static_cast(property_buffer_), count}; - } - - template< - typename TException, - typename TValue - > - void set_value( - const TValue& value) const - { - get_value() = value; - } - - -private: - const bool is_get_; - int version_; - EaxFxSlotIndex fx_slot_index_; - EaxEaxCallPropertySetId property_set_id_; - - ALuint property_id_; - const ALuint property_source_id_; - ALvoid*const property_buffer_; - const ALuint property_size_; - - - [[noreturn]] - static void fail( - const char* message); - - - static ALuint convert_eax_v2_0_listener_property_id( - ALuint property_id); - - static ALuint convert_eax_v2_0_buffer_property_id( - ALuint property_id); -}; // EaxEaxCall - - -EaxEaxCall create_eax_call( - bool is_get, - const GUID* property_set_id, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_buffer, - ALuint property_size); - - -#endif // !EAX_EAX_CALL_INCLUDED diff --git a/al/eax/effect.cpp b/al/eax/effect.cpp deleted file mode 100644 index 4e8faa73..00000000 --- a/al/eax/effect.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "config.h" - -#include "effect.h" diff --git a/al/eax/effect.h b/al/eax/effect.h index 9c9fdef4..b57bf240 100644 --- a/al/eax/effect.h +++ b/al/eax/effect.h @@ -2,43 +2,172 @@ #define EAX_EFFECT_INCLUDED +#include #include +#include "alnumeric.h" #include "AL/al.h" #include "core/effects/base.h" -#include "eax_call.h" +#include "call.h" -class EaxEffect +struct EaxEffectErrorMessages { + static constexpr auto unknown_property_id() noexcept { return "Unknown property id."; } + static constexpr auto unknown_version() noexcept { return "Unknown version."; } +}; // EaxEffectErrorMessages + +class EaxEffect { public: - EaxEffect(ALenum type) : al_effect_type_{type} { } + EaxEffect(ALenum type) noexcept : al_effect_type_{type} { } virtual ~EaxEffect() = default; const ALenum al_effect_type_; EffectProps al_effect_props_{}; - virtual void dispatch(const EaxEaxCall& eax_call) = 0; + virtual void dispatch(const EaxCall& call) = 0; // Returns "true" if any immediated property was changed. - // [[nodiscard]] - virtual bool apply_deferred() = 0; + /*[[nodiscard]]*/ virtual bool commit() = 0; }; // EaxEffect +// Base class for EAX4+ effects. +template +class EaxEffect4 : public EaxEffect +{ +public: + EaxEffect4(ALenum type, const EaxCall& call) + : EaxEffect{type}, version_{clamp(call.get_version(), 4, 5)} + {} + + void initialize() + { + set_defaults(); + set_efx_defaults(); + } + + void dispatch(const EaxCall& call) override + { + call.is_get() ? get(call) : set(call); + version_ = call.get_version(); + } + + bool commit() final + { + switch (version_) + { + case 4: return commit_state(state4_); + case 5: return commit_state(state5_); + default: fail_unknown_version(); + } + } + +protected: + using Exception = TException; + using Props = TProps; + + struct State { + Props i; // Immediate. + Props d; // Deferred. + }; // State + + int version_; + Props props_; + State state4_; + State state5_; + + template + static void defer(const EaxCall& call, TProperty& property) + { + const auto& value = call.get_value(); + TValidator{}(value); + property = value; + } + + virtual void set_defaults(Props& props) = 0; + virtual void set_efx_defaults() = 0; + + virtual void get(const EaxCall& call, const Props& props) = 0; + virtual void set(const EaxCall& call, Props& props) = 0; + + virtual bool commit_props(const Props& props) = 0; + + [[noreturn]] static void fail(const char* message) + { + throw Exception{message}; + } + + [[noreturn]] static void fail_unknown_property_id() + { + fail(EaxEffectErrorMessages::unknown_property_id()); + } + + [[noreturn]] static void fail_unknown_version() + { + fail(EaxEffectErrorMessages::unknown_version()); + } + +private: + void set_defaults() + { + set_defaults(props_); + state4_.i = props_; + state4_.d = props_; + state5_.i = props_; + state5_.d = props_; + } + + void get(const EaxCall& call) + { + switch (call.get_version()) + { + case 4: get(call, state4_.i); break; + case 5: get(call, state5_.i); break; + default: fail_unknown_version(); + } + } + + void set(const EaxCall& call) + { + switch (call.get_version()) + { + case 4: set(call, state4_.d); break; + case 5: set(call, state5_.d); break; + default: fail_unknown_version(); + } + } + + bool commit_state(State& state) + { + const auto props = props_; + state.i = state.d; + props_ = state.d; + return commit_props(props); + } +}; // EaxEffect4 using EaxEffectUPtr = std::unique_ptr; +// Creates EAX4+ effect. +template +EaxEffectUPtr eax_create_eax4_effect(const EaxCall& call) +{ + auto effect = std::make_unique(call); + effect->initialize(); + return effect; +} + EaxEffectUPtr eax_create_eax_null_effect(); -EaxEffectUPtr eax_create_eax_chorus_effect(); -EaxEffectUPtr eax_create_eax_distortion_effect(); -EaxEffectUPtr eax_create_eax_echo_effect(); -EaxEffectUPtr eax_create_eax_flanger_effect(); -EaxEffectUPtr eax_create_eax_frequency_shifter_effect(); -EaxEffectUPtr eax_create_eax_vocal_morpher_effect(); -EaxEffectUPtr eax_create_eax_pitch_shifter_effect(); -EaxEffectUPtr eax_create_eax_ring_modulator_effect(); -EaxEffectUPtr eax_create_eax_auto_wah_effect(); -EaxEffectUPtr eax_create_eax_compressor_effect(); -EaxEffectUPtr eax_create_eax_equalizer_effect(); -EaxEffectUPtr eax_create_eax_reverb_effect(); +EaxEffectUPtr eax_create_eax_chorus_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_distortion_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_echo_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_flanger_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_frequency_shifter_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_vocal_morpher_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_pitch_shifter_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_ring_modulator_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_auto_wah_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_compressor_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_equalizer_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_reverb_effect(const EaxCall& call); #endif // !EAX_EFFECT_INCLUDED diff --git a/al/eax/fx_slots.cpp b/al/eax/fx_slots.cpp index 5897e951..671d2cfb 100644 --- a/al/eax/fx_slots.cpp +++ b/al/eax/fx_slots.cpp @@ -29,9 +29,10 @@ public: void EaxFxSlots::initialize( + const EaxCall& call, ALCcontext& al_context) { - initialize_fx_slots(al_context); + initialize_fx_slots(call, al_context); } void EaxFxSlots::uninitialize() noexcept @@ -70,6 +71,7 @@ void EaxFxSlots::fail( } void EaxFxSlots::initialize_fx_slots( + const EaxCall& call, ALCcontext& al_context) { auto fx_slot_index = EaxFxSlotIndexValue{}; @@ -77,7 +79,7 @@ void EaxFxSlots::initialize_fx_slots( for (auto& fx_slot : fx_slots_) { fx_slot = eax_create_al_effect_slot(al_context); - fx_slot->eax_initialize(al_context, fx_slot_index); + fx_slot->eax_initialize(call, al_context, fx_slot_index); fx_slot_index += 1; } } diff --git a/al/eax/fx_slots.h b/al/eax/fx_slots.h index 49cabd75..e7d1452e 100644 --- a/al/eax/fx_slots.h +++ b/al/eax/fx_slots.h @@ -7,6 +7,7 @@ #include "al/auxeffectslot.h" #include "api.h" +#include "call.h" #include "fx_slot_index.h" @@ -14,6 +15,7 @@ class EaxFxSlots { public: void initialize( + const EaxCall& call, ALCcontext& al_context); void uninitialize() noexcept; @@ -46,6 +48,7 @@ private: const char* message); void initialize_fx_slots( + const EaxCall& call, ALCcontext& al_context); }; // EaxFxSlots diff --git a/al/eax/x_ram.cpp b/al/eax/x_ram.cpp deleted file mode 100644 index 7332c82e..00000000 --- a/al/eax/x_ram.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "config.h" - -#include "x_ram.h" diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 23f43305..7e0e34aa 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -13,7 +13,6 @@ #ifdef ALSOFT_EAX #include "alnumeric.h" - #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -119,178 +118,127 @@ const EffectProps AutowahEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -using EaxAutoWahEffectDirtyFlagsValue = std::uint_least8_t; - -struct EaxAutoWahEffectDirtyFlags -{ - using EaxIsBitFieldStruct = bool; - - EaxAutoWahEffectDirtyFlagsValue flAttackTime : 1; - EaxAutoWahEffectDirtyFlagsValue flReleaseTime : 1; - EaxAutoWahEffectDirtyFlagsValue lResonance : 1; - EaxAutoWahEffectDirtyFlagsValue lPeakLevel : 1; -}; // EaxAutoWahEffectDirtyFlags - - -class EaxAutoWahEffect final : - public EaxEffect -{ +class EaxAutoWahEffectException : public EaxException { public: - EaxAutoWahEffect(); - - - void dispatch(const EaxEaxCall& eax_call) override; + explicit EaxAutoWahEffectException(const char* message) + : EaxException{"EAX_AUTO_WAH_EFFECT", message} + {} +}; // EaxAutoWahEffectException - // [[nodiscard]] - bool apply_deferred() override; +class EaxAutoWahEffect final : public EaxEffect4 { +public: + EaxAutoWahEffect(const EaxCall& call); private: - EAXAUTOWAHPROPERTIES eax_{}; - EAXAUTOWAHPROPERTIES eax_d_{}; - EaxAutoWahEffectDirtyFlags eax_dirty_flags_{}; - - - void set_eax_defaults(); - - - void set_efx_attack_time(); - - void set_efx_release_time(); - - void set_efx_resonance(); - - void set_efx_peak_gain(); - - void set_efx_defaults(); - - - void get(const EaxEaxCall& eax_call); - - - void validate_attack_time( - float flAttackTime); - - void validate_release_time( - float flReleaseTime); - - void validate_resonance( - long lResonance); - - void validate_peak_level( - long lPeakLevel); - - void validate_all( - const EAXAUTOWAHPROPERTIES& eax_all); - - - void defer_attack_time( - float flAttackTime); - - void defer_release_time( - float flReleaseTime); - - void defer_resonance( - long lResonance); - - void defer_peak_level( - long lPeakLevel); - - void defer_all( - const EAXAUTOWAHPROPERTIES& eax_all); - - - void defer_attack_time( - const EaxEaxCall& eax_call); - - void defer_release_time( - const EaxEaxCall& eax_call); - - void defer_resonance( - const EaxEaxCall& eax_call); - - void defer_peak_level( - const EaxEaxCall& eax_call); - - void defer_all( - const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); + struct AttackTimeValidator { + void operator()(float flAttackTime) const + { + eax_validate_range( + "Attack Time", + flAttackTime, + EAXAUTOWAH_MINATTACKTIME, + EAXAUTOWAH_MAXATTACKTIME); + } + }; // AttackTimeValidator + + struct ReleaseTimeValidator { + void operator()(float flReleaseTime) const + { + eax_validate_range( + "Release Time", + flReleaseTime, + EAXAUTOWAH_MINRELEASETIME, + EAXAUTOWAH_MAXRELEASETIME); + } + }; // ReleaseTimeValidator + + struct ResonanceValidator { + void operator()(long lResonance) const + { + eax_validate_range( + "Resonance", + lResonance, + EAXAUTOWAH_MINRESONANCE, + EAXAUTOWAH_MAXRESONANCE); + } + }; // ResonanceValidator + + struct PeakLevelValidator { + void operator()(long lPeakLevel) const + { + eax_validate_range( + "Peak Level", + lPeakLevel, + EAXAUTOWAH_MINPEAKLEVEL, + EAXAUTOWAH_MAXPEAKLEVEL); + } + }; // PeakLevelValidator + + struct AllValidator { + void operator()(const Props& all) const + { + AttackTimeValidator{}(all.flAttackTime); + ReleaseTimeValidator{}(all.flReleaseTime); + ResonanceValidator{}(all.lResonance); + PeakLevelValidator{}(all.lPeakLevel); + } + }; // AllValidator + + void set_defaults(Props& props) override; + + void set_efx_attack_time() noexcept; + void set_efx_release_time() noexcept; + void set_efx_resonance() noexcept; + void set_efx_peak_gain() noexcept; + void set_efx_defaults() override; + + void get(const EaxCall& call, const Props& props) override; + void set(const EaxCall& call, Props& props) override; + bool commit_props(const Props& props) override; }; // EaxAutoWahEffect +EaxAutoWahEffect::EaxAutoWahEffect(const EaxCall& call) + : EaxEffect4{AL_EFFECT_AUTOWAH, call} +{} -class EaxAutoWahEffectException : - public EaxException -{ -public: - explicit EaxAutoWahEffectException( - const char* message) - : - EaxException{"EAX_AUTO_WAH_EFFECT", message} - { - } -}; // EaxAutoWahEffectException - - -EaxAutoWahEffect::EaxAutoWahEffect() - : EaxEffect{AL_EFFECT_AUTOWAH} -{ - set_eax_defaults(); - set_efx_defaults(); -} - -void EaxAutoWahEffect::dispatch(const EaxEaxCall& eax_call) -{ - eax_call.is_get() ? get(eax_call) : set(eax_call); -} - -void EaxAutoWahEffect::set_eax_defaults() +void EaxAutoWahEffect::set_defaults(Props& props) { - eax_.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME; - eax_.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME; - eax_.lResonance = EAXAUTOWAH_DEFAULTRESONANCE; - eax_.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL; - - eax_d_ = eax_; + props.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME; + props.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME; + props.lResonance = EAXAUTOWAH_DEFAULTRESONANCE; + props.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL; } -void EaxAutoWahEffect::set_efx_attack_time() +void EaxAutoWahEffect::set_efx_attack_time() noexcept { - const auto attack_time = clamp( - eax_.flAttackTime, + al_effect_props_.Autowah.AttackTime = clamp( + props_.flAttackTime, AL_AUTOWAH_MIN_ATTACK_TIME, AL_AUTOWAH_MAX_ATTACK_TIME); - - al_effect_props_.Autowah.AttackTime = attack_time; } -void EaxAutoWahEffect::set_efx_release_time() +void EaxAutoWahEffect::set_efx_release_time() noexcept { - const auto release_time = clamp( - eax_.flReleaseTime, + al_effect_props_.Autowah.ReleaseTime = clamp( + props_.flReleaseTime, AL_AUTOWAH_MIN_RELEASE_TIME, AL_AUTOWAH_MAX_RELEASE_TIME); - - al_effect_props_.Autowah.ReleaseTime = release_time; } -void EaxAutoWahEffect::set_efx_resonance() +void EaxAutoWahEffect::set_efx_resonance() noexcept { - const auto resonance = clamp( - level_mb_to_gain(static_cast(eax_.lResonance)), + al_effect_props_.Autowah.Resonance = clamp( + level_mb_to_gain(static_cast(props_.lResonance)), AL_AUTOWAH_MIN_RESONANCE, AL_AUTOWAH_MAX_RESONANCE); - - al_effect_props_.Autowah.Resonance = resonance; } -void EaxAutoWahEffect::set_efx_peak_gain() +void EaxAutoWahEffect::set_efx_peak_gain() noexcept { - const auto peak_gain = clamp( - level_mb_to_gain(static_cast(eax_.lPeakLevel)), + al_effect_props_.Autowah.PeakGain = clamp( + level_mb_to_gain(static_cast(props_.lPeakLevel)), AL_AUTOWAH_MIN_PEAK_GAIN, AL_AUTOWAH_MAX_PEAK_GAIN); - - al_effect_props_.Autowah.PeakGain = peak_gain; } void EaxAutoWahEffect::set_efx_defaults() @@ -301,248 +249,70 @@ void EaxAutoWahEffect::set_efx_defaults() set_efx_peak_gain(); } -void EaxAutoWahEffect::get(const EaxEaxCall& eax_call) +void EaxAutoWahEffect::get(const EaxCall& call, const Props& props) { - switch (eax_call.get_property_id()) + switch (call.get_property_id()) { - case EAXAUTOWAH_NONE: - break; - - case EAXAUTOWAH_ALLPARAMETERS: - eax_call.set_value(eax_); - break; - - case EAXAUTOWAH_ATTACKTIME: - eax_call.set_value(eax_.flAttackTime); - break; - - case EAXAUTOWAH_RELEASETIME: - eax_call.set_value(eax_.flReleaseTime); - break; - - case EAXAUTOWAH_RESONANCE: - eax_call.set_value(eax_.lResonance); - break; - - case EAXAUTOWAH_PEAKLEVEL: - eax_call.set_value(eax_.lPeakLevel); - break; - - default: - throw EaxAutoWahEffectException{"Unsupported property id."}; + case EAXAUTOWAH_NONE: break; + case EAXAUTOWAH_ALLPARAMETERS: call.set_value(props); break; + case EAXAUTOWAH_ATTACKTIME: call.set_value(props.flAttackTime); break; + case EAXAUTOWAH_RELEASETIME: call.set_value(props.flReleaseTime); break; + case EAXAUTOWAH_RESONANCE: call.set_value(props.lResonance); break; + case EAXAUTOWAH_PEAKLEVEL: call.set_value(props.lPeakLevel); break; + default: fail_unknown_property_id(); } } -void EaxAutoWahEffect::validate_attack_time( - float flAttackTime) +void EaxAutoWahEffect::set(const EaxCall& call, Props& props) { - eax_validate_range( - "Attack Time", - flAttackTime, - EAXAUTOWAH_MINATTACKTIME, - EAXAUTOWAH_MAXATTACKTIME); -} - -void EaxAutoWahEffect::validate_release_time( - float flReleaseTime) -{ - eax_validate_range( - "Release Time", - flReleaseTime, - EAXAUTOWAH_MINRELEASETIME, - EAXAUTOWAH_MAXRELEASETIME); -} - -void EaxAutoWahEffect::validate_resonance( - long lResonance) -{ - eax_validate_range( - "Resonance", - lResonance, - EAXAUTOWAH_MINRESONANCE, - EAXAUTOWAH_MAXRESONANCE); -} - -void EaxAutoWahEffect::validate_peak_level( - long lPeakLevel) -{ - eax_validate_range( - "Peak Level", - lPeakLevel, - EAXAUTOWAH_MINPEAKLEVEL, - EAXAUTOWAH_MAXPEAKLEVEL); -} - -void EaxAutoWahEffect::validate_all( - const EAXAUTOWAHPROPERTIES& eax_all) -{ - validate_attack_time(eax_all.flAttackTime); - validate_release_time(eax_all.flReleaseTime); - validate_resonance(eax_all.lResonance); - validate_peak_level(eax_all.lPeakLevel); -} - -void EaxAutoWahEffect::defer_attack_time( - float flAttackTime) -{ - eax_d_.flAttackTime = flAttackTime; - eax_dirty_flags_.flAttackTime = (eax_.flAttackTime != eax_d_.flAttackTime); -} - -void EaxAutoWahEffect::defer_release_time( - float flReleaseTime) -{ - eax_d_.flReleaseTime = flReleaseTime; - eax_dirty_flags_.flReleaseTime = (eax_.flReleaseTime != eax_d_.flReleaseTime); -} - -void EaxAutoWahEffect::defer_resonance( - long lResonance) -{ - eax_d_.lResonance = lResonance; - eax_dirty_flags_.lResonance = (eax_.lResonance != eax_d_.lResonance); -} - -void EaxAutoWahEffect::defer_peak_level( - long lPeakLevel) -{ - eax_d_.lPeakLevel = lPeakLevel; - eax_dirty_flags_.lPeakLevel = (eax_.lPeakLevel != eax_d_.lPeakLevel); -} - -void EaxAutoWahEffect::defer_all( - const EAXAUTOWAHPROPERTIES& eax_all) -{ - validate_all(eax_all); - - defer_attack_time(eax_all.flAttackTime); - defer_release_time(eax_all.flReleaseTime); - defer_resonance(eax_all.lResonance); - defer_peak_level(eax_all.lPeakLevel); -} - -void EaxAutoWahEffect::defer_attack_time( - const EaxEaxCall& eax_call) -{ - const auto& attack_time = - eax_call.get_value(); - - validate_attack_time(attack_time); - defer_attack_time(attack_time); -} - -void EaxAutoWahEffect::defer_release_time( - const EaxEaxCall& eax_call) -{ - const auto& release_time = - eax_call.get_value(); - - validate_release_time(release_time); - defer_release_time(release_time); -} - -void EaxAutoWahEffect::defer_resonance( - const EaxEaxCall& eax_call) -{ - const auto& resonance = - eax_call.get_value(); - - validate_resonance(resonance); - defer_resonance(resonance); -} - -void EaxAutoWahEffect::defer_peak_level( - const EaxEaxCall& eax_call) -{ - const auto& peak_level = - eax_call.get_value(); - - validate_peak_level(peak_level); - defer_peak_level(peak_level); -} - -void EaxAutoWahEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto& all = - eax_call.get_value(); - - validate_all(all); - defer_all(all); -} - -// [[nodiscard]] -bool EaxAutoWahEffect::apply_deferred() -{ - if (eax_dirty_flags_ == EaxAutoWahEffectDirtyFlags{}) + switch (call.get_property_id()) { - return false; + case EAXAUTOWAH_NONE: break; + case EAXAUTOWAH_ALLPARAMETERS: defer(call, props); break; + case EAXAUTOWAH_ATTACKTIME: defer(call, props.flAttackTime); break; + case EAXAUTOWAH_RELEASETIME: defer(call, props.flReleaseTime); break; + case EAXAUTOWAH_RESONANCE: defer(call, props.lResonance); break; + case EAXAUTOWAH_PEAKLEVEL: defer(call, props.lPeakLevel); break; + default: fail_unknown_property_id(); } +} - eax_ = eax_d_; +bool EaxAutoWahEffect::commit_props(const Props& props) +{ + auto is_dirty = false; - if (eax_dirty_flags_.flAttackTime) + if (props_.flAttackTime != props.flAttackTime) { + is_dirty = true; set_efx_attack_time(); } - if (eax_dirty_flags_.flReleaseTime) + if (props_.flReleaseTime != props.flReleaseTime) { + is_dirty = true; set_efx_release_time(); } - if (eax_dirty_flags_.lResonance) + if (props_.lResonance != props.lResonance) { + is_dirty = true; set_efx_resonance(); } - if (eax_dirty_flags_.lPeakLevel) + if (props_.lPeakLevel != props.lPeakLevel) { + is_dirty = true; set_efx_peak_gain(); } - eax_dirty_flags_ = EaxAutoWahEffectDirtyFlags{}; - - return true; -} - -void EaxAutoWahEffect::set(const EaxEaxCall& eax_call) -{ - switch (eax_call.get_property_id()) - { - case EAXAUTOWAH_NONE: - break; - - case EAXAUTOWAH_ALLPARAMETERS: - defer_all(eax_call); - break; - - case EAXAUTOWAH_ATTACKTIME: - defer_attack_time(eax_call); - break; - - case EAXAUTOWAH_RELEASETIME: - defer_release_time(eax_call); - break; - - case EAXAUTOWAH_RESONANCE: - defer_resonance(eax_call); - break; - - case EAXAUTOWAH_PEAKLEVEL: - defer_peak_level(eax_call); - break; - - default: - throw EaxAutoWahEffectException{"Unsupported property id."}; - } + return is_dirty; } } // namespace -EaxEffectUPtr eax_create_eax_auto_wah_effect() +EaxEffectUPtr eax_create_eax_auto_wah_effect(const EaxCall& call) { - return std::make_unique<::EaxAutoWahEffect>(); + return eax_create_eax4_effect(call); } #endif // ALSOFT_EAX diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index b612a6c1..0d4283c9 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -13,9 +13,7 @@ #ifdef ALSOFT_EAX #include - #include "alnumeric.h" - #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -293,1065 +291,444 @@ const EffectProps FlangerEffectProps{genDefaultFlangerProps()}; #ifdef ALSOFT_EAX namespace { -void eax_set_efx_waveform( - ALenum waveform, - EffectProps& al_effect_props) -{ - const auto efx_waveform = WaveformFromEnum(waveform); - assert(efx_waveform.has_value()); - al_effect_props.Chorus.Waveform = *efx_waveform; -} - -void eax_set_efx_phase( - ALint phase, - EffectProps& al_effect_props) -{ - al_effect_props.Chorus.Phase = phase; -} - -void eax_set_efx_rate( - ALfloat rate, - EffectProps& al_effect_props) -{ - al_effect_props.Chorus.Rate = rate; -} - -void eax_set_efx_depth( - ALfloat depth, - EffectProps& al_effect_props) -{ - al_effect_props.Chorus.Depth = depth; -} - -void eax_set_efx_feedback( - ALfloat feedback, - EffectProps& al_effect_props) -{ - al_effect_props.Chorus.Feedback = feedback; -} - -void eax_set_efx_delay( - ALfloat delay, - EffectProps& al_effect_props) -{ - al_effect_props.Chorus.Delay = delay; -} - - -using EaxChorusEffectDirtyFlagsValue = std::uint_least8_t; - -struct EaxChorusEffectDirtyFlags -{ - using EaxIsBitFieldStruct = bool; - - EaxChorusEffectDirtyFlagsValue ulWaveform : 1; - EaxChorusEffectDirtyFlagsValue lPhase : 1; - EaxChorusEffectDirtyFlagsValue flRate : 1; - EaxChorusEffectDirtyFlagsValue flDepth : 1; - EaxChorusEffectDirtyFlagsValue flFeedback : 1; - EaxChorusEffectDirtyFlagsValue flDelay : 1; -}; // EaxChorusEffectDirtyFlags - +class EaxChorusEffectException : public EaxException { +public: + explicit EaxChorusEffectException(const char* message) + : EaxException{"EAX_CHORUS_EFFECT", message} + {} +}; // EaxChorusEffectException -class EaxChorusEffect final : - public EaxEffect -{ +class EaxFlangerEffectException : public EaxException { public: - EaxChorusEffect(); + explicit EaxFlangerEffectException(const char* message) + : EaxException{"EAX_FLANGER_EFFECT", message} + {} +}; // EaxFlangerEffectException - void dispatch(const EaxEaxCall& eax_call) override; +struct EaxChorusTraits +{ + using Exception = EaxChorusEffectException; + using Props = EAXCHORUSPROPERTIES; + + static constexpr auto efx_effect() { return AL_EFFECT_CHORUS; } + + static constexpr auto eax_none_param_id() { return EAXCHORUS_NONE; } + static constexpr auto eax_allparameters_param_id() { return EAXCHORUS_ALLPARAMETERS; } + static constexpr auto eax_waveform_param_id() { return EAXCHORUS_WAVEFORM; } + static constexpr auto eax_phase_param_id() { return EAXCHORUS_PHASE; } + static constexpr auto eax_rate_param_id() { return EAXCHORUS_RATE; } + static constexpr auto eax_depth_param_id() { return EAXCHORUS_DEPTH; } + static constexpr auto eax_feedback_param_id() { return EAXCHORUS_FEEDBACK; } + static constexpr auto eax_delay_param_id() { return EAXCHORUS_DELAY; } + + static constexpr auto eax_min_waveform() { return EAXCHORUS_MINWAVEFORM; } + static constexpr auto eax_min_phase() { return EAXCHORUS_MINPHASE; } + static constexpr auto eax_min_rate() { return EAXCHORUS_MINRATE; } + static constexpr auto eax_min_depth() { return EAXCHORUS_MINDEPTH; } + static constexpr auto eax_min_feedback() { return EAXCHORUS_MINFEEDBACK; } + static constexpr auto eax_min_delay() { return EAXCHORUS_MINDELAY; } + + static constexpr auto eax_max_waveform() { return EAXCHORUS_MAXWAVEFORM; } + static constexpr auto eax_max_phase() { return EAXCHORUS_MAXPHASE; } + static constexpr auto eax_max_rate() { return EAXCHORUS_MAXRATE; } + static constexpr auto eax_max_depth() { return EAXCHORUS_MAXDEPTH; } + static constexpr auto eax_max_feedback() { return EAXCHORUS_MAXFEEDBACK; } + static constexpr auto eax_max_delay() { return EAXCHORUS_MAXDELAY; } + + static constexpr auto eax_default_waveform() { return EAXCHORUS_DEFAULTWAVEFORM; } + static constexpr auto eax_default_phase() { return EAXCHORUS_DEFAULTPHASE; } + static constexpr auto eax_default_rate() { return EAXCHORUS_DEFAULTRATE; } + static constexpr auto eax_default_depth() { return EAXCHORUS_DEFAULTDEPTH; } + static constexpr auto eax_default_feedback() { return EAXCHORUS_DEFAULTFEEDBACK; } + static constexpr auto eax_default_delay() { return EAXCHORUS_DEFAULTDELAY; } + + static constexpr auto efx_min_waveform() { return AL_CHORUS_MIN_WAVEFORM; } + static constexpr auto efx_min_phase() { return AL_CHORUS_MIN_PHASE; } + static constexpr auto efx_min_rate() { return AL_CHORUS_MIN_RATE; } + static constexpr auto efx_min_depth() { return AL_CHORUS_MIN_DEPTH; } + static constexpr auto efx_min_feedback() { return AL_CHORUS_MIN_FEEDBACK; } + static constexpr auto efx_min_delay() { return AL_CHORUS_MIN_DELAY; } + + static constexpr auto efx_max_waveform() { return AL_CHORUS_MAX_WAVEFORM; } + static constexpr auto efx_max_phase() { return AL_CHORUS_MAX_PHASE; } + static constexpr auto efx_max_rate() { return AL_CHORUS_MAX_RATE; } + static constexpr auto efx_max_depth() { return AL_CHORUS_MAX_DEPTH; } + static constexpr auto efx_max_feedback() { return AL_CHORUS_MAX_FEEDBACK; } + static constexpr auto efx_max_delay() { return AL_CHORUS_MAX_DELAY; } + + static constexpr auto efx_default_waveform() { return AL_CHORUS_DEFAULT_WAVEFORM; } + static constexpr auto efx_default_phase() { return AL_CHORUS_DEFAULT_PHASE; } + static constexpr auto efx_default_rate() { return AL_CHORUS_DEFAULT_RATE; } + static constexpr auto efx_default_depth() { return AL_CHORUS_DEFAULT_DEPTH; } + static constexpr auto efx_default_feedback() { return AL_CHORUS_DEFAULT_FEEDBACK; } + static constexpr auto efx_default_delay() { return AL_CHORUS_DEFAULT_DELAY; } +}; // EaxChorusTraits + +struct EaxFlangerTraits +{ + using Exception = EaxFlangerEffectException; + using Props = EAXFLANGERPROPERTIES; + + static constexpr auto efx_effect() { return AL_EFFECT_FLANGER; } + + static constexpr auto eax_none_param_id() { return EAXFLANGER_NONE; } + static constexpr auto eax_allparameters_param_id() { return EAXFLANGER_ALLPARAMETERS; } + static constexpr auto eax_waveform_param_id() { return EAXFLANGER_WAVEFORM; } + static constexpr auto eax_phase_param_id() { return EAXFLANGER_PHASE; } + static constexpr auto eax_rate_param_id() { return EAXFLANGER_RATE; } + static constexpr auto eax_depth_param_id() { return EAXFLANGER_DEPTH; } + static constexpr auto eax_feedback_param_id() { return EAXFLANGER_FEEDBACK; } + static constexpr auto eax_delay_param_id() { return EAXFLANGER_DELAY; } + + static constexpr auto eax_min_waveform() { return EAXFLANGER_MINWAVEFORM; } + static constexpr auto eax_min_phase() { return EAXFLANGER_MINPHASE; } + static constexpr auto eax_min_rate() { return EAXFLANGER_MINRATE; } + static constexpr auto eax_min_depth() { return EAXFLANGER_MINDEPTH; } + static constexpr auto eax_min_feedback() { return EAXFLANGER_MINFEEDBACK; } + static constexpr auto eax_min_delay() { return EAXFLANGER_MINDELAY; } + + static constexpr auto eax_max_waveform() { return EAXFLANGER_MAXWAVEFORM; } + static constexpr auto eax_max_phase() { return EAXFLANGER_MAXPHASE; } + static constexpr auto eax_max_rate() { return EAXFLANGER_MAXRATE; } + static constexpr auto eax_max_depth() { return EAXFLANGER_MAXDEPTH; } + static constexpr auto eax_max_feedback() { return EAXFLANGER_MAXFEEDBACK; } + static constexpr auto eax_max_delay() { return EAXFLANGER_MAXDELAY; } + + static constexpr auto eax_default_waveform() { return EAXFLANGER_DEFAULTWAVEFORM; } + static constexpr auto eax_default_phase() { return EAXFLANGER_DEFAULTPHASE; } + static constexpr auto eax_default_rate() { return EAXFLANGER_DEFAULTRATE; } + static constexpr auto eax_default_depth() { return EAXFLANGER_DEFAULTDEPTH; } + static constexpr auto eax_default_feedback() { return EAXFLANGER_DEFAULTFEEDBACK; } + static constexpr auto eax_default_delay() { return EAXFLANGER_DEFAULTDELAY; } + + static constexpr auto efx_min_waveform() { return AL_FLANGER_MIN_WAVEFORM; } + static constexpr auto efx_min_phase() { return AL_FLANGER_MIN_PHASE; } + static constexpr auto efx_min_rate() { return AL_FLANGER_MIN_RATE; } + static constexpr auto efx_min_depth() { return AL_FLANGER_MIN_DEPTH; } + static constexpr auto efx_min_feedback() { return AL_FLANGER_MIN_FEEDBACK; } + static constexpr auto efx_min_delay() { return AL_FLANGER_MIN_DELAY; } + + static constexpr auto efx_max_waveform() { return AL_FLANGER_MAX_WAVEFORM; } + static constexpr auto efx_max_phase() { return AL_FLANGER_MAX_PHASE; } + static constexpr auto efx_max_rate() { return AL_FLANGER_MAX_RATE; } + static constexpr auto efx_max_depth() { return AL_FLANGER_MAX_DEPTH; } + static constexpr auto efx_max_feedback() { return AL_FLANGER_MAX_FEEDBACK; } + static constexpr auto efx_max_delay() { return AL_FLANGER_MAX_DELAY; } + + static constexpr auto efx_default_waveform() { return AL_FLANGER_DEFAULT_WAVEFORM; } + static constexpr auto efx_default_phase() { return AL_FLANGER_DEFAULT_PHASE; } + static constexpr auto efx_default_rate() { return AL_FLANGER_DEFAULT_RATE; } + static constexpr auto efx_default_depth() { return AL_FLANGER_DEFAULT_DEPTH; } + static constexpr auto efx_default_feedback() { return AL_FLANGER_DEFAULT_FEEDBACK; } + static constexpr auto efx_default_delay() { return AL_FLANGER_DEFAULT_DELAY; } +}; // EaxFlangerTraits + +template +class EaxChorusFlangerEffect final : public EaxEffect4 { +public: + using Traits = TTraits; + using Base = EaxEffect4; + using typename Base::Exception; + using typename Base::Props; + using typename Base::State; + using Base::defer; - // [[nodiscard]] - bool apply_deferred() override; + EaxChorusFlangerEffect(const EaxCall& call) + : Base{Traits::efx_effect(), call} + {} private: - EAXCHORUSPROPERTIES eax_{}; - EAXCHORUSPROPERTIES eax_d_{}; - EaxChorusEffectDirtyFlags eax_dirty_flags_{}; - - void set_eax_defaults() noexcept; - - void set_efx_waveform(); - void set_efx_phase(); - void set_efx_rate(); - void set_efx_depth(); - void set_efx_feedback(); - void set_efx_delay(); - void set_efx_defaults(); - - void get(const EaxEaxCall& eax_call); - - void validate_waveform(unsigned long ulWaveform); - void validate_phase(long lPhase); - void validate_rate(float flRate); - void validate_depth(float flDepth); - void validate_feedback(float flFeedback); - void validate_delay(float flDelay); - void validate_all(const EAXCHORUSPROPERTIES& eax_all); - - void defer_waveform(unsigned long ulWaveform); - void defer_phase(long lPhase); - void defer_rate(float flRate); - void defer_depth(float flDepth); - void defer_feedback(float flFeedback); - void defer_delay(float flDelay); - void defer_all(const EAXCHORUSPROPERTIES& eax_all); - - void defer_waveform(const EaxEaxCall& eax_call); - void defer_phase(const EaxEaxCall& eax_call); - void defer_rate(const EaxEaxCall& eax_call); - void defer_depth(const EaxEaxCall& eax_call); - void defer_feedback(const EaxEaxCall& eax_call); - void defer_delay(const EaxEaxCall& eax_call); - void defer_all(const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); -}; // EaxChorusEffect - - -class EaxChorusEffectException : - public EaxException -{ -public: - explicit EaxChorusEffectException( - const char* message) - : - EaxException{"EAX_CHORUS_EFFECT", message} + struct WaveformValidator { + void operator()(unsigned long ulWaveform) const + { + eax_validate_range( + "Waveform", + ulWaveform, + Traits::eax_min_waveform(), + Traits::eax_max_waveform()); + } + }; // WaveformValidator + + struct PhaseValidator { + void operator()(long lPhase) const + { + eax_validate_range( + "Phase", + lPhase, + Traits::eax_min_phase(), + Traits::eax_max_phase()); + } + }; // PhaseValidator + + struct RateValidator { + void operator()(float flRate) const + { + eax_validate_range( + "Rate", + flRate, + Traits::eax_min_rate(), + Traits::eax_max_rate()); + } + }; // RateValidator + + struct DepthValidator { + void operator()(float flDepth) const + { + eax_validate_range( + "Depth", + flDepth, + Traits::eax_min_depth(), + Traits::eax_max_depth()); + } + }; // DepthValidator + + struct FeedbackValidator { + void operator()(float flFeedback) const + { + eax_validate_range( + "Feedback", + flFeedback, + Traits::eax_min_feedback(), + Traits::eax_max_feedback()); + } + }; // FeedbackValidator + + struct DelayValidator { + void operator()(float flDelay) const + { + eax_validate_range( + "Delay", + flDelay, + Traits::eax_min_delay(), + Traits::eax_max_delay()); + } + }; // DelayValidator + + struct AllValidator { + void operator()(const Props& all) const + { + WaveformValidator{}(all.ulWaveform); + PhaseValidator{}(all.lPhase); + RateValidator{}(all.flRate); + DepthValidator{}(all.flDepth); + FeedbackValidator{}(all.flFeedback); + DelayValidator{}(all.flDelay); + } + }; // AllValidator + + void set_defaults(Props& props) override { + props.ulWaveform = Traits::eax_default_waveform(); + props.lPhase = Traits::eax_default_phase(); + props.flRate = Traits::eax_default_rate(); + props.flDepth = Traits::eax_default_depth(); + props.flFeedback = Traits::eax_default_feedback(); + props.flDelay = Traits::eax_default_delay(); } -}; // EaxChorusEffectException - - -EaxChorusEffect::EaxChorusEffect() - : EaxEffect{AL_EFFECT_CHORUS} -{ - set_eax_defaults(); - set_efx_defaults(); -} - -void EaxChorusEffect::dispatch(const EaxEaxCall& eax_call) -{ - eax_call.is_get() ? get(eax_call) : set(eax_call); -} - -void EaxChorusEffect::set_eax_defaults() noexcept -{ - eax_.ulWaveform = EAXCHORUS_DEFAULTWAVEFORM; - eax_.lPhase = EAXCHORUS_DEFAULTPHASE; - eax_.flRate = EAXCHORUS_DEFAULTRATE; - eax_.flDepth = EAXCHORUS_DEFAULTDEPTH; - eax_.flFeedback = EAXCHORUS_DEFAULTFEEDBACK; - eax_.flDelay = EAXCHORUS_DEFAULTDELAY; - - eax_d_ = eax_; -} - -void EaxChorusEffect::set_efx_waveform() -{ - const auto waveform = clamp( - static_cast(eax_.ulWaveform), - AL_CHORUS_MIN_WAVEFORM, - AL_CHORUS_MAX_WAVEFORM); - eax_set_efx_waveform(waveform, al_effect_props_); -} - -void EaxChorusEffect::set_efx_phase() -{ - const auto phase = clamp( - static_cast(eax_.lPhase), - AL_CHORUS_MIN_PHASE, - AL_CHORUS_MAX_PHASE); - - eax_set_efx_phase(phase, al_effect_props_); -} - -void EaxChorusEffect::set_efx_rate() -{ - const auto rate = clamp( - eax_.flRate, - AL_CHORUS_MIN_RATE, - AL_CHORUS_MAX_RATE); - - eax_set_efx_rate(rate, al_effect_props_); -} - -void EaxChorusEffect::set_efx_depth() -{ - const auto depth = clamp( - eax_.flDepth, - AL_CHORUS_MIN_DEPTH, - AL_CHORUS_MAX_DEPTH); - - eax_set_efx_depth(depth, al_effect_props_); -} - -void EaxChorusEffect::set_efx_feedback() -{ - const auto feedback = clamp( - eax_.flFeedback, - AL_CHORUS_MIN_FEEDBACK, - AL_CHORUS_MAX_FEEDBACK); - - eax_set_efx_feedback(feedback, al_effect_props_); -} - -void EaxChorusEffect::set_efx_delay() -{ - const auto delay = clamp( - eax_.flDelay, - AL_CHORUS_MIN_DELAY, - AL_CHORUS_MAX_DELAY); - - eax_set_efx_delay(delay, al_effect_props_); -} - -void EaxChorusEffect::set_efx_defaults() -{ - set_efx_waveform(); - set_efx_phase(); - set_efx_rate(); - set_efx_depth(); - set_efx_feedback(); - set_efx_delay(); -} - -void EaxChorusEffect::get(const EaxEaxCall& eax_call) -{ - switch(eax_call.get_property_id()) + void set_efx_waveform() { - case EAXCHORUS_NONE: - break; - - case EAXCHORUS_ALLPARAMETERS: - eax_call.set_value(eax_); - break; - - case EAXCHORUS_WAVEFORM: - eax_call.set_value(eax_.ulWaveform); - break; - - case EAXCHORUS_PHASE: - eax_call.set_value(eax_.lPhase); - break; - - case EAXCHORUS_RATE: - eax_call.set_value(eax_.flRate); - break; - - case EAXCHORUS_DEPTH: - eax_call.set_value(eax_.flDepth); - break; - - case EAXCHORUS_FEEDBACK: - eax_call.set_value(eax_.flFeedback); - break; - - case EAXCHORUS_DELAY: - eax_call.set_value(eax_.flDelay); - break; - - default: - throw EaxChorusEffectException{"Unsupported property id."}; + const auto waveform = clamp( + static_cast(Base::props_.ulWaveform), + Traits::efx_min_waveform(), + Traits::efx_max_waveform()); + const auto efx_waveform = WaveformFromEnum(waveform); + assert(efx_waveform.has_value()); + Base::al_effect_props_.Chorus.Waveform = *efx_waveform; } -} - -void EaxChorusEffect::validate_waveform( - unsigned long ulWaveform) -{ - eax_validate_range( - "Waveform", - ulWaveform, - EAXCHORUS_MINWAVEFORM, - EAXCHORUS_MAXWAVEFORM); -} - -void EaxChorusEffect::validate_phase( - long lPhase) -{ - eax_validate_range( - "Phase", - lPhase, - EAXCHORUS_MINPHASE, - EAXCHORUS_MAXPHASE); -} - -void EaxChorusEffect::validate_rate( - float flRate) -{ - eax_validate_range( - "Rate", - flRate, - EAXCHORUS_MINRATE, - EAXCHORUS_MAXRATE); -} - -void EaxChorusEffect::validate_depth( - float flDepth) -{ - eax_validate_range( - "Depth", - flDepth, - EAXCHORUS_MINDEPTH, - EAXCHORUS_MAXDEPTH); -} - -void EaxChorusEffect::validate_feedback( - float flFeedback) -{ - eax_validate_range( - "Feedback", - flFeedback, - EAXCHORUS_MINFEEDBACK, - EAXCHORUS_MAXFEEDBACK); -} - -void EaxChorusEffect::validate_delay( - float flDelay) -{ - eax_validate_range( - "Delay", - flDelay, - EAXCHORUS_MINDELAY, - EAXCHORUS_MAXDELAY); -} - -void EaxChorusEffect::validate_all( - const EAXCHORUSPROPERTIES& eax_all) -{ - validate_waveform(eax_all.ulWaveform); - validate_phase(eax_all.lPhase); - validate_rate(eax_all.flRate); - validate_depth(eax_all.flDepth); - validate_feedback(eax_all.flFeedback); - validate_delay(eax_all.flDelay); -} - -void EaxChorusEffect::defer_waveform( - unsigned long ulWaveform) -{ - eax_d_.ulWaveform = ulWaveform; - eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform); -} - -void EaxChorusEffect::defer_phase( - long lPhase) -{ - eax_d_.lPhase = lPhase; - eax_dirty_flags_.lPhase = (eax_.lPhase != eax_d_.lPhase); -} - -void EaxChorusEffect::defer_rate( - float flRate) -{ - eax_d_.flRate = flRate; - eax_dirty_flags_.flRate = (eax_.flRate != eax_d_.flRate); -} - -void EaxChorusEffect::defer_depth( - float flDepth) -{ - eax_d_.flDepth = flDepth; - eax_dirty_flags_.flDepth = (eax_.flDepth != eax_d_.flDepth); -} - -void EaxChorusEffect::defer_feedback( - float flFeedback) -{ - eax_d_.flFeedback = flFeedback; - eax_dirty_flags_.flFeedback = (eax_.flFeedback != eax_d_.flFeedback); -} - -void EaxChorusEffect::defer_delay( - float flDelay) -{ - eax_d_.flDelay = flDelay; - eax_dirty_flags_.flDelay = (eax_.flDelay != eax_d_.flDelay); -} - -void EaxChorusEffect::defer_all( - const EAXCHORUSPROPERTIES& eax_all) -{ - defer_waveform(eax_all.ulWaveform); - defer_phase(eax_all.lPhase); - defer_rate(eax_all.flRate); - defer_depth(eax_all.flDepth); - defer_feedback(eax_all.flFeedback); - defer_delay(eax_all.flDelay); -} - -void EaxChorusEffect::defer_waveform( - const EaxEaxCall& eax_call) -{ - const auto& waveform = - eax_call.get_value(); - - validate_waveform(waveform); - defer_waveform(waveform); -} - -void EaxChorusEffect::defer_phase( - const EaxEaxCall& eax_call) -{ - const auto& phase = - eax_call.get_value(); - - validate_phase(phase); - defer_phase(phase); -} - -void EaxChorusEffect::defer_rate( - const EaxEaxCall& eax_call) -{ - const auto& rate = - eax_call.get_value(); - - validate_rate(rate); - defer_rate(rate); -} - -void EaxChorusEffect::defer_depth( - const EaxEaxCall& eax_call) -{ - const auto& depth = - eax_call.get_value(); - - validate_depth(depth); - defer_depth(depth); -} - -void EaxChorusEffect::defer_feedback( - const EaxEaxCall& eax_call) -{ - const auto& feedback = - eax_call.get_value(); - - validate_feedback(feedback); - defer_feedback(feedback); -} - -void EaxChorusEffect::defer_delay( - const EaxEaxCall& eax_call) -{ - const auto& delay = - eax_call.get_value(); - validate_delay(delay); - defer_delay(delay); -} - -void EaxChorusEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto& all = - eax_call.get_value(); - - validate_all(all); - defer_all(all); -} - -// [[nodiscard]] -bool EaxChorusEffect::apply_deferred() -{ - if (eax_dirty_flags_ == EaxChorusEffectDirtyFlags{}) + void set_efx_phase() noexcept { - return false; + Base::al_effect_props_.Chorus.Phase = clamp( + static_cast(Base::props_.lPhase), + Traits::efx_min_phase(), + Traits::efx_max_phase()); } - eax_ = eax_d_; - - if (eax_dirty_flags_.ulWaveform) + void set_efx_rate() noexcept { - set_efx_waveform(); + Base::al_effect_props_.Chorus.Rate = clamp( + Base::props_.flRate, + Traits::efx_min_rate(), + Traits::efx_max_rate()); } - if (eax_dirty_flags_.lPhase) + void set_efx_depth() noexcept { - set_efx_phase(); + Base::al_effect_props_.Chorus.Depth = clamp( + Base::props_.flDepth, + Traits::efx_min_depth(), + Traits::efx_max_depth()); } - if (eax_dirty_flags_.flRate) + void set_efx_feedback() noexcept { - set_efx_rate(); + Base::al_effect_props_.Chorus.Feedback = clamp( + Base::props_.flFeedback, + Traits::efx_min_feedback(), + Traits::efx_max_feedback()); } - if (eax_dirty_flags_.flDepth) + void set_efx_delay() noexcept { - set_efx_depth(); + Base::al_effect_props_.Chorus.Delay = clamp( + Base::props_.flDelay, + Traits::efx_min_delay(), + Traits::efx_max_delay()); } - if (eax_dirty_flags_.flFeedback) + void set_efx_defaults() override { + set_efx_waveform(); + set_efx_phase(); + set_efx_rate(); + set_efx_depth(); set_efx_feedback(); - } - - if (eax_dirty_flags_.flDelay) - { set_efx_delay(); } - eax_dirty_flags_ = EaxChorusEffectDirtyFlags{}; - - return true; -} - -void EaxChorusEffect::set(const EaxEaxCall& eax_call) -{ - switch(eax_call.get_property_id()) + void get(const EaxCall& call, const Props& props) override { - case EAXCHORUS_NONE: - break; - - case EAXCHORUS_ALLPARAMETERS: - defer_all(eax_call); - break; - - case EAXCHORUS_WAVEFORM: - defer_waveform(eax_call); - break; - - case EAXCHORUS_PHASE: - defer_phase(eax_call); - break; - - case EAXCHORUS_RATE: - defer_rate(eax_call); - break; - - case EAXCHORUS_DEPTH: - defer_depth(eax_call); - break; - - case EAXCHORUS_FEEDBACK: - defer_feedback(eax_call); - break; - - case EAXCHORUS_DELAY: - defer_delay(eax_call); - break; - - default: - throw EaxChorusEffectException{"Unsupported property id."}; + switch(call.get_property_id()) + { + case Traits::eax_none_param_id(): + break; + + case Traits::eax_allparameters_param_id(): + call.template set_value(props); + break; + + case Traits::eax_waveform_param_id(): + call.template set_value(props.ulWaveform); + break; + + case Traits::eax_phase_param_id(): + call.template set_value(props.lPhase); + break; + + case Traits::eax_rate_param_id(): + call.template set_value(props.flRate); + break; + + case Traits::eax_depth_param_id(): + call.template set_value(props.flDepth); + break; + + case Traits::eax_feedback_param_id(): + call.template set_value(props.flFeedback); + break; + + case Traits::eax_delay_param_id(): + call.template set_value(props.flDelay); + break; + + default: + Base::fail_unknown_property_id(); + } } -} - - -} // namespace - -EaxEffectUPtr eax_create_eax_chorus_effect() -{ - return std::make_unique<::EaxChorusEffect>(); -} - - -namespace -{ - - -using EaxFlangerEffectDirtyFlagsValue = std::uint_least8_t; - -struct EaxFlangerEffectDirtyFlags -{ - using EaxIsBitFieldStruct = bool; - - EaxFlangerEffectDirtyFlagsValue ulWaveform : 1; - EaxFlangerEffectDirtyFlagsValue lPhase : 1; - EaxFlangerEffectDirtyFlagsValue flRate : 1; - EaxFlangerEffectDirtyFlagsValue flDepth : 1; - EaxFlangerEffectDirtyFlagsValue flFeedback : 1; - EaxFlangerEffectDirtyFlagsValue flDelay : 1; -}; // EaxFlangerEffectDirtyFlags - - -class EaxFlangerEffect final : - public EaxEffect -{ -public: - EaxFlangerEffect(); - - - void dispatch(const EaxEaxCall& eax_call) override; - - // [[nodiscard]] - bool apply_deferred() override; - -private: - EAXFLANGERPROPERTIES eax_{}; - EAXFLANGERPROPERTIES eax_d_{}; - EaxFlangerEffectDirtyFlags eax_dirty_flags_{}; - - void set_eax_defaults(); - - void set_efx_waveform(); - void set_efx_phase(); - void set_efx_rate(); - void set_efx_depth(); - void set_efx_feedback(); - void set_efx_delay(); - void set_efx_defaults(); - - void get(const EaxEaxCall& eax_call); - - void validate_waveform(unsigned long ulWaveform); - void validate_phase(long lPhase); - void validate_rate(float flRate); - void validate_depth(float flDepth); - void validate_feedback(float flFeedback); - void validate_delay(float flDelay); - void validate_all(const EAXFLANGERPROPERTIES& all); - - void defer_waveform(unsigned long ulWaveform); - void defer_phase(long lPhase); - void defer_rate(float flRate); - void defer_depth(float flDepth); - void defer_feedback(float flFeedback); - void defer_delay(float flDelay); - void defer_all(const EAXFLANGERPROPERTIES& all); - - void defer_waveform(const EaxEaxCall& eax_call); - void defer_phase(const EaxEaxCall& eax_call); - void defer_rate(const EaxEaxCall& eax_call); - void defer_depth(const EaxEaxCall& eax_call); - void defer_feedback(const EaxEaxCall& eax_call); - void defer_delay(const EaxEaxCall& eax_call); - void defer_all(const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); -}; // EaxFlangerEffect - - -class EaxFlangerEffectException : - public EaxException -{ -public: - explicit EaxFlangerEffectException( - const char* message) - : - EaxException{"EAX_FLANGER_EFFECT", message} + void set(const EaxCall& call, Props& props) override { + switch(call.get_property_id()) + { + case Traits::eax_none_param_id(): + break; + + case Traits::eax_allparameters_param_id(): + Base::template defer(call, props); + break; + + case Traits::eax_waveform_param_id(): + Base::template defer(call, props.ulWaveform); + break; + + case Traits::eax_phase_param_id(): + Base::template defer(call, props.lPhase); + break; + + case Traits::eax_rate_param_id(): + Base::template defer(call, props.flRate); + break; + + case Traits::eax_depth_param_id(): + Base::template defer(call, props.flDepth); + break; + + case Traits::eax_feedback_param_id(): + Base::template defer(call, props.flFeedback); + break; + + case Traits::eax_delay_param_id(): + Base::template defer(call, props.flDelay); + break; + + default: + Base::fail_unknown_property_id(); + } } -}; // EaxFlangerEffectException - - -EaxFlangerEffect::EaxFlangerEffect() - : EaxEffect{AL_EFFECT_FLANGER} -{ - set_eax_defaults(); - set_efx_defaults(); -} - -void EaxFlangerEffect::dispatch(const EaxEaxCall& eax_call) -{ - eax_call.is_get() ? get(eax_call) : set(eax_call); -} - -void EaxFlangerEffect::set_eax_defaults() -{ - eax_.ulWaveform = EAXFLANGER_DEFAULTWAVEFORM; - eax_.lPhase = EAXFLANGER_DEFAULTPHASE; - eax_.flRate = EAXFLANGER_DEFAULTRATE; - eax_.flDepth = EAXFLANGER_DEFAULTDEPTH; - eax_.flFeedback = EAXFLANGER_DEFAULTFEEDBACK; - eax_.flDelay = EAXFLANGER_DEFAULTDELAY; - - eax_d_ = eax_; -} - -void EaxFlangerEffect::set_efx_waveform() -{ - const auto waveform = clamp( - static_cast(eax_.ulWaveform), - AL_FLANGER_MIN_WAVEFORM, - AL_FLANGER_MAX_WAVEFORM); - - eax_set_efx_waveform(waveform, al_effect_props_); -} - -void EaxFlangerEffect::set_efx_phase() -{ - const auto phase = clamp( - static_cast(eax_.lPhase), - AL_FLANGER_MIN_PHASE, - AL_FLANGER_MAX_PHASE); - - eax_set_efx_phase(phase, al_effect_props_); -} - -void EaxFlangerEffect::set_efx_rate() -{ - const auto rate = clamp( - eax_.flRate, - AL_FLANGER_MIN_RATE, - AL_FLANGER_MAX_RATE); - - eax_set_efx_rate(rate, al_effect_props_); -} - -void EaxFlangerEffect::set_efx_depth() -{ - const auto depth = clamp( - eax_.flDepth, - AL_FLANGER_MIN_DEPTH, - AL_FLANGER_MAX_DEPTH); - - eax_set_efx_depth(depth, al_effect_props_); -} - -void EaxFlangerEffect::set_efx_feedback() -{ - const auto feedback = clamp( - eax_.flFeedback, - AL_FLANGER_MIN_FEEDBACK, - AL_FLANGER_MAX_FEEDBACK); - - eax_set_efx_feedback(feedback, al_effect_props_); -} - -void EaxFlangerEffect::set_efx_delay() -{ - const auto delay = clamp( - eax_.flDelay, - AL_FLANGER_MIN_DELAY, - AL_FLANGER_MAX_DELAY); - eax_set_efx_delay(delay, al_effect_props_); -} - -void EaxFlangerEffect::set_efx_defaults() -{ - set_efx_waveform(); - set_efx_phase(); - set_efx_rate(); - set_efx_depth(); - set_efx_feedback(); - set_efx_delay(); -} - -void EaxFlangerEffect::get(const EaxEaxCall& eax_call) -{ - switch(eax_call.get_property_id()) + bool commit_props(const Props& props) override { - case EAXFLANGER_NONE: - break; - - case EAXFLANGER_ALLPARAMETERS: - eax_call.set_value(eax_); - break; - - case EAXFLANGER_WAVEFORM: - eax_call.set_value(eax_.ulWaveform); - break; - - case EAXFLANGER_PHASE: - eax_call.set_value(eax_.lPhase); - break; - - case EAXFLANGER_RATE: - eax_call.set_value(eax_.flRate); - break; - - case EAXFLANGER_DEPTH: - eax_call.set_value(eax_.flDepth); - break; - - case EAXFLANGER_FEEDBACK: - eax_call.set_value(eax_.flFeedback); - break; - - case EAXFLANGER_DELAY: - eax_call.set_value(eax_.flDelay); - break; - - default: - throw EaxFlangerEffectException{"Unsupported property id."}; + auto is_dirty = false; + + if (Base::props_.ulWaveform != props.ulWaveform) + { + is_dirty = true; + set_efx_waveform(); + } + + if (Base::props_.lPhase != props.lPhase) + { + is_dirty = true; + set_efx_phase(); + } + + if (Base::props_.flRate != props.flRate) + { + is_dirty = true; + set_efx_rate(); + } + + if (Base::props_.flDepth != props.flDepth) + { + is_dirty = true; + set_efx_depth(); + } + + if (Base::props_.flFeedback != props.flFeedback) + { + is_dirty = true; + set_efx_feedback(); + } + + if (Base::props_.flDelay != props.flDelay) + { + is_dirty = true; + set_efx_delay(); + } + + return is_dirty; } -} - -void EaxFlangerEffect::validate_waveform( - unsigned long ulWaveform) -{ - eax_validate_range( - "Waveform", - ulWaveform, - EAXFLANGER_MINWAVEFORM, - EAXFLANGER_MAXWAVEFORM); -} - -void EaxFlangerEffect::validate_phase( - long lPhase) -{ - eax_validate_range( - "Phase", - lPhase, - EAXFLANGER_MINPHASE, - EAXFLANGER_MAXPHASE); -} - -void EaxFlangerEffect::validate_rate( - float flRate) -{ - eax_validate_range( - "Rate", - flRate, - EAXFLANGER_MINRATE, - EAXFLANGER_MAXRATE); -} - -void EaxFlangerEffect::validate_depth( - float flDepth) -{ - eax_validate_range( - "Depth", - flDepth, - EAXFLANGER_MINDEPTH, - EAXFLANGER_MAXDEPTH); -} - -void EaxFlangerEffect::validate_feedback( - float flFeedback) -{ - eax_validate_range( - "Feedback", - flFeedback, - EAXFLANGER_MINFEEDBACK, - EAXFLANGER_MAXFEEDBACK); -} - -void EaxFlangerEffect::validate_delay( - float flDelay) -{ - eax_validate_range( - "Delay", - flDelay, - EAXFLANGER_MINDELAY, - EAXFLANGER_MAXDELAY); -} - -void EaxFlangerEffect::validate_all( - const EAXFLANGERPROPERTIES& all) -{ - validate_waveform(all.ulWaveform); - validate_phase(all.lPhase); - validate_rate(all.flRate); - validate_depth(all.flDepth); - validate_feedback(all.flDelay); - validate_delay(all.flDelay); -} +}; // EaxChorusFlangerEffect -void EaxFlangerEffect::defer_waveform( - unsigned long ulWaveform) +template +EaxEffectUPtr eax_create_eax_chorus_flanger_effect(const EaxCall& call) { - eax_d_.ulWaveform = ulWaveform; - eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform); + return eax_create_eax4_effect>(call); } -void EaxFlangerEffect::defer_phase( - long lPhase) -{ - eax_d_.lPhase = lPhase; - eax_dirty_flags_.lPhase = (eax_.lPhase != eax_d_.lPhase); -} - -void EaxFlangerEffect::defer_rate( - float flRate) -{ - eax_d_.flRate = flRate; - eax_dirty_flags_.flRate = (eax_.flRate != eax_d_.flRate); -} - -void EaxFlangerEffect::defer_depth( - float flDepth) -{ - eax_d_.flDepth = flDepth; - eax_dirty_flags_.flDepth = (eax_.flDepth != eax_d_.flDepth); -} - -void EaxFlangerEffect::defer_feedback( - float flFeedback) -{ - eax_d_.flFeedback = flFeedback; - eax_dirty_flags_.flFeedback = (eax_.flFeedback != eax_d_.flFeedback); -} - -void EaxFlangerEffect::defer_delay( - float flDelay) -{ - eax_d_.flDelay = flDelay; - eax_dirty_flags_.flDelay = (eax_.flDelay != eax_d_.flDelay); -} - -void EaxFlangerEffect::defer_all( - const EAXFLANGERPROPERTIES& all) -{ - defer_waveform(all.ulWaveform); - defer_phase(all.lPhase); - defer_rate(all.flRate); - defer_depth(all.flDepth); - defer_feedback(all.flDelay); - defer_delay(all.flDelay); -} - -void EaxFlangerEffect::defer_waveform( - const EaxEaxCall& eax_call) -{ - const auto& waveform = - eax_call.get_value(); - - validate_waveform(waveform); - defer_waveform(waveform); -} - -void EaxFlangerEffect::defer_phase( - const EaxEaxCall& eax_call) -{ - const auto& phase = - eax_call.get_value(); - - validate_phase(phase); - defer_phase(phase); -} - -void EaxFlangerEffect::defer_rate( - const EaxEaxCall& eax_call) -{ - const auto& rate = - eax_call.get_value(); - - validate_rate(rate); - defer_rate(rate); -} - -void EaxFlangerEffect::defer_depth( - const EaxEaxCall& eax_call) -{ - const auto& depth = - eax_call.get_value(); - - validate_depth(depth); - defer_depth(depth); -} - -void EaxFlangerEffect::defer_feedback( - const EaxEaxCall& eax_call) -{ - const auto& feedback = - eax_call.get_value(); - - validate_feedback(feedback); - defer_feedback(feedback); -} - -void EaxFlangerEffect::defer_delay( - const EaxEaxCall& eax_call) -{ - const auto& delay = - eax_call.get_value(); - - validate_delay(delay); - defer_delay(delay); -} - -void EaxFlangerEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto& all = - eax_call.get_value(); - - validate_all(all); - defer_all(all); -} - -// [[nodiscard]] -bool EaxFlangerEffect::apply_deferred() -{ - if (eax_dirty_flags_ == EaxFlangerEffectDirtyFlags{}) - { - return false; - } - - eax_ = eax_d_; - - if (eax_dirty_flags_.ulWaveform) - { - set_efx_waveform(); - } - - if (eax_dirty_flags_.lPhase) - { - set_efx_phase(); - } - - if (eax_dirty_flags_.flRate) - { - set_efx_rate(); - } - - if (eax_dirty_flags_.flDepth) - { - set_efx_depth(); - } - - if (eax_dirty_flags_.flFeedback) - { - set_efx_feedback(); - } - - if (eax_dirty_flags_.flDelay) - { - set_efx_delay(); - } +} // namespace - eax_dirty_flags_ = EaxFlangerEffectDirtyFlags{}; +// ========================================================================== - return true; -} - -void EaxFlangerEffect::set(const EaxEaxCall& eax_call) +EaxEffectUPtr eax_create_eax_chorus_effect(const EaxCall& call) { - switch(eax_call.get_property_id()) - { - case EAXFLANGER_NONE: - break; - - case EAXFLANGER_ALLPARAMETERS: - defer_all(eax_call); - break; - - case EAXFLANGER_WAVEFORM: - defer_waveform(eax_call); - break; - - case EAXFLANGER_PHASE: - defer_phase(eax_call); - break; - - case EAXFLANGER_RATE: - defer_rate(eax_call); - break; - - case EAXFLANGER_DEPTH: - defer_depth(eax_call); - break; - - case EAXFLANGER_FEEDBACK: - defer_feedback(eax_call); - break; - - case EAXFLANGER_DELAY: - defer_delay(eax_call); - break; - - default: - throw EaxFlangerEffectException{"Unsupported property id."}; - } + return eax_create_eax_chorus_flanger_effect(call); } -} // namespace - -EaxEffectUPtr eax_create_eax_flanger_effect() +EaxEffectUPtr eax_create_eax_flanger_effect(const EaxCall& call) { - return std::make_unique(); + return eax_create_eax_chorus_flanger_effect(call); } #endif // ALSOFT_EAX diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp index a18609ca..9824d11b 100644 --- a/al/effects/compressor.cpp +++ b/al/effects/compressor.cpp @@ -9,7 +9,6 @@ #ifdef ALSOFT_EAX #include "alnumeric.h" - #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -81,94 +80,63 @@ const EffectProps CompressorEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -using EaxCompressorEffectDirtyFlagsValue = std::uint_least8_t; - -struct EaxCompressorEffectDirtyFlags +class EaxCompressorEffectException : public EaxException { - using EaxIsBitFieldStruct = bool; - - EaxCompressorEffectDirtyFlagsValue ulOnOff : 1; -}; // EaxCompressorEffectDirtyFlags - +public: + explicit EaxCompressorEffectException(const char* message) + : EaxException{"EAX_COMPRESSOR_EFFECT", message} + {} +}; // EaxCompressorEffectException -class EaxCompressorEffect final : - public EaxEffect +class EaxCompressorEffect final : public EaxEffect4 { public: - EaxCompressorEffect(); - - - void dispatch(const EaxEaxCall& eax_call) override; - - // [[nodiscard]] - bool apply_deferred() override; + EaxCompressorEffect(const EaxCall& call); private: - EAXAGCCOMPRESSORPROPERTIES eax_{}; - EAXAGCCOMPRESSORPROPERTIES eax_d_{}; - EaxCompressorEffectDirtyFlags eax_dirty_flags_{}; - - - void set_eax_defaults(); - - void set_efx_on_off(); - void set_efx_defaults(); - - void get(const EaxEaxCall& eax_call); - - void validate_on_off(unsigned long ulOnOff); - void validate_all(const EAXAGCCOMPRESSORPROPERTIES& eax_all); - - void defer_on_off(unsigned long ulOnOff); - void defer_all(const EAXAGCCOMPRESSORPROPERTIES& eax_all); - - void defer_on_off(const EaxEaxCall& eax_call); - void defer_all(const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); + struct OnOffValidator { + void operator()(unsigned long ulOnOff) const + { + eax_validate_range( + "On-Off", + ulOnOff, + EAXAGCCOMPRESSOR_MINONOFF, + EAXAGCCOMPRESSOR_MAXONOFF); + } + }; // OnOffValidator + + struct AllValidator { + void operator()(const Props& all) const + { + OnOffValidator{}(all.ulOnOff); + } + }; // AllValidator + + void set_defaults(Props& props) override; + + void set_efx_on_off() noexcept; + void set_efx_defaults() override; + + void get(const EaxCall& call, const Props& props) override; + void set(const EaxCall& call, Props& props) override; + bool commit_props(const Props& props) override; }; // EaxCompressorEffect +EaxCompressorEffect::EaxCompressorEffect(const EaxCall& call) + : EaxEffect4{AL_EFFECT_COMPRESSOR, call} +{} -class EaxCompressorEffectException : - public EaxException +void EaxCompressorEffect::set_defaults(Props& props) { -public: - explicit EaxCompressorEffectException( - const char* message) - : - EaxException{"EAX_COMPRESSOR_EFFECT", message} - { - } -}; // EaxCompressorEffectException - - -EaxCompressorEffect::EaxCompressorEffect() - : EaxEffect{AL_EFFECT_COMPRESSOR} -{ - set_eax_defaults(); - set_efx_defaults(); -} - -// [[nodiscard]] -void EaxCompressorEffect::dispatch(const EaxEaxCall& eax_call) -{ - eax_call.is_get() ? get(eax_call) : set(eax_call); -} - -void EaxCompressorEffect::set_eax_defaults() -{ - eax_.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF; - - eax_d_ = eax_; + props.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF; } -void EaxCompressorEffect::set_efx_on_off() +void EaxCompressorEffect::set_efx_on_off() noexcept { const auto on_off = clamp( - static_cast(eax_.ulOnOff), + static_cast(props_.ulOnOff), AL_COMPRESSOR_MIN_ONOFF, AL_COMPRESSOR_MAX_ONOFF); - al_effect_props_.Compressor.OnOff = (on_off != AL_FALSE); } @@ -177,120 +145,46 @@ void EaxCompressorEffect::set_efx_defaults() set_efx_on_off(); } -void EaxCompressorEffect::get(const EaxEaxCall& eax_call) +void EaxCompressorEffect::get(const EaxCall& call, const Props& props) { - switch(eax_call.get_property_id()) + switch(call.get_property_id()) { - case EAXAGCCOMPRESSOR_NONE: - break; - - case EAXAGCCOMPRESSOR_ALLPARAMETERS: - eax_call.set_value(eax_); - break; - - case EAXAGCCOMPRESSOR_ONOFF: - eax_call.set_value(eax_.ulOnOff); - break; - - default: - throw EaxCompressorEffectException{"Unsupported property id."}; + case EAXAGCCOMPRESSOR_NONE: break; + case EAXAGCCOMPRESSOR_ALLPARAMETERS: call.set_value(props); break; + case EAXAGCCOMPRESSOR_ONOFF: call.set_value(props.ulOnOff); break; + default: fail_unknown_property_id(); } } -void EaxCompressorEffect::validate_on_off( - unsigned long ulOnOff) -{ - eax_validate_range( - "On-Off", - ulOnOff, - EAXAGCCOMPRESSOR_MINONOFF, - EAXAGCCOMPRESSOR_MAXONOFF); -} - -void EaxCompressorEffect::validate_all( - const EAXAGCCOMPRESSORPROPERTIES& eax_all) +void EaxCompressorEffect::set(const EaxCall& call, Props& props) { - validate_on_off(eax_all.ulOnOff); -} - -void EaxCompressorEffect::defer_on_off( - unsigned long ulOnOff) -{ - eax_d_.ulOnOff = ulOnOff; - eax_dirty_flags_.ulOnOff = (eax_.ulOnOff != eax_d_.ulOnOff); -} - -void EaxCompressorEffect::defer_all( - const EAXAGCCOMPRESSORPROPERTIES& eax_all) -{ - defer_on_off(eax_all.ulOnOff); -} - -void EaxCompressorEffect::defer_on_off( - const EaxEaxCall& eax_call) -{ - const auto& on_off = - eax_call.get_value(); - - validate_on_off(on_off); - defer_on_off(on_off); -} - -void EaxCompressorEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto& all = - eax_call.get_value(); - - validate_all(all); - defer_all(all); -} - -// [[nodiscard]] -bool EaxCompressorEffect::apply_deferred() -{ - if (eax_dirty_flags_ == EaxCompressorEffectDirtyFlags{}) + switch(call.get_property_id()) { - return false; + case EAXAGCCOMPRESSOR_NONE: break; + case EAXAGCCOMPRESSOR_ALLPARAMETERS: defer(call, props); break; + case EAXAGCCOMPRESSOR_ONOFF: defer(call, props.ulOnOff); break; + default: fail_unknown_property_id(); } +} - eax_ = eax_d_; +bool EaxCompressorEffect::commit_props(const Props& props) +{ + auto is_dirty = false; - if (eax_dirty_flags_.ulOnOff) + if (props_.ulOnOff != props.ulOnOff) { + is_dirty = true; set_efx_on_off(); } - eax_dirty_flags_ = EaxCompressorEffectDirtyFlags{}; - - return true; -} - -void EaxCompressorEffect::set(const EaxEaxCall& eax_call) -{ - switch(eax_call.get_property_id()) - { - case EAXAGCCOMPRESSOR_NONE: - break; - - case EAXAGCCOMPRESSOR_ALLPARAMETERS: - defer_all(eax_call); - break; - - case EAXAGCCOMPRESSOR_ONOFF: - defer_on_off(eax_call); - break; - - default: - throw EaxCompressorEffectException{"Unsupported property id."}; - } + return is_dirty; } } // namespace -EaxEffectUPtr eax_create_eax_compressor_effect() +EaxEffectUPtr eax_create_eax_compressor_effect(const EaxCall& call) { - return std::make_unique(); + return eax_create_eax4_effect(call); } #endif // ALSOFT_EAX diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index 441b89a0..b58412b9 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -9,7 +9,6 @@ #ifdef ALSOFT_EAX #include "alnumeric.h" - #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -123,156 +122,151 @@ const EffectProps DistortionEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -using EaxDistortionEffectDirtyFlagsValue = std::uint_least8_t; - -struct EaxDistortionEffectDirtyFlags +class EaxDistortionEffectException : public EaxException { - using EaxIsBitFieldStruct = bool; - - EaxDistortionEffectDirtyFlagsValue flEdge : 1; - EaxDistortionEffectDirtyFlagsValue lGain : 1; - EaxDistortionEffectDirtyFlagsValue flLowPassCutOff : 1; - EaxDistortionEffectDirtyFlagsValue flEQCenter : 1; - EaxDistortionEffectDirtyFlagsValue flEQBandwidth : 1; -}; // EaxDistortionEffectDirtyFlags - +public: + explicit EaxDistortionEffectException(const char* message) + : EaxException{"EAX_DISTORTION_EFFECT", message} + {} +}; // EaxDistortionEffectException -class EaxDistortionEffect final : - public EaxEffect +class EaxDistortionEffect final : public EaxEffect4 { public: - EaxDistortionEffect(); - - void dispatch(const EaxEaxCall& eax_call) override; - - // [[nodiscard]] - bool apply_deferred() override; + EaxDistortionEffect(const EaxCall& call); private: - EAXDISTORTIONPROPERTIES eax_{}; - EAXDISTORTIONPROPERTIES eax_d_{}; - EaxDistortionEffectDirtyFlags eax_dirty_flags_{}; - - void set_eax_defaults(); - - void set_efx_edge(); - void set_efx_gain(); - void set_efx_lowpass_cutoff(); - void set_efx_eq_center(); - void set_efx_eq_bandwidth(); - void set_efx_defaults(); - - void get(const EaxEaxCall& eax_call); - - void validate_edge(float flEdge); - void validate_gain(long lGain); - void validate_lowpass_cutoff(float flLowPassCutOff); - void validate_eq_center(float flEQCenter); - void validate_eq_bandwidth(float flEQBandwidth); - void validate_all(const EAXDISTORTIONPROPERTIES& eax_all); - - void defer_edge(float flEdge); - void defer_gain(long lGain); - void defer_low_pass_cutoff(float flLowPassCutOff); - void defer_eq_center(float flEQCenter); - void defer_eq_bandwidth(float flEQBandwidth); - void defer_all(const EAXDISTORTIONPROPERTIES& eax_all); - - void defer_edge(const EaxEaxCall& eax_call); - void defer_gain(const EaxEaxCall& eax_call); - void defer_low_pass_cutoff(const EaxEaxCall& eax_call); - void defer_eq_center(const EaxEaxCall& eax_call); - void defer_eq_bandwidth(const EaxEaxCall& eax_call); - void defer_all(const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); + struct EdgeValidator { + void operator()(float flEdge) const + { + eax_validate_range( + "Edge", + flEdge, + EAXDISTORTION_MINEDGE, + EAXDISTORTION_MAXEDGE); + } + }; // EdgeValidator + + struct GainValidator { + void operator()(long lGain) const + { + eax_validate_range( + "Gain", + lGain, + EAXDISTORTION_MINGAIN, + EAXDISTORTION_MAXGAIN); + } + }; // GainValidator + + struct LowPassCutOffValidator { + void operator()(float flLowPassCutOff) const + { + eax_validate_range( + "Low-pass Cut-off", + flLowPassCutOff, + EAXDISTORTION_MINLOWPASSCUTOFF, + EAXDISTORTION_MAXLOWPASSCUTOFF); + } + }; // LowPassCutOffValidator + + struct EqCenterValidator { + void operator()(float flEQCenter) const + { + eax_validate_range( + "EQ Center", + flEQCenter, + EAXDISTORTION_MINEQCENTER, + EAXDISTORTION_MAXEQCENTER); + } + }; // EqCenterValidator + + struct EqBandwidthValidator { + void operator()(float flEQBandwidth) const + { + eax_validate_range( + "EQ Bandwidth", + flEQBandwidth, + EAXDISTORTION_MINEQBANDWIDTH, + EAXDISTORTION_MAXEQBANDWIDTH); + } + }; // EqBandwidthValidator + + struct AllValidator { + void operator()(const Props& all) const + { + EdgeValidator{}(all.flEdge); + GainValidator{}(all.lGain); + LowPassCutOffValidator{}(all.flLowPassCutOff); + EqCenterValidator{}(all.flEQCenter); + EqBandwidthValidator{}(all.flEQBandwidth); + } + }; // AllValidator + + void set_defaults(Props& props) override; + + void set_efx_edge() noexcept; + void set_efx_gain() noexcept; + void set_efx_lowpass_cutoff() noexcept; + void set_efx_eq_center() noexcept; + void set_efx_eq_bandwidth() noexcept; + void set_efx_defaults() override; + + void get(const EaxCall& call, const Props& props) override; + void set(const EaxCall& call, Props& props) override; + bool commit_props(const Props& props) override; }; // EaxDistortionEffect +EaxDistortionEffect::EaxDistortionEffect(const EaxCall& call) + : EaxEffect4{AL_EFFECT_DISTORTION, call} +{} -class EaxDistortionEffectException : - public EaxException -{ -public: - explicit EaxDistortionEffectException( - const char* message) - : - EaxException{"EAX_DISTORTION_EFFECT", message} - { - } -}; // EaxDistortionEffectException - - -EaxDistortionEffect::EaxDistortionEffect() - : EaxEffect{AL_EFFECT_DISTORTION} -{ - set_eax_defaults(); - set_efx_defaults(); -} - -void EaxDistortionEffect::dispatch(const EaxEaxCall& eax_call) -{ - eax_call.is_get() ? get(eax_call) : set(eax_call); -} - -void EaxDistortionEffect::set_eax_defaults() +void EaxDistortionEffect::set_defaults(Props& props) { - eax_.flEdge = EAXDISTORTION_DEFAULTEDGE; - eax_.lGain = EAXDISTORTION_DEFAULTGAIN; - eax_.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF; - eax_.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER; - eax_.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH; - - eax_d_ = eax_; + props.flEdge = EAXDISTORTION_DEFAULTEDGE; + props.lGain = EAXDISTORTION_DEFAULTGAIN; + props.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF; + props.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER; + props.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH; } -void EaxDistortionEffect::set_efx_edge() +void EaxDistortionEffect::set_efx_edge() noexcept { - const auto edge = clamp( - eax_.flEdge, + al_effect_props_.Distortion.Edge = clamp( + props_.flEdge, AL_DISTORTION_MIN_EDGE, AL_DISTORTION_MAX_EDGE); - - al_effect_props_.Distortion.Edge = edge; } -void EaxDistortionEffect::set_efx_gain() +void EaxDistortionEffect::set_efx_gain() noexcept { - const auto gain = clamp( - level_mb_to_gain(static_cast(eax_.lGain)), + al_effect_props_.Distortion.Gain = clamp( + level_mb_to_gain(static_cast(props_.lGain)), AL_DISTORTION_MIN_GAIN, AL_DISTORTION_MAX_GAIN); - - al_effect_props_.Distortion.Gain = gain; } -void EaxDistortionEffect::set_efx_lowpass_cutoff() +void EaxDistortionEffect::set_efx_lowpass_cutoff() noexcept { - const auto lowpass_cutoff = clamp( - eax_.flLowPassCutOff, + al_effect_props_.Distortion.LowpassCutoff = clamp( + props_.flLowPassCutOff, AL_DISTORTION_MIN_LOWPASS_CUTOFF, AL_DISTORTION_MAX_LOWPASS_CUTOFF); - - al_effect_props_.Distortion.LowpassCutoff = lowpass_cutoff; } -void EaxDistortionEffect::set_efx_eq_center() +void EaxDistortionEffect::set_efx_eq_center() noexcept { - const auto eq_center = clamp( - eax_.flEQCenter, + al_effect_props_.Distortion.EQCenter = clamp( + props_.flEQCenter, AL_DISTORTION_MIN_EQCENTER, AL_DISTORTION_MAX_EQCENTER); - - al_effect_props_.Distortion.EQCenter = eq_center; } -void EaxDistortionEffect::set_efx_eq_bandwidth() +void EaxDistortionEffect::set_efx_eq_bandwidth() noexcept { - const auto eq_bandwidth = clamp( - eax_.flEdge, + al_effect_props_.Distortion.EQBandwidth = clamp( + props_.flEdge, AL_DISTORTION_MIN_EQBANDWIDTH, AL_DISTORTION_MAX_EQBANDWIDTH); - - al_effect_props_.Distortion.EQBandwidth = eq_bandwidth; } void EaxDistortionEffect::set_efx_defaults() @@ -284,288 +278,78 @@ void EaxDistortionEffect::set_efx_defaults() set_efx_eq_bandwidth(); } -void EaxDistortionEffect::get(const EaxEaxCall& eax_call) +void EaxDistortionEffect::get(const EaxCall& call, const Props& props) { - switch(eax_call.get_property_id()) + switch(call.get_property_id()) { - case EAXDISTORTION_NONE: - break; - - case EAXDISTORTION_ALLPARAMETERS: - eax_call.set_value(eax_); - break; - - case EAXDISTORTION_EDGE: - eax_call.set_value(eax_.flEdge); - break; - - case EAXDISTORTION_GAIN: - eax_call.set_value(eax_.lGain); - break; - - case EAXDISTORTION_LOWPASSCUTOFF: - eax_call.set_value(eax_.flLowPassCutOff); - break; - - case EAXDISTORTION_EQCENTER: - eax_call.set_value(eax_.flEQCenter); - break; - - case EAXDISTORTION_EQBANDWIDTH: - eax_call.set_value(eax_.flEQBandwidth); - break; - - default: - throw EaxDistortionEffectException{"Unsupported property id."}; + case EAXDISTORTION_NONE: break; + case EAXDISTORTION_ALLPARAMETERS: call.set_value(props); break; + case EAXDISTORTION_EDGE: call.set_value(props.flEdge); break; + case EAXDISTORTION_GAIN: call.set_value(props.lGain); break; + case EAXDISTORTION_LOWPASSCUTOFF: call.set_value(props.flLowPassCutOff); break; + case EAXDISTORTION_EQCENTER: call.set_value(props.flEQCenter); break; + case EAXDISTORTION_EQBANDWIDTH: call.set_value(props.flEQBandwidth); break; + default: fail_unknown_property_id(); } } -void EaxDistortionEffect::validate_edge( - float flEdge) -{ - eax_validate_range( - "Edge", - flEdge, - EAXDISTORTION_MINEDGE, - EAXDISTORTION_MAXEDGE); -} - -void EaxDistortionEffect::validate_gain( - long lGain) -{ - eax_validate_range( - "Gain", - lGain, - EAXDISTORTION_MINGAIN, - EAXDISTORTION_MAXGAIN); -} - -void EaxDistortionEffect::validate_lowpass_cutoff( - float flLowPassCutOff) -{ - eax_validate_range( - "Low-pass Cut-off", - flLowPassCutOff, - EAXDISTORTION_MINLOWPASSCUTOFF, - EAXDISTORTION_MAXLOWPASSCUTOFF); -} - -void EaxDistortionEffect::validate_eq_center( - float flEQCenter) -{ - eax_validate_range( - "EQ Center", - flEQCenter, - EAXDISTORTION_MINEQCENTER, - EAXDISTORTION_MAXEQCENTER); -} - -void EaxDistortionEffect::validate_eq_bandwidth( - float flEQBandwidth) -{ - eax_validate_range( - "EQ Bandwidth", - flEQBandwidth, - EAXDISTORTION_MINEQBANDWIDTH, - EAXDISTORTION_MAXEQBANDWIDTH); -} - -void EaxDistortionEffect::validate_all( - const EAXDISTORTIONPROPERTIES& eax_all) -{ - validate_edge(eax_all.flEdge); - validate_gain(eax_all.lGain); - validate_lowpass_cutoff(eax_all.flLowPassCutOff); - validate_eq_center(eax_all.flEQCenter); - validate_eq_bandwidth(eax_all.flEQBandwidth); -} - -void EaxDistortionEffect::defer_edge( - float flEdge) -{ - eax_d_.flEdge = flEdge; - eax_dirty_flags_.flEdge = (eax_.flEdge != eax_d_.flEdge); -} - -void EaxDistortionEffect::defer_gain( - long lGain) +void EaxDistortionEffect::set(const EaxCall& call, Props& props) { - eax_d_.lGain = lGain; - eax_dirty_flags_.lGain = (eax_.lGain != eax_d_.lGain); -} - -void EaxDistortionEffect::defer_low_pass_cutoff( - float flLowPassCutOff) -{ - eax_d_.flLowPassCutOff = flLowPassCutOff; - eax_dirty_flags_.flLowPassCutOff = (eax_.flLowPassCutOff != eax_d_.flLowPassCutOff); -} - -void EaxDistortionEffect::defer_eq_center( - float flEQCenter) -{ - eax_d_.flEQCenter = flEQCenter; - eax_dirty_flags_.flEQCenter = (eax_.flEQCenter != eax_d_.flEQCenter); -} - -void EaxDistortionEffect::defer_eq_bandwidth( - float flEQBandwidth) -{ - eax_d_.flEQBandwidth = flEQBandwidth; - eax_dirty_flags_.flEQBandwidth = (eax_.flEQBandwidth != eax_d_.flEQBandwidth); -} - -void EaxDistortionEffect::defer_all( - const EAXDISTORTIONPROPERTIES& eax_all) -{ - defer_edge(eax_all.flEdge); - defer_gain(eax_all.lGain); - defer_low_pass_cutoff(eax_all.flLowPassCutOff); - defer_eq_center(eax_all.flEQCenter); - defer_eq_bandwidth(eax_all.flEQBandwidth); -} - -void EaxDistortionEffect::defer_edge( - const EaxEaxCall& eax_call) -{ - const auto& edge = - eax_call.get_value(); - - validate_edge(edge); - defer_edge(edge); -} - -void EaxDistortionEffect::defer_gain( - const EaxEaxCall& eax_call) -{ - const auto& gain = - eax_call.get_value(); - - validate_gain(gain); - defer_gain(gain); -} - -void EaxDistortionEffect::defer_low_pass_cutoff( - const EaxEaxCall& eax_call) -{ - const auto& lowpass_cutoff = - eax_call.get_value(); - - validate_lowpass_cutoff(lowpass_cutoff); - defer_low_pass_cutoff(lowpass_cutoff); -} - -void EaxDistortionEffect::defer_eq_center( - const EaxEaxCall& eax_call) -{ - const auto& eq_center = - eax_call.get_value(); - - validate_eq_center(eq_center); - defer_eq_center(eq_center); -} - -void EaxDistortionEffect::defer_eq_bandwidth( - const EaxEaxCall& eax_call) -{ - const auto& eq_bandwidth = - eax_call.get_value(); - - validate_eq_bandwidth(eq_bandwidth); - defer_eq_bandwidth(eq_bandwidth); -} - -void EaxDistortionEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto& all = - eax_call.get_value(); - - validate_all(all); - defer_all(all); -} - -// [[nodiscard]] -bool EaxDistortionEffect::apply_deferred() -{ - if (eax_dirty_flags_ == EaxDistortionEffectDirtyFlags{}) + switch(call.get_property_id()) { - return false; + case EAXDISTORTION_NONE: break; + case EAXDISTORTION_ALLPARAMETERS: defer(call, props); break; + case EAXDISTORTION_EDGE: defer(call, props.flEdge); break; + case EAXDISTORTION_GAIN: defer(call, props.lGain); break; + case EAXDISTORTION_LOWPASSCUTOFF: defer(call, props.flLowPassCutOff); break; + case EAXDISTORTION_EQCENTER: defer(call, props.flEQCenter); break; + case EAXDISTORTION_EQBANDWIDTH: defer(call, props.flEQBandwidth); break; + default: fail_unknown_property_id(); } +} - eax_ = eax_d_; +bool EaxDistortionEffect::commit_props(const Props& props) +{ + auto is_dirty = false; - if (eax_dirty_flags_.flEdge) + if (props_.flEdge != props.flEdge) { + is_dirty = true; set_efx_edge(); } - if (eax_dirty_flags_.lGain) + if (props_.lGain != props.lGain) { + is_dirty = true; set_efx_gain(); } - if (eax_dirty_flags_.flLowPassCutOff) + if (props_.flLowPassCutOff != props.flLowPassCutOff) { + is_dirty = true; set_efx_lowpass_cutoff(); } - if (eax_dirty_flags_.flEQCenter) + if (props_.flEQCenter != props.flEQCenter) { + is_dirty = true; set_efx_eq_center(); } - if (eax_dirty_flags_.flEQBandwidth) + if (props_.flEQBandwidth != props.flEQBandwidth) { + is_dirty = true; set_efx_eq_bandwidth(); } - eax_dirty_flags_ = EaxDistortionEffectDirtyFlags{}; - - return true; -} - -void EaxDistortionEffect::set(const EaxEaxCall& eax_call) -{ - switch(eax_call.get_property_id()) - { - case EAXDISTORTION_NONE: - break; - - case EAXDISTORTION_ALLPARAMETERS: - defer_all(eax_call); - break; - - case EAXDISTORTION_EDGE: - defer_edge(eax_call); - break; - - case EAXDISTORTION_GAIN: - defer_gain(eax_call); - break; - - case EAXDISTORTION_LOWPASSCUTOFF: - defer_low_pass_cutoff(eax_call); - break; - - case EAXDISTORTION_EQCENTER: - defer_eq_center(eax_call); - break; - - case EAXDISTORTION_EQBANDWIDTH: - defer_eq_bandwidth(eax_call); - break; - - default: - throw EaxDistortionEffectException{"Unsupported property id."}; - } + return is_dirty; } } // namespace -EaxEffectUPtr eax_create_eax_distortion_effect() +EaxEffectUPtr eax_create_eax_distortion_effect(const EaxCall& call) { - return std::make_unique(); + return eax_create_eax4_effect(call); } #endif // ALSOFT_EAX diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index 56849b9d..f25c94bf 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -9,7 +9,6 @@ #ifdef ALSOFT_EAX #include "alnumeric.h" - #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -120,157 +119,151 @@ const EffectProps EchoEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -using EaxEchoEffectDirtyFlagsValue = std::uint_least8_t; - -struct EaxEchoEffectDirtyFlags +class EaxEchoEffectException : public EaxException { - using EaxIsBitFieldStruct = bool; - - EaxEchoEffectDirtyFlagsValue flDelay : 1; - EaxEchoEffectDirtyFlagsValue flLRDelay : 1; - EaxEchoEffectDirtyFlagsValue flDamping : 1; - EaxEchoEffectDirtyFlagsValue flFeedback : 1; - EaxEchoEffectDirtyFlagsValue flSpread : 1; -}; // EaxEchoEffectDirtyFlags - +public: + explicit EaxEchoEffectException(const char* message) + : EaxException{"EAX_ECHO_EFFECT", message} + {} +}; // EaxEchoEffectException -class EaxEchoEffect final : - public EaxEffect +class EaxEchoEffect final : public EaxEffect4 { public: - EaxEchoEffect(); - - void dispatch(const EaxEaxCall& eax_call) override; - - // [[nodiscard]] - bool apply_deferred() override; + EaxEchoEffect(const EaxCall& call); private: - EAXECHOPROPERTIES eax_{}; - EAXECHOPROPERTIES eax_d_{}; - EaxEchoEffectDirtyFlags eax_dirty_flags_{}; - - void set_eax_defaults(); - - void set_efx_delay(); - void set_efx_lr_delay(); - void set_efx_damping(); - void set_efx_feedback(); - void set_efx_spread(); - void set_efx_defaults(); - - void get(const EaxEaxCall& eax_call); - - void validate_delay(float flDelay); - void validate_lr_delay(float flLRDelay); - void validate_damping(float flDamping); - void validate_feedback(float flFeedback); - void validate_spread(float flSpread); - void validate_all(const EAXECHOPROPERTIES& all); - - void defer_delay(float flDelay); - void defer_lr_delay(float flLRDelay); - void defer_damping(float flDamping); - void defer_feedback(float flFeedback); - void defer_spread(float flSpread); - void defer_all(const EAXECHOPROPERTIES& all); - - void defer_delay(const EaxEaxCall& eax_call); - void defer_lr_delay(const EaxEaxCall& eax_call); - void defer_damping(const EaxEaxCall& eax_call); - void defer_feedback(const EaxEaxCall& eax_call); - void defer_spread(const EaxEaxCall& eax_call); - void defer_all(const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); + struct DelayValidator { + void operator()(float flDelay) const + { + eax_validate_range( + "Delay", + flDelay, + EAXECHO_MINDELAY, + EAXECHO_MAXDELAY); + } + }; // DelayValidator + + struct LrDelayValidator { + void operator()(float flLRDelay) const + { + eax_validate_range( + "LR Delay", + flLRDelay, + EAXECHO_MINLRDELAY, + EAXECHO_MAXLRDELAY); + } + }; // LrDelayValidator + + struct DampingValidator { + void operator()(float flDamping) const + { + eax_validate_range( + "Damping", + flDamping, + EAXECHO_MINDAMPING, + EAXECHO_MAXDAMPING); + } + }; // DampingValidator + + struct FeedbackValidator { + void operator()(float flFeedback) const + { + eax_validate_range( + "Feedback", + flFeedback, + EAXECHO_MINFEEDBACK, + EAXECHO_MAXFEEDBACK); + } + }; // FeedbackValidator + + struct SpreadValidator { + void operator()(float flSpread) const + { + eax_validate_range( + "Spread", + flSpread, + EAXECHO_MINSPREAD, + EAXECHO_MAXSPREAD); + } + }; // SpreadValidator + + struct AllValidator { + void operator()(const Props& all) const + { + DelayValidator{}(all.flDelay); + LrDelayValidator{}(all.flLRDelay); + DampingValidator{}(all.flDamping); + FeedbackValidator{}(all.flFeedback); + SpreadValidator{}(all.flSpread); + } + }; // AllValidator + + void set_defaults(Props& props) override; + + void set_efx_delay() noexcept; + void set_efx_lr_delay() noexcept; + void set_efx_damping() noexcept; + void set_efx_feedback() noexcept; + void set_efx_spread() noexcept; + void set_efx_defaults() override; + + void get(const EaxCall& call, const Props& props) override; + void set(const EaxCall& call, Props& props) override; + bool commit_props(const Props& props) override; }; // EaxEchoEffect +EaxEchoEffect::EaxEchoEffect(const EaxCall& call) + : EaxEffect4{AL_EFFECT_ECHO, call} +{} -class EaxEchoEffectException : - public EaxException -{ -public: - explicit EaxEchoEffectException( - const char* message) - : - EaxException{"EAX_ECHO_EFFECT", message} - { - } -}; // EaxEchoEffectException - - -EaxEchoEffect::EaxEchoEffect() - : EaxEffect{AL_EFFECT_ECHO} -{ - set_eax_defaults(); - set_efx_defaults(); -} - -void EaxEchoEffect::dispatch( - const EaxEaxCall& eax_call) -{ - eax_call.is_get() ? get(eax_call) : set(eax_call); -} - -void EaxEchoEffect::set_eax_defaults() +void EaxEchoEffect::set_defaults(Props& props) { - eax_.flDelay = EAXECHO_DEFAULTDELAY; - eax_.flLRDelay = EAXECHO_DEFAULTLRDELAY; - eax_.flDamping = EAXECHO_DEFAULTDAMPING; - eax_.flFeedback = EAXECHO_DEFAULTFEEDBACK; - eax_.flSpread = EAXECHO_DEFAULTSPREAD; - - eax_d_ = eax_; + props.flDelay = EAXECHO_DEFAULTDELAY; + props.flLRDelay = EAXECHO_DEFAULTLRDELAY; + props.flDamping = EAXECHO_DEFAULTDAMPING; + props.flFeedback = EAXECHO_DEFAULTFEEDBACK; + props.flSpread = EAXECHO_DEFAULTSPREAD; } -void EaxEchoEffect::set_efx_delay() +void EaxEchoEffect::set_efx_delay() noexcept { - const auto delay = clamp( - eax_.flDelay, + al_effect_props_.Echo.Delay = clamp( + props_.flDelay, AL_ECHO_MIN_DELAY, AL_ECHO_MAX_DELAY); - - al_effect_props_.Echo.Delay = delay; } -void EaxEchoEffect::set_efx_lr_delay() +void EaxEchoEffect::set_efx_lr_delay() noexcept { - const auto lr_delay = clamp( - eax_.flLRDelay, + al_effect_props_.Echo.LRDelay = clamp( + props_.flLRDelay, AL_ECHO_MIN_LRDELAY, AL_ECHO_MAX_LRDELAY); - - al_effect_props_.Echo.LRDelay = lr_delay; } -void EaxEchoEffect::set_efx_damping() +void EaxEchoEffect::set_efx_damping() noexcept { - const auto damping = clamp( - eax_.flDamping, + al_effect_props_.Echo.Damping = clamp( + props_.flDamping, AL_ECHO_MIN_DAMPING, AL_ECHO_MAX_DAMPING); - - al_effect_props_.Echo.Damping = damping; } -void EaxEchoEffect::set_efx_feedback() +void EaxEchoEffect::set_efx_feedback() noexcept { - const auto feedback = clamp( - eax_.flFeedback, + al_effect_props_.Echo.Feedback = clamp( + props_.flFeedback, AL_ECHO_MIN_FEEDBACK, AL_ECHO_MAX_FEEDBACK); - - al_effect_props_.Echo.Feedback = feedback; } -void EaxEchoEffect::set_efx_spread() +void EaxEchoEffect::set_efx_spread() noexcept { - const auto spread = clamp( - eax_.flSpread, + al_effect_props_.Echo.Spread = clamp( + props_.flSpread, AL_ECHO_MIN_SPREAD, AL_ECHO_MAX_SPREAD); - - al_effect_props_.Echo.Spread = spread; } void EaxEchoEffect::set_efx_defaults() @@ -282,288 +275,78 @@ void EaxEchoEffect::set_efx_defaults() set_efx_spread(); } -void EaxEchoEffect::get(const EaxEaxCall& eax_call) +void EaxEchoEffect::get(const EaxCall& call, const Props& props) { - switch(eax_call.get_property_id()) + switch(call.get_property_id()) { - case EAXECHO_NONE: - break; - - case EAXECHO_ALLPARAMETERS: - eax_call.set_value(eax_); - break; - - case EAXECHO_DELAY: - eax_call.set_value(eax_.flDelay); - break; - - case EAXECHO_LRDELAY: - eax_call.set_value(eax_.flLRDelay); - break; - - case EAXECHO_DAMPING: - eax_call.set_value(eax_.flDamping); - break; - - case EAXECHO_FEEDBACK: - eax_call.set_value(eax_.flFeedback); - break; - - case EAXECHO_SPREAD: - eax_call.set_value(eax_.flSpread); - break; - - default: - throw EaxEchoEffectException{"Unsupported property id."}; + case EAXECHO_NONE: break; + case EAXECHO_ALLPARAMETERS: call.set_value(props); break; + case EAXECHO_DELAY: call.set_value(props.flDelay); break; + case EAXECHO_LRDELAY: call.set_value(props.flLRDelay); break; + case EAXECHO_DAMPING: call.set_value(props.flDamping); break; + case EAXECHO_FEEDBACK: call.set_value(props.flFeedback); break; + case EAXECHO_SPREAD: call.set_value(props.flSpread); break; + default: fail_unknown_property_id(); } } -void EaxEchoEffect::validate_delay( - float flDelay) -{ - eax_validate_range( - "Delay", - flDelay, - EAXECHO_MINDELAY, - EAXECHO_MAXDELAY); -} - -void EaxEchoEffect::validate_lr_delay( - float flLRDelay) -{ - eax_validate_range( - "LR Delay", - flLRDelay, - EAXECHO_MINLRDELAY, - EAXECHO_MAXLRDELAY); -} - -void EaxEchoEffect::validate_damping( - float flDamping) -{ - eax_validate_range( - "Damping", - flDamping, - EAXECHO_MINDAMPING, - EAXECHO_MAXDAMPING); -} - -void EaxEchoEffect::validate_feedback( - float flFeedback) -{ - eax_validate_range( - "Feedback", - flFeedback, - EAXECHO_MINFEEDBACK, - EAXECHO_MAXFEEDBACK); -} - -void EaxEchoEffect::validate_spread( - float flSpread) -{ - eax_validate_range( - "Spread", - flSpread, - EAXECHO_MINSPREAD, - EAXECHO_MAXSPREAD); -} - -void EaxEchoEffect::validate_all( - const EAXECHOPROPERTIES& all) -{ - validate_delay(all.flDelay); - validate_lr_delay(all.flLRDelay); - validate_damping(all.flDamping); - validate_feedback(all.flFeedback); - validate_spread(all.flSpread); -} - -void EaxEchoEffect::defer_delay( - float flDelay) -{ - eax_d_.flDelay = flDelay; - eax_dirty_flags_.flDelay = (eax_.flDelay != eax_d_.flDelay); -} - -void EaxEchoEffect::defer_lr_delay( - float flLRDelay) +void EaxEchoEffect::set(const EaxCall& call, Props& props) { - eax_d_.flLRDelay = flLRDelay; - eax_dirty_flags_.flLRDelay = (eax_.flLRDelay != eax_d_.flLRDelay); -} - -void EaxEchoEffect::defer_damping( - float flDamping) -{ - eax_d_.flDamping = flDamping; - eax_dirty_flags_.flDamping = (eax_.flDamping != eax_d_.flDamping); -} - -void EaxEchoEffect::defer_feedback( - float flFeedback) -{ - eax_d_.flFeedback = flFeedback; - eax_dirty_flags_.flFeedback = (eax_.flFeedback != eax_d_.flFeedback); -} - -void EaxEchoEffect::defer_spread( - float flSpread) -{ - eax_d_.flSpread = flSpread; - eax_dirty_flags_.flSpread = (eax_.flSpread != eax_d_.flSpread); -} - -void EaxEchoEffect::defer_all( - const EAXECHOPROPERTIES& all) -{ - defer_delay(all.flDelay); - defer_lr_delay(all.flLRDelay); - defer_damping(all.flDamping); - defer_feedback(all.flFeedback); - defer_spread(all.flSpread); -} - -void EaxEchoEffect::defer_delay( - const EaxEaxCall& eax_call) -{ - const auto& delay = - eax_call.get_value(); - - validate_delay(delay); - defer_delay(delay); -} - -void EaxEchoEffect::defer_lr_delay( - const EaxEaxCall& eax_call) -{ - const auto& lr_delay = - eax_call.get_value(); - - validate_lr_delay(lr_delay); - defer_lr_delay(lr_delay); -} - -void EaxEchoEffect::defer_damping( - const EaxEaxCall& eax_call) -{ - const auto& damping = - eax_call.get_value(); - - validate_damping(damping); - defer_damping(damping); -} - -void EaxEchoEffect::defer_feedback( - const EaxEaxCall& eax_call) -{ - const auto& feedback = - eax_call.get_value(); - - validate_feedback(feedback); - defer_feedback(feedback); -} - -void EaxEchoEffect::defer_spread( - const EaxEaxCall& eax_call) -{ - const auto& spread = - eax_call.get_value(); - - validate_spread(spread); - defer_spread(spread); -} - -void EaxEchoEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto& all = - eax_call.get_value(); - - validate_all(all); - defer_all(all); -} - -// [[nodiscard]] -bool EaxEchoEffect::apply_deferred() -{ - if (eax_dirty_flags_ == EaxEchoEffectDirtyFlags{}) + switch(call.get_property_id()) { - return false; + case EAXECHO_NONE: break; + case EAXECHO_ALLPARAMETERS: defer(call, props); break; + case EAXECHO_DELAY: defer(call, props.flDelay); break; + case EAXECHO_LRDELAY: defer(call, props.flLRDelay); break; + case EAXECHO_DAMPING: defer(call, props.flDamping); break; + case EAXECHO_FEEDBACK: defer(call, props.flFeedback); break; + case EAXECHO_SPREAD: defer(call, props.flSpread); break; + default: fail_unknown_property_id(); } +} - eax_ = eax_d_; +bool EaxEchoEffect::commit_props(const Props& props) +{ + auto is_dirty = false; - if (eax_dirty_flags_.flDelay) + if (props_.flDelay != props.flDelay) { + is_dirty = true; set_efx_delay(); } - if (eax_dirty_flags_.flLRDelay) + if (props_.flLRDelay != props.flLRDelay) { + is_dirty = true; set_efx_lr_delay(); } - if (eax_dirty_flags_.flDamping) + if (props_.flDamping != props.flDamping) { + is_dirty = true; set_efx_damping(); } - if (eax_dirty_flags_.flFeedback) + if (props_.flFeedback != props.flFeedback) { + is_dirty = true; set_efx_feedback(); } - if (eax_dirty_flags_.flSpread) + if (props_.flSpread != props.flSpread) { + is_dirty = true; set_efx_spread(); } - eax_dirty_flags_ = EaxEchoEffectDirtyFlags{}; - - return true; -} - -void EaxEchoEffect::set(const EaxEaxCall& eax_call) -{ - switch(eax_call.get_property_id()) - { - case EAXECHO_NONE: - break; - - case EAXECHO_ALLPARAMETERS: - defer_all(eax_call); - break; - - case EAXECHO_DELAY: - defer_delay(eax_call); - break; - - case EAXECHO_LRDELAY: - defer_lr_delay(eax_call); - break; - - case EAXECHO_DAMPING: - defer_damping(eax_call); - break; - - case EAXECHO_FEEDBACK: - defer_feedback(eax_call); - break; - - case EAXECHO_SPREAD: - defer_spread(eax_call); - break; - - default: - throw EaxEchoEffectException{"Unsupported property id."}; - } + return is_dirty; } } // namespace -EaxEffectUPtr eax_create_eax_echo_effect() +EaxEffectUPtr eax_create_eax_echo_effect(const EaxCall& call) { - return std::make_unique(); + return eax_create_eax4_effect(call); } #endif // ALSOFT_EAX diff --git a/al/effects/effects.cpp b/al/effects/effects.cpp index faf322d2..e4e61231 100644 --- a/al/effects/effects.cpp +++ b/al/effects/effects.cpp @@ -10,7 +10,7 @@ #include "AL/efx.h" -EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type) +EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, const EaxCall& call) { #define EAX_PREFIX "[EAX_MAKE_EAX_EFFECT] " @@ -20,40 +20,40 @@ EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type) return eax_create_eax_null_effect(); case AL_EFFECT_CHORUS: - return eax_create_eax_chorus_effect(); + return eax_create_eax_chorus_effect(call); case AL_EFFECT_DISTORTION: - return eax_create_eax_distortion_effect(); + return eax_create_eax_distortion_effect(call); case AL_EFFECT_ECHO: - return eax_create_eax_echo_effect(); + return eax_create_eax_echo_effect(call); case AL_EFFECT_FLANGER: - return eax_create_eax_flanger_effect(); + return eax_create_eax_flanger_effect(call); case AL_EFFECT_FREQUENCY_SHIFTER: - return eax_create_eax_frequency_shifter_effect(); + return eax_create_eax_frequency_shifter_effect(call); case AL_EFFECT_VOCAL_MORPHER: - return eax_create_eax_vocal_morpher_effect(); + return eax_create_eax_vocal_morpher_effect(call); case AL_EFFECT_PITCH_SHIFTER: - return eax_create_eax_pitch_shifter_effect(); + return eax_create_eax_pitch_shifter_effect(call); case AL_EFFECT_RING_MODULATOR: - return eax_create_eax_ring_modulator_effect(); + return eax_create_eax_ring_modulator_effect(call); case AL_EFFECT_AUTOWAH: - return eax_create_eax_auto_wah_effect(); + return eax_create_eax_auto_wah_effect(call); case AL_EFFECT_COMPRESSOR: - return eax_create_eax_compressor_effect(); + return eax_create_eax_compressor_effect(call); case AL_EFFECT_EQUALIZER: - return eax_create_eax_equalizer_effect(); + return eax_create_eax_equalizer_effect(call); case AL_EFFECT_EAXREVERB: - return eax_create_eax_reverb_effect(); + return eax_create_eax_reverb_effect(call); default: assert(false && "Unsupported AL effect type."); diff --git a/al/effects/effects.h b/al/effects/effects.h index f8b97eeb..164c0d19 100644 --- a/al/effects/effects.h +++ b/al/effects/effects.h @@ -6,6 +6,7 @@ #include "core/except.h" #ifdef ALSOFT_EAX +#include "al/eax/call.h" #include "al/eax/effect.h" #endif // ALSOFT_EAX @@ -86,7 +87,7 @@ extern const EffectVtable ConvolutionEffectVtable; #ifdef ALSOFT_EAX -EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type); +EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, const EaxCall& call); #endif // ALSOFT_EAX #endif /* AL_EFFECTS_EFFECTS_H */ diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index ccc00f67..80dd1c4b 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -9,7 +9,6 @@ #ifdef ALSOFT_EAX #include "alnumeric.h" - #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -178,236 +177,261 @@ const EffectProps EqualizerEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -using EaxEqualizerEffectDirtyFlagsValue = std::uint_least16_t; - -struct EaxEqualizerEffectDirtyFlags -{ - using EaxIsBitFieldStruct = bool; - - EaxEqualizerEffectDirtyFlagsValue lLowGain : 1; - EaxEqualizerEffectDirtyFlagsValue flLowCutOff : 1; - EaxEqualizerEffectDirtyFlagsValue lMid1Gain : 1; - EaxEqualizerEffectDirtyFlagsValue flMid1Center : 1; - EaxEqualizerEffectDirtyFlagsValue flMid1Width : 1; - EaxEqualizerEffectDirtyFlagsValue lMid2Gain : 1; - EaxEqualizerEffectDirtyFlagsValue flMid2Center : 1; - EaxEqualizerEffectDirtyFlagsValue flMid2Width : 1; - EaxEqualizerEffectDirtyFlagsValue lHighGain : 1; - EaxEqualizerEffectDirtyFlagsValue flHighCutOff : 1; -}; // EaxEqualizerEffectDirtyFlags - - -class EaxEqualizerEffect final : - public EaxEffect +class EaxEqualizerEffectException : public EaxException { public: - EaxEqualizerEffect(); - - void dispatch(const EaxEaxCall& eax_call) override; - - // [[nodiscard]] - bool apply_deferred() override; - -private: - EAXEQUALIZERPROPERTIES eax_{}; - EAXEQUALIZERPROPERTIES eax_d_{}; - EaxEqualizerEffectDirtyFlags eax_dirty_flags_{}; - - void set_eax_defaults(); - - void set_efx_low_gain(); - void set_efx_low_cutoff(); - void set_efx_mid1_gain(); - void set_efx_mid1_center(); - void set_efx_mid1_width(); - void set_efx_mid2_gain(); - void set_efx_mid2_center(); - void set_efx_mid2_width(); - void set_efx_high_gain(); - void set_efx_high_cutoff(); - void set_efx_defaults(); - - void get(const EaxEaxCall& eax_call); - - void validate_low_gain(long lLowGain); - void validate_low_cutoff(float flLowCutOff); - void validate_mid1_gain(long lMid1Gain); - void validate_mid1_center(float flMid1Center); - void validate_mid1_width(float flMid1Width); - void validate_mid2_gain(long lMid2Gain); - void validate_mid2_center(float flMid2Center); - void validate_mid2_width(float flMid2Width); - void validate_high_gain(long lHighGain); - void validate_high_cutoff(float flHighCutOff); - void validate_all(const EAXEQUALIZERPROPERTIES& all); - - void defer_low_gain(long lLowGain); - void defer_low_cutoff(float flLowCutOff); - void defer_mid1_gain(long lMid1Gain); - void defer_mid1_center(float flMid1Center); - void defer_mid1_width(float flMid1Width); - void defer_mid2_gain(long lMid2Gain); - void defer_mid2_center(float flMid2Center); - void defer_mid2_width(float flMid2Width); - void defer_high_gain(long lHighGain); - void defer_high_cutoff(float flHighCutOff); - void defer_all(const EAXEQUALIZERPROPERTIES& all); - - void defer_low_gain(const EaxEaxCall& eax_call); - void defer_low_cutoff(const EaxEaxCall& eax_call); - void defer_mid1_gain(const EaxEaxCall& eax_call); - void defer_mid1_center(const EaxEaxCall& eax_call); - void defer_mid1_width(const EaxEaxCall& eax_call); - void defer_mid2_gain(const EaxEaxCall& eax_call); - void defer_mid2_center(const EaxEaxCall& eax_call); - void defer_mid2_width(const EaxEaxCall& eax_call); - void defer_high_gain(const EaxEaxCall& eax_call); - void defer_high_cutoff(const EaxEaxCall& eax_call); - void defer_all(const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); -}; // EaxEqualizerEffect - + explicit EaxEqualizerEffectException(const char* message) + : EaxException{"EAX_EQUALIZER_EFFECT", message} + {} +}; // EaxEqualizerEffectException -class EaxEqualizerEffectException : - public EaxException +class EaxEqualizerEffect final : public EaxEffect4 { public: - explicit EaxEqualizerEffectException( - const char* message) - : - EaxException{"EAX_EQUALIZER_EFFECT", message} - { - } -}; // EaxEqualizerEffectException - + EaxEqualizerEffect(const EaxCall& call); -EaxEqualizerEffect::EaxEqualizerEffect() - : EaxEffect{AL_EFFECT_EQUALIZER} -{ - set_eax_defaults(); - set_efx_defaults(); -} +private: + struct LowGainValidator { + void operator()(long lLowGain) const + { + eax_validate_range( + "Low Gain", + lLowGain, + EAXEQUALIZER_MINLOWGAIN, + EAXEQUALIZER_MAXLOWGAIN); + } + }; // LowGainValidator + + struct LowCutOffValidator { + void operator()(float flLowCutOff) const + { + eax_validate_range( + "Low Cutoff", + flLowCutOff, + EAXEQUALIZER_MINLOWCUTOFF, + EAXEQUALIZER_MAXLOWCUTOFF); + } + }; // LowCutOffValidator + + struct Mid1GainValidator { + void operator()(long lMid1Gain) const + { + eax_validate_range( + "Mid1 Gain", + lMid1Gain, + EAXEQUALIZER_MINMID1GAIN, + EAXEQUALIZER_MAXMID1GAIN); + } + }; // Mid1GainValidator + + struct Mid1CenterValidator { + void operator()(float flMid1Center) const + { + eax_validate_range( + "Mid1 Center", + flMid1Center, + EAXEQUALIZER_MINMID1CENTER, + EAXEQUALIZER_MAXMID1CENTER); + } + }; // Mid1CenterValidator + + struct Mid1WidthValidator { + void operator()(float flMid1Width) const + { + eax_validate_range( + "Mid1 Width", + flMid1Width, + EAXEQUALIZER_MINMID1WIDTH, + EAXEQUALIZER_MAXMID1WIDTH); + } + }; // Mid1WidthValidator + + struct Mid2GainValidator { + void operator()(long lMid2Gain) const + { + eax_validate_range( + "Mid2 Gain", + lMid2Gain, + EAXEQUALIZER_MINMID2GAIN, + EAXEQUALIZER_MAXMID2GAIN); + } + }; // Mid2GainValidator + + struct Mid2CenterValidator { + void operator()(float flMid2Center) const + { + eax_validate_range( + "Mid2 Center", + flMid2Center, + EAXEQUALIZER_MINMID2CENTER, + EAXEQUALIZER_MAXMID2CENTER); + } + }; // Mid2CenterValidator + + struct Mid2WidthValidator { + void operator()(float flMid2Width) const + { + eax_validate_range( + "Mid2 Width", + flMid2Width, + EAXEQUALIZER_MINMID2WIDTH, + EAXEQUALIZER_MAXMID2WIDTH); + } + }; // Mid2WidthValidator + + struct HighGainValidator { + void operator()(long lHighGain) const + { + eax_validate_range( + "High Gain", + lHighGain, + EAXEQUALIZER_MINHIGHGAIN, + EAXEQUALIZER_MAXHIGHGAIN); + } + }; // HighGainValidator + + struct HighCutOffValidator { + void operator()(float flHighCutOff) const + { + eax_validate_range( + "High Cutoff", + flHighCutOff, + EAXEQUALIZER_MINHIGHCUTOFF, + EAXEQUALIZER_MAXHIGHCUTOFF); + } + }; // HighCutOffValidator + + struct AllValidator { + void operator()(const Props& all) const + { + LowGainValidator{}(all.lLowGain); + LowCutOffValidator{}(all.flLowCutOff); + Mid1GainValidator{}(all.lMid1Gain); + Mid1CenterValidator{}(all.flMid1Center); + Mid1WidthValidator{}(all.flMid1Width); + Mid2GainValidator{}(all.lMid2Gain); + Mid2CenterValidator{}(all.flMid2Center); + Mid2WidthValidator{}(all.flMid2Width); + HighGainValidator{}(all.lHighGain); + HighCutOffValidator{}(all.flHighCutOff); + } + }; // AllValidator + + void set_defaults(Props& props) override; + + void set_efx_low_gain() noexcept; + void set_efx_low_cutoff() noexcept; + void set_efx_mid1_gain() noexcept; + void set_efx_mid1_center() noexcept; + void set_efx_mid1_width() noexcept; + void set_efx_mid2_gain() noexcept; + void set_efx_mid2_center() noexcept; + void set_efx_mid2_width() noexcept; + void set_efx_high_gain() noexcept; + void set_efx_high_cutoff() noexcept; + void set_efx_defaults() override; + + void get(const EaxCall& call, const Props& props) override; + void set(const EaxCall& call, Props& props) override; + bool commit_props(const Props& props) override; +}; // EaxEqualizerEffect -void EaxEqualizerEffect::dispatch(const EaxEaxCall& eax_call) -{ - eax_call.is_get() ? get(eax_call) : set(eax_call); -} +EaxEqualizerEffect::EaxEqualizerEffect(const EaxCall& call) + : EaxEffect4{AL_EFFECT_EQUALIZER, call} +{} -void EaxEqualizerEffect::set_eax_defaults() +void EaxEqualizerEffect::set_defaults(Props& props) { - eax_.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN; - eax_.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF; - eax_.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN; - eax_.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER; - eax_.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH; - eax_.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN; - eax_.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER; - eax_.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH; - eax_.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN; - eax_.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF; - - eax_d_ = eax_; + props.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN; + props.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF; + props.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN; + props.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER; + props.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH; + props.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN; + props.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER; + props.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH; + props.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN; + props.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF; } -void EaxEqualizerEffect::set_efx_low_gain() +void EaxEqualizerEffect::set_efx_low_gain() noexcept { - const auto low_gain = clamp( - level_mb_to_gain(static_cast(eax_.lLowGain)), + al_effect_props_.Equalizer.LowGain = clamp( + level_mb_to_gain(static_cast(props_.lLowGain)), AL_EQUALIZER_MIN_LOW_GAIN, AL_EQUALIZER_MAX_LOW_GAIN); - - al_effect_props_.Equalizer.LowGain = low_gain; } -void EaxEqualizerEffect::set_efx_low_cutoff() +void EaxEqualizerEffect::set_efx_low_cutoff() noexcept { - const auto low_cutoff = clamp( - eax_.flLowCutOff, + al_effect_props_.Equalizer.LowCutoff = clamp( + props_.flLowCutOff, AL_EQUALIZER_MIN_LOW_CUTOFF, AL_EQUALIZER_MAX_LOW_CUTOFF); - - al_effect_props_.Equalizer.LowCutoff = low_cutoff; } -void EaxEqualizerEffect::set_efx_mid1_gain() +void EaxEqualizerEffect::set_efx_mid1_gain() noexcept { - const auto mid1_gain = clamp( - level_mb_to_gain(static_cast(eax_.lMid1Gain)), + al_effect_props_.Equalizer.Mid1Gain = clamp( + level_mb_to_gain(static_cast(props_.lMid1Gain)), AL_EQUALIZER_MIN_MID1_GAIN, AL_EQUALIZER_MAX_MID1_GAIN); - - al_effect_props_.Equalizer.Mid1Gain = mid1_gain; } -void EaxEqualizerEffect::set_efx_mid1_center() +void EaxEqualizerEffect::set_efx_mid1_center() noexcept { - const auto mid1_center = clamp( - eax_.flMid1Center, + al_effect_props_.Equalizer.Mid1Center = clamp( + props_.flMid1Center, AL_EQUALIZER_MIN_MID1_CENTER, AL_EQUALIZER_MAX_MID1_CENTER); - - al_effect_props_.Equalizer.Mid1Center = mid1_center; } -void EaxEqualizerEffect::set_efx_mid1_width() +void EaxEqualizerEffect::set_efx_mid1_width() noexcept { - const auto mid1_width = clamp( - eax_.flMid1Width, + al_effect_props_.Equalizer.Mid1Width = clamp( + props_.flMid1Width, AL_EQUALIZER_MIN_MID1_WIDTH, AL_EQUALIZER_MAX_MID1_WIDTH); - - al_effect_props_.Equalizer.Mid1Width = mid1_width; } -void EaxEqualizerEffect::set_efx_mid2_gain() +void EaxEqualizerEffect::set_efx_mid2_gain() noexcept { - const auto mid2_gain = clamp( - level_mb_to_gain(static_cast(eax_.lMid2Gain)), + al_effect_props_.Equalizer.Mid2Gain = clamp( + level_mb_to_gain(static_cast(props_.lMid2Gain)), AL_EQUALIZER_MIN_MID2_GAIN, AL_EQUALIZER_MAX_MID2_GAIN); - - al_effect_props_.Equalizer.Mid2Gain = mid2_gain; } -void EaxEqualizerEffect::set_efx_mid2_center() +void EaxEqualizerEffect::set_efx_mid2_center() noexcept { - const auto mid2_center = clamp( - eax_.flMid2Center, + al_effect_props_.Equalizer.Mid2Center = clamp( + props_.flMid2Center, AL_EQUALIZER_MIN_MID2_CENTER, AL_EQUALIZER_MAX_MID2_CENTER); - - al_effect_props_.Equalizer.Mid2Center = mid2_center; } -void EaxEqualizerEffect::set_efx_mid2_width() +void EaxEqualizerEffect::set_efx_mid2_width() noexcept { - const auto mid2_width = clamp( - eax_.flMid2Width, + al_effect_props_.Equalizer.Mid2Width = clamp( + props_.flMid2Width, AL_EQUALIZER_MIN_MID2_WIDTH, AL_EQUALIZER_MAX_MID2_WIDTH); - - al_effect_props_.Equalizer.Mid2Width = mid2_width; } -void EaxEqualizerEffect::set_efx_high_gain() +void EaxEqualizerEffect::set_efx_high_gain() noexcept { - const auto high_gain = clamp( - level_mb_to_gain(static_cast(eax_.lHighGain)), + al_effect_props_.Equalizer.HighGain = clamp( + level_mb_to_gain(static_cast(props_.lHighGain)), AL_EQUALIZER_MIN_HIGH_GAIN, AL_EQUALIZER_MAX_HIGH_GAIN); - - al_effect_props_.Equalizer.HighGain = high_gain; } -void EaxEqualizerEffect::set_efx_high_cutoff() +void EaxEqualizerEffect::set_efx_high_cutoff() noexcept { - const auto high_cutoff = clamp( - eax_.flHighCutOff, + al_effect_props_.Equalizer.HighCutoff = clamp( + props_.flHighCutOff, AL_EQUALIZER_MIN_HIGH_CUTOFF, AL_EQUALIZER_MAX_HIGH_CUTOFF); - - al_effect_props_.Equalizer.HighCutoff = high_cutoff; } void EaxEqualizerEffect::set_efx_defaults() @@ -424,498 +448,118 @@ void EaxEqualizerEffect::set_efx_defaults() set_efx_high_cutoff(); } -void EaxEqualizerEffect::get(const EaxEaxCall& eax_call) +void EaxEqualizerEffect::get(const EaxCall& call, const Props& props) { - switch(eax_call.get_property_id()) + switch(call.get_property_id()) { - case EAXEQUALIZER_NONE: - break; - - case EAXEQUALIZER_ALLPARAMETERS: - eax_call.set_value(eax_); - break; - - case EAXEQUALIZER_LOWGAIN: - eax_call.set_value(eax_.lLowGain); - break; - - case EAXEQUALIZER_LOWCUTOFF: - eax_call.set_value(eax_.flLowCutOff); - break; - - case EAXEQUALIZER_MID1GAIN: - eax_call.set_value(eax_.lMid1Gain); - break; - - case EAXEQUALIZER_MID1CENTER: - eax_call.set_value(eax_.flMid1Center); - break; - - case EAXEQUALIZER_MID1WIDTH: - eax_call.set_value(eax_.flMid1Width); - break; - - case EAXEQUALIZER_MID2GAIN: - eax_call.set_value(eax_.lMid2Gain); - break; - - case EAXEQUALIZER_MID2CENTER: - eax_call.set_value(eax_.flMid2Center); - break; - - case EAXEQUALIZER_MID2WIDTH: - eax_call.set_value(eax_.flMid2Width); - break; - - case EAXEQUALIZER_HIGHGAIN: - eax_call.set_value(eax_.lHighGain); - break; - - case EAXEQUALIZER_HIGHCUTOFF: - eax_call.set_value(eax_.flHighCutOff); - break; - - default: - throw EaxEqualizerEffectException{"Unsupported property id."}; + case EAXEQUALIZER_NONE: break; + case EAXEQUALIZER_ALLPARAMETERS: call.set_value(props); break; + case EAXEQUALIZER_LOWGAIN: call.set_value(props.lLowGain); break; + case EAXEQUALIZER_LOWCUTOFF: call.set_value(props.flLowCutOff); break; + case EAXEQUALIZER_MID1GAIN: call.set_value(props.lMid1Gain); break; + case EAXEQUALIZER_MID1CENTER: call.set_value(props.flMid1Center); break; + case EAXEQUALIZER_MID1WIDTH: call.set_value(props.flMid1Width); break; + case EAXEQUALIZER_MID2GAIN: call.set_value(props.lMid2Gain); break; + case EAXEQUALIZER_MID2CENTER: call.set_value(props.flMid2Center); break; + case EAXEQUALIZER_MID2WIDTH: call.set_value(props.flMid2Width); break; + case EAXEQUALIZER_HIGHGAIN: call.set_value(props.lHighGain); break; + case EAXEQUALIZER_HIGHCUTOFF: call.set_value(props.flHighCutOff); break; + default: fail_unknown_property_id(); } } -void EaxEqualizerEffect::validate_low_gain( - long lLowGain) -{ - eax_validate_range( - "Low Gain", - lLowGain, - EAXEQUALIZER_MINLOWGAIN, - EAXEQUALIZER_MAXLOWGAIN); -} - -void EaxEqualizerEffect::validate_low_cutoff( - float flLowCutOff) -{ - eax_validate_range( - "Low Cutoff", - flLowCutOff, - EAXEQUALIZER_MINLOWCUTOFF, - EAXEQUALIZER_MAXLOWCUTOFF); -} - -void EaxEqualizerEffect::validate_mid1_gain( - long lMid1Gain) -{ - eax_validate_range( - "Mid1 Gain", - lMid1Gain, - EAXEQUALIZER_MINMID1GAIN, - EAXEQUALIZER_MAXMID1GAIN); -} - -void EaxEqualizerEffect::validate_mid1_center( - float flMid1Center) -{ - eax_validate_range( - "Mid1 Center", - flMid1Center, - EAXEQUALIZER_MINMID1CENTER, - EAXEQUALIZER_MAXMID1CENTER); -} - -void EaxEqualizerEffect::validate_mid1_width( - float flMid1Width) -{ - eax_validate_range( - "Mid1 Width", - flMid1Width, - EAXEQUALIZER_MINMID1WIDTH, - EAXEQUALIZER_MAXMID1WIDTH); -} - -void EaxEqualizerEffect::validate_mid2_gain( - long lMid2Gain) -{ - eax_validate_range( - "Mid2 Gain", - lMid2Gain, - EAXEQUALIZER_MINMID2GAIN, - EAXEQUALIZER_MAXMID2GAIN); -} - -void EaxEqualizerEffect::validate_mid2_center( - float flMid2Center) -{ - eax_validate_range( - "Mid2 Center", - flMid2Center, - EAXEQUALIZER_MINMID2CENTER, - EAXEQUALIZER_MAXMID2CENTER); -} - -void EaxEqualizerEffect::validate_mid2_width( - float flMid2Width) -{ - eax_validate_range( - "Mid2 Width", - flMid2Width, - EAXEQUALIZER_MINMID2WIDTH, - EAXEQUALIZER_MAXMID2WIDTH); -} - -void EaxEqualizerEffect::validate_high_gain( - long lHighGain) -{ - eax_validate_range( - "High Gain", - lHighGain, - EAXEQUALIZER_MINHIGHGAIN, - EAXEQUALIZER_MAXHIGHGAIN); -} - -void EaxEqualizerEffect::validate_high_cutoff( - float flHighCutOff) -{ - eax_validate_range( - "High Cutoff", - flHighCutOff, - EAXEQUALIZER_MINHIGHCUTOFF, - EAXEQUALIZER_MAXHIGHCUTOFF); -} - -void EaxEqualizerEffect::validate_all( - const EAXEQUALIZERPROPERTIES& all) -{ - validate_low_gain(all.lLowGain); - validate_low_cutoff(all.flLowCutOff); - validate_mid1_gain(all.lMid1Gain); - validate_mid1_center(all.flMid1Center); - validate_mid1_width(all.flMid1Width); - validate_mid2_gain(all.lMid2Gain); - validate_mid2_center(all.flMid2Center); - validate_mid2_width(all.flMid2Width); - validate_high_gain(all.lHighGain); - validate_high_cutoff(all.flHighCutOff); -} - -void EaxEqualizerEffect::defer_low_gain( - long lLowGain) -{ - eax_d_.lLowGain = lLowGain; - eax_dirty_flags_.lLowGain = (eax_.lLowGain != eax_d_.lLowGain); -} - -void EaxEqualizerEffect::defer_low_cutoff( - float flLowCutOff) -{ - eax_d_.flLowCutOff = flLowCutOff; - eax_dirty_flags_.flLowCutOff = (eax_.flLowCutOff != eax_d_.flLowCutOff); -} - -void EaxEqualizerEffect::defer_mid1_gain( - long lMid1Gain) -{ - eax_d_.lMid1Gain = lMid1Gain; - eax_dirty_flags_.lMid1Gain = (eax_.lMid1Gain != eax_d_.lMid1Gain); -} - -void EaxEqualizerEffect::defer_mid1_center( - float flMid1Center) -{ - eax_d_.flMid1Center = flMid1Center; - eax_dirty_flags_.flMid1Center = (eax_.flMid1Center != eax_d_.flMid1Center); -} - -void EaxEqualizerEffect::defer_mid1_width( - float flMid1Width) -{ - eax_d_.flMid1Width = flMid1Width; - eax_dirty_flags_.flMid1Width = (eax_.flMid1Width != eax_d_.flMid1Width); -} - -void EaxEqualizerEffect::defer_mid2_gain( - long lMid2Gain) -{ - eax_d_.lMid2Gain = lMid2Gain; - eax_dirty_flags_.lMid2Gain = (eax_.lMid2Gain != eax_d_.lMid2Gain); -} - -void EaxEqualizerEffect::defer_mid2_center( - float flMid2Center) -{ - eax_d_.flMid2Center = flMid2Center; - eax_dirty_flags_.flMid2Center = (eax_.flMid2Center != eax_d_.flMid2Center); -} - -void EaxEqualizerEffect::defer_mid2_width( - float flMid2Width) -{ - eax_d_.flMid2Width = flMid2Width; - eax_dirty_flags_.flMid2Width = (eax_.flMid2Width != eax_d_.flMid2Width); -} - -void EaxEqualizerEffect::defer_high_gain( - long lHighGain) -{ - eax_d_.lHighGain = lHighGain; - eax_dirty_flags_.lHighGain = (eax_.lHighGain != eax_d_.lHighGain); -} - -void EaxEqualizerEffect::defer_high_cutoff( - float flHighCutOff) -{ - eax_d_.flHighCutOff = flHighCutOff; - eax_dirty_flags_.flHighCutOff = (eax_.flHighCutOff != eax_d_.flHighCutOff); -} - -void EaxEqualizerEffect::defer_all( - const EAXEQUALIZERPROPERTIES& all) -{ - defer_low_gain(all.lLowGain); - defer_low_cutoff(all.flLowCutOff); - defer_mid1_gain(all.lMid1Gain); - defer_mid1_center(all.flMid1Center); - defer_mid1_width(all.flMid1Width); - defer_mid2_gain(all.lMid2Gain); - defer_mid2_center(all.flMid2Center); - defer_mid2_width(all.flMid2Width); - defer_high_gain(all.lHighGain); - defer_high_cutoff(all.flHighCutOff); -} - -void EaxEqualizerEffect::defer_low_gain( - const EaxEaxCall& eax_call) -{ - const auto& low_gain = - eax_call.get_value(); - - validate_low_gain(low_gain); - defer_low_gain(low_gain); -} - -void EaxEqualizerEffect::defer_low_cutoff( - const EaxEaxCall& eax_call) -{ - const auto& low_cutoff = - eax_call.get_value(); - - validate_low_cutoff(low_cutoff); - defer_low_cutoff(low_cutoff); -} - -void EaxEqualizerEffect::defer_mid1_gain( - const EaxEaxCall& eax_call) -{ - const auto& mid1_gain = - eax_call.get_value(); - - validate_mid1_gain(mid1_gain); - defer_mid1_gain(mid1_gain); -} - -void EaxEqualizerEffect::defer_mid1_center( - const EaxEaxCall& eax_call) -{ - const auto& mid1_center = - eax_call.get_value(); - - validate_mid1_center(mid1_center); - defer_mid1_center(mid1_center); -} - -void EaxEqualizerEffect::defer_mid1_width( - const EaxEaxCall& eax_call) -{ - const auto& mid1_width = - eax_call.get_value(); - - validate_mid1_width(mid1_width); - defer_mid1_width(mid1_width); -} - -void EaxEqualizerEffect::defer_mid2_gain( - const EaxEaxCall& eax_call) -{ - const auto& mid2_gain = - eax_call.get_value(); - - validate_mid2_gain(mid2_gain); - defer_mid2_gain(mid2_gain); -} - -void EaxEqualizerEffect::defer_mid2_center( - const EaxEaxCall& eax_call) -{ - const auto& mid2_center = - eax_call.get_value(); - - validate_mid2_center(mid2_center); - defer_mid2_center(mid2_center); -} - -void EaxEqualizerEffect::defer_mid2_width( - const EaxEaxCall& eax_call) -{ - const auto& mid2_width = - eax_call.get_value(); - - validate_mid2_width(mid2_width); - defer_mid2_width(mid2_width); -} - -void EaxEqualizerEffect::defer_high_gain( - const EaxEaxCall& eax_call) +void EaxEqualizerEffect::set(const EaxCall& call, Props& props) { - const auto& high_gain = - eax_call.get_value(); - - validate_high_gain(high_gain); - defer_high_gain(high_gain); -} - -void EaxEqualizerEffect::defer_high_cutoff( - const EaxEaxCall& eax_call) -{ - const auto& high_cutoff = - eax_call.get_value(); - - validate_high_cutoff(high_cutoff); - defer_high_cutoff(high_cutoff); -} - -void EaxEqualizerEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto& all = - eax_call.get_value(); - - validate_all(all); - defer_all(all); -} - -// [[nodiscard]] -bool EaxEqualizerEffect::apply_deferred() -{ - if (eax_dirty_flags_ == EaxEqualizerEffectDirtyFlags{}) + switch(call.get_property_id()) { - return false; + case EAXEQUALIZER_NONE: break; + case EAXEQUALIZER_ALLPARAMETERS: defer(call, props); break; + case EAXEQUALIZER_LOWGAIN: defer(call, props.lLowGain); break; + case EAXEQUALIZER_LOWCUTOFF: defer(call, props.flLowCutOff); break; + case EAXEQUALIZER_MID1GAIN: defer(call, props.lMid1Gain); break; + case EAXEQUALIZER_MID1CENTER: defer(call, props.flMid1Center); break; + case EAXEQUALIZER_MID1WIDTH: defer(call, props.flMid1Width); break; + case EAXEQUALIZER_MID2GAIN: defer(call, props.lMid2Gain); break; + case EAXEQUALIZER_MID2CENTER: defer(call, props.flMid2Center); break; + case EAXEQUALIZER_MID2WIDTH: defer(call, props.flMid2Width); break; + case EAXEQUALIZER_HIGHGAIN: defer(call, props.lHighGain); break; + case EAXEQUALIZER_HIGHCUTOFF: defer(call, props.flHighCutOff); break; + default: fail_unknown_property_id(); } +} - eax_ = eax_d_; +bool EaxEqualizerEffect::commit_props(const Props& props) +{ + auto is_dirty = false; - if (eax_dirty_flags_.lLowGain) + if (props_.lLowGain != props.lLowGain) { + is_dirty = true; set_efx_low_gain(); } - if (eax_dirty_flags_.flLowCutOff) + if (props_.flLowCutOff != props.flLowCutOff) { + is_dirty = true; set_efx_low_cutoff(); } - if (eax_dirty_flags_.lMid1Gain) + if (props_.lMid1Gain != props.lMid1Gain) { + is_dirty = true; set_efx_mid1_gain(); } - if (eax_dirty_flags_.flMid1Center) + if (props_.flMid1Center != props.flMid1Center) { + is_dirty = true; set_efx_mid1_center(); } - if (eax_dirty_flags_.flMid1Width) + if (props_.flMid1Width != props.flMid1Width) { + is_dirty = true; set_efx_mid1_width(); } - if (eax_dirty_flags_.lMid2Gain) + if (props_.lMid2Gain != props.lMid2Gain) { + is_dirty = true; set_efx_mid2_gain(); } - if (eax_dirty_flags_.flMid2Center) + if (props_.flMid2Center != props.flMid2Center) { + is_dirty = true; set_efx_mid2_center(); } - if (eax_dirty_flags_.flMid2Width) + if (props_.flMid2Width != props.flMid2Width) { + is_dirty = true; set_efx_mid2_width(); } - if (eax_dirty_flags_.lHighGain) + if (props_.lHighGain != props.lHighGain) { + is_dirty = true; set_efx_high_gain(); } - if (eax_dirty_flags_.flHighCutOff) + if (props_.flHighCutOff != props.flHighCutOff) { + is_dirty = true; set_efx_high_cutoff(); } - eax_dirty_flags_ = EaxEqualizerEffectDirtyFlags{}; - - return true; -} - -void EaxEqualizerEffect::set(const EaxEaxCall& eax_call) -{ - switch(eax_call.get_property_id()) - { - case EAXEQUALIZER_NONE: - break; - - case EAXEQUALIZER_ALLPARAMETERS: - defer_all(eax_call); - break; - - case EAXEQUALIZER_LOWGAIN: - defer_low_gain(eax_call); - break; - - case EAXEQUALIZER_LOWCUTOFF: - defer_low_cutoff(eax_call); - break; - - case EAXEQUALIZER_MID1GAIN: - defer_mid1_gain(eax_call); - break; - - case EAXEQUALIZER_MID1CENTER: - defer_mid1_center(eax_call); - break; - - case EAXEQUALIZER_MID1WIDTH: - defer_mid1_width(eax_call); - break; - - case EAXEQUALIZER_MID2GAIN: - defer_mid2_gain(eax_call); - break; - - case EAXEQUALIZER_MID2CENTER: - defer_mid2_center(eax_call); - break; - - case EAXEQUALIZER_MID2WIDTH: - defer_mid2_width(eax_call); - break; - - case EAXEQUALIZER_HIGHGAIN: - defer_high_gain(eax_call); - break; - - case EAXEQUALIZER_HIGHCUTOFF: - defer_high_cutoff(eax_call); - break; - - default: - throw EaxEqualizerEffectException{"Unsupported property id."}; - } + return is_dirty; } } // namespace -EaxEffectUPtr eax_create_eax_equalizer_effect() +EaxEffectUPtr eax_create_eax_equalizer_effect(const EaxCall& call) { - return std::make_unique(); + return eax_create_eax4_effect(call); } #endif // ALSOFT_EAX diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index 1ca97ecb..2b1710ad 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -12,9 +12,7 @@ #ifdef ALSOFT_EAX #include - #include "alnumeric.h" - #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -141,113 +139,99 @@ const EffectProps FshifterEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -using EaxFrequencyShifterEffectDirtyFlagsValue = std::uint_least8_t; - -struct EaxFrequencyShifterEffectDirtyFlags -{ - using EaxIsBitFieldStruct = bool; - - EaxFrequencyShifterEffectDirtyFlagsValue flFrequency : 1; - EaxFrequencyShifterEffectDirtyFlagsValue ulLeftDirection : 1; - EaxFrequencyShifterEffectDirtyFlagsValue ulRightDirection : 1; -}; // EaxFrequencyShifterEffectDirtyFlags - - -class EaxFrequencyShifterEffect final : - public EaxEffect +class EaxFrequencyShifterEffectException : public EaxException { public: - EaxFrequencyShifterEffect(); - - void dispatch(const EaxEaxCall& eax_call) override; + explicit EaxFrequencyShifterEffectException(const char* message) + : EaxException{"EAX_FREQUENCY_SHIFTER_EFFECT", message} + {} +}; // EaxFrequencyShifterEffectException - // [[nodiscard]] - bool apply_deferred() override; +class EaxFrequencyShifterEffect final : public EaxEffect4 { +public: + EaxFrequencyShifterEffect(const EaxCall& call); private: - EAXFREQUENCYSHIFTERPROPERTIES eax_{}; - EAXFREQUENCYSHIFTERPROPERTIES eax_d_{}; - EaxFrequencyShifterEffectDirtyFlags eax_dirty_flags_{}; - - void set_eax_defaults(); - - void set_efx_frequency(); + struct FrequencyValidator { + void operator()(float flFrequency) const + { + eax_validate_range( + "Frequency", + flFrequency, + EAXFREQUENCYSHIFTER_MINFREQUENCY, + EAXFREQUENCYSHIFTER_MAXFREQUENCY); + } + }; // FrequencyValidator + + struct LeftDirectionValidator { + void operator()(unsigned long ulLeftDirection) const + { + eax_validate_range( + "Left Direction", + ulLeftDirection, + EAXFREQUENCYSHIFTER_MINLEFTDIRECTION, + EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION); + } + }; // LeftDirectionValidator + + struct RightDirectionValidator { + void operator()(unsigned long ulRightDirection) const + { + eax_validate_range( + "Right Direction", + ulRightDirection, + EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION, + EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION); + } + }; // RightDirectionValidator + + struct AllValidator { + void operator()(const Props& all) const + { + FrequencyValidator{}(all.flFrequency); + LeftDirectionValidator{}(all.ulLeftDirection); + RightDirectionValidator{}(all.ulRightDirection); + } + }; // AllValidator + + void set_defaults(Props& props) override; + + void set_efx_frequency() noexcept; void set_efx_left_direction(); void set_efx_right_direction(); - void set_efx_defaults(); + void set_efx_defaults() override; - void get(const EaxEaxCall& eax_call); - - void validate_frequency(float flFrequency); - void validate_left_direction(unsigned long ulLeftDirection); - void validate_right_direction(unsigned long ulRightDirection); - void validate_all(const EAXFREQUENCYSHIFTERPROPERTIES& all); - - void defer_frequency(float flFrequency); - void defer_left_direction(unsigned long ulLeftDirection); - void defer_right_direction(unsigned long ulRightDirection); - void defer_all(const EAXFREQUENCYSHIFTERPROPERTIES& all); - - void defer_frequency(const EaxEaxCall& eax_call); - void defer_left_direction(const EaxEaxCall& eax_call); - void defer_right_direction(const EaxEaxCall& eax_call); - void defer_all(const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); + void get(const EaxCall& call, const Props& props) override; + void set(const EaxCall& call, Props& props) override; + bool commit_props(const Props& props) override; }; // EaxFrequencyShifterEffect -class EaxFrequencyShifterEffectException : - public EaxException -{ -public: - explicit EaxFrequencyShifterEffectException( - const char* message) - : - EaxException{"EAX_FREQUENCY_SHIFTER_EFFECT", message} - { - } -}; // EaxFrequencyShifterEffectException +EaxFrequencyShifterEffect::EaxFrequencyShifterEffect(const EaxCall& call) + : EaxEffect4{AL_EFFECT_FREQUENCY_SHIFTER, call} +{} - -EaxFrequencyShifterEffect::EaxFrequencyShifterEffect() - : EaxEffect{AL_EFFECT_FREQUENCY_SHIFTER} +void EaxFrequencyShifterEffect::set_defaults(Props& props) { - set_eax_defaults(); - set_efx_defaults(); + props.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY; + props.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION; + props.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION; } -void EaxFrequencyShifterEffect::dispatch(const EaxEaxCall& eax_call) +void EaxFrequencyShifterEffect::set_efx_frequency() noexcept { - eax_call.is_get() ? get(eax_call) : set(eax_call); -} - -void EaxFrequencyShifterEffect::set_eax_defaults() -{ - eax_.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY; - eax_.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION; - eax_.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION; - - eax_d_ = eax_; -} - -void EaxFrequencyShifterEffect::set_efx_frequency() -{ - const auto frequency = clamp( - eax_.flFrequency, + al_effect_props_.Fshifter.Frequency = clamp( + props_.flFrequency, AL_FREQUENCY_SHIFTER_MIN_FREQUENCY, AL_FREQUENCY_SHIFTER_MAX_FREQUENCY); - - al_effect_props_.Fshifter.Frequency = frequency; } void EaxFrequencyShifterEffect::set_efx_left_direction() { const auto left_direction = clamp( - static_cast(eax_.ulLeftDirection), + static_cast(props_.ulLeftDirection), AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION, AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION); - const auto efx_left_direction = DirectionFromEmum(left_direction); assert(efx_left_direction.has_value()); al_effect_props_.Fshifter.LeftDirection = *efx_left_direction; @@ -256,10 +240,9 @@ void EaxFrequencyShifterEffect::set_efx_left_direction() void EaxFrequencyShifterEffect::set_efx_right_direction() { const auto right_direction = clamp( - static_cast(eax_.ulRightDirection), + static_cast(props_.ulRightDirection), AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION, AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION); - const auto efx_right_direction = DirectionFromEmum(right_direction); assert(efx_right_direction.has_value()); al_effect_props_.Fshifter.RightDirection = *efx_right_direction; @@ -272,208 +255,62 @@ void EaxFrequencyShifterEffect::set_efx_defaults() set_efx_right_direction(); } -void EaxFrequencyShifterEffect::get(const EaxEaxCall& eax_call) +void EaxFrequencyShifterEffect::get(const EaxCall& call, const Props& props) { - switch(eax_call.get_property_id()) + switch(call.get_property_id()) { - case EAXFREQUENCYSHIFTER_NONE: - break; - - case EAXFREQUENCYSHIFTER_ALLPARAMETERS: - eax_call.set_value(eax_); - break; - - case EAXFREQUENCYSHIFTER_FREQUENCY: - eax_call.set_value(eax_.flFrequency); - break; - - case EAXFREQUENCYSHIFTER_LEFTDIRECTION: - eax_call.set_value(eax_.ulLeftDirection); - break; - - case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: - eax_call.set_value(eax_.ulRightDirection); - break; - - default: - throw EaxFrequencyShifterEffectException{"Unsupported property id."}; + case EAXFREQUENCYSHIFTER_NONE: break; + case EAXFREQUENCYSHIFTER_ALLPARAMETERS: call.set_value(props); break; + case EAXFREQUENCYSHIFTER_FREQUENCY: call.set_value(props.flFrequency); break; + case EAXFREQUENCYSHIFTER_LEFTDIRECTION: call.set_value(props.ulLeftDirection); break; + case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: call.set_value(props.ulRightDirection); break; + default: fail_unknown_property_id(); } } -void EaxFrequencyShifterEffect::validate_frequency( - float flFrequency) -{ - eax_validate_range( - "Frequency", - flFrequency, - EAXFREQUENCYSHIFTER_MINFREQUENCY, - EAXFREQUENCYSHIFTER_MAXFREQUENCY); -} - -void EaxFrequencyShifterEffect::validate_left_direction( - unsigned long ulLeftDirection) -{ - eax_validate_range( - "Left Direction", - ulLeftDirection, - EAXFREQUENCYSHIFTER_MINLEFTDIRECTION, - EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION); -} - -void EaxFrequencyShifterEffect::validate_right_direction( - unsigned long ulRightDirection) -{ - eax_validate_range( - "Right Direction", - ulRightDirection, - EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION, - EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION); -} - -void EaxFrequencyShifterEffect::validate_all( - const EAXFREQUENCYSHIFTERPROPERTIES& all) -{ - validate_frequency(all.flFrequency); - validate_left_direction(all.ulLeftDirection); - validate_right_direction(all.ulRightDirection); -} - -void EaxFrequencyShifterEffect::defer_frequency( - float flFrequency) -{ - eax_d_.flFrequency = flFrequency; - eax_dirty_flags_.flFrequency = (eax_.flFrequency != eax_d_.flFrequency); -} - -void EaxFrequencyShifterEffect::defer_left_direction( - unsigned long ulLeftDirection) -{ - eax_d_.ulLeftDirection = ulLeftDirection; - eax_dirty_flags_.ulLeftDirection = (eax_.ulLeftDirection != eax_d_.ulLeftDirection); -} - -void EaxFrequencyShifterEffect::defer_right_direction( - unsigned long ulRightDirection) +void EaxFrequencyShifterEffect::set(const EaxCall& call, Props& props) { - eax_d_.ulRightDirection = ulRightDirection; - eax_dirty_flags_.ulRightDirection = (eax_.ulRightDirection != eax_d_.ulRightDirection); -} - -void EaxFrequencyShifterEffect::defer_all( - const EAXFREQUENCYSHIFTERPROPERTIES& all) -{ - defer_frequency(all.flFrequency); - defer_left_direction(all.ulLeftDirection); - defer_right_direction(all.ulRightDirection); -} - -void EaxFrequencyShifterEffect::defer_frequency( - const EaxEaxCall& eax_call) -{ - const auto& frequency = - eax_call.get_value< - EaxFrequencyShifterEffectException, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::flFrequency)>(); - - validate_frequency(frequency); - defer_frequency(frequency); -} - -void EaxFrequencyShifterEffect::defer_left_direction( - const EaxEaxCall& eax_call) -{ - const auto& left_direction = - eax_call.get_value< - EaxFrequencyShifterEffectException, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::ulLeftDirection)>(); - - validate_left_direction(left_direction); - defer_left_direction(left_direction); -} - -void EaxFrequencyShifterEffect::defer_right_direction( - const EaxEaxCall& eax_call) -{ - const auto& right_direction = - eax_call.get_value< - EaxFrequencyShifterEffectException, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::ulRightDirection)>(); - - validate_right_direction(right_direction); - defer_right_direction(right_direction); -} - -void EaxFrequencyShifterEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto& all = - eax_call.get_value< - EaxFrequencyShifterEffectException, const EAXFREQUENCYSHIFTERPROPERTIES>(); - - validate_all(all); - defer_all(all); -} - -// [[nodiscard]] -bool EaxFrequencyShifterEffect::apply_deferred() -{ - if (eax_dirty_flags_ == EaxFrequencyShifterEffectDirtyFlags{}) + switch(call.get_property_id()) { - return false; + case EAXFREQUENCYSHIFTER_NONE: break; + case EAXFREQUENCYSHIFTER_ALLPARAMETERS: defer(call, props); break; + case EAXFREQUENCYSHIFTER_FREQUENCY: defer(call, props.flFrequency); break; + case EAXFREQUENCYSHIFTER_LEFTDIRECTION: defer(call, props.ulLeftDirection); break; + case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: defer(call, props.ulRightDirection); break; + default: fail_unknown_property_id(); } +} - eax_ = eax_d_; +bool EaxFrequencyShifterEffect::commit_props(const Props& props) +{ + auto is_dirty = false; - if (eax_dirty_flags_.flFrequency) + if (props_.flFrequency != props.flFrequency) { + is_dirty = true; set_efx_frequency(); } - if (eax_dirty_flags_.ulLeftDirection) + if (props_.ulLeftDirection != props.ulLeftDirection) { + is_dirty = true; set_efx_left_direction(); } - if (eax_dirty_flags_.ulRightDirection) + if (props_.ulRightDirection != props.ulRightDirection) { + is_dirty = true; set_efx_right_direction(); } - eax_dirty_flags_ = EaxFrequencyShifterEffectDirtyFlags{}; - - return true; -} - -void EaxFrequencyShifterEffect::set(const EaxEaxCall& eax_call) -{ - switch(eax_call.get_property_id()) - { - case EAXFREQUENCYSHIFTER_NONE: - break; - - case EAXFREQUENCYSHIFTER_ALLPARAMETERS: - defer_all(eax_call); - break; - - case EAXFREQUENCYSHIFTER_FREQUENCY: - defer_frequency(eax_call); - break; - - case EAXFREQUENCYSHIFTER_LEFTDIRECTION: - defer_left_direction(eax_call); - break; - - case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: - defer_right_direction(eax_call); - break; - - default: - throw EaxFrequencyShifterEffectException{"Unsupported property id."}; - } + return is_dirty; } } // namespace -EaxEffectUPtr eax_create_eax_frequency_shifter_effect() +EaxEffectUPtr eax_create_eax_frequency_shifter_effect(const EaxCall& call) { - return std::make_unique(); + return eax_create_eax4_effect(call); } #endif // ALSOFT_EAX diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index 082597cd..774fb767 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -12,9 +12,7 @@ #ifdef ALSOFT_EAX #include - #include "alnumeric.h" - #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -147,123 +145,107 @@ const EffectProps ModulatorEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -using EaxRingModulatorEffectDirtyFlagsValue = std::uint_least8_t; - -struct EaxRingModulatorEffectDirtyFlags +class EaxRingModulatorEffectException : public EaxException { - using EaxIsBitFieldStruct = bool; - - EaxRingModulatorEffectDirtyFlagsValue flFrequency : 1; - EaxRingModulatorEffectDirtyFlagsValue flHighPassCutOff : 1; - EaxRingModulatorEffectDirtyFlagsValue ulWaveform : 1; -}; // EaxPitchShifterEffectDirtyFlags - +public: + explicit EaxRingModulatorEffectException(const char* message) + : EaxException{"EAX_RING_MODULATOR_EFFECT", message} + {} +}; // EaxRingModulatorEffectException -class EaxRingModulatorEffect final : - public EaxEffect +class EaxRingModulatorEffect final : public EaxEffect4 { public: - EaxRingModulatorEffect(); - - void dispatch(const EaxEaxCall& eax_call) override; - - // [[nodiscard]] - bool apply_deferred() override; + EaxRingModulatorEffect(const EaxCall& call); private: - EAXRINGMODULATORPROPERTIES eax_{}; - EAXRINGMODULATORPROPERTIES eax_d_{}; - EaxRingModulatorEffectDirtyFlags eax_dirty_flags_{}; - - void set_eax_defaults(); - - void set_efx_frequency(); - void set_efx_high_pass_cutoff(); + struct FrequencyValidator { + void operator()(float flFrequency) const + { + eax_validate_range( + "Frequency", + flFrequency, + EAXRINGMODULATOR_MINFREQUENCY, + EAXRINGMODULATOR_MAXFREQUENCY); + } + }; // FrequencyValidator + + struct HighPassCutOffValidator { + void operator()(float flHighPassCutOff) const + { + eax_validate_range( + "High-Pass Cutoff", + flHighPassCutOff, + EAXRINGMODULATOR_MINHIGHPASSCUTOFF, + EAXRINGMODULATOR_MAXHIGHPASSCUTOFF); + } + }; // HighPassCutOffValidator + + struct WaveformValidator { + void operator()(unsigned long ulWaveform) const + { + eax_validate_range( + "Waveform", + ulWaveform, + EAXRINGMODULATOR_MINWAVEFORM, + EAXRINGMODULATOR_MAXWAVEFORM); + } + }; // WaveformValidator + + struct AllValidator { + void operator()(const Props& all) const + { + FrequencyValidator{}(all.flFrequency); + HighPassCutOffValidator{}(all.flHighPassCutOff); + WaveformValidator{}(all.ulWaveform); + } + }; // AllValidator + + void set_defaults(Props& props) override; + + void set_efx_frequency() noexcept; + void set_efx_high_pass_cutoff() noexcept; void set_efx_waveform(); - void set_efx_defaults(); - - void get(const EaxEaxCall& eax_call); + void set_efx_defaults() override; - void validate_frequency(float flFrequency); - void validate_high_pass_cutoff(float flHighPassCutOff); - void validate_waveform(unsigned long ulWaveform); - void validate_all(const EAXRINGMODULATORPROPERTIES& all); - - void defer_frequency(float flFrequency); - void defer_high_pass_cutoff(float flHighPassCutOff); - void defer_waveform(unsigned long ulWaveform); - void defer_all(const EAXRINGMODULATORPROPERTIES& all); - - void defer_frequency(const EaxEaxCall& eax_call); - void defer_high_pass_cutoff(const EaxEaxCall& eax_call); - void defer_waveform(const EaxEaxCall& eax_call); - void defer_all(const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); + void get(const EaxCall& call, const Props& props) override; + void set(const EaxCall& call, Props& props) override; + bool commit_props(const Props& props) override; }; // EaxRingModulatorEffect +EaxRingModulatorEffect::EaxRingModulatorEffect(const EaxCall& call) + : EaxEffect4{AL_EFFECT_RING_MODULATOR, call} +{} -class EaxRingModulatorEffectException : - public EaxException +void EaxRingModulatorEffect::set_defaults(Props& props) { -public: - explicit EaxRingModulatorEffectException( - const char* message) - : - EaxException{"EAX_RING_MODULATOR_EFFECT", message} - { - } -}; // EaxRingModulatorEffectException - - -EaxRingModulatorEffect::EaxRingModulatorEffect() - : EaxEffect{AL_EFFECT_RING_MODULATOR} -{ - set_eax_defaults(); - set_efx_defaults(); + props.flFrequency = EAXRINGMODULATOR_DEFAULTFREQUENCY; + props.flHighPassCutOff = EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF; + props.ulWaveform = EAXRINGMODULATOR_DEFAULTWAVEFORM; } -void EaxRingModulatorEffect::dispatch(const EaxEaxCall& eax_call) +void EaxRingModulatorEffect::set_efx_frequency() noexcept { - eax_call.is_get() ? get(eax_call) : set(eax_call); -} - -void EaxRingModulatorEffect::set_eax_defaults() -{ - eax_.flFrequency = EAXRINGMODULATOR_DEFAULTFREQUENCY; - eax_.flHighPassCutOff = EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF; - eax_.ulWaveform = EAXRINGMODULATOR_DEFAULTWAVEFORM; - - eax_d_ = eax_; -} - -void EaxRingModulatorEffect::set_efx_frequency() -{ - const auto frequency = clamp( - eax_.flFrequency, + al_effect_props_.Modulator.Frequency = clamp( + props_.flFrequency, AL_RING_MODULATOR_MIN_FREQUENCY, AL_RING_MODULATOR_MAX_FREQUENCY); - - al_effect_props_.Modulator.Frequency = frequency; } -void EaxRingModulatorEffect::set_efx_high_pass_cutoff() +void EaxRingModulatorEffect::set_efx_high_pass_cutoff() noexcept { - const auto high_pass_cutoff = clamp( - eax_.flHighPassCutOff, + al_effect_props_.Modulator.HighPassCutoff = clamp( + props_.flHighPassCutOff, AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF, AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF); - - al_effect_props_.Modulator.HighPassCutoff = high_pass_cutoff; } void EaxRingModulatorEffect::set_efx_waveform() { const auto waveform = clamp( - static_cast(eax_.ulWaveform), + static_cast(props_.ulWaveform), AL_RING_MODULATOR_MIN_WAVEFORM, AL_RING_MODULATOR_MAX_WAVEFORM); - const auto efx_waveform = WaveformFromEmum(waveform); assert(efx_waveform.has_value()); al_effect_props_.Modulator.Waveform = *efx_waveform; @@ -276,207 +258,62 @@ void EaxRingModulatorEffect::set_efx_defaults() set_efx_waveform(); } -void EaxRingModulatorEffect::get(const EaxEaxCall& eax_call) +void EaxRingModulatorEffect::get(const EaxCall& call, const Props& props) { - switch(eax_call.get_property_id()) + switch(call.get_property_id()) { - case EAXRINGMODULATOR_NONE: - break; - - case EAXRINGMODULATOR_ALLPARAMETERS: - eax_call.set_value(eax_); - break; - - case EAXRINGMODULATOR_FREQUENCY: - eax_call.set_value(eax_.flFrequency); - break; - - case EAXRINGMODULATOR_HIGHPASSCUTOFF: - eax_call.set_value(eax_.flHighPassCutOff); - break; - - case EAXRINGMODULATOR_WAVEFORM: - eax_call.set_value(eax_.ulWaveform); - break; - - default: - throw EaxRingModulatorEffectException{"Unsupported property id."}; + case EAXRINGMODULATOR_NONE: break; + case EAXRINGMODULATOR_ALLPARAMETERS: call.set_value(props); break; + case EAXRINGMODULATOR_FREQUENCY: call.set_value(props.flFrequency); break; + case EAXRINGMODULATOR_HIGHPASSCUTOFF: call.set_value(props.flHighPassCutOff); break; + case EAXRINGMODULATOR_WAVEFORM: call.set_value(props.ulWaveform); break; + default: fail_unknown_property_id(); } } -void EaxRingModulatorEffect::validate_frequency( - float flFrequency) -{ - eax_validate_range( - "Frequency", - flFrequency, - EAXRINGMODULATOR_MINFREQUENCY, - EAXRINGMODULATOR_MAXFREQUENCY); -} - -void EaxRingModulatorEffect::validate_high_pass_cutoff( - float flHighPassCutOff) -{ - eax_validate_range( - "High-Pass Cutoff", - flHighPassCutOff, - EAXRINGMODULATOR_MINHIGHPASSCUTOFF, - EAXRINGMODULATOR_MAXHIGHPASSCUTOFF); -} - -void EaxRingModulatorEffect::validate_waveform( - unsigned long ulWaveform) -{ - eax_validate_range( - "Waveform", - ulWaveform, - EAXRINGMODULATOR_MINWAVEFORM, - EAXRINGMODULATOR_MAXWAVEFORM); -} - -void EaxRingModulatorEffect::validate_all( - const EAXRINGMODULATORPROPERTIES& all) -{ - validate_frequency(all.flFrequency); - validate_high_pass_cutoff(all.flHighPassCutOff); - validate_waveform(all.ulWaveform); -} - -void EaxRingModulatorEffect::defer_frequency( - float flFrequency) -{ - eax_d_.flFrequency = flFrequency; - eax_dirty_flags_.flFrequency = (eax_.flFrequency != eax_d_.flFrequency); -} - -void EaxRingModulatorEffect::defer_high_pass_cutoff( - float flHighPassCutOff) -{ - eax_d_.flHighPassCutOff = flHighPassCutOff; - eax_dirty_flags_.flHighPassCutOff = (eax_.flHighPassCutOff != eax_d_.flHighPassCutOff); -} - -void EaxRingModulatorEffect::defer_waveform( - unsigned long ulWaveform) +void EaxRingModulatorEffect::set(const EaxCall& call, Props& props) { - eax_d_.ulWaveform = ulWaveform; - eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform); -} - -void EaxRingModulatorEffect::defer_all( - const EAXRINGMODULATORPROPERTIES& all) -{ - defer_frequency(all.flFrequency); - defer_high_pass_cutoff(all.flHighPassCutOff); - defer_waveform(all.ulWaveform); -} - -void EaxRingModulatorEffect::defer_frequency( - const EaxEaxCall& eax_call) -{ - const auto& frequency = - eax_call.get_value< - EaxRingModulatorEffectException, const decltype(EAXRINGMODULATORPROPERTIES::flFrequency)>(); - - validate_frequency(frequency); - defer_frequency(frequency); -} - -void EaxRingModulatorEffect::defer_high_pass_cutoff( - const EaxEaxCall& eax_call) -{ - const auto& high_pass_cutoff = - eax_call.get_value< - EaxRingModulatorEffectException, const decltype(EAXRINGMODULATORPROPERTIES::flHighPassCutOff)>(); - - validate_high_pass_cutoff(high_pass_cutoff); - defer_high_pass_cutoff(high_pass_cutoff); -} - -void EaxRingModulatorEffect::defer_waveform( - const EaxEaxCall& eax_call) -{ - const auto& waveform = - eax_call.get_value< - EaxRingModulatorEffectException, const decltype(EAXRINGMODULATORPROPERTIES::ulWaveform)>(); - - validate_waveform(waveform); - defer_waveform(waveform); -} - -void EaxRingModulatorEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto& all = - eax_call.get_value(); - - validate_all(all); - defer_all(all); -} - -// [[nodiscard]] -bool EaxRingModulatorEffect::apply_deferred() -{ - if (eax_dirty_flags_ == EaxRingModulatorEffectDirtyFlags{}) + switch (call.get_property_id()) { - return false; + case EAXRINGMODULATOR_NONE: break; + case EAXRINGMODULATOR_ALLPARAMETERS: defer(call, props); break; + case EAXRINGMODULATOR_FREQUENCY: defer(call, props.flFrequency); break; + case EAXRINGMODULATOR_HIGHPASSCUTOFF: defer(call, props.flHighPassCutOff); break; + case EAXRINGMODULATOR_WAVEFORM: defer(call, props.ulWaveform); break; + default: fail_unknown_property_id(); } +} - eax_ = eax_d_; +bool EaxRingModulatorEffect::commit_props(const Props& props) +{ + auto is_dirty = false; - if (eax_dirty_flags_.flFrequency) + if (props_.flFrequency != props.flFrequency) { + is_dirty = true; set_efx_frequency(); } - if (eax_dirty_flags_.flHighPassCutOff) + if (props_.flHighPassCutOff != props.flHighPassCutOff) { + is_dirty = true; set_efx_high_pass_cutoff(); } - if (eax_dirty_flags_.ulWaveform) + if (props_.ulWaveform != props.ulWaveform) { + is_dirty = true; set_efx_waveform(); } - eax_dirty_flags_ = EaxRingModulatorEffectDirtyFlags{}; - - return true; -} - -void EaxRingModulatorEffect::set(const EaxEaxCall& eax_call) -{ - switch (eax_call.get_property_id()) - { - case EAXRINGMODULATOR_NONE: - break; - - case EAXRINGMODULATOR_ALLPARAMETERS: - defer_all(eax_call); - break; - - case EAXRINGMODULATOR_FREQUENCY: - defer_frequency(eax_call); - break; - - case EAXRINGMODULATOR_HIGHPASSCUTOFF: - defer_high_pass_cutoff(eax_call); - break; - - case EAXRINGMODULATOR_WAVEFORM: - defer_waveform(eax_call); - break; - - default: - throw EaxRingModulatorEffectException{"Unsupported property id."}; - } + return is_dirty; } } // namespace -EaxEffectUPtr eax_create_eax_ring_modulator_effect() +EaxEffectUPtr eax_create_eax_ring_modulator_effect(const EaxCall& call) { - return std::make_unique(); + return eax_create_eax4_effect(call); } #endif // ALSOFT_EAX diff --git a/al/effects/null.cpp b/al/effects/null.cpp index 0ec387d4..2243dfe1 100644 --- a/al/effects/null.cpp +++ b/al/effects/null.cpp @@ -100,44 +100,34 @@ const EffectProps NullEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -class EaxNullEffect final : - public EaxEffect -{ +class EaxNullEffect final : public EaxEffect { public: - EaxNullEffect(); - - void dispatch(const EaxEaxCall& eax_call) override; + EaxNullEffect() noexcept; - // [[nodiscard]] - bool apply_deferred() override; + void dispatch(const EaxCall& call) override; + /*[[nodiscard]]*/ bool commit() override; }; // EaxNullEffect -class EaxNullEffectException : - public EaxException +class EaxNullEffectException : public EaxException { public: - explicit EaxNullEffectException( - const char* message) - : - EaxException{"EAX_NULL_EFFECT", message} - { - } + explicit EaxNullEffectException(const char* message) + : EaxException{"EAX_NULL_EFFECT", message} + {} }; // EaxNullEffectException - -EaxNullEffect::EaxNullEffect() +EaxNullEffect::EaxNullEffect() noexcept : EaxEffect{AL_EFFECT_NULL} -{ -} +{} -void EaxNullEffect::dispatch(const EaxEaxCall& eax_call) +void EaxNullEffect::dispatch(const EaxCall& call) { - if(eax_call.get_property_id() != 0) + if(call.get_property_id() != 0) throw EaxNullEffectException{"Unsupported property id."}; } -bool EaxNullEffect::apply_deferred() +bool EaxNullEffect::commit() { return false; } diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp index cb81d831..51dbdd8f 100644 --- a/al/effects/pshifter.cpp +++ b/al/effects/pshifter.cpp @@ -9,7 +9,6 @@ #ifdef ALSOFT_EAX #include "alnumeric.h" - #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -93,108 +92,84 @@ const EffectProps PshifterEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -using EaxPitchShifterEffectDirtyFlagsValue = std::uint_least8_t; - -struct EaxPitchShifterEffectDirtyFlags -{ - using EaxIsBitFieldStruct = bool; - - EaxPitchShifterEffectDirtyFlagsValue lCoarseTune : 1; - EaxPitchShifterEffectDirtyFlagsValue lFineTune : 1; -}; // EaxPitchShifterEffectDirtyFlags - - -class EaxPitchShifterEffect final : - public EaxEffect +class EaxPitchShifterEffectException : public EaxException { public: - EaxPitchShifterEffect(); - - void dispatch(const EaxEaxCall& eax_call) override; + explicit EaxPitchShifterEffectException(const char* message) + : EaxException{"EAX_PITCH_SHIFTER_EFFECT", message} + {} +}; // EaxPitchShifterEffectException - // [[nodiscard]] - bool apply_deferred() override; +class EaxPitchShifterEffect final : public EaxEffect4 { +public: + EaxPitchShifterEffect(const EaxCall& call); private: - EAXPITCHSHIFTERPROPERTIES eax_{}; - EAXPITCHSHIFTERPROPERTIES eax_d_{}; - EaxPitchShifterEffectDirtyFlags eax_dirty_flags_{}; - - void set_eax_defaults(); - - void set_efx_coarse_tune(); - void set_efx_fine_tune(); - void set_efx_defaults(); - - void get(const EaxEaxCall& eax_call); - - void validate_coarse_tune(long lCoarseTune); - void validate_fine_tune(long lFineTune); - void validate_all(const EAXPITCHSHIFTERPROPERTIES& all); - - void defer_coarse_tune(long lCoarseTune); - void defer_fine_tune(long lFineTune); - void defer_all(const EAXPITCHSHIFTERPROPERTIES& all); - - void defer_coarse_tune(const EaxEaxCall& eax_call); - void defer_fine_tune(const EaxEaxCall& eax_call); - void defer_all(const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); + struct CoarseTuneValidator { + void operator()(long lCoarseTune) const + { + eax_validate_range( + "Coarse Tune", + lCoarseTune, + EAXPITCHSHIFTER_MINCOARSETUNE, + EAXPITCHSHIFTER_MAXCOARSETUNE); + } + }; // CoarseTuneValidator + + struct FineTuneValidator { + void operator()(long lFineTune) const + { + eax_validate_range( + "Fine Tune", + lFineTune, + EAXPITCHSHIFTER_MINFINETUNE, + EAXPITCHSHIFTER_MAXFINETUNE); + } + }; // FineTuneValidator + + struct AllValidator { + void operator()(const Props& all) const + { + CoarseTuneValidator{}(all.lCoarseTune); + FineTuneValidator{}(all.lFineTune); + } + }; // AllValidator + + void set_defaults(Props& props) override; + + void set_efx_coarse_tune() noexcept; + void set_efx_fine_tune() noexcept; + void set_efx_defaults() override; + + void get(const EaxCall& call, const Props& props) override; + void set(const EaxCall& call, Props& props) override; + bool commit_props(const Props& old_i) override; }; // EaxPitchShifterEffect +EaxPitchShifterEffect::EaxPitchShifterEffect(const EaxCall& call) + : EaxEffect4{AL_EFFECT_PITCH_SHIFTER, call} +{} -class EaxPitchShifterEffectException : - public EaxException +void EaxPitchShifterEffect::set_defaults(Props& props) { -public: - explicit EaxPitchShifterEffectException( - const char* message) - : - EaxException{"EAX_PITCH_SHIFTER_EFFECT", message} - { - } -}; // EaxPitchShifterEffectException - - -EaxPitchShifterEffect::EaxPitchShifterEffect() - : EaxEffect{AL_EFFECT_PITCH_SHIFTER} -{ - set_eax_defaults(); - set_efx_defaults(); -} - -void EaxPitchShifterEffect::dispatch(const EaxEaxCall& eax_call) -{ - eax_call.is_get() ? get(eax_call) : set(eax_call); -} - -void EaxPitchShifterEffect::set_eax_defaults() -{ - eax_.lCoarseTune = EAXPITCHSHIFTER_DEFAULTCOARSETUNE; - eax_.lFineTune = EAXPITCHSHIFTER_DEFAULTFINETUNE; - - eax_d_ = eax_; + props.lCoarseTune = EAXPITCHSHIFTER_DEFAULTCOARSETUNE; + props.lFineTune = EAXPITCHSHIFTER_DEFAULTFINETUNE; } -void EaxPitchShifterEffect::set_efx_coarse_tune() +void EaxPitchShifterEffect::set_efx_coarse_tune() noexcept { - const auto coarse_tune = clamp( - static_cast(eax_.lCoarseTune), + al_effect_props_.Pshifter.CoarseTune = clamp( + static_cast(props_.lCoarseTune), AL_PITCH_SHIFTER_MIN_COARSE_TUNE, AL_PITCH_SHIFTER_MAX_COARSE_TUNE); - - al_effect_props_.Pshifter.CoarseTune = coarse_tune; } -void EaxPitchShifterEffect::set_efx_fine_tune() +void EaxPitchShifterEffect::set_efx_fine_tune() noexcept { - const auto fine_tune = clamp( - static_cast(eax_.lFineTune), + al_effect_props_.Pshifter.FineTune = clamp( + static_cast(props_.lFineTune), AL_PITCH_SHIFTER_MIN_FINE_TUNE, AL_PITCH_SHIFTER_MAX_FINE_TUNE); - - al_effect_props_.Pshifter.FineTune = fine_tune; } void EaxPitchShifterEffect::set_efx_defaults() @@ -203,162 +178,54 @@ void EaxPitchShifterEffect::set_efx_defaults() set_efx_fine_tune(); } -void EaxPitchShifterEffect::get(const EaxEaxCall& eax_call) +void EaxPitchShifterEffect::get(const EaxCall& call, const Props& props) { - switch(eax_call.get_property_id()) + switch(call.get_property_id()) { - case EAXPITCHSHIFTER_NONE: - break; - - case EAXPITCHSHIFTER_ALLPARAMETERS: - eax_call.set_value(eax_); - break; - - case EAXPITCHSHIFTER_COARSETUNE: - eax_call.set_value(eax_.lCoarseTune); - break; - - case EAXPITCHSHIFTER_FINETUNE: - eax_call.set_value(eax_.lFineTune); - break; - - default: - throw EaxPitchShifterEffectException{"Unsupported property id."}; + case EAXPITCHSHIFTER_NONE: break; + case EAXPITCHSHIFTER_ALLPARAMETERS: call.set_value(props); break; + case EAXPITCHSHIFTER_COARSETUNE: call.set_value(props.lCoarseTune); break; + case EAXPITCHSHIFTER_FINETUNE: call.set_value(props.lFineTune); break; + default: fail_unknown_property_id(); } } -void EaxPitchShifterEffect::validate_coarse_tune( - long lCoarseTune) -{ - eax_validate_range( - "Coarse Tune", - lCoarseTune, - EAXPITCHSHIFTER_MINCOARSETUNE, - EAXPITCHSHIFTER_MAXCOARSETUNE); -} - -void EaxPitchShifterEffect::validate_fine_tune( - long lFineTune) +void EaxPitchShifterEffect::set(const EaxCall& call, Props& props) { - eax_validate_range( - "Fine Tune", - lFineTune, - EAXPITCHSHIFTER_MINFINETUNE, - EAXPITCHSHIFTER_MAXFINETUNE); -} - -void EaxPitchShifterEffect::validate_all( - const EAXPITCHSHIFTERPROPERTIES& all) -{ - validate_coarse_tune(all.lCoarseTune); - validate_fine_tune(all.lFineTune); -} - -void EaxPitchShifterEffect::defer_coarse_tune( - long lCoarseTune) -{ - eax_d_.lCoarseTune = lCoarseTune; - eax_dirty_flags_.lCoarseTune = (eax_.lCoarseTune != eax_d_.lCoarseTune); -} - -void EaxPitchShifterEffect::defer_fine_tune( - long lFineTune) -{ - eax_d_.lFineTune = lFineTune; - eax_dirty_flags_.lFineTune = (eax_.lFineTune != eax_d_.lFineTune); -} - -void EaxPitchShifterEffect::defer_all( - const EAXPITCHSHIFTERPROPERTIES& all) -{ - defer_coarse_tune(all.lCoarseTune); - defer_fine_tune(all.lFineTune); -} - -void EaxPitchShifterEffect::defer_coarse_tune( - const EaxEaxCall& eax_call) -{ - const auto& coarse_tune = - eax_call.get_value(); - - validate_coarse_tune(coarse_tune); - defer_coarse_tune(coarse_tune); -} - -void EaxPitchShifterEffect::defer_fine_tune( - const EaxEaxCall& eax_call) -{ - const auto& fine_tune = - eax_call.get_value(); - - validate_fine_tune(fine_tune); - defer_fine_tune(fine_tune); -} - -void EaxPitchShifterEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto& all = - eax_call.get_value(); - - validate_all(all); - defer_all(all); -} - -// [[nodiscard]] -bool EaxPitchShifterEffect::apply_deferred() -{ - if (eax_dirty_flags_ == EaxPitchShifterEffectDirtyFlags{}) + switch(call.get_property_id()) { - return false; + case EAXPITCHSHIFTER_NONE: break; + case EAXPITCHSHIFTER_ALLPARAMETERS: defer(call, props); break; + case EAXPITCHSHIFTER_COARSETUNE: defer(call, props.lCoarseTune); break; + case EAXPITCHSHIFTER_FINETUNE: defer(call, props.lFineTune); break; + default: fail_unknown_property_id(); } +} - eax_ = eax_d_; +bool EaxPitchShifterEffect::commit_props(const Props& props) +{ + auto is_dirty = false; - if (eax_dirty_flags_.lCoarseTune) + if (props_.lCoarseTune != props.lCoarseTune) { + is_dirty = true; set_efx_coarse_tune(); } - if (eax_dirty_flags_.lFineTune) + if (props_.lFineTune != props.lFineTune) { + is_dirty = true; set_efx_fine_tune(); } - eax_dirty_flags_ = EaxPitchShifterEffectDirtyFlags{}; - - return true; -} - -void EaxPitchShifterEffect::set(const EaxEaxCall& eax_call) -{ - switch(eax_call.get_property_id()) - { - case EAXPITCHSHIFTER_NONE: - break; - - case EAXPITCHSHIFTER_ALLPARAMETERS: - defer_all(eax_call); - break; - - case EAXPITCHSHIFTER_COARSETUNE: - defer_coarse_tune(eax_call); - break; - - case EAXPITCHSHIFTER_FINETUNE: - defer_fine_tune(eax_call); - break; - - default: - throw EaxPitchShifterEffectException{"Unsupported property id."}; - } + return is_dirty; } } // namespace -EaxEffectUPtr eax_create_eax_pitch_shifter_effect() +EaxEffectUPtr eax_create_eax_pitch_shifter_effect(const EaxCall& call) { - return std::make_unique(); + return eax_create_eax4_effect(call); } #endif // ALSOFT_EAX diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index 4184eda0..da4c3fb4 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -10,12 +10,9 @@ #include "effects.h" #ifdef ALSOFT_EAX -#include - -#include "AL/efx-presets.h" - +#include #include "alnumeric.h" - +#include "AL/efx-presets.h" #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -569,475 +566,884 @@ const EffectProps StdReverbEffectProps{genDefaultStdProps()}; #ifdef ALSOFT_EAX namespace { -extern const EFXEAXREVERBPROPERTIES eax_efx_reverb_presets[]; - -using EaxReverbEffectDirtyFlagsValue = std::uint_least32_t; - -struct EaxReverbEffectDirtyFlags -{ - using EaxIsBitFieldStruct = bool; - - EaxReverbEffectDirtyFlagsValue ulEnvironment : 1; - EaxReverbEffectDirtyFlagsValue flEnvironmentSize : 1; - EaxReverbEffectDirtyFlagsValue flEnvironmentDiffusion : 1; - EaxReverbEffectDirtyFlagsValue lRoom : 1; - EaxReverbEffectDirtyFlagsValue lRoomHF : 1; - EaxReverbEffectDirtyFlagsValue lRoomLF : 1; - EaxReverbEffectDirtyFlagsValue flDecayTime : 1; - EaxReverbEffectDirtyFlagsValue flDecayHFRatio : 1; - EaxReverbEffectDirtyFlagsValue flDecayLFRatio : 1; - EaxReverbEffectDirtyFlagsValue lReflections : 1; - EaxReverbEffectDirtyFlagsValue flReflectionsDelay : 1; - EaxReverbEffectDirtyFlagsValue vReflectionsPan : 1; - EaxReverbEffectDirtyFlagsValue lReverb : 1; - EaxReverbEffectDirtyFlagsValue flReverbDelay : 1; - EaxReverbEffectDirtyFlagsValue vReverbPan : 1; - EaxReverbEffectDirtyFlagsValue flEchoTime : 1; - EaxReverbEffectDirtyFlagsValue flEchoDepth : 1; - EaxReverbEffectDirtyFlagsValue flModulationTime : 1; - EaxReverbEffectDirtyFlagsValue flModulationDepth : 1; - EaxReverbEffectDirtyFlagsValue flAirAbsorptionHF : 1; - EaxReverbEffectDirtyFlagsValue flHFReference : 1; - EaxReverbEffectDirtyFlagsValue flLFReference : 1; - EaxReverbEffectDirtyFlagsValue flRoomRolloffFactor : 1; - EaxReverbEffectDirtyFlagsValue ulFlags : 1; -}; // EaxReverbEffectDirtyFlags - -struct Eax1ReverbEffectDirtyFlags +class EaxReverbEffectException : public EaxException { - using EaxIsBitFieldStruct = bool; - - EaxReverbEffectDirtyFlagsValue ulEnvironment : 1; - EaxReverbEffectDirtyFlagsValue flVolume : 1; - EaxReverbEffectDirtyFlagsValue flDecayTime : 1; - EaxReverbEffectDirtyFlagsValue flDamping : 1; -}; // Eax1ReverbEffectDirtyFlags +public: + explicit EaxReverbEffectException(const char* message) + : EaxException{"EAX_REVERB_EFFECT", message} + {} +}; // EaxReverbEffectException -class EaxReverbEffect final : - public EaxEffect +class EaxReverbEffect final : public EaxEffect { public: - EaxReverbEffect(); - - void dispatch(const EaxEaxCall& eax_call) override; + EaxReverbEffect(const EaxCall& call) noexcept; - // [[nodiscard]] - bool apply_deferred() override; + void dispatch(const EaxCall& call) override; + /*[[nodiscard]]*/ bool commit() override; private: - EAX_REVERBPROPERTIES eax1_{}; - EAX_REVERBPROPERTIES eax1_d_{}; - Eax1ReverbEffectDirtyFlags eax1_dirty_flags_{}; - EAXREVERBPROPERTIES eax_{}; - EAXREVERBPROPERTIES eax_d_{}; - EaxReverbEffectDirtyFlags eax_dirty_flags_{}; - - [[noreturn]] static void eax_fail(const char* message); - - void set_eax_defaults(); - - void set_efx_density_from_environment_size(); - void set_efx_diffusion(); - void set_efx_gain(); - void set_efx_gain_hf(); - void set_efx_gain_lf(); - void set_efx_decay_time(); - void set_efx_decay_hf_ratio(); - void set_efx_decay_lf_ratio(); - void set_efx_reflections_gain(); - void set_efx_reflections_delay(); - void set_efx_reflections_pan(); - void set_efx_late_reverb_gain(); - void set_efx_late_reverb_delay(); - void set_efx_late_reverb_pan(); - void set_efx_echo_time(); - void set_efx_echo_depth(); - void set_efx_modulation_time(); - void set_efx_modulation_depth(); - void set_efx_air_absorption_gain_hf(); - void set_efx_hf_reference(); - void set_efx_lf_reference(); - void set_efx_room_rolloff_factor(); - void set_efx_flags(); - void set_efx_defaults(); - - void v1_get(const EaxEaxCall& eax_call) const; - - void get_all(const EaxEaxCall& eax_call) const; - - void get(const EaxEaxCall& eax_call) const; - - static void v1_validate_environment(unsigned long environment); - static void v1_validate_volume(float volume); - static void v1_validate_decay_time(float decay_time); - static void v1_validate_damping(float damping); - static void v1_validate_all(const EAX_REVERBPROPERTIES& all); - - void v1_defer_environment(unsigned long environment); - void v1_defer_volume(float volume); - void v1_defer_decay_time(float decay_time); - void v1_defer_damping(float damping); - void v1_defer_all(const EAX_REVERBPROPERTIES& all); - - void v1_defer_environment(const EaxEaxCall& eax_call); - void v1_defer_volume(const EaxEaxCall& eax_call); - void v1_defer_decay_time(const EaxEaxCall& eax_call); - void v1_defer_damping(const EaxEaxCall& eax_call); - void v1_defer_all(const EaxEaxCall& eax_call); - void v1_defer(const EaxEaxCall& eax_call); - - void v1_set_efx(); - - static void validate_environment(unsigned long ulEnvironment, int version, bool is_standalone); - static void validate_environment_size(float flEnvironmentSize); - static void validate_environment_diffusion(float flEnvironmentDiffusion); - static void validate_room(long lRoom); - static void validate_room_hf(long lRoomHF); - static void validate_room_lf(long lRoomLF); - static void validate_decay_time(float flDecayTime); - static void validate_decay_hf_ratio(float flDecayHFRatio); - static void validate_decay_lf_ratio(float flDecayLFRatio); - static void validate_reflections(long lReflections); - static void validate_reflections_delay(float flReflectionsDelay); - static void validate_reflections_pan(const EAXVECTOR& vReflectionsPan); - static void validate_reverb(long lReverb); - static void validate_reverb_delay(float flReverbDelay); - static void validate_reverb_pan(const EAXVECTOR& vReverbPan); - static void validate_echo_time(float flEchoTime); - static void validate_echo_depth(float flEchoDepth); - static void validate_modulation_time(float flModulationTime); - static void validate_modulation_depth(float flModulationDepth); - static void validate_air_absorbtion_hf(float air_absorbtion_hf); - static void validate_hf_reference(float flHFReference); - static void validate_lf_reference(float flLFReference); - static void validate_room_rolloff_factor(float flRoomRolloffFactor); - static void validate_flags(unsigned long ulFlags); - static void validate_all(const EAX20LISTENERPROPERTIES& all, int version); - static void validate_all(const EAXREVERBPROPERTIES& all, int version); - - void defer_environment(unsigned long ulEnvironment); - void defer_environment_size(float flEnvironmentSize); - void defer_environment_diffusion(float flEnvironmentDiffusion); - void defer_room(long lRoom); - void defer_room_hf(long lRoomHF); - void defer_room_lf(long lRoomLF); - void defer_decay_time(float flDecayTime); - void defer_decay_hf_ratio(float flDecayHFRatio); - void defer_decay_lf_ratio(float flDecayLFRatio); - void defer_reflections(long lReflections); - void defer_reflections_delay(float flReflectionsDelay); - void defer_reflections_pan(const EAXVECTOR& vReflectionsPan); - void defer_reverb(long lReverb); - void defer_reverb_delay(float flReverbDelay); - void defer_reverb_pan(const EAXVECTOR& vReverbPan); - void defer_echo_time(float flEchoTime); - void defer_echo_depth(float flEchoDepth); - void defer_modulation_time(float flModulationTime); - void defer_modulation_depth(float flModulationDepth); - void defer_air_absorbtion_hf(float flAirAbsorptionHF); - void defer_hf_reference(float flHFReference); - void defer_lf_reference(float flLFReference); - void defer_room_rolloff_factor(float flRoomRolloffFactor); - void defer_flags(unsigned long ulFlags); - void defer_all(const EAX20LISTENERPROPERTIES& all); - void defer_all(const EAXREVERBPROPERTIES& all); - - void defer_environment(const EaxEaxCall& eax_call); - void defer_environment_size(const EaxEaxCall& eax_call); - void defer_environment_diffusion(const EaxEaxCall& eax_call); - void defer_room(const EaxEaxCall& eax_call); - void defer_room_hf(const EaxEaxCall& eax_call); - void defer_room_lf(const EaxEaxCall& eax_call); - void defer_decay_time(const EaxEaxCall& eax_call); - void defer_decay_hf_ratio(const EaxEaxCall& eax_call); - void defer_decay_lf_ratio(const EaxEaxCall& eax_call); - void defer_reflections(const EaxEaxCall& eax_call); - void defer_reflections_delay(const EaxEaxCall& eax_call); - void defer_reflections_pan(const EaxEaxCall& eax_call); - void defer_reverb(const EaxEaxCall& eax_call); - void defer_reverb_delay(const EaxEaxCall& eax_call); - void defer_reverb_pan(const EaxEaxCall& eax_call); - void defer_echo_time(const EaxEaxCall& eax_call); - void defer_echo_depth(const EaxEaxCall& eax_call); - void defer_modulation_time(const EaxEaxCall& eax_call); - void defer_modulation_depth(const EaxEaxCall& eax_call); - void defer_air_absorbtion_hf(const EaxEaxCall& eax_call); - void defer_hf_reference(const EaxEaxCall& eax_call); - void defer_lf_reference(const EaxEaxCall& eax_call); - void defer_room_rolloff_factor(const EaxEaxCall& eax_call); - void defer_flags(const EaxEaxCall& eax_call); - void defer_all(const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); -}; // EaxReverbEffect + static constexpr auto initial_room2 = -10'000L; + using Exception = EaxReverbEffectException; -class EaxReverbEffectException : - public EaxException -{ -public: - explicit EaxReverbEffectException( - const char* message) - : - EaxException{"EAX_REVERB_EFFECT", message} + using Props1 = EAX_REVERBPROPERTIES; + using Props2 = EAX20LISTENERPROPERTIES; + using Props3 = EAXREVERBPROPERTIES; + + struct State1 + { + Props1 i; // Immediate. + Props1 d; // Deferred. + }; // State1 + + struct State2 + { + Props2 i; // Immediate. + Props2 d; // Deferred. + }; // State2 + + struct State3 + { + Props3 i; // Immediate. + Props3 d; // Deferred. + }; // State3 + + struct EnvironmentValidator1 { + void operator()(unsigned long ulEnvironment) const + { + eax_validate_range( + "Environment", + ulEnvironment, + EAXREVERB_MINENVIRONMENT, + EAX1REVERB_MAXENVIRONMENT); + } + }; // EnvironmentValidator1 + + struct VolumeValidator { + void operator()(float volume) const + { + eax_validate_range( + "Volume", + volume, + EAX1REVERB_MINVOLUME, + EAX1REVERB_MAXVOLUME); + } + }; // VolumeValidator + + struct DecayTimeValidator { + void operator()(float flDecayTime) const + { + eax_validate_range( + "Decay Time", + flDecayTime, + EAXREVERB_MINDECAYTIME, + EAXREVERB_MAXDECAYTIME); + } + }; // DecayTimeValidator + + struct DampingValidator { + void operator()(float damping) const + { + eax_validate_range( + "Damping", + damping, + EAX1REVERB_MINDAMPING, + EAX1REVERB_MAXDAMPING); + } + }; // DampingValidator + + struct AllValidator1 { + void operator()(const Props1& all) const + { + EnvironmentValidator1{}(all.environment); + VolumeValidator{}(all.fVolume); + DecayTimeValidator{}(all.fDecayTime_sec); + DampingValidator{}(all.fDamping); + } + }; // AllValidator1 + + struct RoomValidator { + void operator()(long lRoom) const + { + eax_validate_range( + "Room", + lRoom, + EAXREVERB_MINROOM, + EAXREVERB_MAXROOM); + } + }; // RoomValidator + + struct RoomHFValidator { + void operator()(long lRoomHF) const + { + eax_validate_range( + "Room HF", + lRoomHF, + EAXREVERB_MINROOMHF, + EAXREVERB_MAXROOMHF); + } + }; // RoomHFValidator + + struct RoomRolloffFactorValidator { + void operator()(float flRoomRolloffFactor) const + { + eax_validate_range( + "Room Rolloff Factor", + flRoomRolloffFactor, + EAXREVERB_MINROOMROLLOFFFACTOR, + EAXREVERB_MAXROOMROLLOFFFACTOR); + } + }; // RoomRolloffFactorValidator + + struct DecayHFRatioValidator { + void operator()(float flDecayHFRatio) const + { + eax_validate_range( + "Decay HF Ratio", + flDecayHFRatio, + EAXREVERB_MINDECAYHFRATIO, + EAXREVERB_MAXDECAYHFRATIO); + } + }; // DecayHFRatioValidator + + struct ReflectionsValidator { + void operator()(long lReflections) const + { + eax_validate_range( + "Reflections", + lReflections, + EAXREVERB_MINREFLECTIONS, + EAXREVERB_MAXREFLECTIONS); + } + }; // ReflectionsValidator + + struct ReflectionsDelayValidator { + void operator()(float flReflectionsDelay) const + { + eax_validate_range( + "Reflections Delay", + flReflectionsDelay, + EAXREVERB_MINREFLECTIONSDELAY, + EAXREVERB_MAXREFLECTIONSDELAY); + } + }; // ReflectionsDelayValidator + + struct ReverbValidator { + void operator()(long lReverb) const + { + eax_validate_range( + "Reverb", + lReverb, + EAXREVERB_MINREVERB, + EAXREVERB_MAXREVERB); + } + }; // ReverbValidator + + struct ReverbDelayValidator { + void operator()(float flReverbDelay) const + { + eax_validate_range( + "Reverb Delay", + flReverbDelay, + EAXREVERB_MINREVERBDELAY, + EAXREVERB_MAXREVERBDELAY); + } + }; // ReverbDelayValidator + + struct EnvironmentSizeValidator { + void operator()(float flEnvironmentSize) const + { + eax_validate_range( + "Environment Size", + flEnvironmentSize, + EAXREVERB_MINENVIRONMENTSIZE, + EAXREVERB_MAXENVIRONMENTSIZE); + } + }; // EnvironmentSizeValidator + + struct EnvironmentDiffusionValidator { + void operator()(float flEnvironmentDiffusion) const + { + eax_validate_range( + "Environment Diffusion", + flEnvironmentDiffusion, + EAXREVERB_MINENVIRONMENTDIFFUSION, + EAXREVERB_MAXENVIRONMENTDIFFUSION); + } + }; // EnvironmentDiffusionValidator + + struct AirAbsorptionHFValidator { + void operator()(float flAirAbsorptionHF) const + { + eax_validate_range( + "Air Absorbtion HF", + flAirAbsorptionHF, + EAXREVERB_MINAIRABSORPTIONHF, + EAXREVERB_MAXAIRABSORPTIONHF); + } + }; // AirAbsorptionHFValidator + + struct FlagsValidator2 { + void operator()(unsigned long ulFlags) const + { + eax_validate_range( + "Flags", + ulFlags, + 0UL, + ~EAX2LISTENERFLAGS_RESERVED); + } + }; // FlagsValidator2 + + struct AllValidator2 { + void operator()(const Props2& all) const + { + RoomValidator{}(all.lRoom); + RoomHFValidator{}(all.lRoomHF); + RoomRolloffFactorValidator{}(all.flRoomRolloffFactor); + DecayTimeValidator{}(all.flDecayTime); + DecayHFRatioValidator{}(all.flDecayHFRatio); + ReflectionsValidator{}(all.lReflections); + ReflectionsDelayValidator{}(all.flReflectionsDelay); + ReverbValidator{}(all.lReverb); + ReverbDelayValidator{}(all.flReverbDelay); + EnvironmentValidator1{}(all.dwEnvironment); + EnvironmentSizeValidator{}(all.flEnvironmentSize); + EnvironmentDiffusionValidator{}(all.flEnvironmentDiffusion); + AirAbsorptionHFValidator{}(all.flAirAbsorptionHF); + FlagsValidator2{}(all.dwFlags); + } + }; // AllValidator2 + + struct EnvironmentValidator3 { + void operator()(unsigned long ulEnvironment) const + { + eax_validate_range( + "Environment", + ulEnvironment, + EAXREVERB_MINENVIRONMENT, + EAX30REVERB_MAXENVIRONMENT); + } + }; // EnvironmentValidator1 + + struct RoomLFValidator { + void operator()(long lRoomLF) const + { + eax_validate_range( + "Room LF", + lRoomLF, + EAXREVERB_MINROOMLF, + EAXREVERB_MAXROOMLF); + } + }; // RoomLFValidator + + struct DecayLFRatioValidator { + void operator()(float flDecayLFRatio) const + { + eax_validate_range( + "Decay LF Ratio", + flDecayLFRatio, + EAXREVERB_MINDECAYLFRATIO, + EAXREVERB_MAXDECAYLFRATIO); + } + }; // DecayLFRatioValidator + + struct VectorValidator { + void operator()(const EAXVECTOR&) const + {} + }; // VectorValidator + + struct EchoTimeValidator { + void operator()(float flEchoTime) const + { + eax_validate_range( + "Echo Time", + flEchoTime, + EAXREVERB_MINECHOTIME, + EAXREVERB_MAXECHOTIME); + } + }; // EchoTimeValidator + + struct EchoDepthValidator { + void operator()(float flEchoDepth) const + { + eax_validate_range( + "Echo Depth", + flEchoDepth, + EAXREVERB_MINECHODEPTH, + EAXREVERB_MAXECHODEPTH); + } + }; // EchoDepthValidator + + struct ModulationTimeValidator { + void operator()(float flModulationTime) const + { + eax_validate_range( + "Modulation Time", + flModulationTime, + EAXREVERB_MINMODULATIONTIME, + EAXREVERB_MAXMODULATIONTIME); + } + }; // ModulationTimeValidator + + struct ModulationDepthValidator { + void operator()(float flModulationDepth) const + { + eax_validate_range( + "Modulation Depth", + flModulationDepth, + EAXREVERB_MINMODULATIONDEPTH, + EAXREVERB_MAXMODULATIONDEPTH); + } + }; // ModulationDepthValidator + + struct HFReferenceValidator { + void operator()(float flHFReference) const + { + eax_validate_range( + "HF Reference", + flHFReference, + EAXREVERB_MINHFREFERENCE, + EAXREVERB_MAXHFREFERENCE); + } + }; // HFReferenceValidator + + struct LFReferenceValidator { + void operator()(float flLFReference) const + { + eax_validate_range( + "LF Reference", + flLFReference, + EAXREVERB_MINLFREFERENCE, + EAXREVERB_MAXLFREFERENCE); + } + }; // LFReferenceValidator + + struct FlagsValidator3 { + void operator()(unsigned long ulFlags) const + { + eax_validate_range( + "Flags", + ulFlags, + 0UL, + ~EAXREVERBFLAGS_RESERVED); + } + }; // FlagsValidator3 + + struct AllValidator3 { + void operator()(const Props3& all) const + { + EnvironmentValidator3{}(all.ulEnvironment); + EnvironmentSizeValidator{}(all.flEnvironmentSize); + EnvironmentDiffusionValidator{}(all.flEnvironmentDiffusion); + RoomValidator{}(all.lRoom); + RoomHFValidator{}(all.lRoomHF); + RoomLFValidator{}(all.lRoomLF); + DecayTimeValidator{}(all.flDecayTime); + DecayHFRatioValidator{}(all.flDecayHFRatio); + DecayLFRatioValidator{}(all.flDecayLFRatio); + ReflectionsValidator{}(all.lReflections); + ReflectionsDelayValidator{}(all.flReflectionsDelay); + VectorValidator{}(all.vReflectionsPan); + ReverbValidator{}(all.lReverb); + ReverbDelayValidator{}(all.flReverbDelay); + VectorValidator{}(all.vReverbPan); + EchoTimeValidator{}(all.flEchoTime); + EchoDepthValidator{}(all.flEchoDepth); + ModulationTimeValidator{}(all.flModulationTime); + ModulationDepthValidator{}(all.flModulationDepth); + AirAbsorptionHFValidator{}(all.flAirAbsorptionHF); + HFReferenceValidator{}(all.flHFReference); + LFReferenceValidator{}(all.flLFReference); + RoomRolloffFactorValidator{}(all.flRoomRolloffFactor); + FlagsValidator3{}(all.ulFlags); + } + }; // AllValidator3 + + struct EnvironmentDeferrer2 { + void operator()(Props2& props, unsigned long dwEnvironment) const + { + props = EAX2REVERB_PRESETS[dwEnvironment]; + } + }; // EnvironmentDeferrer2 + + struct EnvironmentSizeDeferrer2 { + void operator()(Props2& props, float flEnvironmentSize) const + { + if (props.flEnvironmentSize == flEnvironmentSize) + { + return; + } + + const auto scale = flEnvironmentSize / props.flEnvironmentSize; + props.flEnvironmentSize = flEnvironmentSize; + + if ((props.dwFlags & EAX2LISTENERFLAGS_DECAYTIMESCALE) != 0) + { + props.flDecayTime = clamp( + props.flDecayTime * scale, + EAXREVERB_MINDECAYTIME, + EAXREVERB_MAXDECAYTIME); + } + + if ((props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSSCALE) != 0 && + (props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE) != 0) + { + props.lReflections = clamp( + props.lReflections - static_cast(gain_to_level_mb(scale)), + EAXREVERB_MINREFLECTIONS, + EAXREVERB_MAXREFLECTIONS); + } + + if ((props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE) != 0) + { + props.flReflectionsDelay = clamp( + props.flReflectionsDelay * scale, + EAXREVERB_MINREFLECTIONSDELAY, + EAXREVERB_MAXREFLECTIONSDELAY); + } + + if ((props.dwFlags & EAX2LISTENERFLAGS_REVERBSCALE) != 0) + { + const auto log_scalar = ((props.dwFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F; + + props.lReverb = clamp( + props.lReverb - static_cast(std::log10(scale) * log_scalar), + EAXREVERB_MINREVERB, + EAXREVERB_MAXREVERB); + } + + if ((props.dwFlags & EAX2LISTENERFLAGS_REVERBDELAYSCALE) != 0) + { + props.flReverbDelay = clamp( + props.flReverbDelay * scale, + EAXREVERB_MINREVERBDELAY, + EAXREVERB_MAXREVERBDELAY); + } + } + }; // EnvironmentSizeDeferrer2 + + struct EnvironmentDeferrer3 { + void operator()(Props3& props, unsigned long ulEnvironment) const + { + if (ulEnvironment == EAX_ENVIRONMENT_UNDEFINED) + { + props.ulEnvironment = EAX_ENVIRONMENT_UNDEFINED; + return; + } + + props = EAXREVERB_PRESETS[ulEnvironment]; + } + }; // EnvironmentDeferrer3 + + struct EnvironmentSizeDeferrer3 { + void operator()(Props3& props, float flEnvironmentSize) const + { + if (props.flEnvironmentSize == flEnvironmentSize) + { + return; + } + + const auto scale = flEnvironmentSize / props.flEnvironmentSize; + props.ulEnvironment = EAX_ENVIRONMENT_UNDEFINED; + props.flEnvironmentSize = flEnvironmentSize; + + if ((props.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) + { + props.flDecayTime = clamp( + props.flDecayTime * scale, + EAXREVERB_MINDECAYTIME, + EAXREVERB_MAXDECAYTIME); + } + + if ((props.ulFlags & EAXREVERBFLAGS_REFLECTIONSSCALE) != 0 && + (props.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0) + { + props.lReflections = clamp( + props.lReflections - static_cast(gain_to_level_mb(scale)), + EAXREVERB_MINREFLECTIONS, + EAXREVERB_MAXREFLECTIONS); + } + + if ((props.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0) + { + props.flReflectionsDelay = clamp( + props.flReflectionsDelay * scale, + EAXREVERB_MINREFLECTIONSDELAY, + EAXREVERB_MAXREFLECTIONSDELAY); + } + + if ((props.ulFlags & EAXREVERBFLAGS_REVERBSCALE) != 0) + { + const auto log_scalar = ((props.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F; + props.lReverb = clamp( + props.lReverb - static_cast(std::log10(scale) * log_scalar), + EAXREVERB_MINREVERB, + EAXREVERB_MAXREVERB); + } + + if ((props.ulFlags & EAXREVERBFLAGS_REVERBDELAYSCALE) != 0) + { + props.flReverbDelay = clamp( + props.flReverbDelay * scale, + EAXREVERB_MINREVERBDELAY, + EAXREVERB_MAXREVERBDELAY); + } + + if ((props.ulFlags & EAXREVERBFLAGS_ECHOTIMESCALE) != 0) + { + props.flEchoTime = clamp( + props.flEchoTime * scale, + EAXREVERB_MINECHOTIME, + EAXREVERB_MAXECHOTIME); + } + + if ((props.ulFlags & EAXREVERBFLAGS_MODULATIONTIMESCALE) != 0) + { + props.flModulationTime = clamp( + props.flModulationTime * scale, + EAXREVERB_MINMODULATIONTIME, + EAXREVERB_MAXMODULATIONTIME); + } + } + }; // EnvironmentSizeDeferrer3 + + int version_; + Props3 props_{}; + State1 state1_{}; + State2 state2_{}; + State3 state3_{}; + State3 state4_{}; + State3 state5_{}; + + [[noreturn]] static void fail(const char* message); + [[noreturn]] static void fail_unknown_property_id(); + [[noreturn]] static void fail_unknown_version(); + + static void set_defaults(State1& state) noexcept; + static void set_defaults(State2& state) noexcept; + static void set_defaults(State3& state) noexcept; + void set_defaults() noexcept; + + void set_current_defaults(); + + void set_efx_density_from_environment_size() noexcept; + void set_efx_diffusion() noexcept; + void set_efx_gain() noexcept; + void set_efx_gain_hf() noexcept; + void set_efx_gain_lf() noexcept; + void set_efx_decay_time() noexcept; + void set_efx_decay_hf_ratio() noexcept; + void set_efx_decay_lf_ratio() noexcept; + void set_efx_reflections_gain() noexcept; + void set_efx_reflections_delay() noexcept; + void set_efx_reflections_pan() noexcept; + void set_efx_late_reverb_gain() noexcept; + void set_efx_late_reverb_delay() noexcept; + void set_efx_late_reverb_pan() noexcept; + void set_efx_echo_time() noexcept; + void set_efx_echo_depth() noexcept; + void set_efx_modulation_time() noexcept; + void set_efx_modulation_depth() noexcept; + void set_efx_air_absorption_gain_hf() noexcept; + void set_efx_hf_reference() noexcept; + void set_efx_lf_reference() noexcept; + void set_efx_room_rolloff_factor() noexcept; + void set_efx_flags() noexcept; + void set_efx_defaults() noexcept; + + static void get1(const EaxCall& call, const Props1& props); + static void get2(const EaxCall& call, const Props2& props); + static void get3(const EaxCall& call, const Props3& props); + void get(const EaxCall& call); + + template + static void defer(const EaxCall& call, TProperty& property) { + const auto& value = call.get_value(); + TValidator{}(value); + property = value; + } + + template + static void defer(const EaxCall& call, TProperties& properties, TProperty&) + { + const auto& value = call.get_value(); + TValidator{}(value); + TDeferrer{}(properties, value); } -}; // EaxReverbEffectException + template + static void defer3(const EaxCall& call, Props3& properties, TProperty& property) + { + const auto& value = call.get_value(); + TValidator{}(value); + if (value == property) + return; + property = value; + properties.ulEnvironment = EAX_ENVIRONMENT_UNDEFINED; + } + + static void set1(const EaxCall& call, Props1& props); + static void set2(const EaxCall& call, Props2& props); + static void set3(const EaxCall& call, Props3& props); + void set(const EaxCall& call); + + static void translate(const Props1& src, Props3& dst) noexcept; + static void translate(const Props2& src, Props3& dst) noexcept; +}; // EaxReverbEffect -EaxReverbEffect::EaxReverbEffect() - : EaxEffect{AL_EFFECT_EAXREVERB} +EaxReverbEffect::EaxReverbEffect(const EaxCall& call) noexcept + : EaxEffect{AL_EFFECT_EAXREVERB}, version_{call.get_version()} { - set_eax_defaults(); + set_defaults(); + set_current_defaults(); set_efx_defaults(); } -void EaxReverbEffect::dispatch(const EaxEaxCall& eax_call) +void EaxReverbEffect::dispatch(const EaxCall& call) +{ + call.is_get() ? get(call) : set(call); +} + +[[noreturn]] void EaxReverbEffect::fail(const char* message) +{ + throw Exception{message}; +} + +[[noreturn]] void EaxReverbEffect::fail_unknown_property_id() +{ + fail(EaxEffectErrorMessages::unknown_property_id()); +} + +[[noreturn]] void EaxReverbEffect::fail_unknown_version() +{ + fail(EaxEffectErrorMessages::unknown_version()); +} + +void EaxReverbEffect::set_defaults(State1& state) noexcept +{ + state.i = EAX1REVERB_PRESETS[EAX_ENVIRONMENT_GENERIC]; + state.d = state.i; +} + +void EaxReverbEffect::set_defaults(State2& state) noexcept { - eax_call.is_get() ? get(eax_call) : set(eax_call); + state.i = EAX2REVERB_PRESETS[EAX2_ENVIRONMENT_GENERIC]; + state.i.lRoom = initial_room2; + state.d = state.i; } -[[noreturn]] void EaxReverbEffect::eax_fail(const char* message) +void EaxReverbEffect::set_defaults(State3& state) noexcept { - throw EaxReverbEffectException{message}; + state.i = EAXREVERB_PRESETS[EAX_ENVIRONMENT_GENERIC]; + state.d = state.i; } -void EaxReverbEffect::set_eax_defaults() +void EaxReverbEffect::set_defaults() noexcept { - eax1_ = EAX1REVERB_PRESETS[EAX_ENVIRONMENT_GENERIC]; - eax1_d_ = eax1_; - eax_ = EAXREVERB_PRESETS[EAX_ENVIRONMENT_GENERIC]; - /* HACK: EAX2 has a default room volume of -10,000dB (silence), although - * newer versions use -1,000dB. What should be happening is properties for - * each EAX version is tracked separately, with the last version used for - * the properties to apply (presumably v2 or nothing being the default). - */ - eax_.lRoom = EAXREVERB_MINROOM; - eax_d_ = eax_; + set_defaults(state1_); + set_defaults(state2_); + set_defaults(state3_); + state4_ = state3_; + state5_ = state3_; } -void EaxReverbEffect::set_efx_density_from_environment_size() +void EaxReverbEffect::set_current_defaults() { - const auto eax_environment_size = eax_.flEnvironmentSize; + switch (version_) + { + case 1: translate(state1_.i, props_); break; + case 2: translate(state2_.i, props_); break; + case 3: props_ = state3_.i; break; + case 4: props_ = state4_.i; break; + case 5: props_ = state5_.i; break; + default: fail_unknown_version(); + } +} - const auto efx_density = clamp( - (eax_environment_size * eax_environment_size * eax_environment_size) / 16.0F, +void EaxReverbEffect::set_efx_density_from_environment_size() noexcept +{ + const auto size = props_.flEnvironmentSize; + const auto density = (size * size * size) / 16.0F; + al_effect_props_.Reverb.Density = clamp( + density, AL_EAXREVERB_MIN_DENSITY, AL_EAXREVERB_MAX_DENSITY); - - al_effect_props_.Reverb.Density = efx_density; } -void EaxReverbEffect::set_efx_diffusion() +void EaxReverbEffect::set_efx_diffusion() noexcept { - const auto efx_diffusion = clamp( - eax_.flEnvironmentDiffusion, + al_effect_props_.Reverb.Diffusion = clamp( + props_.flEnvironmentDiffusion, AL_EAXREVERB_MIN_DIFFUSION, AL_EAXREVERB_MAX_DIFFUSION); - - al_effect_props_.Reverb.Diffusion = efx_diffusion; } -void EaxReverbEffect::set_efx_gain() +void EaxReverbEffect::set_efx_gain() noexcept { - const auto efx_gain = clamp( - level_mb_to_gain(static_cast(eax_.lRoom)), + al_effect_props_.Reverb.Gain = clamp( + level_mb_to_gain(static_cast(props_.lRoom)), AL_EAXREVERB_MIN_GAIN, AL_EAXREVERB_MAX_GAIN); - - al_effect_props_.Reverb.Gain = efx_gain; } -void EaxReverbEffect::set_efx_gain_hf() +void EaxReverbEffect::set_efx_gain_hf() noexcept { - const auto efx_gain_hf = clamp( - level_mb_to_gain(static_cast(eax_.lRoomHF)), + al_effect_props_.Reverb.GainHF = clamp( + level_mb_to_gain(static_cast(props_.lRoomHF)), AL_EAXREVERB_MIN_GAINHF, AL_EAXREVERB_MAX_GAINHF); - - al_effect_props_.Reverb.GainHF = efx_gain_hf; } -void EaxReverbEffect::set_efx_gain_lf() +void EaxReverbEffect::set_efx_gain_lf() noexcept { - const auto efx_gain_lf = clamp( - level_mb_to_gain(static_cast(eax_.lRoomLF)), + al_effect_props_.Reverb.GainLF = clamp( + level_mb_to_gain(static_cast(props_.lRoomLF)), AL_EAXREVERB_MIN_GAINLF, AL_EAXREVERB_MAX_GAINLF); - - al_effect_props_.Reverb.GainLF = efx_gain_lf; } -void EaxReverbEffect::set_efx_decay_time() +void EaxReverbEffect::set_efx_decay_time() noexcept { - const auto efx_decay_time = clamp( - eax_.flDecayTime, + al_effect_props_.Reverb.DecayTime = clamp( + props_.flDecayTime, AL_EAXREVERB_MIN_DECAY_TIME, AL_EAXREVERB_MAX_DECAY_TIME); - - al_effect_props_.Reverb.DecayTime = efx_decay_time; } -void EaxReverbEffect::set_efx_decay_hf_ratio() +void EaxReverbEffect::set_efx_decay_hf_ratio() noexcept { - const auto efx_decay_hf_ratio = clamp( - eax_.flDecayHFRatio, + al_effect_props_.Reverb.DecayHFRatio = clamp( + props_.flDecayHFRatio, AL_EAXREVERB_MIN_DECAY_HFRATIO, AL_EAXREVERB_MAX_DECAY_HFRATIO); - - al_effect_props_.Reverb.DecayHFRatio = efx_decay_hf_ratio; } -void EaxReverbEffect::set_efx_decay_lf_ratio() +void EaxReverbEffect::set_efx_decay_lf_ratio() noexcept { - const auto efx_decay_lf_ratio = clamp( - eax_.flDecayLFRatio, + al_effect_props_.Reverb.DecayLFRatio = clamp( + props_.flDecayLFRatio, AL_EAXREVERB_MIN_DECAY_LFRATIO, AL_EAXREVERB_MAX_DECAY_LFRATIO); - - al_effect_props_.Reverb.DecayLFRatio = efx_decay_lf_ratio; } -void EaxReverbEffect::set_efx_reflections_gain() +void EaxReverbEffect::set_efx_reflections_gain() noexcept { - const auto efx_reflections_gain = clamp( - level_mb_to_gain(static_cast(eax_.lReflections)), + al_effect_props_.Reverb.ReflectionsGain = clamp( + level_mb_to_gain(static_cast(props_.lReflections)), AL_EAXREVERB_MIN_REFLECTIONS_GAIN, AL_EAXREVERB_MAX_REFLECTIONS_GAIN); - - al_effect_props_.Reverb.ReflectionsGain = efx_reflections_gain; } -void EaxReverbEffect::set_efx_reflections_delay() +void EaxReverbEffect::set_efx_reflections_delay() noexcept { - const auto efx_reflections_delay = clamp( - eax_.flReflectionsDelay, + al_effect_props_.Reverb.ReflectionsDelay = clamp( + props_.flReflectionsDelay, AL_EAXREVERB_MIN_REFLECTIONS_DELAY, AL_EAXREVERB_MAX_REFLECTIONS_DELAY); - - al_effect_props_.Reverb.ReflectionsDelay = efx_reflections_delay; } -void EaxReverbEffect::set_efx_reflections_pan() +void EaxReverbEffect::set_efx_reflections_pan() noexcept { - al_effect_props_.Reverb.ReflectionsPan[0] = eax_.vReflectionsPan.x; - al_effect_props_.Reverb.ReflectionsPan[1] = eax_.vReflectionsPan.y; - al_effect_props_.Reverb.ReflectionsPan[2] = eax_.vReflectionsPan.z; + al_effect_props_.Reverb.ReflectionsPan[0] = props_.vReflectionsPan.x; + al_effect_props_.Reverb.ReflectionsPan[1] = props_.vReflectionsPan.y; + al_effect_props_.Reverb.ReflectionsPan[2] = props_.vReflectionsPan.z; } -void EaxReverbEffect::set_efx_late_reverb_gain() +void EaxReverbEffect::set_efx_late_reverb_gain() noexcept { - const auto efx_late_reverb_gain = clamp( - level_mb_to_gain(static_cast(eax_.lReverb)), + al_effect_props_.Reverb.LateReverbGain = clamp( + level_mb_to_gain(static_cast(props_.lReverb)), AL_EAXREVERB_MIN_LATE_REVERB_GAIN, AL_EAXREVERB_MAX_LATE_REVERB_GAIN); - - al_effect_props_.Reverb.LateReverbGain = efx_late_reverb_gain; } -void EaxReverbEffect::set_efx_late_reverb_delay() +void EaxReverbEffect::set_efx_late_reverb_delay() noexcept { - const auto efx_late_reverb_delay = clamp( - eax_.flReverbDelay, + al_effect_props_.Reverb.LateReverbDelay = clamp( + props_.flReverbDelay, AL_EAXREVERB_MIN_LATE_REVERB_DELAY, AL_EAXREVERB_MAX_LATE_REVERB_DELAY); - - al_effect_props_.Reverb.LateReverbDelay = efx_late_reverb_delay; } -void EaxReverbEffect::set_efx_late_reverb_pan() +void EaxReverbEffect::set_efx_late_reverb_pan() noexcept { - al_effect_props_.Reverb.LateReverbPan[0] = eax_.vReverbPan.x; - al_effect_props_.Reverb.LateReverbPan[1] = eax_.vReverbPan.y; - al_effect_props_.Reverb.LateReverbPan[2] = eax_.vReverbPan.z; + al_effect_props_.Reverb.LateReverbPan[0] = props_.vReverbPan.x; + al_effect_props_.Reverb.LateReverbPan[1] = props_.vReverbPan.y; + al_effect_props_.Reverb.LateReverbPan[2] = props_.vReverbPan.z; } -void EaxReverbEffect::set_efx_echo_time() +void EaxReverbEffect::set_efx_echo_time() noexcept { - const auto efx_echo_time = clamp( - eax_.flEchoTime, + al_effect_props_.Reverb.EchoTime = clamp( + props_.flEchoTime, AL_EAXREVERB_MIN_ECHO_TIME, AL_EAXREVERB_MAX_ECHO_TIME); - - al_effect_props_.Reverb.EchoTime = efx_echo_time; } -void EaxReverbEffect::set_efx_echo_depth() +void EaxReverbEffect::set_efx_echo_depth() noexcept { - const auto efx_echo_depth = clamp( - eax_.flEchoDepth, + al_effect_props_.Reverb.EchoDepth = clamp( + props_.flEchoDepth, AL_EAXREVERB_MIN_ECHO_DEPTH, AL_EAXREVERB_MAX_ECHO_DEPTH); - - al_effect_props_.Reverb.EchoDepth = efx_echo_depth; } -void EaxReverbEffect::set_efx_modulation_time() +void EaxReverbEffect::set_efx_modulation_time() noexcept { - const auto efx_modulation_time = clamp( - eax_.flModulationTime, + al_effect_props_.Reverb.ModulationTime = clamp( + props_.flModulationTime, AL_EAXREVERB_MIN_MODULATION_TIME, AL_EAXREVERB_MAX_MODULATION_TIME); - - al_effect_props_.Reverb.ModulationTime = efx_modulation_time; } -void EaxReverbEffect::set_efx_modulation_depth() +void EaxReverbEffect::set_efx_modulation_depth() noexcept { - const auto efx_modulation_depth = clamp( - eax_.flModulationDepth, + al_effect_props_.Reverb.ModulationDepth = clamp( + props_.flModulationDepth, AL_EAXREVERB_MIN_MODULATION_DEPTH, AL_EAXREVERB_MAX_MODULATION_DEPTH); - - al_effect_props_.Reverb.ModulationDepth = efx_modulation_depth; } -void EaxReverbEffect::set_efx_air_absorption_gain_hf() +void EaxReverbEffect::set_efx_air_absorption_gain_hf() noexcept { - const auto efx_air_absorption_hf = clamp( - level_mb_to_gain(eax_.flAirAbsorptionHF), + al_effect_props_.Reverb.AirAbsorptionGainHF = clamp( + level_mb_to_gain(props_.flAirAbsorptionHF), AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF, AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF); - - al_effect_props_.Reverb.AirAbsorptionGainHF = efx_air_absorption_hf; } -void EaxReverbEffect::set_efx_hf_reference() +void EaxReverbEffect::set_efx_hf_reference() noexcept { - const auto efx_hf_reference = clamp( - eax_.flHFReference, + al_effect_props_.Reverb.HFReference = clamp( + props_.flHFReference, AL_EAXREVERB_MIN_HFREFERENCE, AL_EAXREVERB_MAX_HFREFERENCE); - - al_effect_props_.Reverb.HFReference = efx_hf_reference; } -void EaxReverbEffect::set_efx_lf_reference() +void EaxReverbEffect::set_efx_lf_reference() noexcept { - const auto efx_lf_reference = clamp( - eax_.flLFReference, + al_effect_props_.Reverb.LFReference = clamp( + props_.flLFReference, AL_EAXREVERB_MIN_LFREFERENCE, AL_EAXREVERB_MAX_LFREFERENCE); - - al_effect_props_.Reverb.LFReference = efx_lf_reference; } -void EaxReverbEffect::set_efx_room_rolloff_factor() +void EaxReverbEffect::set_efx_room_rolloff_factor() noexcept { - const auto efx_room_rolloff_factor = clamp( - eax_.flRoomRolloffFactor, + al_effect_props_.Reverb.RoomRolloffFactor = clamp( + props_.flRoomRolloffFactor, AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR, AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR); - - al_effect_props_.Reverb.RoomRolloffFactor = efx_room_rolloff_factor; } -void EaxReverbEffect::set_efx_flags() +void EaxReverbEffect::set_efx_flags() noexcept { - al_effect_props_.Reverb.DecayHFLimit = ((eax_.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0); + al_effect_props_.Reverb.DecayHFLimit = ((props_.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0); } -void EaxReverbEffect::set_efx_defaults() +void EaxReverbEffect::set_efx_defaults() noexcept { set_efx_density_from_environment_size(); set_efx_diffusion(); @@ -1064,1482 +1470,536 @@ void EaxReverbEffect::set_efx_defaults() set_efx_flags(); } -void EaxReverbEffect::v1_get(const EaxEaxCall& eax_call) const +void EaxReverbEffect::get1(const EaxCall& call, const Props1& props) { - switch(eax_call.get_property_id()) + switch(call.get_property_id()) { - case DSPROPERTY_EAX_ALL: - eax_call.set_value(eax1_); - break; - - case DSPROPERTY_EAX_ENVIRONMENT: - eax_call.set_value(eax1_.environment); - break; - - case DSPROPERTY_EAX_VOLUME: - eax_call.set_value(eax1_.fVolume); - break; - - case DSPROPERTY_EAX_DECAYTIME: - eax_call.set_value(eax1_.fDecayTime_sec); - break; - - case DSPROPERTY_EAX_DAMPING: - eax_call.set_value(eax1_.fDamping); - break; - - default: - eax_fail("Unsupported property id."); + case DSPROPERTY_EAX_ALL: call.set_value(props); break; + case DSPROPERTY_EAX_ENVIRONMENT: call.set_value(props.environment); break; + case DSPROPERTY_EAX_VOLUME: call.set_value(props.fVolume); break; + case DSPROPERTY_EAX_DECAYTIME: call.set_value(props.fDecayTime_sec); break; + case DSPROPERTY_EAX_DAMPING: call.set_value(props.fDamping); break; + default: fail_unknown_property_id(); } } -void EaxReverbEffect::get_all( - const EaxEaxCall& eax_call) const +void EaxReverbEffect::get2(const EaxCall& call, const Props2& props) { - if (eax_call.get_version() == 2) + switch(call.get_property_id()) { - auto& eax_reverb = eax_call.get_value(); - eax_reverb.lRoom = eax_.lRoom; - eax_reverb.lRoomHF = eax_.lRoomHF; - eax_reverb.flRoomRolloffFactor = eax_.flRoomRolloffFactor; - eax_reverb.flDecayTime = eax_.flDecayTime; - eax_reverb.flDecayHFRatio = eax_.flDecayHFRatio; - eax_reverb.lReflections = eax_.lReflections; - eax_reverb.flReflectionsDelay = eax_.flReflectionsDelay; - eax_reverb.lReverb = eax_.lReverb; - eax_reverb.flReverbDelay = eax_.flReverbDelay; - eax_reverb.dwEnvironment = eax_.ulEnvironment; - eax_reverb.flEnvironmentSize = eax_.flEnvironmentSize; - eax_reverb.flEnvironmentDiffusion = eax_.flEnvironmentDiffusion; - eax_reverb.flAirAbsorptionHF = eax_.flAirAbsorptionHF; - eax_reverb.dwFlags = eax_.ulFlags; + case DSPROPERTY_EAX20LISTENER_NONE: break; + case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: call.set_value(props); break; + case DSPROPERTY_EAX20LISTENER_ROOM: call.set_value(props.lRoom); break; + case DSPROPERTY_EAX20LISTENER_ROOMHF: call.set_value(props.lRoomHF); break; + case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: call.set_value(props.flRoomRolloffFactor); break; + case DSPROPERTY_EAX20LISTENER_DECAYTIME: call.set_value(props.flDecayTime); break; + case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: call.set_value(props.flDecayHFRatio); break; + case DSPROPERTY_EAX20LISTENER_REFLECTIONS: call.set_value(props.lReflections); break; + case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: call.set_value(props.flReverbDelay); break; + case DSPROPERTY_EAX20LISTENER_REVERB: call.set_value(props.lReverb); break; + case DSPROPERTY_EAX20LISTENER_REVERBDELAY: call.set_value(props.flReverbDelay); break; + case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: call.set_value(props.dwEnvironment); break; + case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE: call.set_value(props.flEnvironmentSize); break; + case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION: call.set_value(props.flEnvironmentDiffusion); break; + case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: call.set_value(props.flAirAbsorptionHF); break; + case DSPROPERTY_EAX20LISTENER_FLAGS: call.set_value(props.dwFlags); break; + default: fail_unknown_property_id(); } - else +} + +void EaxReverbEffect::get3(const EaxCall& call, const Props3& props) +{ + switch(call.get_property_id()) { - eax_call.set_value(eax_); + case EAXREVERB_NONE: break; + case EAXREVERB_ALLPARAMETERS: call.set_value(props); break; + case EAXREVERB_ENVIRONMENT: call.set_value(props.ulEnvironment); break; + case EAXREVERB_ENVIRONMENTSIZE: call.set_value(props.flEnvironmentSize); break; + case EAXREVERB_ENVIRONMENTDIFFUSION: call.set_value(props.flEnvironmentDiffusion); break; + case EAXREVERB_ROOM: call.set_value(props.lRoom); break; + case EAXREVERB_ROOMHF: call.set_value(props.lRoomHF); break; + case EAXREVERB_ROOMLF: call.set_value(props.lRoomLF); break; + case EAXREVERB_DECAYTIME: call.set_value(props.flDecayTime); break; + case EAXREVERB_DECAYHFRATIO: call.set_value(props.flDecayHFRatio); break; + case EAXREVERB_DECAYLFRATIO: call.set_value(props.flDecayLFRatio); break; + case EAXREVERB_REFLECTIONS: call.set_value(props.lReflections); break; + case EAXREVERB_REFLECTIONSDELAY: call.set_value(props.flReflectionsDelay); break; + case EAXREVERB_REFLECTIONSPAN: call.set_value(props.vReflectionsPan); break; + case EAXREVERB_REVERB: call.set_value(props.lReverb); break; + case EAXREVERB_REVERBDELAY: call.set_value(props.flReverbDelay); break; + case EAXREVERB_REVERBPAN: call.set_value(props.vReverbPan); break; + case EAXREVERB_ECHOTIME: call.set_value(props.flEchoTime); break; + case EAXREVERB_ECHODEPTH: call.set_value(props.flEchoDepth); break; + case EAXREVERB_MODULATIONTIME: call.set_value(props.flModulationTime); break; + case EAXREVERB_MODULATIONDEPTH: call.set_value(props.flModulationDepth); break; + case EAXREVERB_AIRABSORPTIONHF: call.set_value(props.flAirAbsorptionHF); break; + case EAXREVERB_HFREFERENCE: call.set_value(props.flHFReference); break; + case EAXREVERB_LFREFERENCE: call.set_value(props.flLFReference); break; + case EAXREVERB_ROOMROLLOFFFACTOR: call.set_value(props.flRoomRolloffFactor); break; + case EAXREVERB_FLAGS: call.set_value(props.ulFlags); break; + default: fail_unknown_property_id(); } } -void EaxReverbEffect::get(const EaxEaxCall& eax_call) const +void EaxReverbEffect::get(const EaxCall& call) { - if(eax_call.get_version() == 1) - v1_get(eax_call); - else switch(eax_call.get_property_id()) - { - case EAXREVERB_NONE: - break; + const auto version = call.get_version(); - case EAXREVERB_ALLPARAMETERS: - get_all(eax_call); - break; + switch (version) + { + case 1: get1(call, state1_.i); break; + case 2: get2(call, state2_.i); break; + case 3: get3(call, state3_.i); break; + case 4: get3(call, state4_.i); break; + case 5: get3(call, state5_.i); break; + default: fail_unknown_version(); + } - case EAXREVERB_ENVIRONMENT: - eax_call.set_value(eax_.ulEnvironment); - break; + version_ = version; +} - case EAXREVERB_ENVIRONMENTSIZE: - eax_call.set_value(eax_.flEnvironmentSize); - break; +/*[[nodiscard]]*/ bool EaxReverbEffect::commit() +{ + if ((version_ == 1 && state1_.i == state1_.d) || + (version_ == 2 && state2_.i == state2_.d)) + { + return false; + } - case EAXREVERB_ENVIRONMENTDIFFUSION: - eax_call.set_value(eax_.flEnvironmentDiffusion); - break; + const auto props = props_; - case EAXREVERB_ROOM: - eax_call.set_value(eax_.lRoom); + switch (version_) + { + case 1: + state1_.i = state1_.d; + translate(state1_.d, props_); break; - case EAXREVERB_ROOMHF: - eax_call.set_value(eax_.lRoomHF); + case 2: + state2_.i = state2_.d; + translate(state2_.d, props_); break; - case EAXREVERB_ROOMLF: - eax_call.set_value(eax_.lRoomLF); + case 3: + state3_.i = state3_.d; + props_ = state3_.d; break; - case EAXREVERB_DECAYTIME: - eax_call.set_value(eax_.flDecayTime); + case 4: + state4_.i = state4_.d; + props_ = state4_.d; break; - case EAXREVERB_DECAYHFRATIO: - eax_call.set_value(eax_.flDecayHFRatio); + case 5: + state5_.i = state5_.d; + props_ = state5_.d; break; - case EAXREVERB_DECAYLFRATIO: - eax_call.set_value(eax_.flDecayLFRatio); - break; + default: + fail_unknown_version(); + } - case EAXREVERB_REFLECTIONS: - eax_call.set_value(eax_.lReflections); - break; + auto is_dirty = false; - case EAXREVERB_REFLECTIONSDELAY: - eax_call.set_value(eax_.flReflectionsDelay); - break; + if (props_.flEnvironmentSize != props.flEnvironmentSize) + { + is_dirty = true; + set_efx_density_from_environment_size(); + } - case EAXREVERB_REFLECTIONSPAN: - eax_call.set_value(eax_.vReflectionsPan); - break; + if (props_.flEnvironmentDiffusion != props.flEnvironmentDiffusion) + { + is_dirty = true; + set_efx_diffusion(); + } - case EAXREVERB_REVERB: - eax_call.set_value(eax_.lReverb); - break; + if (props_.lRoom != props.lRoom) + { + is_dirty = true; + set_efx_gain(); + } - case EAXREVERB_REVERBDELAY: - eax_call.set_value(eax_.flReverbDelay); - break; + if (props_.lRoomHF != props.lRoomHF) + { + is_dirty = true; + set_efx_gain_hf(); + } - case EAXREVERB_REVERBPAN: - eax_call.set_value(eax_.vReverbPan); - break; + if (props_.lRoomLF != props.lRoomLF) + { + is_dirty = true; + set_efx_gain_lf(); + } - case EAXREVERB_ECHOTIME: - eax_call.set_value(eax_.flEchoTime); - break; + if (props_.flDecayTime != props.flDecayTime) + { + is_dirty = true; + set_efx_decay_time(); + } - case EAXREVERB_ECHODEPTH: - eax_call.set_value(eax_.flEchoDepth); - break; + if (props_.flDecayHFRatio != props.flDecayHFRatio) + { + is_dirty = true; + set_efx_decay_hf_ratio(); + } - case EAXREVERB_MODULATIONTIME: - eax_call.set_value(eax_.flModulationTime); - break; + if (props_.flDecayLFRatio != props.flDecayLFRatio) + { + is_dirty = true; + set_efx_decay_lf_ratio(); + } - case EAXREVERB_MODULATIONDEPTH: - eax_call.set_value(eax_.flModulationDepth); - break; - - case EAXREVERB_AIRABSORPTIONHF: - eax_call.set_value(eax_.flAirAbsorptionHF); - break; - - case EAXREVERB_HFREFERENCE: - eax_call.set_value(eax_.flHFReference); - break; - - case EAXREVERB_LFREFERENCE: - eax_call.set_value(eax_.flLFReference); - break; - - case EAXREVERB_ROOMROLLOFFFACTOR: - eax_call.set_value(eax_.flRoomRolloffFactor); - break; - - case EAXREVERB_FLAGS: - eax_call.set_value(eax_.ulFlags); - break; - - default: - eax_fail("Unsupported property id."); - } -} - -void EaxReverbEffect::v1_validate_environment(unsigned long environment) -{ - validate_environment(environment, 1, true); -} - -void EaxReverbEffect::v1_validate_volume(float volume) -{ - eax_validate_range("Volume", volume, EAX1REVERB_MINVOLUME, EAX1REVERB_MAXVOLUME); -} - -void EaxReverbEffect::v1_validate_decay_time(float decay_time) -{ - validate_decay_time(decay_time); -} - -void EaxReverbEffect::v1_validate_damping(float damping) -{ - eax_validate_range("Damping", damping, EAX1REVERB_MINDAMPING, EAX1REVERB_MAXDAMPING); -} - -void EaxReverbEffect::v1_validate_all(const EAX_REVERBPROPERTIES& all) -{ - v1_validate_environment(all.environment); - v1_validate_volume(all.fVolume); - v1_validate_decay_time(all.fDecayTime_sec); - v1_validate_damping(all.fDamping); -} - -void EaxReverbEffect::validate_environment( - unsigned long ulEnvironment, - int version, - bool is_standalone) -{ - eax_validate_range( - "Environment", - ulEnvironment, - EAXREVERB_MINENVIRONMENT, - (version <= 2 || is_standalone) ? EAX1REVERB_MAXENVIRONMENT : EAX30REVERB_MAXENVIRONMENT); -} - -void EaxReverbEffect::validate_environment_size( - float flEnvironmentSize) -{ - eax_validate_range( - "Environment Size", - flEnvironmentSize, - EAXREVERB_MINENVIRONMENTSIZE, - EAXREVERB_MAXENVIRONMENTSIZE); -} - -void EaxReverbEffect::validate_environment_diffusion( - float flEnvironmentDiffusion) -{ - eax_validate_range( - "Environment Diffusion", - flEnvironmentDiffusion, - EAXREVERB_MINENVIRONMENTDIFFUSION, - EAXREVERB_MAXENVIRONMENTDIFFUSION); -} - -void EaxReverbEffect::validate_room( - long lRoom) -{ - eax_validate_range( - "Room", - lRoom, - EAXREVERB_MINROOM, - EAXREVERB_MAXROOM); -} - -void EaxReverbEffect::validate_room_hf( - long lRoomHF) -{ - eax_validate_range( - "Room HF", - lRoomHF, - EAXREVERB_MINROOMHF, - EAXREVERB_MAXROOMHF); -} - -void EaxReverbEffect::validate_room_lf( - long lRoomLF) -{ - eax_validate_range( - "Room LF", - lRoomLF, - EAXREVERB_MINROOMLF, - EAXREVERB_MAXROOMLF); -} - -void EaxReverbEffect::validate_decay_time( - float flDecayTime) -{ - eax_validate_range( - "Decay Time", - flDecayTime, - EAXREVERB_MINDECAYTIME, - EAXREVERB_MAXDECAYTIME); -} - -void EaxReverbEffect::validate_decay_hf_ratio( - float flDecayHFRatio) -{ - eax_validate_range( - "Decay HF Ratio", - flDecayHFRatio, - EAXREVERB_MINDECAYHFRATIO, - EAXREVERB_MAXDECAYHFRATIO); -} - -void EaxReverbEffect::validate_decay_lf_ratio( - float flDecayLFRatio) -{ - eax_validate_range( - "Decay LF Ratio", - flDecayLFRatio, - EAXREVERB_MINDECAYLFRATIO, - EAXREVERB_MAXDECAYLFRATIO); -} - -void EaxReverbEffect::validate_reflections( - long lReflections) -{ - eax_validate_range( - "Reflections", - lReflections, - EAXREVERB_MINREFLECTIONS, - EAXREVERB_MAXREFLECTIONS); -} - -void EaxReverbEffect::validate_reflections_delay( - float flReflectionsDelay) -{ - eax_validate_range( - "Reflections Delay", - flReflectionsDelay, - EAXREVERB_MINREFLECTIONSDELAY, - EAXREVERB_MAXREFLECTIONSDELAY); -} - -void EaxReverbEffect::validate_reflections_pan( - const EAXVECTOR& vReflectionsPan) -{ - std::ignore = vReflectionsPan; -} - -void EaxReverbEffect::validate_reverb( - long lReverb) -{ - eax_validate_range( - "Reverb", - lReverb, - EAXREVERB_MINREVERB, - EAXREVERB_MAXREVERB); -} - -void EaxReverbEffect::validate_reverb_delay( - float flReverbDelay) -{ - eax_validate_range( - "Reverb Delay", - flReverbDelay, - EAXREVERB_MINREVERBDELAY, - EAXREVERB_MAXREVERBDELAY); -} - -void EaxReverbEffect::validate_reverb_pan( - const EAXVECTOR& vReverbPan) -{ - std::ignore = vReverbPan; -} - -void EaxReverbEffect::validate_echo_time( - float flEchoTime) -{ - eax_validate_range( - "Echo Time", - flEchoTime, - EAXREVERB_MINECHOTIME, - EAXREVERB_MAXECHOTIME); -} - -void EaxReverbEffect::validate_echo_depth( - float flEchoDepth) -{ - eax_validate_range( - "Echo Depth", - flEchoDepth, - EAXREVERB_MINECHODEPTH, - EAXREVERB_MAXECHODEPTH); -} - -void EaxReverbEffect::validate_modulation_time( - float flModulationTime) -{ - eax_validate_range( - "Modulation Time", - flModulationTime, - EAXREVERB_MINMODULATIONTIME, - EAXREVERB_MAXMODULATIONTIME); -} - -void EaxReverbEffect::validate_modulation_depth( - float flModulationDepth) -{ - eax_validate_range( - "Modulation Depth", - flModulationDepth, - EAXREVERB_MINMODULATIONDEPTH, - EAXREVERB_MAXMODULATIONDEPTH); -} - -void EaxReverbEffect::validate_air_absorbtion_hf( - float air_absorbtion_hf) -{ - eax_validate_range( - "Air Absorbtion HF", - air_absorbtion_hf, - EAXREVERB_MINAIRABSORPTIONHF, - EAXREVERB_MAXAIRABSORPTIONHF); -} - -void EaxReverbEffect::validate_hf_reference( - float flHFReference) -{ - eax_validate_range( - "HF Reference", - flHFReference, - EAXREVERB_MINHFREFERENCE, - EAXREVERB_MAXHFREFERENCE); -} - -void EaxReverbEffect::validate_lf_reference( - float flLFReference) -{ - eax_validate_range( - "LF Reference", - flLFReference, - EAXREVERB_MINLFREFERENCE, - EAXREVERB_MAXLFREFERENCE); -} - -void EaxReverbEffect::validate_room_rolloff_factor( - float flRoomRolloffFactor) -{ - eax_validate_range( - "Room Rolloff Factor", - flRoomRolloffFactor, - EAXREVERB_MINROOMROLLOFFFACTOR, - EAXREVERB_MAXROOMROLLOFFFACTOR); -} - -void EaxReverbEffect::validate_flags( - unsigned long ulFlags) -{ - eax_validate_range( - "Flags", - ulFlags, - 0UL, - ~EAXREVERBFLAGS_RESERVED); -} - -void EaxReverbEffect::validate_all( - const EAX20LISTENERPROPERTIES& listener, - int version) -{ - validate_room(listener.lRoom); - validate_room_hf(listener.lRoomHF); - validate_room_rolloff_factor(listener.flRoomRolloffFactor); - validate_decay_time(listener.flDecayTime); - validate_decay_hf_ratio(listener.flDecayHFRatio); - validate_reflections(listener.lReflections); - validate_reflections_delay(listener.flReflectionsDelay); - validate_reverb(listener.lReverb); - validate_reverb_delay(listener.flReverbDelay); - validate_environment(listener.dwEnvironment, version, false); - validate_environment_size(listener.flEnvironmentSize); - validate_environment_diffusion(listener.flEnvironmentDiffusion); - validate_air_absorbtion_hf(listener.flAirAbsorptionHF); - validate_flags(listener.dwFlags); -} - -void EaxReverbEffect::validate_all( - const EAXREVERBPROPERTIES& lReverb, - int version) -{ - validate_environment(lReverb.ulEnvironment, version, false); - validate_environment_size(lReverb.flEnvironmentSize); - validate_environment_diffusion(lReverb.flEnvironmentDiffusion); - validate_room(lReverb.lRoom); - validate_room_hf(lReverb.lRoomHF); - validate_room_lf(lReverb.lRoomLF); - validate_decay_time(lReverb.flDecayTime); - validate_decay_hf_ratio(lReverb.flDecayHFRatio); - validate_decay_lf_ratio(lReverb.flDecayLFRatio); - validate_reflections(lReverb.lReflections); - validate_reflections_delay(lReverb.flReflectionsDelay); - validate_reverb(lReverb.lReverb); - validate_reverb_delay(lReverb.flReverbDelay); - validate_echo_time(lReverb.flEchoTime); - validate_echo_depth(lReverb.flEchoDepth); - validate_modulation_time(lReverb.flModulationTime); - validate_modulation_depth(lReverb.flModulationDepth); - validate_air_absorbtion_hf(lReverb.flAirAbsorptionHF); - validate_hf_reference(lReverb.flHFReference); - validate_lf_reference(lReverb.flLFReference); - validate_room_rolloff_factor(lReverb.flRoomRolloffFactor); - validate_flags(lReverb.ulFlags); -} - -void EaxReverbEffect::v1_defer_environment(unsigned long environment) -{ - eax1_d_ = EAX1REVERB_PRESETS[environment]; - eax1_dirty_flags_.ulEnvironment = true; -} - -void EaxReverbEffect::v1_defer_volume(float volume) -{ - eax1_d_.fVolume = volume; - eax1_dirty_flags_.flVolume = (eax1_.fVolume != eax1_d_.fVolume); -} - -void EaxReverbEffect::v1_defer_decay_time(float decay_time) -{ - eax1_d_.fDecayTime_sec = decay_time; - eax1_dirty_flags_.flDecayTime = (eax1_.fDecayTime_sec != eax1_d_.fDecayTime_sec); -} - -void EaxReverbEffect::v1_defer_damping(float damping) -{ - eax1_d_.fDamping = damping; - eax1_dirty_flags_.flDamping = (eax1_.fDamping != eax1_d_.fDamping); -} - -void EaxReverbEffect::v1_defer_all(const EAX_REVERBPROPERTIES& lReverb) -{ - v1_defer_environment(lReverb.environment); - v1_defer_volume(lReverb.fVolume); - v1_defer_decay_time(lReverb.fDecayTime_sec); - v1_defer_damping(lReverb.fDamping); -} - - -void EaxReverbEffect::v1_set_efx() -{ - auto efx_props = eax_efx_reverb_presets[eax1_.environment]; - efx_props.flGain = eax1_.fVolume; - efx_props.flDecayTime = eax1_.fDecayTime_sec; - efx_props.flDecayHFRatio = clamp(eax1_.fDamping, AL_EAXREVERB_MIN_DECAY_HFRATIO, AL_EAXREVERB_MAX_DECAY_HFRATIO); - - al_effect_props_.Reverb.Density = efx_props.flDensity; - al_effect_props_.Reverb.Diffusion = efx_props.flDiffusion; - al_effect_props_.Reverb.Gain = efx_props.flGain; - al_effect_props_.Reverb.GainHF = efx_props.flGainHF; - al_effect_props_.Reverb.GainLF = efx_props.flGainLF; - al_effect_props_.Reverb.DecayTime = efx_props.flDecayTime; - al_effect_props_.Reverb.DecayHFRatio = efx_props.flDecayHFRatio; - al_effect_props_.Reverb.DecayLFRatio = efx_props.flDecayLFRatio; - al_effect_props_.Reverb.ReflectionsGain = efx_props.flReflectionsGain; - al_effect_props_.Reverb.ReflectionsDelay = efx_props.flReflectionsDelay; - al_effect_props_.Reverb.ReflectionsPan[0] = efx_props.flReflectionsPan[0]; - al_effect_props_.Reverb.ReflectionsPan[1] = efx_props.flReflectionsPan[1]; - al_effect_props_.Reverb.ReflectionsPan[2] = efx_props.flReflectionsPan[2]; - al_effect_props_.Reverb.LateReverbGain = efx_props.flLateReverbGain; - al_effect_props_.Reverb.LateReverbDelay = efx_props.flLateReverbDelay; - al_effect_props_.Reverb.LateReverbPan[0] = efx_props.flLateReverbPan[0]; - al_effect_props_.Reverb.LateReverbPan[1] = efx_props.flLateReverbPan[1]; - al_effect_props_.Reverb.LateReverbPan[2] = efx_props.flLateReverbPan[2]; - al_effect_props_.Reverb.EchoTime = efx_props.flEchoTime; - al_effect_props_.Reverb.EchoDepth = efx_props.flEchoDepth; - al_effect_props_.Reverb.ModulationTime = efx_props.flModulationTime; - al_effect_props_.Reverb.ModulationDepth = efx_props.flModulationDepth; - al_effect_props_.Reverb.HFReference = efx_props.flHFReference; - al_effect_props_.Reverb.LFReference = efx_props.flLFReference; - al_effect_props_.Reverb.RoomRolloffFactor = efx_props.flRoomRolloffFactor; - al_effect_props_.Reverb.AirAbsorptionGainHF = efx_props.flAirAbsorptionGainHF; - al_effect_props_.Reverb.DecayHFLimit = false; -} - -void EaxReverbEffect::defer_environment( - unsigned long ulEnvironment) -{ - eax_d_.ulEnvironment = ulEnvironment; - eax_dirty_flags_.ulEnvironment = (eax_.ulEnvironment != eax_d_.ulEnvironment); -} - -void EaxReverbEffect::defer_environment_size( - float flEnvironmentSize) -{ - eax_d_.flEnvironmentSize = flEnvironmentSize; - eax_dirty_flags_.flEnvironmentSize = (eax_.flEnvironmentSize != eax_d_.flEnvironmentSize); -} - -void EaxReverbEffect::defer_environment_diffusion( - float flEnvironmentDiffusion) -{ - eax_d_.flEnvironmentDiffusion = flEnvironmentDiffusion; - eax_dirty_flags_.flEnvironmentDiffusion = (eax_.flEnvironmentDiffusion != eax_d_.flEnvironmentDiffusion); -} - -void EaxReverbEffect::defer_room( - long lRoom) -{ - eax_d_.lRoom = lRoom; - eax_dirty_flags_.lRoom = (eax_.lRoom != eax_d_.lRoom); -} - -void EaxReverbEffect::defer_room_hf( - long lRoomHF) -{ - eax_d_.lRoomHF = lRoomHF; - eax_dirty_flags_.lRoomHF = (eax_.lRoomHF != eax_d_.lRoomHF); -} - -void EaxReverbEffect::defer_room_lf( - long lRoomLF) -{ - eax_d_.lRoomLF = lRoomLF; - eax_dirty_flags_.lRoomLF = (eax_.lRoomLF != eax_d_.lRoomLF); -} - -void EaxReverbEffect::defer_decay_time( - float flDecayTime) -{ - eax_d_.flDecayTime = flDecayTime; - eax_dirty_flags_.flDecayTime = (eax_.flDecayTime != eax_d_.flDecayTime); -} - -void EaxReverbEffect::defer_decay_hf_ratio( - float flDecayHFRatio) -{ - eax_d_.flDecayHFRatio = flDecayHFRatio; - eax_dirty_flags_.flDecayHFRatio = (eax_.flDecayHFRatio != eax_d_.flDecayHFRatio); -} - -void EaxReverbEffect::defer_decay_lf_ratio( - float flDecayLFRatio) -{ - eax_d_.flDecayLFRatio = flDecayLFRatio; - eax_dirty_flags_.flDecayLFRatio = (eax_.flDecayLFRatio != eax_d_.flDecayLFRatio); -} - -void EaxReverbEffect::defer_reflections( - long lReflections) -{ - eax_d_.lReflections = lReflections; - eax_dirty_flags_.lReflections = (eax_.lReflections != eax_d_.lReflections); -} - -void EaxReverbEffect::defer_reflections_delay( - float flReflectionsDelay) -{ - eax_d_.flReflectionsDelay = flReflectionsDelay; - eax_dirty_flags_.flReflectionsDelay = (eax_.flReflectionsDelay != eax_d_.flReflectionsDelay); -} - -void EaxReverbEffect::defer_reflections_pan( - const EAXVECTOR& vReflectionsPan) -{ - eax_d_.vReflectionsPan = vReflectionsPan; - eax_dirty_flags_.vReflectionsPan = (eax_.vReflectionsPan != eax_d_.vReflectionsPan); -} - -void EaxReverbEffect::defer_reverb( - long lReverb) -{ - eax_d_.lReverb = lReverb; - eax_dirty_flags_.lReverb = (eax_.lReverb != eax_d_.lReverb); -} - -void EaxReverbEffect::defer_reverb_delay( - float flReverbDelay) -{ - eax_d_.flReverbDelay = flReverbDelay; - eax_dirty_flags_.flReverbDelay = (eax_.flReverbDelay != eax_d_.flReverbDelay); -} - -void EaxReverbEffect::defer_reverb_pan( - const EAXVECTOR& vReverbPan) -{ - eax_d_.vReverbPan = vReverbPan; - eax_dirty_flags_.vReverbPan = (eax_.vReverbPan != eax_d_.vReverbPan); -} - -void EaxReverbEffect::defer_echo_time( - float flEchoTime) -{ - eax_d_.flEchoTime = flEchoTime; - eax_dirty_flags_.flEchoTime = (eax_.flEchoTime != eax_d_.flEchoTime); -} - -void EaxReverbEffect::defer_echo_depth( - float flEchoDepth) -{ - eax_d_.flEchoDepth = flEchoDepth; - eax_dirty_flags_.flEchoDepth = (eax_.flEchoDepth != eax_d_.flEchoDepth); -} - -void EaxReverbEffect::defer_modulation_time( - float flModulationTime) -{ - eax_d_.flModulationTime = flModulationTime; - eax_dirty_flags_.flModulationTime = (eax_.flModulationTime != eax_d_.flModulationTime); -} - -void EaxReverbEffect::defer_modulation_depth( - float flModulationDepth) -{ - eax_d_.flModulationDepth = flModulationDepth; - eax_dirty_flags_.flModulationDepth = (eax_.flModulationDepth != eax_d_.flModulationDepth); -} - -void EaxReverbEffect::defer_air_absorbtion_hf( - float flAirAbsorptionHF) -{ - eax_d_.flAirAbsorptionHF = flAirAbsorptionHF; - eax_dirty_flags_.flAirAbsorptionHF = (eax_.flAirAbsorptionHF != eax_d_.flAirAbsorptionHF); -} - -void EaxReverbEffect::defer_hf_reference( - float flHFReference) -{ - eax_d_.flHFReference = flHFReference; - eax_dirty_flags_.flHFReference = (eax_.flHFReference != eax_d_.flHFReference); -} - -void EaxReverbEffect::defer_lf_reference( - float flLFReference) -{ - eax_d_.flLFReference = flLFReference; - eax_dirty_flags_.flLFReference = (eax_.flLFReference != eax_d_.flLFReference); -} - -void EaxReverbEffect::defer_room_rolloff_factor( - float flRoomRolloffFactor) -{ - eax_d_.flRoomRolloffFactor = flRoomRolloffFactor; - eax_dirty_flags_.flRoomRolloffFactor = (eax_.flRoomRolloffFactor != eax_d_.flRoomRolloffFactor); -} - -void EaxReverbEffect::defer_flags( - unsigned long ulFlags) -{ - eax_d_.ulFlags = ulFlags; - eax_dirty_flags_.ulFlags = (eax_.ulFlags != eax_d_.ulFlags); -} - -void EaxReverbEffect::defer_all( - const EAX20LISTENERPROPERTIES& listener) -{ - defer_room(listener.lRoom); - defer_room_hf(listener.lRoomHF); - defer_room_rolloff_factor(listener.flRoomRolloffFactor); - defer_decay_time(listener.flDecayTime); - defer_decay_hf_ratio(listener.flDecayHFRatio); - defer_reflections(listener.lReflections); - defer_reflections_delay(listener.flReflectionsDelay); - defer_reverb(listener.lReverb); - defer_reverb_delay(listener.flReverbDelay); - defer_environment(listener.dwEnvironment); - defer_environment_size(listener.flEnvironmentSize); - defer_environment_diffusion(listener.flEnvironmentDiffusion); - defer_air_absorbtion_hf(listener.flAirAbsorptionHF); - defer_flags(listener.dwFlags); -} - -void EaxReverbEffect::defer_all( - const EAXREVERBPROPERTIES& lReverb) -{ - defer_environment(lReverb.ulEnvironment); - defer_environment_size(lReverb.flEnvironmentSize); - defer_environment_diffusion(lReverb.flEnvironmentDiffusion); - defer_room(lReverb.lRoom); - defer_room_hf(lReverb.lRoomHF); - defer_room_lf(lReverb.lRoomLF); - defer_decay_time(lReverb.flDecayTime); - defer_decay_hf_ratio(lReverb.flDecayHFRatio); - defer_decay_lf_ratio(lReverb.flDecayLFRatio); - defer_reflections(lReverb.lReflections); - defer_reflections_delay(lReverb.flReflectionsDelay); - defer_reflections_pan(lReverb.vReflectionsPan); - defer_reverb(lReverb.lReverb); - defer_reverb_delay(lReverb.flReverbDelay); - defer_reverb_pan(lReverb.vReverbPan); - defer_echo_time(lReverb.flEchoTime); - defer_echo_depth(lReverb.flEchoDepth); - defer_modulation_time(lReverb.flModulationTime); - defer_modulation_depth(lReverb.flModulationDepth); - defer_air_absorbtion_hf(lReverb.flAirAbsorptionHF); - defer_hf_reference(lReverb.flHFReference); - defer_lf_reference(lReverb.flLFReference); - defer_room_rolloff_factor(lReverb.flRoomRolloffFactor); - defer_flags(lReverb.ulFlags); -} - - -void EaxReverbEffect::v1_defer_environment(const EaxEaxCall& eax_call) -{ - const auto& environment = eax_call.get_value(); - - validate_environment(environment, 1, true); - - const auto& reverb_preset = EAX1REVERB_PRESETS[environment]; - v1_defer_all(reverb_preset); -} - -void EaxReverbEffect::v1_defer_volume(const EaxEaxCall& eax_call) -{ - const auto& volume = eax_call.get_value(); - - v1_validate_volume(volume); - v1_defer_volume(volume); -} - -void EaxReverbEffect::v1_defer_decay_time(const EaxEaxCall& eax_call) -{ - const auto& decay_time = eax_call.get_value(); - - v1_validate_decay_time(decay_time); - v1_defer_decay_time(decay_time); -} - -void EaxReverbEffect::v1_defer_damping(const EaxEaxCall& eax_call) -{ - const auto& damping = eax_call.get_value(); - - v1_validate_damping(damping); - v1_defer_damping(damping); -} - -void EaxReverbEffect::v1_defer_all(const EaxEaxCall& eax_call) -{ - const auto& reverb_all = eax_call.get_value(); - - v1_validate_all(reverb_all); - v1_defer_all(reverb_all); -} - - -void EaxReverbEffect::defer_environment( - const EaxEaxCall& eax_call) -{ - const auto& ulEnvironment = - eax_call.get_value(); - - validate_environment(ulEnvironment, eax_call.get_version(), true); - - if (eax_d_.ulEnvironment == ulEnvironment) - { - return; - } - - const auto& reverb_preset = EAXREVERB_PRESETS[ulEnvironment]; - - defer_all(reverb_preset); -} - -void EaxReverbEffect::defer_environment_size( - const EaxEaxCall& eax_call) -{ - const auto& flEnvironmentSize = - eax_call.get_value(); - - validate_environment_size(flEnvironmentSize); - - if (eax_d_.flEnvironmentSize == flEnvironmentSize) - { - return; - } - - const auto scale = flEnvironmentSize / eax_d_.flEnvironmentSize; - - defer_environment_size(flEnvironmentSize); - - if ((eax_d_.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) + if (props_.lReflections != props.lReflections) { - const auto flDecayTime = clamp( - scale * eax_d_.flDecayTime, - EAXREVERB_MINDECAYTIME, - EAXREVERB_MAXDECAYTIME); - - defer_decay_time(flDecayTime); + is_dirty = true; + set_efx_reflections_gain(); } - if ((eax_d_.ulFlags & EAXREVERBFLAGS_REFLECTIONSSCALE) != 0) + if (props_.flReflectionsDelay != props.flReflectionsDelay) { - if ((eax_d_.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0) - { - const auto lReflections = clamp( - eax_d_.lReflections - static_cast(gain_to_level_mb(scale)), - EAXREVERB_MINREFLECTIONS, - EAXREVERB_MAXREFLECTIONS); - - defer_reflections(lReflections); - } + is_dirty = true; + set_efx_reflections_delay(); } - if ((eax_d_.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0) + if (props_.vReflectionsPan != props.vReflectionsPan) { - const auto flReflectionsDelay = clamp( - eax_d_.flReflectionsDelay * scale, - EAXREVERB_MINREFLECTIONSDELAY, - EAXREVERB_MAXREFLECTIONSDELAY); - - defer_reflections_delay(flReflectionsDelay); + is_dirty = true; + set_efx_reflections_pan(); } - if ((eax_d_.ulFlags & EAXREVERBFLAGS_REVERBSCALE) != 0) + if (props_.lReverb != props.lReverb) { - const auto log_scalar = ((eax_d_.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F; - - const auto lReverb = clamp( - eax_d_.lReverb - static_cast(std::log10(scale) * log_scalar), - EAXREVERB_MINREVERB, - EAXREVERB_MAXREVERB); - - defer_reverb(lReverb); + is_dirty = true; + set_efx_late_reverb_gain(); } - if ((eax_d_.ulFlags & EAXREVERBFLAGS_REVERBDELAYSCALE) != 0) + if (props_.flReverbDelay != props.flReverbDelay) { - const auto flReverbDelay = clamp( - scale * eax_d_.flReverbDelay, - EAXREVERB_MINREVERBDELAY, - EAXREVERB_MAXREVERBDELAY); - - defer_reverb_delay(flReverbDelay); + is_dirty = true; + set_efx_late_reverb_delay(); } - if ((eax_d_.ulFlags & EAXREVERBFLAGS_ECHOTIMESCALE) != 0) + if (props_.vReverbPan != props.vReverbPan) { - const auto flEchoTime = clamp( - eax_d_.flEchoTime * scale, - EAXREVERB_MINECHOTIME, - EAXREVERB_MAXECHOTIME); - - defer_echo_time(flEchoTime); + is_dirty = true; + set_efx_late_reverb_pan(); } - if ((eax_d_.ulFlags & EAXREVERBFLAGS_MODULATIONTIMESCALE) != 0) + if (props_.flEchoTime != props.flEchoTime) { - const auto flModulationTime = clamp( - scale * eax_d_.flModulationTime, - EAXREVERB_MINMODULATIONTIME, - EAXREVERB_MAXMODULATIONTIME); - - defer_modulation_time(flModulationTime); + is_dirty = true; + set_efx_echo_time(); } -} - -void EaxReverbEffect::defer_environment_diffusion( - const EaxEaxCall& eax_call) -{ - const auto& flEnvironmentDiffusion = - eax_call.get_value(); - - validate_environment_diffusion(flEnvironmentDiffusion); - defer_environment_diffusion(flEnvironmentDiffusion); -} - -void EaxReverbEffect::defer_room( - const EaxEaxCall& eax_call) -{ - const auto& lRoom = - eax_call.get_value(); - - validate_room(lRoom); - defer_room(lRoom); -} - -void EaxReverbEffect::defer_room_hf( - const EaxEaxCall& eax_call) -{ - const auto& lRoomHF = - eax_call.get_value(); - - validate_room_hf(lRoomHF); - defer_room_hf(lRoomHF); -} - -void EaxReverbEffect::defer_room_lf( - const EaxEaxCall& eax_call) -{ - const auto& lRoomLF = - eax_call.get_value(); - - validate_room_lf(lRoomLF); - defer_room_lf(lRoomLF); -} - -void EaxReverbEffect::defer_decay_time( - const EaxEaxCall& eax_call) -{ - const auto& flDecayTime = - eax_call.get_value(); - - validate_decay_time(flDecayTime); - defer_decay_time(flDecayTime); -} - -void EaxReverbEffect::defer_decay_hf_ratio( - const EaxEaxCall& eax_call) -{ - const auto& flDecayHFRatio = - eax_call.get_value(); - - validate_decay_hf_ratio(flDecayHFRatio); - defer_decay_hf_ratio(flDecayHFRatio); -} - -void EaxReverbEffect::defer_decay_lf_ratio( - const EaxEaxCall& eax_call) -{ - const auto& flDecayLFRatio = - eax_call.get_value(); - - validate_decay_lf_ratio(flDecayLFRatio); - defer_decay_lf_ratio(flDecayLFRatio); -} - -void EaxReverbEffect::defer_reflections( - const EaxEaxCall& eax_call) -{ - const auto& lReflections = - eax_call.get_value(); - - validate_reflections(lReflections); - defer_reflections(lReflections); -} - -void EaxReverbEffect::defer_reflections_delay( - const EaxEaxCall& eax_call) -{ - const auto& flReflectionsDelay = - eax_call.get_value(); - - validate_reflections_delay(flReflectionsDelay); - defer_reflections_delay(flReflectionsDelay); -} - -void EaxReverbEffect::defer_reflections_pan( - const EaxEaxCall& eax_call) -{ - const auto& vReflectionsPan = - eax_call.get_value(); - - validate_reflections_pan(vReflectionsPan); - defer_reflections_pan(vReflectionsPan); -} - -void EaxReverbEffect::defer_reverb( - const EaxEaxCall& eax_call) -{ - const auto& lReverb = - eax_call.get_value(); - - validate_reverb(lReverb); - defer_reverb(lReverb); -} - -void EaxReverbEffect::defer_reverb_delay( - const EaxEaxCall& eax_call) -{ - const auto& flReverbDelay = - eax_call.get_value(); - - validate_reverb_delay(flReverbDelay); - defer_reverb_delay(flReverbDelay); -} - -void EaxReverbEffect::defer_reverb_pan( - const EaxEaxCall& eax_call) -{ - const auto& vReverbPan = - eax_call.get_value(); - - validate_reverb_pan(vReverbPan); - defer_reverb_pan(vReverbPan); -} - -void EaxReverbEffect::defer_echo_time( - const EaxEaxCall& eax_call) -{ - const auto& flEchoTime = - eax_call.get_value(); - - validate_echo_time(flEchoTime); - defer_echo_time(flEchoTime); -} - -void EaxReverbEffect::defer_echo_depth( - const EaxEaxCall& eax_call) -{ - const auto& flEchoDepth = - eax_call.get_value(); - - validate_echo_depth(flEchoDepth); - defer_echo_depth(flEchoDepth); -} - -void EaxReverbEffect::defer_modulation_time( - const EaxEaxCall& eax_call) -{ - const auto& flModulationTime = - eax_call.get_value(); - - validate_modulation_time(flModulationTime); - defer_modulation_time(flModulationTime); -} - -void EaxReverbEffect::defer_modulation_depth( - const EaxEaxCall& eax_call) -{ - const auto& flModulationDepth = - eax_call.get_value(); - - validate_modulation_depth(flModulationDepth); - defer_modulation_depth(flModulationDepth); -} - -void EaxReverbEffect::defer_air_absorbtion_hf( - const EaxEaxCall& eax_call) -{ - const auto& air_absorbtion_hf = - eax_call.get_value(); - - validate_air_absorbtion_hf(air_absorbtion_hf); - defer_air_absorbtion_hf(air_absorbtion_hf); -} - -void EaxReverbEffect::defer_hf_reference( - const EaxEaxCall& eax_call) -{ - const auto& flHFReference = - eax_call.get_value(); - - validate_hf_reference(flHFReference); - defer_hf_reference(flHFReference); -} - -void EaxReverbEffect::defer_lf_reference( - const EaxEaxCall& eax_call) -{ - const auto& flLFReference = - eax_call.get_value(); - - validate_lf_reference(flLFReference); - defer_lf_reference(flLFReference); -} - -void EaxReverbEffect::defer_room_rolloff_factor( - const EaxEaxCall& eax_call) -{ - const auto& flRoomRolloffFactor = - eax_call.get_value(); - - validate_room_rolloff_factor(flRoomRolloffFactor); - defer_room_rolloff_factor(flRoomRolloffFactor); -} - -void EaxReverbEffect::defer_flags( - const EaxEaxCall& eax_call) -{ - const auto& ulFlags = - eax_call.get_value(); - - validate_flags(ulFlags); - defer_flags(ulFlags); -} -void EaxReverbEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto eax_version = eax_call.get_version(); - - if (eax_version == 2) - { - const auto& listener = - eax_call.get_value(); - - validate_all(listener, eax_version); - defer_all(listener); - } - else + if (props_.flEchoDepth != props.flEchoDepth) { - const auto& reverb_all = - eax_call.get_value(); - - validate_all(reverb_all, eax_version); - defer_all(reverb_all); + is_dirty = true; + set_efx_echo_depth(); } -} - -void EaxReverbEffect::v1_defer(const EaxEaxCall& eax_call) -{ - switch (eax_call.get_property_id()) + if (props_.flModulationTime != props.flModulationTime) { - case DSPROPERTY_EAX_ALL: return v1_defer_all(eax_call); - case DSPROPERTY_EAX_ENVIRONMENT: return v1_defer_environment(eax_call); - case DSPROPERTY_EAX_VOLUME: return v1_defer_volume(eax_call); - case DSPROPERTY_EAX_DECAYTIME: return v1_defer_decay_time(eax_call); - case DSPROPERTY_EAX_DAMPING: return v1_defer_damping(eax_call); - default: eax_fail("Unsupported property id."); + is_dirty = true; + set_efx_modulation_time(); } -} -// [[nodiscard]] -bool EaxReverbEffect::apply_deferred() -{ - bool ret{false}; - - if(unlikely(eax1_dirty_flags_ != Eax1ReverbEffectDirtyFlags{})) + if (props_.flModulationDepth != props.flModulationDepth) { - eax1_ = eax1_d_; - - v1_set_efx(); - - eax1_dirty_flags_ = Eax1ReverbEffectDirtyFlags{}; - - ret = true; + is_dirty = true; + set_efx_modulation_depth(); } - if(eax_dirty_flags_ == EaxReverbEffectDirtyFlags{}) - return ret; - - eax_ = eax_d_; - - if (eax_dirty_flags_.ulEnvironment) + if (props_.flAirAbsorptionHF != props.flAirAbsorptionHF) { + is_dirty = true; + set_efx_air_absorption_gain_hf(); } - if (eax_dirty_flags_.flEnvironmentSize) + if (props_.flHFReference != props.flHFReference) { - set_efx_density_from_environment_size(); + is_dirty = true; + set_efx_hf_reference(); } - if (eax_dirty_flags_.flEnvironmentDiffusion) + if (props_.flLFReference != props.flLFReference) { - set_efx_diffusion(); + is_dirty = true; + set_efx_lf_reference(); } - if (eax_dirty_flags_.lRoom) + if (props_.flRoomRolloffFactor != props.flRoomRolloffFactor) { - set_efx_gain(); + is_dirty = true; + set_efx_room_rolloff_factor(); } - if (eax_dirty_flags_.lRoomHF) + if (props_.ulFlags != props.ulFlags) { - set_efx_gain_hf(); + is_dirty = true; + set_efx_flags(); } - if (eax_dirty_flags_.lRoomLF) - { - set_efx_gain_lf(); - } + return is_dirty; +} - if (eax_dirty_flags_.flDecayTime) +void EaxReverbEffect::set1(const EaxCall& call, Props1& props) +{ + switch (call.get_property_id()) { - set_efx_decay_time(); + case DSPROPERTY_EAX_ALL: defer(call, props); break; + case DSPROPERTY_EAX_ENVIRONMENT: defer(call, props.environment); break; + case DSPROPERTY_EAX_VOLUME: defer(call, props.fVolume); break; + case DSPROPERTY_EAX_DECAYTIME: defer(call, props.fDecayTime_sec); break; + case DSPROPERTY_EAX_DAMPING: defer(call, props.fDamping); break; + default: fail_unknown_property_id(); } +} - if (eax_dirty_flags_.flDecayHFRatio) +void EaxReverbEffect::set2(const EaxCall& call, Props2& props) +{ + switch (call.get_property_id()) { - set_efx_decay_hf_ratio(); - } + case DSPROPERTY_EAX20LISTENER_NONE: + break; - if (eax_dirty_flags_.flDecayLFRatio) - { - set_efx_decay_lf_ratio(); - } + case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: + defer(call, props); + break; - if (eax_dirty_flags_.lReflections) - { - set_efx_reflections_gain(); - } + case DSPROPERTY_EAX20LISTENER_ROOM: + defer(call, props.lRoom); + break; - if (eax_dirty_flags_.flReflectionsDelay) - { - set_efx_reflections_delay(); - } + case DSPROPERTY_EAX20LISTENER_ROOMHF: + defer(call, props.lRoomHF); + break; - if (eax_dirty_flags_.vReflectionsPan) - { - set_efx_reflections_pan(); - } + case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: + defer(call, props.flRoomRolloffFactor); + break; - if (eax_dirty_flags_.lReverb) - { - set_efx_late_reverb_gain(); - } + case DSPROPERTY_EAX20LISTENER_DECAYTIME: + defer(call, props.flDecayTime); + break; - if (eax_dirty_flags_.flReverbDelay) - { - set_efx_late_reverb_delay(); - } + case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: + defer(call, props.flDecayHFRatio); + break; - if (eax_dirty_flags_.vReverbPan) - { - set_efx_late_reverb_pan(); - } + case DSPROPERTY_EAX20LISTENER_REFLECTIONS: + defer(call, props.lReflections); + break; - if (eax_dirty_flags_.flEchoTime) - { - set_efx_echo_time(); - } + case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: + defer(call, props.flReverbDelay); + break; - if (eax_dirty_flags_.flEchoDepth) - { - set_efx_echo_depth(); - } + case DSPROPERTY_EAX20LISTENER_REVERB: + defer(call, props.lReverb); + break; - if (eax_dirty_flags_.flModulationTime) - { - set_efx_modulation_time(); - } + case DSPROPERTY_EAX20LISTENER_REVERBDELAY: + defer(call, props.flReverbDelay); + break; - if (eax_dirty_flags_.flModulationDepth) - { - set_efx_modulation_depth(); - } + case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: + defer(call, props, props.dwEnvironment); + break; - if (eax_dirty_flags_.flAirAbsorptionHF) - { - set_efx_air_absorption_gain_hf(); - } + case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE: + defer(call, props, props.flEnvironmentSize); + break; - if (eax_dirty_flags_.flHFReference) - { - set_efx_hf_reference(); - } + case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION: + defer(call, props.flEnvironmentDiffusion); + break; - if (eax_dirty_flags_.flLFReference) - { - set_efx_lf_reference(); - } + case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: + defer(call, props.flAirAbsorptionHF); + break; - if (eax_dirty_flags_.flRoomRolloffFactor) - { - set_efx_room_rolloff_factor(); - } + case DSPROPERTY_EAX20LISTENER_FLAGS: + defer(call, props.dwFlags); + break; - if (eax_dirty_flags_.ulFlags) - { - set_efx_flags(); + default: + fail_unknown_property_id(); } - - eax_dirty_flags_ = EaxReverbEffectDirtyFlags{}; - - return true; } -void EaxReverbEffect::set(const EaxEaxCall& eax_call) +void EaxReverbEffect::set3(const EaxCall& call, Props3& props) { - if(eax_call.get_version() == 1) - v1_defer(eax_call); - else switch(eax_call.get_property_id()) + switch(call.get_property_id()) { case EAXREVERB_NONE: break; case EAXREVERB_ALLPARAMETERS: - defer_all(eax_call); + defer(call, props); break; case EAXREVERB_ENVIRONMENT: - defer_environment(eax_call); + defer(call, props, props.ulEnvironment); break; case EAXREVERB_ENVIRONMENTSIZE: - defer_environment_size(eax_call); + defer(call, props, props.flEnvironmentSize); break; case EAXREVERB_ENVIRONMENTDIFFUSION: - defer_environment_diffusion(eax_call); + defer3(call, props, props.flEnvironmentDiffusion); break; case EAXREVERB_ROOM: - defer_room(eax_call); + defer3(call, props, props.lRoom); break; case EAXREVERB_ROOMHF: - defer_room_hf(eax_call); + defer3(call, props, props.lRoomHF); break; case EAXREVERB_ROOMLF: - defer_room_lf(eax_call); + defer3(call, props, props.lRoomLF); break; case EAXREVERB_DECAYTIME: - defer_decay_time(eax_call); + defer3(call, props, props.flDecayTime); break; case EAXREVERB_DECAYHFRATIO: - defer_decay_hf_ratio(eax_call); + defer3(call, props, props.flDecayHFRatio); break; case EAXREVERB_DECAYLFRATIO: - defer_decay_lf_ratio(eax_call); + defer3(call, props, props.flDecayLFRatio); break; case EAXREVERB_REFLECTIONS: - defer_reflections(eax_call); + defer3(call, props, props.lReflections); break; case EAXREVERB_REFLECTIONSDELAY: - defer_reflections_delay(eax_call); + defer3(call, props, props.flReflectionsDelay); break; case EAXREVERB_REFLECTIONSPAN: - defer_reflections_pan(eax_call); + defer3(call, props, props.vReflectionsPan); break; case EAXREVERB_REVERB: - defer_reverb(eax_call); + defer3(call, props, props.lReverb); break; case EAXREVERB_REVERBDELAY: - defer_reverb_delay(eax_call); + defer3(call, props, props.flReverbDelay); break; case EAXREVERB_REVERBPAN: - defer_reverb_pan(eax_call); + defer3(call, props, props.vReverbPan); break; case EAXREVERB_ECHOTIME: - defer_echo_time(eax_call); + defer3(call, props, props.flEchoTime); break; case EAXREVERB_ECHODEPTH: - defer_echo_depth(eax_call); + defer3(call, props, props.flEchoDepth); break; case EAXREVERB_MODULATIONTIME: - defer_modulation_time(eax_call); + defer3(call, props, props.flModulationTime); break; case EAXREVERB_MODULATIONDEPTH: - defer_modulation_depth(eax_call); + defer3(call, props, props.flModulationDepth); break; case EAXREVERB_AIRABSORPTIONHF: - defer_air_absorbtion_hf(eax_call); + defer3(call, props, props.flAirAbsorptionHF); break; case EAXREVERB_HFREFERENCE: - defer_hf_reference(eax_call); + defer3(call, props, props.flHFReference); break; case EAXREVERB_LFREFERENCE: - defer_lf_reference(eax_call); + defer3(call, props, props.flLFReference); break; case EAXREVERB_ROOMROLLOFFFACTOR: - defer_room_rolloff_factor(eax_call); + defer3(call, props, props.flRoomRolloffFactor); break; case EAXREVERB_FLAGS: - defer_flags(eax_call); + defer3(call, props, props.ulFlags); break; default: - eax_fail("Unsupported property id."); + fail_unknown_property_id(); } } -const EFXEAXREVERBPROPERTIES eax_efx_reverb_presets[EAX1_ENVIRONMENT_COUNT] = +void EaxReverbEffect::set(const EaxCall& call) { - EFX_REVERB_PRESET_GENERIC, - EFX_REVERB_PRESET_PADDEDCELL, - EFX_REVERB_PRESET_ROOM, - EFX_REVERB_PRESET_BATHROOM, - EFX_REVERB_PRESET_LIVINGROOM, - EFX_REVERB_PRESET_STONEROOM, - EFX_REVERB_PRESET_AUDITORIUM, - EFX_REVERB_PRESET_CONCERTHALL, - EFX_REVERB_PRESET_CAVE, - EFX_REVERB_PRESET_ARENA, - EFX_REVERB_PRESET_HANGAR, - EFX_REVERB_PRESET_CARPETEDHALLWAY, - EFX_REVERB_PRESET_HALLWAY, - EFX_REVERB_PRESET_STONECORRIDOR, - EFX_REVERB_PRESET_ALLEY, - EFX_REVERB_PRESET_FOREST, - EFX_REVERB_PRESET_CITY, - EFX_REVERB_PRESET_MOUNTAINS, - EFX_REVERB_PRESET_QUARRY, - EFX_REVERB_PRESET_PLAIN, - EFX_REVERB_PRESET_PARKINGLOT, - EFX_REVERB_PRESET_SEWERPIPE, - EFX_REVERB_PRESET_UNDERWATER, - EFX_REVERB_PRESET_DRUGGED, - EFX_REVERB_PRESET_DIZZY, - EFX_REVERB_PRESET_PSYCHOTIC, -}; // EFXEAXREVERBPROPERTIES + const auto version = call.get_version(); + + switch (version) + { + case 1: set1(call, state1_.d); break; + case 2: set2(call, state2_.d); break; + case 3: set3(call, state3_.d); break; + case 4: set3(call, state4_.d); break; + case 5: set3(call, state5_.d); break; + default: fail_unknown_version(); + } + + version_ = version; +} + +void EaxReverbEffect::translate(const Props1& src, Props3& dst) noexcept +{ + assert(src.environment <= EAX1REVERB_MAXENVIRONMENT); + dst = EAXREVERB_PRESETS[src.environment]; + dst.flDecayTime = src.fDecayTime_sec; + dst.flDecayHFRatio = src.fDamping; + dst.lReverb = mini(static_cast(gain_to_level_mb(src.fVolume)), 0); +} + +void EaxReverbEffect::translate(const Props2& src, Props3& dst) noexcept +{ + assert(src.dwEnvironment <= EAX1REVERB_MAXENVIRONMENT); + const auto& env = EAXREVERB_PRESETS[src.dwEnvironment]; + dst.ulEnvironment = src.dwEnvironment; + dst.flEnvironmentSize = src.flEnvironmentSize; + dst.flEnvironmentDiffusion = src.flEnvironmentDiffusion; + dst.lRoom = src.lRoom; + dst.lRoomHF = src.lRoomHF; + dst.lRoomLF = env.lRoomLF; + dst.flDecayTime = src.flDecayTime; + dst.flDecayHFRatio = src.flDecayHFRatio; + dst.flDecayLFRatio = env.flDecayLFRatio; + dst.lReflections = src.lReflections; + dst.flReflectionsDelay = src.flReflectionsDelay; + dst.vReflectionsPan = env.vReflectionsPan; + dst.lReverb = src.lReverb; + dst.flReverbDelay = src.flReverbDelay; + dst.vReverbPan = env.vReverbPan; + dst.flEchoTime = env.flEchoTime; + dst.flEchoDepth = env.flEchoDepth; + dst.flModulationTime = env.flModulationTime; + dst.flModulationDepth = env.flModulationDepth; + dst.flAirAbsorptionHF = src.flAirAbsorptionHF; + dst.flHFReference = env.flHFReference; + dst.flLFReference = env.flLFReference; + dst.flRoomRolloffFactor = src.flRoomRolloffFactor; + dst.ulFlags = src.dwFlags; +} } // namespace -EaxEffectUPtr eax_create_eax_reverb_effect() +EaxEffectUPtr eax_create_eax_reverb_effect(const EaxCall& call) { - return std::make_unique(); + return std::make_unique(call); } #endif // ALSOFT_EAX diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index da513015..95f98db5 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -12,9 +12,7 @@ #ifdef ALSOFT_EAX #include - #include "alnumeric.h" - #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -260,178 +258,181 @@ const EffectProps VmorpherEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -using EaxVocalMorpherEffectDirtyFlagsValue = std::uint_least8_t; - -struct EaxVocalMorpherEffectDirtyFlags -{ - using EaxIsBitFieldStruct = bool; - - EaxVocalMorpherEffectDirtyFlagsValue ulPhonemeA : 1; - EaxVocalMorpherEffectDirtyFlagsValue lPhonemeACoarseTuning : 1; - EaxVocalMorpherEffectDirtyFlagsValue ulPhonemeB : 1; - EaxVocalMorpherEffectDirtyFlagsValue lPhonemeBCoarseTuning : 1; - EaxVocalMorpherEffectDirtyFlagsValue ulWaveform : 1; - EaxVocalMorpherEffectDirtyFlagsValue flRate : 1; -}; // EaxPitchShifterEffectDirtyFlags - - -class EaxVocalMorpherEffect final : - public EaxEffect -{ +class EaxVocalMorpherEffectException : public EaxException { public: - EaxVocalMorpherEffect(); - - void dispatch(const EaxEaxCall& eax_call) override; + explicit EaxVocalMorpherEffectException(const char* message) + : EaxException{"EAX_VOCAL_MORPHER_EFFECT", message} + {} +}; // EaxVocalMorpherEffectException - // [[nodiscard]] - bool apply_deferred() override; +class EaxVocalMorpherEffect final : public EaxEffect4 { +public: + EaxVocalMorpherEffect(const EaxCall& call); private: - EAXVOCALMORPHERPROPERTIES eax_{}; - EAXVOCALMORPHERPROPERTIES eax_d_{}; - EaxVocalMorpherEffectDirtyFlags eax_dirty_flags_{}; - - void set_eax_defaults(); + struct PhonemeAValidator { + void operator()(unsigned long ulPhonemeA) const + { + eax_validate_range( + "Phoneme A", + ulPhonemeA, + EAXVOCALMORPHER_MINPHONEMEA, + EAXVOCALMORPHER_MAXPHONEMEA); + } + }; // PhonemeAValidator + + struct PhonemeACoarseTuningValidator { + void operator()(long lPhonemeACoarseTuning) const + { + eax_validate_range( + "Phoneme A Coarse Tuning", + lPhonemeACoarseTuning, + EAXVOCALMORPHER_MINPHONEMEACOARSETUNING, + EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING); + } + }; // PhonemeACoarseTuningValidator + + struct PhonemeBValidator { + void operator()(unsigned long ulPhonemeB) const + { + eax_validate_range( + "Phoneme B", + ulPhonemeB, + EAXVOCALMORPHER_MINPHONEMEB, + EAXVOCALMORPHER_MAXPHONEMEB); + } + }; // PhonemeBValidator + + struct PhonemeBCoarseTuningValidator { + void operator()(long lPhonemeBCoarseTuning) const + { + eax_validate_range( + "Phoneme B Coarse Tuning", + lPhonemeBCoarseTuning, + EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING, + EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING); + } + }; // PhonemeBCoarseTuningValidator + + struct WaveformValidator { + void operator()(unsigned long ulWaveform) const + { + eax_validate_range( + "Waveform", + ulWaveform, + EAXVOCALMORPHER_MINWAVEFORM, + EAXVOCALMORPHER_MAXWAVEFORM); + } + }; // WaveformValidator + + struct RateValidator { + void operator()(float flRate) const + { + eax_validate_range( + "Rate", + flRate, + EAXVOCALMORPHER_MINRATE, + EAXVOCALMORPHER_MAXRATE); + } + }; // RateValidator + + struct AllValidator { + void operator()(const Props& all) const + { + PhonemeAValidator{}(all.ulPhonemeA); + PhonemeACoarseTuningValidator{}(all.lPhonemeACoarseTuning); + PhonemeBValidator{}(all.ulPhonemeB); + PhonemeBCoarseTuningValidator{}(all.lPhonemeBCoarseTuning); + WaveformValidator{}(all.ulWaveform); + RateValidator{}(all.flRate); + } + }; // AllValidator + + void set_defaults(Props& props) override; void set_efx_phoneme_a(); - void set_efx_phoneme_a_coarse_tuning(); + void set_efx_phoneme_a_coarse_tuning() noexcept; void set_efx_phoneme_b(); - void set_efx_phoneme_b_coarse_tuning(); + void set_efx_phoneme_b_coarse_tuning() noexcept; void set_efx_waveform(); - void set_efx_rate(); - void set_efx_defaults(); - - void get(const EaxEaxCall& eax_call); - - void validate_phoneme_a(unsigned long ulPhonemeA); - void validate_phoneme_a_coarse_tuning(long lPhonemeACoarseTuning); - void validate_phoneme_b(unsigned long ulPhonemeB); - void validate_phoneme_b_coarse_tuning(long lPhonemeBCoarseTuning); - void validate_waveform(unsigned long ulWaveform); - void validate_rate(float flRate); - void validate_all(const EAXVOCALMORPHERPROPERTIES& all); - - void defer_phoneme_a(unsigned long ulPhonemeA); - void defer_phoneme_a_coarse_tuning(long lPhonemeACoarseTuning); - void defer_phoneme_b(unsigned long ulPhonemeB); - void defer_phoneme_b_coarse_tuning(long lPhonemeBCoarseTuning); - void defer_waveform(unsigned long ulWaveform); - void defer_rate(float flRate); - void defer_all(const EAXVOCALMORPHERPROPERTIES& all); - - void defer_phoneme_a(const EaxEaxCall& eax_call); - void defer_phoneme_a_coarse_tuning(const EaxEaxCall& eax_call); - void defer_phoneme_b(const EaxEaxCall& eax_call); - void defer_phoneme_b_coarse_tuning(const EaxEaxCall& eax_call); - void defer_waveform(const EaxEaxCall& eax_call); - void defer_rate(const EaxEaxCall& eax_call); - void defer_all(const EaxEaxCall& eax_call); - - void set(const EaxEaxCall& eax_call); -}; // EaxVocalMorpherEffect + void set_efx_rate() noexcept; + void set_efx_defaults() override; + void get(const EaxCall& call, const Props& props) override; + void set(const EaxCall& call, Props& props) override; + bool commit_props(const Props& props) override; +}; // EaxVocalMorpherEffect -class EaxVocalMorpherEffectException : - public EaxException -{ -public: - explicit EaxVocalMorpherEffectException( - const char* message) - : - EaxException{"EAX_VOCAL_MORPHER_EFFECT", message} - { - } -}; // EaxVocalMorpherEffectException - +EaxVocalMorpherEffect::EaxVocalMorpherEffect(const EaxCall& call) + : EaxEffect4{AL_EFFECT_VOCAL_MORPHER, call} +{} -EaxVocalMorpherEffect::EaxVocalMorpherEffect() - : EaxEffect{AL_EFFECT_VOCAL_MORPHER} +void EaxVocalMorpherEffect::set_defaults(Props& props) { - set_eax_defaults(); - set_efx_defaults(); -} - -void EaxVocalMorpherEffect::dispatch(const EaxEaxCall& eax_call) -{ - eax_call.is_get() ? get(eax_call) : set(eax_call); -} - -void EaxVocalMorpherEffect::set_eax_defaults() -{ - eax_.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA; - eax_.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING; - eax_.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB; - eax_.lPhonemeBCoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING; - eax_.ulWaveform = EAXVOCALMORPHER_DEFAULTWAVEFORM; - eax_.flRate = EAXVOCALMORPHER_DEFAULTRATE; - - eax_d_ = eax_; + props.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA; + props.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING; + props.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB; + props.lPhonemeBCoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING; + props.ulWaveform = EAXVOCALMORPHER_DEFAULTWAVEFORM; + props.flRate = EAXVOCALMORPHER_DEFAULTRATE; } void EaxVocalMorpherEffect::set_efx_phoneme_a() { const auto phoneme_a = clamp( - static_cast(eax_.ulPhonemeA), + static_cast(props_.ulPhonemeA), AL_VOCAL_MORPHER_MIN_PHONEMEA, AL_VOCAL_MORPHER_MAX_PHONEMEA); - const auto efx_phoneme_a = PhenomeFromEnum(phoneme_a); assert(efx_phoneme_a.has_value()); al_effect_props_.Vmorpher.PhonemeA = *efx_phoneme_a; } -void EaxVocalMorpherEffect::set_efx_phoneme_a_coarse_tuning() +void EaxVocalMorpherEffect::set_efx_phoneme_a_coarse_tuning() noexcept { const auto phoneme_a_coarse_tuning = clamp( - static_cast(eax_.lPhonemeACoarseTuning), + static_cast(props_.lPhonemeACoarseTuning), AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING, AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING); - al_effect_props_.Vmorpher.PhonemeACoarseTuning = phoneme_a_coarse_tuning; } void EaxVocalMorpherEffect::set_efx_phoneme_b() { const auto phoneme_b = clamp( - static_cast(eax_.ulPhonemeB), + static_cast(props_.ulPhonemeB), AL_VOCAL_MORPHER_MIN_PHONEMEB, AL_VOCAL_MORPHER_MAX_PHONEMEB); - const auto efx_phoneme_b = PhenomeFromEnum(phoneme_b); assert(efx_phoneme_b.has_value()); al_effect_props_.Vmorpher.PhonemeB = *efx_phoneme_b; } -void EaxVocalMorpherEffect::set_efx_phoneme_b_coarse_tuning() +void EaxVocalMorpherEffect::set_efx_phoneme_b_coarse_tuning() noexcept { - const auto phoneme_b_coarse_tuning = clamp( - static_cast(eax_.lPhonemeBCoarseTuning), + al_effect_props_.Vmorpher.PhonemeBCoarseTuning = clamp( + static_cast(props_.lPhonemeBCoarseTuning), AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING, AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING); - - al_effect_props_.Vmorpher.PhonemeBCoarseTuning = phoneme_b_coarse_tuning; } void EaxVocalMorpherEffect::set_efx_waveform() { const auto waveform = clamp( - static_cast(eax_.ulWaveform), + static_cast(props_.ulWaveform), AL_VOCAL_MORPHER_MIN_WAVEFORM, AL_VOCAL_MORPHER_MAX_WAVEFORM); - const auto wfx_waveform = WaveformFromEmum(waveform); assert(wfx_waveform.has_value()); al_effect_props_.Vmorpher.Waveform = *wfx_waveform; } -void EaxVocalMorpherEffect::set_efx_rate() +void EaxVocalMorpherEffect::set_efx_rate() noexcept { - const auto rate = clamp( - eax_.flRate, + al_effect_props_.Vmorpher.Rate = clamp( + props_.flRate, AL_VOCAL_MORPHER_MIN_RATE, AL_VOCAL_MORPHER_MAX_RATE); - - al_effect_props_.Vmorpher.Rate = rate; } void EaxVocalMorpherEffect::set_efx_defaults() @@ -444,343 +445,134 @@ void EaxVocalMorpherEffect::set_efx_defaults() set_efx_rate(); } -void EaxVocalMorpherEffect::get(const EaxEaxCall& eax_call) +void EaxVocalMorpherEffect::get(const EaxCall& call, const Props& props) { - switch(eax_call.get_property_id()) + switch(call.get_property_id()) { case EAXVOCALMORPHER_NONE: break; case EAXVOCALMORPHER_ALLPARAMETERS: - eax_call.set_value(eax_); + call.set_value(props); break; case EAXVOCALMORPHER_PHONEMEA: - eax_call.set_value(eax_.ulPhonemeA); + call.set_value(props.ulPhonemeA); break; case EAXVOCALMORPHER_PHONEMEACOARSETUNING: - eax_call.set_value(eax_.lPhonemeACoarseTuning); + call.set_value(props.lPhonemeACoarseTuning); break; case EAXVOCALMORPHER_PHONEMEB: - eax_call.set_value(eax_.ulPhonemeB); + call.set_value(props.ulPhonemeB); break; case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: - eax_call.set_value(eax_.lPhonemeBCoarseTuning); + call.set_value(props.lPhonemeBCoarseTuning); break; case EAXVOCALMORPHER_WAVEFORM: - eax_call.set_value(eax_.ulWaveform); + call.set_value(props.ulWaveform); break; case EAXVOCALMORPHER_RATE: - eax_call.set_value(eax_.flRate); + call.set_value(props.flRate); break; default: - throw EaxVocalMorpherEffectException{"Unsupported property id."}; + fail_unknown_property_id(); } } -void EaxVocalMorpherEffect::validate_phoneme_a( - unsigned long ulPhonemeA) +void EaxVocalMorpherEffect::set(const EaxCall& call, Props& props) { - eax_validate_range( - "Phoneme A", - ulPhonemeA, - EAXVOCALMORPHER_MINPHONEMEA, - EAXVOCALMORPHER_MAXPHONEMEA); -} - -void EaxVocalMorpherEffect::validate_phoneme_a_coarse_tuning( - long lPhonemeACoarseTuning) -{ - eax_validate_range( - "Phoneme A Coarse Tuning", - lPhonemeACoarseTuning, - EAXVOCALMORPHER_MINPHONEMEACOARSETUNING, - EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING); -} - -void EaxVocalMorpherEffect::validate_phoneme_b( - unsigned long ulPhonemeB) -{ - eax_validate_range( - "Phoneme B", - ulPhonemeB, - EAXVOCALMORPHER_MINPHONEMEB, - EAXVOCALMORPHER_MAXPHONEMEB); -} - -void EaxVocalMorpherEffect::validate_phoneme_b_coarse_tuning( - long lPhonemeBCoarseTuning) -{ - eax_validate_range( - "Phoneme B Coarse Tuning", - lPhonemeBCoarseTuning, - EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING, - EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING); -} - -void EaxVocalMorpherEffect::validate_waveform( - unsigned long ulWaveform) -{ - eax_validate_range( - "Waveform", - ulWaveform, - EAXVOCALMORPHER_MINWAVEFORM, - EAXVOCALMORPHER_MAXWAVEFORM); -} - -void EaxVocalMorpherEffect::validate_rate( - float flRate) -{ - eax_validate_range( - "Rate", - flRate, - EAXVOCALMORPHER_MINRATE, - EAXVOCALMORPHER_MAXRATE); -} - -void EaxVocalMorpherEffect::validate_all( - const EAXVOCALMORPHERPROPERTIES& all) -{ - validate_phoneme_a(all.ulPhonemeA); - validate_phoneme_a_coarse_tuning(all.lPhonemeACoarseTuning); - validate_phoneme_b(all.ulPhonemeB); - validate_phoneme_b_coarse_tuning(all.lPhonemeBCoarseTuning); - validate_waveform(all.ulWaveform); - validate_rate(all.flRate); -} - -void EaxVocalMorpherEffect::defer_phoneme_a( - unsigned long ulPhonemeA) -{ - eax_d_.ulPhonemeA = ulPhonemeA; - eax_dirty_flags_.ulPhonemeA = (eax_.ulPhonemeA != eax_d_.ulPhonemeA); -} - -void EaxVocalMorpherEffect::defer_phoneme_a_coarse_tuning( - long lPhonemeACoarseTuning) -{ - eax_d_.lPhonemeACoarseTuning = lPhonemeACoarseTuning; - eax_dirty_flags_.lPhonemeACoarseTuning = (eax_.lPhonemeACoarseTuning != eax_d_.lPhonemeACoarseTuning); -} - -void EaxVocalMorpherEffect::defer_phoneme_b( - unsigned long ulPhonemeB) -{ - eax_d_.ulPhonemeB = ulPhonemeB; - eax_dirty_flags_.ulPhonemeB = (eax_.ulPhonemeB != eax_d_.ulPhonemeB); -} - -void EaxVocalMorpherEffect::defer_phoneme_b_coarse_tuning( - long lPhonemeBCoarseTuning) -{ - eax_d_.lPhonemeBCoarseTuning = lPhonemeBCoarseTuning; - eax_dirty_flags_.lPhonemeBCoarseTuning = (eax_.lPhonemeBCoarseTuning != eax_d_.lPhonemeBCoarseTuning); -} - -void EaxVocalMorpherEffect::defer_waveform( - unsigned long ulWaveform) -{ - eax_d_.ulWaveform = ulWaveform; - eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform); -} - -void EaxVocalMorpherEffect::defer_rate( - float flRate) -{ - eax_d_.flRate = flRate; - eax_dirty_flags_.flRate = (eax_.flRate != eax_d_.flRate); -} - -void EaxVocalMorpherEffect::defer_all( - const EAXVOCALMORPHERPROPERTIES& all) -{ - defer_phoneme_a(all.ulPhonemeA); - defer_phoneme_a_coarse_tuning(all.lPhonemeACoarseTuning); - defer_phoneme_b(all.ulPhonemeB); - defer_phoneme_b_coarse_tuning(all.lPhonemeBCoarseTuning); - defer_waveform(all.ulWaveform); - defer_rate(all.flRate); -} - -void EaxVocalMorpherEffect::defer_phoneme_a( - const EaxEaxCall& eax_call) -{ - const auto& phoneme_a = eax_call.get_value(); - - validate_phoneme_a(phoneme_a); - defer_phoneme_a(phoneme_a); -} - -void EaxVocalMorpherEffect::defer_phoneme_a_coarse_tuning( - const EaxEaxCall& eax_call) -{ - const auto& phoneme_a_coarse_tuning = eax_call.get_value< - EaxVocalMorpherEffectException, - const decltype(EAXVOCALMORPHERPROPERTIES::lPhonemeACoarseTuning) - >(); - - validate_phoneme_a_coarse_tuning(phoneme_a_coarse_tuning); - defer_phoneme_a_coarse_tuning(phoneme_a_coarse_tuning); -} - -void EaxVocalMorpherEffect::defer_phoneme_b( - const EaxEaxCall& eax_call) -{ - const auto& phoneme_b = eax_call.get_value< - EaxVocalMorpherEffectException, - const decltype(EAXVOCALMORPHERPROPERTIES::ulPhonemeB) - >(); - - validate_phoneme_b(phoneme_b); - defer_phoneme_b(phoneme_b); -} + switch(call.get_property_id()) + { + case EAXVOCALMORPHER_NONE: + break; -void EaxVocalMorpherEffect::defer_phoneme_b_coarse_tuning( - const EaxEaxCall& eax_call) -{ - const auto& phoneme_b_coarse_tuning = eax_call.get_value< - EaxVocalMorpherEffectException, - const decltype(EAXVOCALMORPHERPROPERTIES::lPhonemeBCoarseTuning) - >(); + case EAXVOCALMORPHER_ALLPARAMETERS: + defer(call, props); + break; - validate_phoneme_b_coarse_tuning(phoneme_b_coarse_tuning); - defer_phoneme_b_coarse_tuning(phoneme_b_coarse_tuning); -} + case EAXVOCALMORPHER_PHONEMEA: + defer(call, props.ulPhonemeA); + break; -void EaxVocalMorpherEffect::defer_waveform( - const EaxEaxCall& eax_call) -{ - const auto& waveform = eax_call.get_value< - EaxVocalMorpherEffectException, - const decltype(EAXVOCALMORPHERPROPERTIES::ulWaveform) - >(); + case EAXVOCALMORPHER_PHONEMEACOARSETUNING: + defer(call, props.lPhonemeACoarseTuning); + break; - validate_waveform(waveform); - defer_waveform(waveform); -} + case EAXVOCALMORPHER_PHONEMEB: + defer(call, props.ulPhonemeB); + break; -void EaxVocalMorpherEffect::defer_rate( - const EaxEaxCall& eax_call) -{ - const auto& rate = eax_call.get_value< - EaxVocalMorpherEffectException, - const decltype(EAXVOCALMORPHERPROPERTIES::flRate) - >(); + case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: + defer(call, props.lPhonemeBCoarseTuning); + break; - validate_rate(rate); - defer_rate(rate); -} + case EAXVOCALMORPHER_WAVEFORM: + defer(call, props.ulWaveform); + break; -void EaxVocalMorpherEffect::defer_all( - const EaxEaxCall& eax_call) -{ - const auto& all = eax_call.get_value< - EaxVocalMorpherEffectException, - const EAXVOCALMORPHERPROPERTIES - >(); + case EAXVOCALMORPHER_RATE: + defer(call, props.flRate); + break; - validate_all(all); - defer_all(all); + default: + fail_unknown_property_id(); + } } -// [[nodiscard]] -bool EaxVocalMorpherEffect::apply_deferred() +bool EaxVocalMorpherEffect::commit_props(const Props& props) { - if (eax_dirty_flags_ == EaxVocalMorpherEffectDirtyFlags{}) - { - return false; - } + auto is_dirty = false; - eax_ = eax_d_; - - if (eax_dirty_flags_.ulPhonemeA) + if (props_.ulPhonemeA != props.ulPhonemeA) { + is_dirty = true; set_efx_phoneme_a(); } - if (eax_dirty_flags_.lPhonemeACoarseTuning) + if (props_.lPhonemeACoarseTuning != props.lPhonemeACoarseTuning) { + is_dirty = true; set_efx_phoneme_a_coarse_tuning(); } - if (eax_dirty_flags_.ulPhonemeB) + if (props_.ulPhonemeB != props.ulPhonemeB) { + is_dirty = true; set_efx_phoneme_b(); } - if (eax_dirty_flags_.lPhonemeBCoarseTuning) + if (props_.lPhonemeBCoarseTuning != props.lPhonemeBCoarseTuning) { + is_dirty = true; set_efx_phoneme_b_coarse_tuning(); } - if (eax_dirty_flags_.ulWaveform) + if (props_.ulWaveform != props.ulWaveform) { + is_dirty = true; set_efx_waveform(); } - if (eax_dirty_flags_.flRate) + if (props_.flRate != props.flRate) { + is_dirty = true; set_efx_rate(); } - eax_dirty_flags_ = EaxVocalMorpherEffectDirtyFlags{}; - - return true; -} - -void EaxVocalMorpherEffect::set(const EaxEaxCall& eax_call) -{ - switch(eax_call.get_property_id()) - { - case EAXVOCALMORPHER_NONE: - break; - - case EAXVOCALMORPHER_ALLPARAMETERS: - defer_all(eax_call); - break; - - case EAXVOCALMORPHER_PHONEMEA: - defer_phoneme_a(eax_call); - break; - - case EAXVOCALMORPHER_PHONEMEACOARSETUNING: - defer_phoneme_a_coarse_tuning(eax_call); - break; - - case EAXVOCALMORPHER_PHONEMEB: - defer_phoneme_b(eax_call); - break; - - case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: - defer_phoneme_b_coarse_tuning(eax_call); - break; - - case EAXVOCALMORPHER_WAVEFORM: - defer_waveform(eax_call); - break; - - case EAXVOCALMORPHER_RATE: - defer_rate(eax_call); - break; - - default: - throw EaxVocalMorpherEffectException{"Unsupported property id."}; - } + return is_dirty; } } // namespace - -EaxEffectUPtr eax_create_eax_vocal_morpher_effect() +EaxEffectUPtr eax_create_eax_vocal_morpher_effect(const EaxCall& call) { - return std::make_unique(); + return eax_create_eax4_effect(call); } #endif // ALSOFT_EAX diff --git a/al/source.cpp b/al/source.cpp index 604d4566..f2c7e2f8 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -4068,10 +4068,10 @@ void ALsource::eax_update_primary_fx_slot_id() } void ALsource::eax_defer_active_fx_slots( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto active_fx_slots_span = - eax_call.get_values(); + call.get_values(); const auto fx_slot_count = active_fx_slots_span.size(); @@ -4436,10 +4436,10 @@ void ALsource::eax_defer_send_all( } void ALsource::eax_defer_send( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto eax_all_span = - eax_call.get_values(); + call.get_values(); const auto count = eax_all_span.size(); @@ -4463,10 +4463,10 @@ void ALsource::eax_defer_send( } void ALsource::eax_defer_send_exclusion_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto eax_all_span = - eax_call.get_values(); + call.get_values(); const auto count = eax_all_span.size(); @@ -4490,10 +4490,10 @@ void ALsource::eax_defer_send_exclusion_all( } void ALsource::eax_defer_send_occlusion_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto eax_all_span = - eax_call.get_values(); + call.get_values(); const auto count = eax_all_span.size(); @@ -4517,10 +4517,10 @@ void ALsource::eax_defer_send_occlusion_all( } void ALsource::eax_defer_send_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto eax_all_span = - eax_call.get_values(); + call.get_values(); const auto count = eax_all_span.size(); @@ -5074,6 +5074,29 @@ void ALsource::eax_defer_source_speaker_level_all( } } +ALuint ALsource::eax2_translate_property_id(const EaxCall& call) +{ + switch (call.get_property_id()) + { + case DSPROPERTY_EAX20BUFFER_NONE: return EAXSOURCE_NONE; + case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS: return EAXSOURCE_ALLPARAMETERS; + case DSPROPERTY_EAX20BUFFER_DIRECT: return EAXSOURCE_DIRECT; + case DSPROPERTY_EAX20BUFFER_DIRECTHF: return EAXSOURCE_DIRECTHF; + case DSPROPERTY_EAX20BUFFER_ROOM: return EAXSOURCE_ROOM; + case DSPROPERTY_EAX20BUFFER_ROOMHF: return EAXSOURCE_ROOMHF; + case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR: return EAXSOURCE_ROOMROLLOFFFACTOR; + case DSPROPERTY_EAX20BUFFER_OBSTRUCTION: return EAXSOURCE_OBSTRUCTION; + case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO: return EAXSOURCE_OBSTRUCTIONLFRATIO; + case DSPROPERTY_EAX20BUFFER_OCCLUSION: return EAXSOURCE_OCCLUSION; + case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO: return EAXSOURCE_OCCLUSIONLFRATIO; + case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO: return EAXSOURCE_OCCLUSIONROOMRATIO; + case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF: return EAXSOURCE_OUTSIDEVOLUMEHF; + case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR: return EAXSOURCE_AIRABSORPTIONFACTOR; + case DSPROPERTY_EAX20BUFFER_FLAGS: return EAXSOURCE_FLAGS; + default: eax_fail("Unknown property id."); + } +} + void ALsource::eax1_set_efx() { const auto primary_fx_slot_index = eax_al_context_->eax_get_primary_fx_slot_index(); @@ -5088,9 +5111,9 @@ void ALsource::eax1_set_efx() mPropsDirty = true; } -void ALsource::eax1_set_reverb_mix(const EaxEaxCall& eax_call) +void ALsource::eax1_set_reverb_mix(const EaxCall& call) { - const auto reverb_mix = eax_call.get_value(); + const auto reverb_mix = call.get_value(); eax1_validate_reverb_mix(reverb_mix); if (eax1_.fMix == reverb_mix) @@ -5101,253 +5124,253 @@ void ALsource::eax1_set_reverb_mix(const EaxEaxCall& eax_call) } void ALsource::eax_defer_source_direct( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto direct = - eax_call.get_value(); + call.get_value(); eax_validate_source_direct(direct); eax_defer_source_direct(direct); } void ALsource::eax_defer_source_direct_hf( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto direct_hf = - eax_call.get_value(); + call.get_value(); eax_validate_source_direct_hf(direct_hf); eax_defer_source_direct_hf(direct_hf); } void ALsource::eax_defer_source_room( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto room = - eax_call.get_value(); + call.get_value(); eax_validate_source_room(room); eax_defer_source_room(room); } void ALsource::eax_defer_source_room_hf( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto room_hf = - eax_call.get_value(); + call.get_value(); eax_validate_source_room_hf(room_hf); eax_defer_source_room_hf(room_hf); } void ALsource::eax_defer_source_obstruction( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto obstruction = - eax_call.get_value(); + call.get_value(); eax_validate_source_obstruction(obstruction); eax_defer_source_obstruction(obstruction); } void ALsource::eax_defer_source_obstruction_lf_ratio( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto obstruction_lf_ratio = - eax_call.get_value(); + call.get_value(); eax_validate_source_obstruction_lf_ratio(obstruction_lf_ratio); eax_defer_source_obstruction_lf_ratio(obstruction_lf_ratio); } void ALsource::eax_defer_source_occlusion( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto occlusion = - eax_call.get_value(); + call.get_value(); eax_validate_source_occlusion(occlusion); eax_defer_source_occlusion(occlusion); } void ALsource::eax_defer_source_occlusion_lf_ratio( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto occlusion_lf_ratio = - eax_call.get_value(); + call.get_value(); eax_validate_source_occlusion_lf_ratio(occlusion_lf_ratio); eax_defer_source_occlusion_lf_ratio(occlusion_lf_ratio); } void ALsource::eax_defer_source_occlusion_room_ratio( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto occlusion_room_ratio = - eax_call.get_value(); + call.get_value(); eax_validate_source_occlusion_room_ratio(occlusion_room_ratio); eax_defer_source_occlusion_room_ratio(occlusion_room_ratio); } void ALsource::eax_defer_source_occlusion_direct_ratio( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto occlusion_direct_ratio = - eax_call.get_value(); + call.get_value(); eax_validate_source_occlusion_direct_ratio(occlusion_direct_ratio); eax_defer_source_occlusion_direct_ratio(occlusion_direct_ratio); } void ALsource::eax_defer_source_exclusion( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto exclusion = - eax_call.get_value(); + call.get_value(); eax_validate_source_exclusion(exclusion); eax_defer_source_exclusion(exclusion); } void ALsource::eax_defer_source_exclusion_lf_ratio( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto exclusion_lf_ratio = - eax_call.get_value(); + call.get_value(); eax_validate_source_exclusion_lf_ratio(exclusion_lf_ratio); eax_defer_source_exclusion_lf_ratio(exclusion_lf_ratio); } void ALsource::eax_defer_source_outside_volume_hf( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto outside_volume_hf = - eax_call.get_value(); + call.get_value(); eax_validate_source_outside_volume_hf(outside_volume_hf); eax_defer_source_outside_volume_hf(outside_volume_hf); } void ALsource::eax_defer_source_doppler_factor( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto doppler_factor = - eax_call.get_value(); + call.get_value(); eax_validate_source_doppler_factor(doppler_factor); eax_defer_source_doppler_factor(doppler_factor); } void ALsource::eax_defer_source_rolloff_factor( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto rolloff_factor = - eax_call.get_value(); + call.get_value(); eax_validate_source_rolloff_factor(rolloff_factor); eax_defer_source_rolloff_factor(rolloff_factor); } void ALsource::eax_defer_source_room_rolloff_factor( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto room_rolloff_factor = - eax_call.get_value(); + call.get_value(); eax_validate_source_room_rolloff_factor(room_rolloff_factor); eax_defer_source_room_rolloff_factor(room_rolloff_factor); } void ALsource::eax_defer_source_air_absorption_factor( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto air_absorption_factor = - eax_call.get_value(); + call.get_value(); eax_validate_source_air_absorption_factor(air_absorption_factor); eax_defer_source_air_absorption_factor(air_absorption_factor); } void ALsource::eax_defer_source_flags( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto flags = - eax_call.get_value(); + call.get_value(); - eax_validate_source_flags(flags, eax_call.get_version()); + eax_validate_source_flags(flags, call.get_version()); eax_defer_source_flags(flags); } void ALsource::eax_defer_source_macro_fx_factor( - const EaxEaxCall& eax_call) + const EaxCall& call) { const auto macro_fx_factor = - eax_call.get_value(); + call.get_value(); eax_validate_source_macro_fx_factor(macro_fx_factor); eax_defer_source_macro_fx_factor(macro_fx_factor); } void ALsource::eax_defer_source_2d_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - const auto all = eax_call.get_value(); + const auto all = call.get_value(); - eax_validate_source_2d_all(all, eax_call.get_version()); + eax_validate_source_2d_all(all, call.get_version()); eax_defer_source_2d_all(all); } void ALsource::eax_defer_source_obstruction_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - const auto all = eax_call.get_value(); + const auto all = call.get_value(); eax_validate_source_obstruction_all(all); eax_defer_source_obstruction_all(all); } void ALsource::eax_defer_source_exclusion_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - const auto all = eax_call.get_value(); + const auto all = call.get_value(); eax_validate_source_exclusion_all(all); eax_defer_source_exclusion_all(all); } void ALsource::eax_defer_source_occlusion_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - const auto all = eax_call.get_value(); + const auto all = call.get_value(); eax_validate_source_occlusion_all(all); eax_defer_source_occlusion_all(all); } void ALsource::eax_defer_source_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - const auto eax_version = eax_call.get_version(); + const auto eax_version = call.get_version(); if (eax_version == 2) { - const auto all = eax_call.get_value(); + const auto all = call.get_value(); eax_validate_source_all(all, eax_version); eax_defer_source_all(all); } else if (eax_version < 5) { - const auto all = eax_call.get_value(); + const auto all = call.get_value(); eax_validate_source_all(all, eax_version); eax_defer_source_all(all); } else { - const auto all = eax_call.get_value(); + const auto all = call.get_value(); eax_validate_source_all(all, eax_version); eax_defer_source_all(all); @@ -5355,9 +5378,9 @@ void ALsource::eax_defer_source_all( } void ALsource::eax_defer_source_speaker_level_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - const auto speaker_level_properties = eax_call.get_value(); + const auto speaker_level_properties = call.get_value(); eax_validate_source_speaker_level_all(speaker_level_properties); eax_defer_source_speaker_level_all(speaker_level_properties); @@ -5433,13 +5456,13 @@ void ALsource::eax_set_speaker_levels() // TODO } -void ALsource::eax1_set(const EaxEaxCall& eax_call) +void ALsource::eax1_set(const EaxCall& call) { - switch (eax_call.get_property_id()) + switch (call.get_property_id()) { case DSPROPERTY_EAXBUFFER_ALL: case DSPROPERTY_EAXBUFFER_REVERBMIX: - eax1_set_reverb_mix(eax_call); + eax1_set_reverb_mix(call); break; default: @@ -5534,137 +5557,141 @@ void ALsource::eax_apply_deferred() } void ALsource::eax_set( - const EaxEaxCall& eax_call) + const EaxCall& call) { - if (eax_call.get_version() == 1) + const auto version = call.get_version(); + + if (version == 1) { - eax1_set(eax_call); + eax1_set(call); return; } - switch (eax_call.get_property_id()) + const auto property_id = (version == 2 ? eax2_translate_property_id(call) : call.get_property_id()); + + switch (property_id) { case EAXSOURCE_NONE: break; case EAXSOURCE_ALLPARAMETERS: - eax_defer_source_all(eax_call); + eax_defer_source_all(call); break; case EAXSOURCE_OBSTRUCTIONPARAMETERS: - eax_defer_source_obstruction_all(eax_call); + eax_defer_source_obstruction_all(call); break; case EAXSOURCE_OCCLUSIONPARAMETERS: - eax_defer_source_occlusion_all(eax_call); + eax_defer_source_occlusion_all(call); break; case EAXSOURCE_EXCLUSIONPARAMETERS: - eax_defer_source_exclusion_all(eax_call); + eax_defer_source_exclusion_all(call); break; case EAXSOURCE_DIRECT: - eax_defer_source_direct(eax_call); + eax_defer_source_direct(call); break; case EAXSOURCE_DIRECTHF: - eax_defer_source_direct_hf(eax_call); + eax_defer_source_direct_hf(call); break; case EAXSOURCE_ROOM: - eax_defer_source_room(eax_call); + eax_defer_source_room(call); break; case EAXSOURCE_ROOMHF: - eax_defer_source_room_hf(eax_call); + eax_defer_source_room_hf(call); break; case EAXSOURCE_OBSTRUCTION: - eax_defer_source_obstruction(eax_call); + eax_defer_source_obstruction(call); break; case EAXSOURCE_OBSTRUCTIONLFRATIO: - eax_defer_source_obstruction_lf_ratio(eax_call); + eax_defer_source_obstruction_lf_ratio(call); break; case EAXSOURCE_OCCLUSION: - eax_defer_source_occlusion(eax_call); + eax_defer_source_occlusion(call); break; case EAXSOURCE_OCCLUSIONLFRATIO: - eax_defer_source_occlusion_lf_ratio(eax_call); + eax_defer_source_occlusion_lf_ratio(call); break; case EAXSOURCE_OCCLUSIONROOMRATIO: - eax_defer_source_occlusion_room_ratio(eax_call); + eax_defer_source_occlusion_room_ratio(call); break; case EAXSOURCE_OCCLUSIONDIRECTRATIO: - eax_defer_source_occlusion_direct_ratio(eax_call); + eax_defer_source_occlusion_direct_ratio(call); break; case EAXSOURCE_EXCLUSION: - eax_defer_source_exclusion(eax_call); + eax_defer_source_exclusion(call); break; case EAXSOURCE_EXCLUSIONLFRATIO: - eax_defer_source_exclusion_lf_ratio(eax_call); + eax_defer_source_exclusion_lf_ratio(call); break; case EAXSOURCE_OUTSIDEVOLUMEHF: - eax_defer_source_outside_volume_hf(eax_call); + eax_defer_source_outside_volume_hf(call); break; case EAXSOURCE_DOPPLERFACTOR: - eax_defer_source_doppler_factor(eax_call); + eax_defer_source_doppler_factor(call); break; case EAXSOURCE_ROLLOFFFACTOR: - eax_defer_source_rolloff_factor(eax_call); + eax_defer_source_rolloff_factor(call); break; case EAXSOURCE_ROOMROLLOFFFACTOR: - eax_defer_source_room_rolloff_factor(eax_call); + eax_defer_source_room_rolloff_factor(call); break; case EAXSOURCE_AIRABSORPTIONFACTOR: - eax_defer_source_air_absorption_factor(eax_call); + eax_defer_source_air_absorption_factor(call); break; case EAXSOURCE_FLAGS: - eax_defer_source_flags(eax_call); + eax_defer_source_flags(call); break; case EAXSOURCE_SENDPARAMETERS: - eax_defer_send(eax_call); + eax_defer_send(call); break; case EAXSOURCE_ALLSENDPARAMETERS: - eax_defer_send_all(eax_call); + eax_defer_send_all(call); break; case EAXSOURCE_OCCLUSIONSENDPARAMETERS: - eax_defer_send_occlusion_all(eax_call); + eax_defer_send_occlusion_all(call); break; case EAXSOURCE_EXCLUSIONSENDPARAMETERS: - eax_defer_send_exclusion_all(eax_call); + eax_defer_send_exclusion_all(call); break; case EAXSOURCE_ACTIVEFXSLOTID: - eax_defer_active_fx_slots(eax_call); + eax_defer_active_fx_slots(call); break; case EAXSOURCE_MACROFXFACTOR: - eax_defer_source_macro_fx_factor(eax_call); + eax_defer_source_macro_fx_factor(call); break; case EAXSOURCE_SPEAKERLEVELS: - eax_defer_source_speaker_level_all(eax_call); + eax_defer_source_speaker_level_all(call); break; case EAXSOURCE_ALL2DPARAMETERS: - eax_defer_source_2d_all(eax_call); + eax_defer_source_2d_all(call); break; default: @@ -5754,13 +5781,13 @@ void ALsource::eax_copy_send( dst_send.flExclusionLFRatio = src_send.flExclusionLFRatio; } -void ALsource::eax1_get(const EaxEaxCall& eax_call) +void ALsource::eax1_get(const EaxCall& call) { - switch (eax_call.get_property_id()) + switch (call.get_property_id()) { case DSPROPERTY_EAXBUFFER_ALL: case DSPROPERTY_EAXBUFFER_REVERBMIX: - eax_call.set_value(eax1_); + call.set_value(eax1_); break; default: @@ -5769,7 +5796,7 @@ void ALsource::eax1_get(const EaxEaxCall& eax_call) } void ALsource::eax_api_get_source_all_v2( - const EaxEaxCall& eax_call) + const EaxCall& call) { auto eax_2_all = EAX20BUFFERPROPERTIES{}; eax_2_all.lDirect = eax_.source.lDirect; @@ -5786,37 +5813,37 @@ void ALsource::eax_api_get_source_all_v2( eax_2_all.flAirAbsorptionFactor = eax_.source.flAirAbsorptionFactor; eax_2_all.dwFlags = eax_.source.ulFlags; - eax_call.set_value(eax_2_all); + call.set_value(eax_2_all); } void ALsource::eax_api_get_source_all_v3( - const EaxEaxCall& eax_call) + const EaxCall& call) { - eax_call.set_value(static_cast(eax_.source)); + call.set_value(static_cast(eax_.source)); } void ALsource::eax_api_get_source_all_v5( - const EaxEaxCall& eax_call) + const EaxCall& call) { - eax_call.set_value(eax_.source); + call.set_value(eax_.source); } void ALsource::eax_api_get_source_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - switch (eax_call.get_version()) + switch (call.get_version()) { case 2: - eax_api_get_source_all_v2(eax_call); + eax_api_get_source_all_v2(call); break; case 3: case 4: - eax_api_get_source_all_v3(eax_call); + eax_api_get_source_all_v3(call); break; case 5: - eax_api_get_source_all_v5(eax_call); + eax_api_get_source_all_v5(call); break; default: @@ -5825,17 +5852,17 @@ void ALsource::eax_api_get_source_all( } void ALsource::eax_api_get_source_all_obstruction( - const EaxEaxCall& eax_call) + const EaxCall& call) { auto eax_obstruction_all = EAXOBSTRUCTIONPROPERTIES{}; eax_obstruction_all.lObstruction = eax_.source.lObstruction; eax_obstruction_all.flObstructionLFRatio = eax_.source.flObstructionLFRatio; - eax_call.set_value(eax_obstruction_all); + call.set_value(eax_obstruction_all); } void ALsource::eax_api_get_source_all_occlusion( - const EaxEaxCall& eax_call) + const EaxCall& call) { auto eax_occlusion_all = EAXOCCLUSIONPROPERTIES{}; eax_occlusion_all.lOcclusion = eax_.source.lOcclusion; @@ -5843,35 +5870,35 @@ void ALsource::eax_api_get_source_all_occlusion( eax_occlusion_all.flOcclusionRoomRatio = eax_.source.flOcclusionRoomRatio; eax_occlusion_all.flOcclusionDirectRatio = eax_.source.flOcclusionDirectRatio; - eax_call.set_value(eax_occlusion_all); + call.set_value(eax_occlusion_all); } void ALsource::eax_api_get_source_all_exclusion( - const EaxEaxCall& eax_call) + const EaxCall& call) { auto eax_exclusion_all = EAXEXCLUSIONPROPERTIES{}; eax_exclusion_all.lExclusion = eax_.source.lExclusion; eax_exclusion_all.flExclusionLFRatio = eax_.source.flExclusionLFRatio; - eax_call.set_value(eax_exclusion_all); + call.set_value(eax_exclusion_all); } void ALsource::eax_api_get_source_active_fx_slot_id( - const EaxEaxCall& eax_call) + const EaxCall& call) { - switch (eax_call.get_version()) + switch (call.get_version()) { case 4: { const auto& active_fx_slots = reinterpret_cast(eax_.active_fx_slots); - eax_call.set_value(active_fx_slots); + call.set_value(active_fx_slots); } break; case 5: { const auto& active_fx_slots = reinterpret_cast(eax_.active_fx_slots); - eax_call.set_value(active_fx_slots); + call.set_value(active_fx_slots); } break; @@ -5881,7 +5908,7 @@ void ALsource::eax_api_get_source_active_fx_slot_id( } void ALsource::eax_api_get_source_all_2d( - const EaxEaxCall& eax_call) + const EaxCall& call) { auto eax_2d_all = EAXSOURCE2DPROPERTIES{}; eax_2d_all.lDirect = eax_.source.lDirect; @@ -5890,13 +5917,13 @@ void ALsource::eax_api_get_source_all_2d( eax_2d_all.lRoomHF = eax_.source.lRoomHF; eax_2d_all.ulFlags = eax_.source.ulFlags; - eax_call.set_value(eax_2d_all); + call.set_value(eax_2d_all); } void ALsource::eax_api_get_source_speaker_level_all( - const EaxEaxCall& eax_call) + const EaxCall& call) { - auto& all = eax_call.get_value(); + auto& all = call.get_value(); eax_validate_source_speaker_id(all.lSpeakerID); const auto speaker_index = static_cast(all.lSpeakerID - 1); @@ -5904,137 +5931,141 @@ void ALsource::eax_api_get_source_speaker_level_all( } void ALsource::eax_get( - const EaxEaxCall& eax_call) + const EaxCall& call) { - if (eax_call.get_version() == 1) + const auto version = call.get_version(); + + if (version == 1) { - eax1_get(eax_call); + eax1_get(call); return; } - switch (eax_call.get_property_id()) + const auto property_id = (version == 2 ? eax2_translate_property_id(call) : call.get_property_id()); + + switch (property_id) { case EAXSOURCE_NONE: break; case EAXSOURCE_ALLPARAMETERS: - eax_api_get_source_all(eax_call); + eax_api_get_source_all(call); break; case EAXSOURCE_OBSTRUCTIONPARAMETERS: - eax_api_get_source_all_obstruction(eax_call); + eax_api_get_source_all_obstruction(call); break; case EAXSOURCE_OCCLUSIONPARAMETERS: - eax_api_get_source_all_occlusion(eax_call); + eax_api_get_source_all_occlusion(call); break; case EAXSOURCE_EXCLUSIONPARAMETERS: - eax_api_get_source_all_exclusion(eax_call); + eax_api_get_source_all_exclusion(call); break; case EAXSOURCE_DIRECT: - eax_call.set_value(eax_.source.lDirect); + call.set_value(eax_.source.lDirect); break; case EAXSOURCE_DIRECTHF: - eax_call.set_value(eax_.source.lDirectHF); + call.set_value(eax_.source.lDirectHF); break; case EAXSOURCE_ROOM: - eax_call.set_value(eax_.source.lRoom); + call.set_value(eax_.source.lRoom); break; case EAXSOURCE_ROOMHF: - eax_call.set_value(eax_.source.lRoomHF); + call.set_value(eax_.source.lRoomHF); break; case EAXSOURCE_OBSTRUCTION: - eax_call.set_value(eax_.source.lObstruction); + call.set_value(eax_.source.lObstruction); break; case EAXSOURCE_OBSTRUCTIONLFRATIO: - eax_call.set_value(eax_.source.flObstructionLFRatio); + call.set_value(eax_.source.flObstructionLFRatio); break; case EAXSOURCE_OCCLUSION: - eax_call.set_value(eax_.source.lOcclusion); + call.set_value(eax_.source.lOcclusion); break; case EAXSOURCE_OCCLUSIONLFRATIO: - eax_call.set_value(eax_.source.flOcclusionLFRatio); + call.set_value(eax_.source.flOcclusionLFRatio); break; case EAXSOURCE_OCCLUSIONROOMRATIO: - eax_call.set_value(eax_.source.flOcclusionRoomRatio); + call.set_value(eax_.source.flOcclusionRoomRatio); break; case EAXSOURCE_OCCLUSIONDIRECTRATIO: - eax_call.set_value(eax_.source.flOcclusionDirectRatio); + call.set_value(eax_.source.flOcclusionDirectRatio); break; case EAXSOURCE_EXCLUSION: - eax_call.set_value(eax_.source.lExclusion); + call.set_value(eax_.source.lExclusion); break; case EAXSOURCE_EXCLUSIONLFRATIO: - eax_call.set_value(eax_.source.flExclusionLFRatio); + call.set_value(eax_.source.flExclusionLFRatio); break; case EAXSOURCE_OUTSIDEVOLUMEHF: - eax_call.set_value(eax_.source.lOutsideVolumeHF); + call.set_value(eax_.source.lOutsideVolumeHF); break; case EAXSOURCE_DOPPLERFACTOR: - eax_call.set_value(eax_.source.flDopplerFactor); + call.set_value(eax_.source.flDopplerFactor); break; case EAXSOURCE_ROLLOFFFACTOR: - eax_call.set_value(eax_.source.flRolloffFactor); + call.set_value(eax_.source.flRolloffFactor); break; case EAXSOURCE_ROOMROLLOFFFACTOR: - eax_call.set_value(eax_.source.flRoomRolloffFactor); + call.set_value(eax_.source.flRoomRolloffFactor); break; case EAXSOURCE_AIRABSORPTIONFACTOR: - eax_call.set_value(eax_.source.flAirAbsorptionFactor); + call.set_value(eax_.source.flAirAbsorptionFactor); break; case EAXSOURCE_FLAGS: - eax_call.set_value(eax_.source.ulFlags); + call.set_value(eax_.source.ulFlags); break; case EAXSOURCE_SENDPARAMETERS: - eax_api_get_send_properties(eax_call); + eax_api_get_send_properties(call); break; case EAXSOURCE_ALLSENDPARAMETERS: - eax_api_get_send_properties(eax_call); + eax_api_get_send_properties(call); break; case EAXSOURCE_OCCLUSIONSENDPARAMETERS: - eax_api_get_send_properties(eax_call); + eax_api_get_send_properties(call); break; case EAXSOURCE_EXCLUSIONSENDPARAMETERS: - eax_api_get_send_properties(eax_call); + eax_api_get_send_properties(call); break; case EAXSOURCE_ACTIVEFXSLOTID: - eax_api_get_source_active_fx_slot_id(eax_call); + eax_api_get_source_active_fx_slot_id(call); break; case EAXSOURCE_MACROFXFACTOR: - eax_call.set_value(eax_.source.flMacroFXFactor); + call.set_value(eax_.source.flMacroFXFactor); break; case EAXSOURCE_SPEAKERLEVELS: - eax_api_get_source_speaker_level_all(eax_call); + eax_api_get_source_speaker_level_all(call); break; case EAXSOURCE_ALL2DPARAMETERS: - eax_api_get_source_all_2d(eax_call); + eax_api_get_source_all_2d(call); break; default: diff --git a/al/source.h b/al/source.h index 6fc1c1d4..2d93e177 100644 --- a/al/source.h +++ b/al/source.h @@ -22,7 +22,7 @@ #include "vector.h" #ifdef ALSOFT_EAX -#include "eax/eax_call.h" +#include "eax/call.h" #include "eax/fx_slot_index.h" #include "eax/utils.h" #endif // ALSOFT_EAX @@ -216,8 +216,8 @@ public: void eax_initialize(ALCcontext *context) noexcept; - void eax_dispatch(const EaxEaxCall& eax_call) - { eax_call.is_get() ? eax_get(eax_call) : eax_set(eax_call); } + void eax_dispatch(const EaxCall& call) + { call.is_get() ? eax_get(call) : eax_set(call); } void eax_update_filters(); @@ -308,7 +308,7 @@ private: void eax_defer_active_fx_slots( - const EaxEaxCall& eax_call); + const EaxCall& call); static const char* eax_get_exclusion_name() noexcept; @@ -421,16 +421,16 @@ private: void eax_defer_send( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_send_exclusion_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_send_occlusion_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_send_all( - const EaxEaxCall& eax_call); + const EaxCall& call); static void eax_validate_source_direct( @@ -609,79 +609,79 @@ private: void eax_defer_source_direct( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_direct_hf( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_room( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_room_hf( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_obstruction( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_obstruction_lf_ratio( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_occlusion( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_occlusion_lf_ratio( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_occlusion_room_ratio( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_occlusion_direct_ratio( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_exclusion( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_exclusion_lf_ratio( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_outside_volume_hf( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_doppler_factor( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_rolloff_factor( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_room_rolloff_factor( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_air_absorption_factor( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_flags( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_macro_fx_factor( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_2d_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_obstruction_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_exclusion_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_occlusion_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_defer_source_speaker_level_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_set_outside_volume_hf(); @@ -708,15 +708,16 @@ private: void eax_set_speaker_levels(); + static ALuint eax2_translate_property_id(const EaxCall& call); void eax1_set_efx(); - void eax1_set_reverb_mix(const EaxEaxCall& eax_call); - void eax1_set(const EaxEaxCall& eax_call); + void eax1_set_reverb_mix(const EaxCall& call); + void eax1_set(const EaxCall& call); void eax_apply_deferred(); void eax_set( - const EaxEaxCall& eax_call); + const EaxCall& call); static const GUID& eax_get_send_fx_slot_guid( @@ -744,10 +745,10 @@ private: typename TSrcSend > void eax_api_get_send_properties( - const EaxEaxCall& eax_call) const + const EaxCall& call) const { - const auto eax_version = eax_call.get_version(); - const auto dst_sends = eax_call.get_values(); + const auto eax_version = call.get_version(); + const auto dst_sends = call.get_values(); const auto send_count = dst_sends.size(); for (auto fx_slot_index = EaxFxSlotIndexValue{}; fx_slot_index < send_count; ++fx_slot_index) @@ -762,40 +763,40 @@ private: } - void eax1_get(const EaxEaxCall& eax_call); + void eax1_get(const EaxCall& call); void eax_api_get_source_all_v2( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all_v3( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all_v5( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all_obstruction( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all_occlusion( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all_exclusion( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_active_fx_slot_id( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_all_2d( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_api_get_source_speaker_level_all( - const EaxEaxCall& eax_call); + const EaxCall& call); void eax_get( - const EaxEaxCall& eax_call); + const EaxCall& call); // `alSource3i(source, AL_AUXILIARY_SEND_FILTER, ...)` diff --git a/alc/context.cpp b/alc/context.cpp index 5fe03e78..33c888e7 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -330,32 +330,29 @@ ALenum ALCcontext::eax_eax_set( ALvoid* property_value, ALuint property_value_size) { - eax_initialize(); - - const auto eax_call = create_eax_call( - false, + const auto call = create_eax_call( + EaxCallType::set, property_set_id, property_id, property_source_id, property_value, - property_value_size - ); - - eax_unlock_legacy_fx_slots(eax_call); + property_value_size); + eax_initialize(call); + eax_unlock_legacy_fx_slots(call); - switch (eax_call.get_property_set_id()) + switch (call.get_property_set_id()) { - case EaxEaxCallPropertySetId::context: - eax_set(eax_call); + case EaxCallPropertySetId::context: + eax_set(call); break; - case EaxEaxCallPropertySetId::fx_slot: - case EaxEaxCallPropertySetId::fx_slot_effect: - eax_dispatch_fx_slot(eax_call); + case EaxCallPropertySetId::fx_slot: + case EaxCallPropertySetId::fx_slot_effect: + eax_dispatch_fx_slot(call); break; - case EaxEaxCallPropertySetId::source: - eax_dispatch_source(eax_call); + case EaxCallPropertySetId::source: + eax_dispatch_source(call); break; default: @@ -376,32 +373,29 @@ ALenum ALCcontext::eax_eax_get( ALvoid* property_value, ALuint property_value_size) { - eax_initialize(); - - const auto eax_call = create_eax_call( - true, + const auto call = create_eax_call( + EaxCallType::get, property_set_id, property_id, property_source_id, property_value, - property_value_size - ); + property_value_size); + eax_initialize(call); + eax_unlock_legacy_fx_slots(call); - eax_unlock_legacy_fx_slots(eax_call); - - switch (eax_call.get_property_set_id()) + switch (call.get_property_set_id()) { - case EaxEaxCallPropertySetId::context: - eax_get(eax_call); + case EaxCallPropertySetId::context: + eax_get(call); break; - case EaxEaxCallPropertySetId::fx_slot: - case EaxEaxCallPropertySetId::fx_slot_effect: - eax_dispatch_fx_slot(eax_call); + case EaxCallPropertySetId::fx_slot: + case EaxCallPropertySetId::fx_slot_effect: + eax_dispatch_fx_slot(call); break; - case EaxEaxCallPropertySetId::source: - eax_dispatch_source(eax_call); + case EaxCallPropertySetId::source: + eax_dispatch_source(call); break; default: @@ -478,7 +472,7 @@ void ALCcontext::eax_initialize_extensions() mExtensionList = eax_extension_list_.c_str(); } -void ALCcontext::eax_initialize() +void ALCcontext::eax_initialize(const EaxCall& call) { if (eax_is_initialized_) { @@ -501,7 +495,7 @@ void ALCcontext::eax_initialize() eax_set_defaults(); eax_set_air_absorbtion_hf(); eax_update_speaker_configuration(); - eax_initialize_fx_slots(); + eax_initialize_fx_slots(call); eax_initialize_sources(); eax_is_initialized_ = true; @@ -607,34 +601,32 @@ void ALCcontext::eax_set_defaults() noexcept eax_d_ = eax_; } -void ALCcontext::eax_unlock_legacy_fx_slots(const EaxEaxCall& eax_call) noexcept +void ALCcontext::eax_unlock_legacy_fx_slots(const EaxCall& call) noexcept { - if (eax_call.get_version() != 5 || eax_are_legacy_fx_slots_unlocked_) + if (call.get_version() != 5 || eax_are_legacy_fx_slots_unlocked_) return; eax_are_legacy_fx_slots_unlocked_ = true; eax_fx_slots_.unlock_legacy(); } -void ALCcontext::eax_dispatch_fx_slot( - const EaxEaxCall& eax_call) +void ALCcontext::eax_dispatch_fx_slot(const EaxCall& call) { - const auto fx_slot_index = eax_call.get_fx_slot_index(); + const auto fx_slot_index = call.get_fx_slot_index(); if(!fx_slot_index.has_value()) eax_fail("Invalid fx slot index."); auto& fx_slot = eax_get_fx_slot(*fx_slot_index); - if(fx_slot.eax_dispatch(eax_call)) + if(fx_slot.eax_dispatch(call)) { std::lock_guard source_lock{mSourceLock}; eax_update_filters(); } } -void ALCcontext::eax_dispatch_source( - const EaxEaxCall& eax_call) +void ALCcontext::eax_dispatch_source(const EaxCall& call) { - const auto source_id = eax_call.get_property_al_name(); + const auto source_id = call.get_property_al_name(); std::lock_guard source_lock{mSourceLock}; @@ -645,70 +637,61 @@ void ALCcontext::eax_dispatch_source( eax_fail("Source not found."); } - source->eax_dispatch(eax_call); + source->eax_dispatch(call); } -void ALCcontext::eax_get_primary_fx_slot_id( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_primary_fx_slot_id(const EaxCall& call) { - eax_call.set_value(eax_.context.guidPrimaryFXSlotID); + call.set_value(eax_.context.guidPrimaryFXSlotID); } -void ALCcontext::eax_get_distance_factor( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_distance_factor(const EaxCall& call) { - eax_call.set_value(eax_.context.flDistanceFactor); + call.set_value(eax_.context.flDistanceFactor); } -void ALCcontext::eax_get_air_absorption_hf( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_air_absorption_hf(const EaxCall& call) { - eax_call.set_value(eax_.context.flAirAbsorptionHF); + call.set_value(eax_.context.flAirAbsorptionHF); } -void ALCcontext::eax_get_hf_reference( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_hf_reference(const EaxCall& call) { - eax_call.set_value(eax_.context.flHFReference); + call.set_value(eax_.context.flHFReference); } -void ALCcontext::eax_get_last_error( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_last_error(const EaxCall& call) { const auto eax_last_error = eax_last_error_; eax_last_error_ = EAX_OK; - eax_call.set_value(eax_last_error); + call.set_value(eax_last_error); } -void ALCcontext::eax_get_speaker_config( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_speaker_config(const EaxCall& call) { - eax_call.set_value(eax_speaker_config_); + call.set_value(eax_speaker_config_); } -void ALCcontext::eax_get_session( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_session(const EaxCall& call) { - eax_call.set_value(eax_session_); + call.set_value(eax_session_); } -void ALCcontext::eax_get_macro_fx_factor( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_macro_fx_factor(const EaxCall& call) { - eax_call.set_value(eax_.context.flMacroFXFactor); + call.set_value(eax_.context.flMacroFXFactor); } -void ALCcontext::eax_get_context_all( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get_context_all(const EaxCall& call) { - switch (eax_call.get_version()) + switch (call.get_version()) { case 4: - eax_call.set_value(static_cast(eax_.context)); + call.set_value(static_cast(eax_.context)); break; case 5: - eax_call.set_value(static_cast(eax_.context)); + call.set_value(static_cast(eax_.context)); break; default: @@ -716,48 +699,47 @@ void ALCcontext::eax_get_context_all( } } -void ALCcontext::eax_get( - const EaxEaxCall& eax_call) +void ALCcontext::eax_get(const EaxCall& call) { - switch (eax_call.get_property_id()) + switch (call.get_property_id()) { case EAXCONTEXT_NONE: break; case EAXCONTEXT_ALLPARAMETERS: - eax_get_context_all(eax_call); + eax_get_context_all(call); break; case EAXCONTEXT_PRIMARYFXSLOTID: - eax_get_primary_fx_slot_id(eax_call); + eax_get_primary_fx_slot_id(call); break; case EAXCONTEXT_DISTANCEFACTOR: - eax_get_distance_factor(eax_call); + eax_get_distance_factor(call); break; case EAXCONTEXT_AIRABSORPTIONHF: - eax_get_air_absorption_hf(eax_call); + eax_get_air_absorption_hf(call); break; case EAXCONTEXT_HFREFERENCE: - eax_get_hf_reference(eax_call); + eax_get_hf_reference(call); break; case EAXCONTEXT_LASTERROR: - eax_get_last_error(eax_call); + eax_get_last_error(call); break; case EAXCONTEXT_SPEAKERCONFIG: - eax_get_speaker_config(eax_call); + eax_get_speaker_config(call); break; case EAXCONTEXT_EAXSESSION: - eax_get_session(eax_call); + eax_get_session(call); break; case EAXCONTEXT_MACROFXFACTOR: - eax_get_macro_fx_factor(eax_call); + eax_get_macro_fx_factor(call); break; default: @@ -801,9 +783,9 @@ void ALCcontext::eax_set_context() eax_set_hf_reference(); } -void ALCcontext::eax_initialize_fx_slots() +void ALCcontext::eax_initialize_fx_slots(const EaxCall& call) { - eax_fx_slots_.initialize(*this); + eax_fx_slots_.initialize(call, *this); eax_previous_primary_fx_slot_index_ = eax_.context.guidPrimaryFXSlotID; eax_primary_fx_slot_index_ = eax_.context.guidPrimaryFXSlotID; } @@ -1007,15 +989,14 @@ void ALCcontext::eax_defer_context_all( eax_defer_macro_fx_factor(context_all.flMacroFXFactor); } -void ALCcontext::eax_defer_context_all( - const EaxEaxCall& eax_call) +void ALCcontext::eax_defer_context_all(const EaxCall& call) { - switch(eax_call.get_version()) + switch(call.get_version()) { case 4: { const auto& context_all = - eax_call.get_value(); + call.get_value(); eax_validate_context_all(context_all); eax_defer_context_all(context_all); @@ -1025,7 +1006,7 @@ void ALCcontext::eax_defer_context_all( case 5: { const auto& context_all = - eax_call.get_value(); + call.get_value(); eax_validate_context_all(context_all); eax_defer_context_all(context_all); @@ -1037,93 +1018,86 @@ void ALCcontext::eax_defer_context_all( } } -void ALCcontext::eax_defer_primary_fx_slot_id( - const EaxEaxCall& eax_call) +void ALCcontext::eax_defer_primary_fx_slot_id(const EaxCall& call) { const auto& primary_fx_slot_id = - eax_call.get_value(); + call.get_value(); eax_validate_primary_fx_slot_id(primary_fx_slot_id); eax_defer_primary_fx_slot_id(primary_fx_slot_id); } -void ALCcontext::eax_defer_distance_factor( - const EaxEaxCall& eax_call) +void ALCcontext::eax_defer_distance_factor(const EaxCall& call) { const auto& distance_factor = - eax_call.get_value(); + call.get_value(); eax_validate_distance_factor(distance_factor); eax_defer_distance_factor(distance_factor); } -void ALCcontext::eax_defer_air_absorption_hf( - const EaxEaxCall& eax_call) +void ALCcontext::eax_defer_air_absorption_hf(const EaxCall& call) { const auto& air_absorption_hf = - eax_call.get_value(); + call.get_value(); eax_validate_air_absorption_hf(air_absorption_hf); eax_defer_air_absorption_hf(air_absorption_hf); } -void ALCcontext::eax_defer_hf_reference( - const EaxEaxCall& eax_call) +void ALCcontext::eax_defer_hf_reference(const EaxCall& call) { const auto& hf_reference = - eax_call.get_value(); + call.get_value(); eax_validate_hf_reference(hf_reference); eax_defer_hf_reference(hf_reference); } -void ALCcontext::eax_set_session( - const EaxEaxCall& eax_call) +void ALCcontext::eax_set_session(const EaxCall& call) { const auto& eax_session = - eax_call.get_value(); + call.get_value(); eax_validate_session(eax_session); eax_session_ = eax_session; } -void ALCcontext::eax_defer_macro_fx_factor( - const EaxEaxCall& eax_call) +void ALCcontext::eax_defer_macro_fx_factor(const EaxCall& call) { const auto& macro_fx_factor = - eax_call.get_value(); + call.get_value(); eax_validate_macro_fx_factor(macro_fx_factor); eax_defer_macro_fx_factor(macro_fx_factor); } -void ALCcontext::eax_set( - const EaxEaxCall& eax_call) +void ALCcontext::eax_set(const EaxCall& call) { - switch (eax_call.get_property_id()) + switch (call.get_property_id()) { case EAXCONTEXT_NONE: break; case EAXCONTEXT_ALLPARAMETERS: - eax_defer_context_all(eax_call); + eax_defer_context_all(call); break; case EAXCONTEXT_PRIMARYFXSLOTID: - eax_defer_primary_fx_slot_id(eax_call); + eax_defer_primary_fx_slot_id(call); break; case EAXCONTEXT_DISTANCEFACTOR: - eax_defer_distance_factor(eax_call); + eax_defer_distance_factor(call); break; case EAXCONTEXT_AIRABSORPTIONHF: - eax_defer_air_absorption_hf(eax_call); + eax_defer_air_absorption_hf(call); break; case EAXCONTEXT_HFREFERENCE: - eax_defer_hf_reference(eax_call); + eax_defer_hf_reference(call); break; case EAXCONTEXT_LASTERROR: @@ -1133,11 +1107,11 @@ void ALCcontext::eax_set( eax_fail("Speaker configuration is read-only."); case EAXCONTEXT_EAXSESSION: - eax_set_session(eax_call); + eax_set_session(call); break; case EAXCONTEXT_MACROFXFACTOR: - eax_defer_macro_fx_factor(eax_call); + eax_defer_macro_fx_factor(call); break; default: diff --git a/alc/context.h b/alc/context.h index b3f1ea09..a34e3e4b 100644 --- a/alc/context.h +++ b/alc/context.h @@ -20,7 +20,7 @@ #include "vector.h" #ifdef ALSOFT_EAX -#include "al/eax/eax_call.h" +#include "al/eax/call.h" #include "al/eax/fx_slot_index.h" #include "al/eax/fx_slots.h" #include "al/eax/utils.h" @@ -297,7 +297,7 @@ private: void eax_initialize_extensions(); - void eax_initialize(); + void eax_initialize(const EaxCall& call); bool eax_has_no_default_effect_slot() const noexcept; @@ -326,45 +326,33 @@ private: void eax_initialize_sources(); - void eax_unlock_legacy_fx_slots(const EaxEaxCall& eax_call) noexcept; + void eax_unlock_legacy_fx_slots(const EaxCall& call) noexcept; - void eax_dispatch_fx_slot( - const EaxEaxCall& eax_call); + void eax_dispatch_fx_slot(const EaxCall& call); - void eax_dispatch_source( - const EaxEaxCall& eax_call); + void eax_dispatch_source(const EaxCall& call); - void eax_get_primary_fx_slot_id( - const EaxEaxCall& eax_call); + void eax_get_primary_fx_slot_id(const EaxCall& call); - void eax_get_distance_factor( - const EaxEaxCall& eax_call); + void eax_get_distance_factor(const EaxCall& call); - void eax_get_air_absorption_hf( - const EaxEaxCall& eax_call); + void eax_get_air_absorption_hf(const EaxCall& call); - void eax_get_hf_reference( - const EaxEaxCall& eax_call); + void eax_get_hf_reference(const EaxCall& call); - void eax_get_last_error( - const EaxEaxCall& eax_call); + void eax_get_last_error(const EaxCall& call); - void eax_get_speaker_config( - const EaxEaxCall& eax_call); + void eax_get_speaker_config(const EaxCall& call); - void eax_get_session( - const EaxEaxCall& eax_call); + void eax_get_session(const EaxCall& call); - void eax_get_macro_fx_factor( - const EaxEaxCall& eax_call); + void eax_get_macro_fx_factor(const EaxCall& call); - void eax_get_context_all( - const EaxEaxCall& eax_call); + void eax_get_context_all(const EaxCall& call); - void eax_get( - const EaxEaxCall& eax_call); + void eax_get(const EaxCall& call); void eax_set_primary_fx_slot_id(); @@ -379,7 +367,7 @@ private: void eax_set_context(); - void eax_initialize_fx_slots(); + void eax_initialize_fx_slots(const EaxCall& call); void eax_update_sources(); @@ -441,29 +429,21 @@ private: const EAX50CONTEXTPROPERTIES& context_all); - void eax_defer_context_all( - const EaxEaxCall& eax_call); + void eax_defer_context_all(const EaxCall& call); - void eax_defer_primary_fx_slot_id( - const EaxEaxCall& eax_call); + void eax_defer_primary_fx_slot_id(const EaxCall& call); - void eax_defer_distance_factor( - const EaxEaxCall& eax_call); + void eax_defer_distance_factor(const EaxCall& call); - void eax_defer_air_absorption_hf( - const EaxEaxCall& eax_call); + void eax_defer_air_absorption_hf(const EaxCall& call); - void eax_defer_hf_reference( - const EaxEaxCall& eax_call); + void eax_defer_hf_reference(const EaxCall& call); - void eax_set_session( - const EaxEaxCall& eax_call); + void eax_set_session(const EaxCall& call); - void eax_defer_macro_fx_factor( - const EaxEaxCall& eax_call); + void eax_defer_macro_fx_factor(const EaxCall& call); - void eax_set( - const EaxEaxCall& eax_call); + void eax_set(const EaxCall& call); void eax_apply_deferred(); #endif // ALSOFT_EAX -- cgit v1.2.3 From 6fb5cb553f4c2faf4b991ac377ec457a7bba7e4c Mon Sep 17 00:00:00 2001 From: "Boris I. Bendovsky" Date: Tue, 12 Jul 2022 12:46:51 +0300 Subject: [EAX] Use separate FX slot state for each version (#730) * [EAX] Use separate FX slot state for each version [EAX] Don't defer FX slot properties * [EAX_FXSLOT] Use mPropsDirty to defer update [EAX_CONTEXT] Commit all updates on first initialization --- al/auxeffectslot.cpp | 838 ++++++++++++++++++---------------------------- al/auxeffectslot.h | 370 +++++++++++++------- al/eax/call.cpp | 1 + al/eax/call.h | 2 + al/eax/effect.h | 40 +-- al/eax/fx_slots.cpp | 6 - al/eax/fx_slots.h | 3 - al/eax/utils.h | 2 + al/effects/autowah.cpp | 10 +- al/effects/chorus.cpp | 16 +- al/effects/compressor.cpp | 10 +- al/effects/distortion.cpp | 10 +- al/effects/echo.cpp | 10 +- al/effects/effects.cpp | 32 +- al/effects/effects.h | 3 +- al/effects/equalizer.cpp | 10 +- al/effects/fshifter.cpp | 10 +- al/effects/modulator.cpp | 10 +- al/effects/pshifter.cpp | 10 +- al/effects/reverb.cpp | 10 +- al/effects/vmorpher.cpp | 10 +- alc/context.cpp | 17 +- alc/context.h | 4 - 23 files changed, 680 insertions(+), 754 deletions(-) (limited to 'al/effects/distortion.cpp') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index d37168e7..8a5915a6 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -50,11 +50,6 @@ #include "effect.h" #include "opthelpers.h" -#ifdef ALSOFT_EAX -#include "eax/exception.h" -#include "eax/utils.h" -#endif // ALSOFT_EAX - namespace { struct FactoryItem { @@ -1057,667 +1052,500 @@ EffectSlotSubList::~EffectSlotSubList() } #ifdef ALSOFT_EAX -namespace { - -class EaxFxSlotException : - public EaxException -{ -public: - explicit EaxFxSlotException( - const char* message) - : - EaxException{"EAX_FX_SLOT", message} - { - } -}; // EaxFxSlotException - - -} // namespace - - void ALeffectslot::eax_initialize( const EaxCall& call, ALCcontext& al_context, EaxFxSlotIndexValue index) { - eax_al_context_ = &al_context; - - if (index >= EAX_MAX_FXSLOTS) - { + if(index >= EAX_MAX_FXSLOTS) eax_fail("Index out of range."); - } + mPropsDirty = true; + eax_al_context_ = &al_context; eax_fx_slot_index_ = index; - - eax_initialize_eax(); - eax_initialize_lock(); - eax_initialize_effects(call); + eax_version_ = call.get_version(); + eax_fx_slot_set_defaults(); } const EAX50FXSLOTPROPERTIES& ALeffectslot::eax_get_eax_fx_slot() const noexcept { - return eax_eax_fx_slot_; + return eax_; } -void ALeffectslot::eax_ensure_is_unlocked() const +void ALeffectslot::eax_commit() { - if (eax_is_locked_) - eax_fail("Locked."); -} + auto df = EaxDirtyFlags{}; -void ALeffectslot::eax_validate_fx_slot_effect(const GUID& eax_effect_id) -{ - eax_ensure_is_unlocked(); - - if (eax_effect_id != EAX_NULL_GUID && - eax_effect_id != EAX_REVERB_EFFECT && - eax_effect_id != EAX_AGCCOMPRESSOR_EFFECT && - eax_effect_id != EAX_AUTOWAH_EFFECT && - eax_effect_id != EAX_CHORUS_EFFECT && - eax_effect_id != EAX_DISTORTION_EFFECT && - eax_effect_id != EAX_ECHO_EFFECT && - eax_effect_id != EAX_EQUALIZER_EFFECT && - eax_effect_id != EAX_FLANGER_EFFECT && - eax_effect_id != EAX_FREQUENCYSHIFTER_EFFECT && - eax_effect_id != EAX_VOCALMORPHER_EFFECT && - eax_effect_id != EAX_PITCHSHIFTER_EFFECT && - eax_effect_id != EAX_RINGMODULATOR_EFFECT) + switch(eax_version_) { - eax_fail("Unsupported EAX effect GUID."); + case 1: + case 2: + case 3: + eax5_fx_slot_commit(eax123_, df); + break; + case 4: + eax4_fx_slot_commit(df); + break; + case 5: + eax5_fx_slot_commit(eax5_, df); + break; + default: + eax_fail_unknown_version(); } -} -void ALeffectslot::eax_validate_fx_slot_volume(long eax_volume) -{ - eax_validate_range( - "Volume", - eax_volume, - EAXFXSLOT_MINVOLUME, - EAXFXSLOT_MAXVOLUME); -} + if(df == EaxDirtyFlags{}) { + if(eax_effect_ != nullptr && eax_effect_->commit()) + eax_set_efx_slot_effect(*eax_effect_); -void ALeffectslot::eax_validate_fx_slot_lock(long eax_lock) -{ - eax_ensure_is_unlocked(); + return; + } - eax_validate_range( - "Lock", - eax_lock, - EAXFXSLOT_MINLOCK, - EAXFXSLOT_MAXLOCK); -} + if((df & eax_load_effect_dirty_bit) != EaxDirtyFlags{}) + eax_fx_slot_load_effect(); + else { + if(eax_effect_ != nullptr && eax_effect_->commit()) + eax_set_efx_slot_effect(*eax_effect_); + } -void ALeffectslot::eax_validate_fx_slot_flags(const EaxCall& call, unsigned long eax_flags) -{ - eax_validate_range( - "Flags", - eax_flags, - 0UL, - ~(call.get_version() == 4 ? EAX40FXSLOTFLAGS_RESERVED : EAX50FXSLOTFLAGS_RESERVED)); -} + if((df & eax_volume_dirty_bit) != EaxDirtyFlags{}) + eax_fx_slot_set_volume(); -void ALeffectslot::eax_validate_fx_slot_occlusion(long eax_occlusion) -{ - eax_validate_range( - "Occlusion", - eax_occlusion, - EAXFXSLOT_MINOCCLUSION, - EAXFXSLOT_MAXOCCLUSION); + if((df & eax_flags_dirty_bit) != EaxDirtyFlags{}) + eax_fx_slot_set_flags(); } -void ALeffectslot::eax_validate_fx_slot_occlusion_lf_ratio(float eax_occlusion_lf_ratio) +[[noreturn]] void ALeffectslot::eax_fail(const char* message) { - eax_validate_range( - "Occlusion LF Ratio", - eax_occlusion_lf_ratio, - EAXFXSLOT_MINOCCLUSIONLFRATIO, - EAXFXSLOT_MAXOCCLUSIONLFRATIO); + throw Exception{message}; } -void ALeffectslot::eax_validate_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& fx_slot) +[[noreturn]] void ALeffectslot::eax_fail_unknown_effect_id() { - eax_validate_fx_slot_effect(fx_slot.guidLoadEffect); - eax_validate_fx_slot_volume(fx_slot.lVolume); - eax_validate_fx_slot_lock(fx_slot.lLock); - eax_validate_fx_slot_flags(call, fx_slot.ulFlags); + eax_fail("Unknown effect ID."); } -void ALeffectslot::eax_validate_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& fx_slot) +[[noreturn]] void ALeffectslot::eax_fail_unknown_property_id() { - eax_validate_fx_slot_all(call, static_cast(fx_slot)); - eax_validate_fx_slot_occlusion(fx_slot.lOcclusion); - eax_validate_fx_slot_occlusion_lf_ratio(fx_slot.flOcclusionLFRatio); + eax_fail("Unknown property ID."); } -void ALeffectslot::eax_set_fx_slot_effect(const EaxCall& call, const GUID& eax_effect_id) +[[noreturn]] void ALeffectslot::eax_fail_unknown_version() { - if (eax_eax_fx_slot_.guidLoadEffect == eax_effect_id) - { - return; - } - - eax_eax_fx_slot_.guidLoadEffect = eax_effect_id; - - eax_set_fx_slot_effect(call); + eax_fail("Unknown version."); } -void ALeffectslot::eax_set_fx_slot_volume( - long eax_volume) +void ALeffectslot::eax4_fx_slot_ensure_unlocked() const { - if (eax_eax_fx_slot_.lVolume == eax_volume) - { - return; - } - - eax_eax_fx_slot_.lVolume = eax_volume; - - eax_set_fx_slot_volume(); + if(eax4_fx_slot_is_legacy()) + eax_fail("Locked legacy slot."); } -void ALeffectslot::eax_set_fx_slot_lock( - long eax_lock) +ALenum ALeffectslot::eax_get_efx_effect_type(const GUID& guid) { - if (eax_eax_fx_slot_.lLock == eax_lock) - { - return; - } + if(guid == EAX_NULL_GUID) + return AL_EFFECT_NULL; + if(guid == EAX_AUTOWAH_EFFECT) + return AL_EFFECT_AUTOWAH; + if(guid == EAX_CHORUS_EFFECT) + return AL_EFFECT_CHORUS; + if(guid == EAX_AGCCOMPRESSOR_EFFECT) + return AL_EFFECT_COMPRESSOR; + if(guid == EAX_DISTORTION_EFFECT) + return AL_EFFECT_DISTORTION; + if(guid == EAX_REVERB_EFFECT) + return AL_EFFECT_EAXREVERB; + if(guid == EAX_ECHO_EFFECT) + return AL_EFFECT_ECHO; + if(guid == EAX_EQUALIZER_EFFECT) + return AL_EFFECT_EQUALIZER; + if(guid == EAX_FLANGER_EFFECT) + return AL_EFFECT_FLANGER; + if(guid == EAX_FREQUENCYSHIFTER_EFFECT) + return AL_EFFECT_FREQUENCY_SHIFTER; + if(guid == EAX_PITCHSHIFTER_EFFECT) + return AL_EFFECT_PITCH_SHIFTER; + if(guid == EAX_RINGMODULATOR_EFFECT) + return AL_EFFECT_RING_MODULATOR; + if(guid == EAX_VOCALMORPHER_EFFECT) + return AL_EFFECT_VOCAL_MORPHER; - eax_eax_fx_slot_.lLock = eax_lock; + eax_fail_unknown_effect_id(); } -void ALeffectslot::eax_set_fx_slot_flags( - unsigned long eax_flags) +const GUID& ALeffectslot::eax_get_eax_default_effect_guid() const noexcept { - if (eax_eax_fx_slot_.ulFlags == eax_flags) + switch(eax_fx_slot_index_) { - return; + case 0: return EAX_REVERB_EFFECT; + case 1: return EAX_CHORUS_EFFECT; + default: return EAX_NULL_GUID; } - - eax_eax_fx_slot_.ulFlags = eax_flags; - - eax_set_fx_slot_flags(); } -// [[nodiscard]] -bool ALeffectslot::eax_set_fx_slot_occlusion( - long eax_occlusion) +long ALeffectslot::eax_get_eax_default_lock() const noexcept { - if (eax_eax_fx_slot_.lOcclusion == eax_occlusion) - { - return false; - } - - eax_eax_fx_slot_.lOcclusion = eax_occlusion; - - return true; + return eax4_fx_slot_is_legacy() ? EAXFXSLOT_LOCKED : EAXFXSLOT_UNLOCKED; } -// [[nodiscard]] -bool ALeffectslot::eax_set_fx_slot_occlusion_lf_ratio( - float eax_occlusion_lf_ratio) +void ALeffectslot::eax4_fx_slot_set_defaults(Eax4Props& props) { - if (eax_eax_fx_slot_.flOcclusionLFRatio == eax_occlusion_lf_ratio) - { - return false; - } - - eax_eax_fx_slot_.flOcclusionLFRatio = eax_occlusion_lf_ratio; - - return true; + props.guidLoadEffect = eax_get_eax_default_effect_guid(); + props.lVolume = EAXFXSLOT_DEFAULTVOLUME; + props.lLock = eax_get_eax_default_lock(); + props.ulFlags = EAX40FXSLOT_DEFAULTFLAGS; } -void ALeffectslot::eax_set_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& eax_fx_slot) +void ALeffectslot::eax4_fx_slot_set_defaults() { - eax_set_fx_slot_effect(call, eax_fx_slot.guidLoadEffect); - eax_set_fx_slot_volume(eax_fx_slot.lVolume); - eax_set_fx_slot_lock(eax_fx_slot.lLock); - eax_set_fx_slot_flags(eax_fx_slot.ulFlags); + eax4_fx_slot_set_defaults(eax4_.i); + eax4_.df = ~EaxDirtyFlags{}; } -// [[nodiscard]] -bool ALeffectslot::eax_set_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& eax_fx_slot) +void ALeffectslot::eax5_fx_slot_set_defaults(Eax5Props& props) { - eax_set_fx_slot_all(call, static_cast(eax_fx_slot)); - - const auto is_occlusion_modified = eax_set_fx_slot_occlusion(eax_fx_slot.lOcclusion); - const auto is_occlusion_lf_ratio_modified = eax_set_fx_slot_occlusion_lf_ratio(eax_fx_slot.flOcclusionLFRatio); - - return is_occlusion_modified || is_occlusion_lf_ratio_modified; + eax4_fx_slot_set_defaults(static_cast(props)); + props.lOcclusion = EAXFXSLOT_DEFAULTOCCLUSION; + props.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO; } -void ALeffectslot::eax_unlock_legacy() noexcept +void ALeffectslot::eax5_fx_slot_set_defaults() { - assert(eax_fx_slot_index_ < 2); - eax_is_locked_ = false; - eax_eax_fx_slot_.lLock = EAXFXSLOT_UNLOCKED; + eax5_fx_slot_set_defaults(eax5_.i); + eax5_.df = ~EaxDirtyFlags{}; } -[[noreturn]] -void ALeffectslot::eax_fail( - const char* message) +void ALeffectslot::eax_fx_slot_set_defaults() { - throw EaxFxSlotException{message}; + eax4_fx_slot_set_defaults(); + eax5_fx_slot_set_defaults(); + eax123_ = eax5_; + eax_ = eax5_.i; } -GUID ALeffectslot::eax_get_eax_default_effect_guid() const noexcept +void ALeffectslot::eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props) const { - switch (eax_fx_slot_index_) + switch(call.get_property_id()) { - case 0: return EAX_REVERB_EFFECT; - case 1: return EAX_CHORUS_EFFECT; - default: return EAX_NULL_GUID; + case EAXFXSLOT_ALLPARAMETERS: + call.set_value(props); + break; + case EAXFXSLOT_LOADEFFECT: + call.set_value(props.guidLoadEffect); + break; + case EAXFXSLOT_VOLUME: + call.set_value(props.lVolume); + break; + case EAXFXSLOT_LOCK: + call.set_value(props.lLock); + break; + case EAXFXSLOT_FLAGS: + call.set_value(props.ulFlags); + break; + default: + eax_fail_unknown_property_id(); } } -long ALeffectslot::eax_get_eax_default_lock() const noexcept +void ALeffectslot::eax5_fx_slot_get(const EaxCall& call, const Eax5Props& props) const { - return eax_fx_slot_index_ < 2 ? EAXFXSLOT_LOCKED : EAXFXSLOT_UNLOCKED; -} - -void ALeffectslot::eax_set_eax_fx_slot_defaults() -{ - eax_eax_fx_slot_.guidLoadEffect = eax_get_eax_default_effect_guid(); - eax_eax_fx_slot_.lVolume = EAXFXSLOT_DEFAULTVOLUME; - eax_eax_fx_slot_.lLock = eax_get_eax_default_lock(); - eax_eax_fx_slot_.ulFlags = EAX40FXSLOT_DEFAULTFLAGS; - eax_eax_fx_slot_.lOcclusion = EAXFXSLOT_DEFAULTOCCLUSION; - eax_eax_fx_slot_.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO; -} - -void ALeffectslot::eax_initialize_eax() -{ - eax_set_eax_fx_slot_defaults(); -} - -void ALeffectslot::eax_initialize_lock() -{ - eax_is_locked_ = (eax_fx_slot_index_ < 2); -} - -void ALeffectslot::eax_initialize_effects(const EaxCall& call) -{ - eax_set_fx_slot_effect(call); -} - -void ALeffectslot::eax_get_fx_slot_all(const EaxCall& call) const -{ - switch (call.get_version()) + switch(call.get_property_id()) { - case 4: - call.set_value(eax_eax_fx_slot_); - break; - - case 5: - call.set_value(eax_eax_fx_slot_); - break; - - default: - eax_fail("Unsupported EAX version."); + case EAXFXSLOT_ALLPARAMETERS: + call.set_value(props); + break; + case EAXFXSLOT_LOADEFFECT: + call.set_value(props.guidLoadEffect); + break; + case EAXFXSLOT_VOLUME: + call.set_value(props.lVolume); + break; + case EAXFXSLOT_LOCK: + call.set_value(props.lLock); + break; + case EAXFXSLOT_FLAGS: + call.set_value(props.ulFlags); + break; + case EAXFXSLOT_OCCLUSION: + call.set_value(props.lOcclusion); + break; + case EAXFXSLOT_OCCLUSIONLFRATIO: + call.set_value(props.flOcclusionLFRatio); + break; + default: + eax_fail_unknown_property_id(); } } -void ALeffectslot::eax_get_fx_slot(const EaxCall& call) const +void ALeffectslot::eax_fx_slot_get(const EaxCall& call) const { - switch (call.get_property_id()) + switch(call.get_version()) { - case EAXFXSLOT_ALLPARAMETERS: - eax_get_fx_slot_all(call); - break; - - case EAXFXSLOT_LOADEFFECT: - call.set_value(eax_eax_fx_slot_.guidLoadEffect); - break; - - case EAXFXSLOT_VOLUME: - call.set_value(eax_eax_fx_slot_.lVolume); - break; - - case EAXFXSLOT_LOCK: - call.set_value(eax_eax_fx_slot_.lLock); - break; - - case EAXFXSLOT_FLAGS: - call.set_value(eax_eax_fx_slot_.ulFlags); - break; - - case EAXFXSLOT_OCCLUSION: - call.set_value(eax_eax_fx_slot_.lOcclusion); - break; - - case EAXFXSLOT_OCCLUSIONLFRATIO: - call.set_value(eax_eax_fx_slot_.flOcclusionLFRatio); - break; - - default: - eax_fail("Unsupported FX slot property id."); + case 4: eax4_fx_slot_get(call, eax4_.i); break; + case 5: eax4_fx_slot_get(call, eax5_.i); break; + default: eax_fail_unknown_version(); } } -// [[nodiscard]] bool ALeffectslot::eax_get(const EaxCall& call) { - switch (call.get_property_set_id()) + switch(call.get_property_set_id()) { - case EaxCallPropertySetId::fx_slot: - eax_get_fx_slot(call); - break; - - case EaxCallPropertySetId::fx_slot_effect: - eax_dispatch_effect(call); - break; - - default: - eax_fail("Unsupported property id."); + case EaxCallPropertySetId::fx_slot: + eax_fx_slot_get(call); + break; + case EaxCallPropertySetId::fx_slot_effect: + eax_dispatch_effect(call); + break; + default: + eax_fail_unknown_property_id(); } return false; } -void ALeffectslot::eax_set_fx_slot_effect(const EaxCall& call, ALenum al_effect_type) +void ALeffectslot::eax_fx_slot_load_effect() { - if(!IsValidEffectType(al_effect_type)) - eax_fail("Unsupported effect."); - eax_effect_ = nullptr; - eax_effect_ = eax_create_eax_effect(al_effect_type, call); - - eax_set_effect_slot_effect(*eax_effect_); -} - -void ALeffectslot::eax_set_fx_slot_effect(const EaxCall& call) -{ - auto al_effect_type = ALenum{}; - - if (false) - { - } - else if (eax_eax_fx_slot_.guidLoadEffect == EAX_NULL_GUID) - { - al_effect_type = AL_EFFECT_NULL; - } - else if (eax_eax_fx_slot_.guidLoadEffect == EAX_AUTOWAH_EFFECT) - { - al_effect_type = AL_EFFECT_AUTOWAH; - } - else if (eax_eax_fx_slot_.guidLoadEffect == EAX_CHORUS_EFFECT) - { - al_effect_type = AL_EFFECT_CHORUS; - } - else if (eax_eax_fx_slot_.guidLoadEffect == EAX_AGCCOMPRESSOR_EFFECT) - { - al_effect_type = AL_EFFECT_COMPRESSOR; - } - else if (eax_eax_fx_slot_.guidLoadEffect == EAX_DISTORTION_EFFECT) - { - al_effect_type = AL_EFFECT_DISTORTION; - } - else if (eax_eax_fx_slot_.guidLoadEffect == EAX_REVERB_EFFECT) - { - al_effect_type = AL_EFFECT_EAXREVERB; - } - else if (eax_eax_fx_slot_.guidLoadEffect == EAX_ECHO_EFFECT) - { - al_effect_type = AL_EFFECT_ECHO; - } - else if (eax_eax_fx_slot_.guidLoadEffect == EAX_EQUALIZER_EFFECT) - { - al_effect_type = AL_EFFECT_EQUALIZER; - } - else if (eax_eax_fx_slot_.guidLoadEffect == EAX_FLANGER_EFFECT) - { - al_effect_type = AL_EFFECT_FLANGER; - } - else if (eax_eax_fx_slot_.guidLoadEffect == EAX_FREQUENCYSHIFTER_EFFECT) - { - al_effect_type = AL_EFFECT_FREQUENCY_SHIFTER; - } - else if (eax_eax_fx_slot_.guidLoadEffect == EAX_PITCHSHIFTER_EFFECT) - { - al_effect_type = AL_EFFECT_PITCH_SHIFTER; - } - else if (eax_eax_fx_slot_.guidLoadEffect == EAX_RINGMODULATOR_EFFECT) - { - al_effect_type = AL_EFFECT_RING_MODULATOR; - } - else if (eax_eax_fx_slot_.guidLoadEffect == EAX_VOCALMORPHER_EFFECT) - { - al_effect_type = AL_EFFECT_VOCAL_MORPHER; - } - else - { - eax_fail("Unsupported effect."); - } - - eax_set_fx_slot_effect(call, al_effect_type); -} + const auto efx_effect_type = eax_get_efx_effect_type(eax_.guidLoadEffect); -void ALeffectslot::eax_set_efx_effect_slot_gain() -{ - const auto gain = level_mb_to_gain( - static_cast(clamp( - eax_eax_fx_slot_.lVolume, - EAXFXSLOT_MINVOLUME, - EAXFXSLOT_MAXVOLUME))); + if(!IsValidEffectType(efx_effect_type)) + eax_fail("Invalid effect type."); - eax_set_effect_slot_gain(gain); + eax_effect_ = eax_create_eax_effect(efx_effect_type, eax_version_); + eax_set_efx_slot_effect(*eax_effect_); } -void ALeffectslot::eax_set_fx_slot_volume() +void ALeffectslot::eax_fx_slot_set_volume() { - eax_set_efx_effect_slot_gain(); + const auto volume = clamp(eax_.lVolume, EAXFXSLOT_MINVOLUME, EAXFXSLOT_MAXVOLUME); + const auto gain = level_mb_to_gain(static_cast(volume)); + eax_set_efx_slot_gain(gain); } -void ALeffectslot::eax_set_effect_slot_send_auto() +void ALeffectslot::eax_fx_slot_set_environment_flag() { - eax_set_effect_slot_send_auto((eax_eax_fx_slot_.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0); + eax_set_efx_slot_send_auto((eax_.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0u); } -void ALeffectslot::eax_set_fx_slot_flags() +void ALeffectslot::eax_fx_slot_set_flags() { - eax_set_effect_slot_send_auto(); + eax_fx_slot_set_environment_flag(); } -void ALeffectslot::eax_defer_fx_slot_effect(const EaxCall& call) +void ALeffectslot::eax4_fx_slot_set_all(const EaxCall& call) { - const auto& eax_effect_id = - call.get_value(); - - eax_validate_fx_slot_effect(eax_effect_id); - eax_set_fx_slot_effect(call, eax_effect_id); + eax4_fx_slot_ensure_unlocked(); + const auto& src = call.get_value(); + Eax4AllValidator{}(src); + auto& dst = eax4_.i; + auto& df = eax4_.df; + df |= eax_load_effect_dirty_bit; // Always reset the effect. + df |= (dst.lVolume != src.lVolume ? eax_volume_dirty_bit : EaxDirtyFlags{}); + df |= (dst.lLock != src.lLock ? eax_lock_dirty_bit : EaxDirtyFlags{}); + df |= (dst.ulFlags != src.ulFlags ? eax_flags_dirty_bit : EaxDirtyFlags{}); + dst = src; } -void ALeffectslot::eax_defer_fx_slot_volume(const EaxCall& call) +void ALeffectslot::eax5_fx_slot_set_all(const EaxCall& call) { - const auto& eax_volume = - call.get_value(); - - eax_validate_fx_slot_volume(eax_volume); - eax_set_fx_slot_volume(eax_volume); -} - -void ALeffectslot::eax_defer_fx_slot_lock(const EaxCall& call) -{ - const auto& eax_lock = - call.get_value(); - - eax_validate_fx_slot_lock(eax_lock); - eax_set_fx_slot_lock(eax_lock); -} - -void ALeffectslot::eax_defer_fx_slot_flags(const EaxCall& call) -{ - const auto& eax_flags = - call.get_value(); - - eax_validate_fx_slot_flags(call, eax_flags); - eax_set_fx_slot_flags(eax_flags); + const auto& src = call.get_value(); + Eax5AllValidator{}(src); + auto& dst = eax5_.i; + auto& df = eax5_.df; + df |= eax_load_effect_dirty_bit; // Always reset the effect. + df |= (dst.lVolume != src.lVolume ? eax_volume_dirty_bit : EaxDirtyFlags{}); + df |= (dst.lLock != src.lLock ? eax_lock_dirty_bit : EaxDirtyFlags{}); + df |= (dst.ulFlags != src.ulFlags ? eax_flags_dirty_bit : EaxDirtyFlags{}); + df |= (dst.lOcclusion != src.lOcclusion ? eax_flags_dirty_bit : EaxDirtyFlags{}); + df |= (dst.flOcclusionLFRatio != src.flOcclusionLFRatio ? eax_flags_dirty_bit : EaxDirtyFlags{}); + dst = src; } -// [[nodiscard]] -bool ALeffectslot::eax_defer_fx_slot_occlusion(const EaxCall& call) +// Returns `true` if all sources should be updated, or `false` otherwise. +bool ALeffectslot::eax4_fx_slot_set(const EaxCall& call) { - const auto& eax_occlusion = - call.get_value(); + auto& df = eax4_.df; + auto& dst = eax4_.i; - eax_validate_fx_slot_occlusion(eax_occlusion); + switch(call.get_property_id()) + { + case EAXFXSLOT_NONE: + break; + case EAXFXSLOT_ALLPARAMETERS: + eax4_fx_slot_set_all(call); + break; + case EAXFXSLOT_LOADEFFECT: + eax4_fx_slot_ensure_unlocked(); + eax_fx_slot_set_dirty(call, dst.guidLoadEffect, df); + break; + case EAXFXSLOT_VOLUME: + eax_fx_slot_set(call, dst.lVolume, df); + break; + case EAXFXSLOT_LOCK: + eax4_fx_slot_ensure_unlocked(); + eax_fx_slot_set(call, dst.lLock, df); + break; + case EAXFXSLOT_FLAGS: + eax_fx_slot_set(call, dst.ulFlags, df); + break; + default: + eax_fail_unknown_property_id(); + } - return eax_set_fx_slot_occlusion(eax_occlusion); + return (df & (eax_occlusion_dirty_bit | eax_occlusion_lf_ratio_dirty_bit)) != EaxDirtyFlags{}; } -// [[nodiscard]] -bool ALeffectslot::eax_defer_fx_slot_occlusion_lf_ratio(const EaxCall& call) +// Returns `true` if all sources should be updated, or `false` otherwise. +bool ALeffectslot::eax5_fx_slot_set(const EaxCall& call) { - const auto& eax_occlusion_lf_ratio = - call.get_value(); + auto& df = eax5_.df; + auto& dst = eax5_.i; - eax_validate_fx_slot_occlusion_lf_ratio(eax_occlusion_lf_ratio); + switch(call.get_property_id()) + { + case EAXFXSLOT_NONE: + break; + case EAXFXSLOT_ALLPARAMETERS: + eax5_fx_slot_set_all(call); + break; + case EAXFXSLOT_LOADEFFECT: + eax_fx_slot_set_dirty(call, dst.guidLoadEffect, df); + break; + case EAXFXSLOT_VOLUME: + eax_fx_slot_set(call, dst.lVolume, df); + break; + case EAXFXSLOT_LOCK: + eax_fx_slot_set(call, dst.lLock, df); + break; + case EAXFXSLOT_FLAGS: + eax_fx_slot_set(call, dst.ulFlags, df); + break; + case EAXFXSLOT_OCCLUSION: + eax_fx_slot_set(call, dst.lOcclusion, df); + break; + case EAXFXSLOT_OCCLUSIONLFRATIO: + eax_fx_slot_set(call, dst.flOcclusionLFRatio, df); + break; + default: + eax_fail_unknown_property_id(); + } - return eax_set_fx_slot_occlusion_lf_ratio(eax_occlusion_lf_ratio); + return (df & (eax_occlusion_dirty_bit | eax_occlusion_lf_ratio_dirty_bit)) != EaxDirtyFlags{}; } -// [[nodiscard]] -bool ALeffectslot::eax_defer_fx_slot_all(const EaxCall& call) +// Returns `true` if all sources should be updated, or `false` otherwise. +bool ALeffectslot::eax_fx_slot_set(const EaxCall& call) { switch (call.get_version()) { - case 4: - { - const auto& eax_all = - call.get_value(); - - eax_validate_fx_slot_all(call, eax_all); - eax_set_fx_slot_all(call, eax_all); - - return false; - } - - case 5: - { - const auto& eax_all = - call.get_value(); - - eax_validate_fx_slot_all(call, eax_all); - return eax_set_fx_slot_all(call, eax_all); - } - - default: - eax_fail("Unsupported EAX version."); + case 4: return eax4_fx_slot_set(call); + case 5: return eax5_fx_slot_set(call); + default: eax_fail_unknown_version(); } } -bool ALeffectslot::eax_set_fx_slot(const EaxCall& call) +// Returns `true` if all sources should be updated, or `false` otherwise. +bool ALeffectslot::eax_set(const EaxCall& call) { - switch (call.get_property_id()) - { - case EAXFXSLOT_NONE: - return false; - - case EAXFXSLOT_ALLPARAMETERS: - return eax_defer_fx_slot_all(call); + const auto version = call.get_version(); - case EAXFXSLOT_LOADEFFECT: - eax_defer_fx_slot_effect(call); - return false; + if(eax_version_ != version) { + constexpr auto all_bits = ~EaxDirtyFlags{}; + eax123_.df = all_bits; + eax4_.df = all_bits; + eax5_.df = all_bits; + } - case EAXFXSLOT_VOLUME: - eax_defer_fx_slot_volume(call); - return false; + eax_version_ = version; - case EAXFXSLOT_LOCK: - eax_defer_fx_slot_lock(call); - return false; + switch(call.get_property_set_id()) + { + case EaxCallPropertySetId::fx_slot: return eax_fx_slot_set(call); + case EaxCallPropertySetId::fx_slot_effect: eax_dispatch_effect(call); return false; + default: eax_fail_unknown_property_id(); + } +} - case EAXFXSLOT_FLAGS: - eax_defer_fx_slot_flags(call); - return false; +void ALeffectslot::eax4_fx_slot_commit(EaxDirtyFlags& dst_df) +{ + if(eax4_.df == EaxDirtyFlags{}) + return; - case EAXFXSLOT_OCCLUSION: - return eax_defer_fx_slot_occlusion(call); + eax_fx_slot_commit_property(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::guidLoadEffect); + eax_fx_slot_commit_property(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::lVolume); + eax_fx_slot_commit_property(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::lLock); + eax_fx_slot_commit_property(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::ulFlags); - case EAXFXSLOT_OCCLUSIONLFRATIO: - return eax_defer_fx_slot_occlusion_lf_ratio(call); + auto& dst_i = eax_; + if(dst_i.lOcclusion != EAXFXSLOT_DEFAULTOCCLUSION) { + dst_df |= eax_occlusion_dirty_bit; + dst_i.lOcclusion = EAXFXSLOT_DEFAULTOCCLUSION; + } - default: - eax_fail("Unsupported FX slot property id."); + if(dst_i.flOcclusionLFRatio != EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO) { + dst_df |= eax_occlusion_lf_ratio_dirty_bit; + dst_i.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO; } + + eax4_.df = EaxDirtyFlags{}; } -// [[nodiscard]] -bool ALeffectslot::eax_set(const EaxCall& call) +void ALeffectslot::eax5_fx_slot_commit(Eax5State& state, EaxDirtyFlags& dst_df) { - switch(call.get_property_set_id()) - { - case EaxCallPropertySetId::fx_slot: - return eax_set_fx_slot(call); - - case EaxCallPropertySetId::fx_slot_effect: - eax_dispatch_effect(call); - break; - - default: - eax_fail("Unsupported property id."); - } + if(state.df == EaxDirtyFlags{}) + return; - return false; + eax_fx_slot_commit_property(state, dst_df, &EAX50FXSLOTPROPERTIES::guidLoadEffect); + eax_fx_slot_commit_property(state, dst_df, &EAX50FXSLOTPROPERTIES::lVolume); + eax_fx_slot_commit_property(state, dst_df, &EAX50FXSLOTPROPERTIES::lLock); + eax_fx_slot_commit_property(state, dst_df, &EAX50FXSLOTPROPERTIES::ulFlags); + eax_fx_slot_commit_property(state, dst_df, &EAX50FXSLOTPROPERTIES::lOcclusion); + eax_fx_slot_commit_property(state, dst_df, &EAX50FXSLOTPROPERTIES::flOcclusionLFRatio); + state.df = EaxDirtyFlags{}; } void ALeffectslot::eax_dispatch_effect(const EaxCall& call) -{ if(eax_effect_) eax_effect_->dispatch(call); } - -void ALeffectslot::eax_apply_deferred() { - /* The other FXSlot properties (volume, effect, etc) aren't deferred? */ - - auto is_changed = false; - if(eax_effect_) - is_changed = eax_effect_->commit(); - if(is_changed) - eax_set_effect_slot_effect(*eax_effect_); + if(eax_effect_ != nullptr) + eax_effect_->dispatch(call); } - -void ALeffectslot::eax_set_effect_slot_effect(EaxEffect &effect) +void ALeffectslot::eax_set_efx_slot_effect(EaxEffect &effect) { #define EAX_PREFIX "[EAX_SET_EFFECT_SLOT_EFFECT] " const auto error = initEffect(effect.al_effect_type_, effect.al_effect_props_, eax_al_context_); - if (error != AL_NO_ERROR) - { + + if(error != AL_NO_ERROR) { ERR(EAX_PREFIX "%s\n", "Failed to initialize an effect."); return; } - if (mState == SlotState::Initial) - { + if(mState == SlotState::Initial) { mPropsDirty = false; updateProps(eax_al_context_); - auto effect_slot_ptr = this; - AddActiveEffectSlots({&effect_slot_ptr, 1}, eax_al_context_); mState = SlotState::Playing; - return; } - UpdateProps(this, eax_al_context_); + mPropsDirty = true; #undef EAX_PREFIX } -void ALeffectslot::eax_set_effect_slot_send_auto( - bool is_send_auto) +void ALeffectslot::eax_set_efx_slot_send_auto(bool is_send_auto) { if(AuxSendAuto == is_send_auto) return; AuxSendAuto = is_send_auto; - UpdateProps(this, eax_al_context_); + mPropsDirty = true; } -void ALeffectslot::eax_set_effect_slot_gain( - ALfloat gain) +void ALeffectslot::eax_set_efx_slot_gain(ALfloat gain) { #define EAX_PREFIX "[EAX_SET_EFFECT_SLOT_GAIN] " @@ -1727,43 +1555,37 @@ void ALeffectslot::eax_set_effect_slot_gain( ERR(EAX_PREFIX "Gain out of range (%f)\n", gain); Gain = clampf(gain, 0.0f, 1.0f); - UpdateProps(this, eax_al_context_); + mPropsDirty = true; #undef EAX_PREFIX } - void ALeffectslot::EaxDeleter::operator()(ALeffectslot* effect_slot) { assert(effect_slot); eax_delete_al_effect_slot(*effect_slot->eax_al_context_, *effect_slot); } - -EaxAlEffectSlotUPtr eax_create_al_effect_slot( - ALCcontext& context) +EaxAlEffectSlotUPtr eax_create_al_effect_slot(ALCcontext& context) { #define EAX_PREFIX "[EAX_MAKE_EFFECT_SLOT] " std::unique_lock effect_slot_lock{context.mEffectSlotLock}; - auto& device = *context.mALDevice; - if (context.mNumEffectSlots == device.AuxiliaryEffectSlotMax) - { + if(context.mNumEffectSlots == device.AuxiliaryEffectSlotMax) { ERR(EAX_PREFIX "%s\n", "Out of memory."); return nullptr; } - if (!EnsureEffectSlots(&context, 1)) - { + if(!EnsureEffectSlots(&context, 1)) { ERR(EAX_PREFIX "%s\n", "Failed to ensure."); return nullptr; } auto effect_slot = EaxAlEffectSlotUPtr{AllocEffectSlot(&context)}; - if (!effect_slot) - { + + if(effect_slot == nullptr) { ERR(EAX_PREFIX "%s\n", "Failed to allocate."); return nullptr; } @@ -1773,22 +1595,18 @@ EaxAlEffectSlotUPtr eax_create_al_effect_slot( #undef EAX_PREFIX } -void eax_delete_al_effect_slot( - ALCcontext& context, - ALeffectslot& effect_slot) +void eax_delete_al_effect_slot(ALCcontext& context, ALeffectslot& effect_slot) { #define EAX_PREFIX "[EAX_DELETE_EFFECT_SLOT] " std::lock_guard effect_slot_lock{context.mEffectSlotLock}; - if (ReadRef(effect_slot.ref) != 0) - { + if(ReadRef(effect_slot.ref) != 0) { ERR(EAX_PREFIX "Deleting in-use effect slot %u.\n", effect_slot.id); return; } auto effect_slot_ptr = &effect_slot; - RemoveActiveEffectSlots({&effect_slot_ptr, 1}, &context); FreeEffectSlot(&context, &effect_slot); diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 83711372..fb6a2e1e 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -20,13 +20,23 @@ #include #include "eax/call.h" #include "eax/effect.h" +#include "eax/exception.h" #include "eax/fx_slot_index.h" +#include "eax/utils.h" #endif // ALSOFT_EAX struct ALbuffer; struct ALeffect; struct WetBuffer; +#ifdef ALSOFT_EAX +class EaxFxSlotException : public EaxException { +public: + explicit EaxFxSlotException(const char* message) + : EaxException{"EAX_FX_SLOT", message} + {} +}; +#endif // ALSOFT_EAX enum class SlotState : ALenum { Initial = AL_INITIAL, @@ -79,162 +89,282 @@ public: const EAX50FXSLOTPROPERTIES& eax_get_eax_fx_slot() const noexcept; - - // [[nodiscard]] + // Returns `true` if all sources should be updated, or `false` otherwise. bool eax_dispatch(const EaxCall& call) { return call.is_get() ? eax_get(call) : eax_set(call); } - - void eax_unlock_legacy() noexcept; - - void eax_commit() { eax_apply_deferred(); } + void eax_commit(); private: - ALCcontext* eax_al_context_{}; + static constexpr auto eax_load_effect_dirty_bit = EaxDirtyFlags{1} << 0; + static constexpr auto eax_volume_dirty_bit = EaxDirtyFlags{1} << 1; + static constexpr auto eax_lock_dirty_bit = EaxDirtyFlags{1} << 2; + static constexpr auto eax_flags_dirty_bit = EaxDirtyFlags{1} << 3; + static constexpr auto eax_occlusion_dirty_bit = EaxDirtyFlags{1} << 4; + static constexpr auto eax_occlusion_lf_ratio_dirty_bit = EaxDirtyFlags{1} << 5; + + using Exception = EaxFxSlotException; + + using Eax4Props = EAX40FXSLOTPROPERTIES; + + struct Eax4State { + Eax4Props i; // Immediate. + EaxDirtyFlags df; // Dirty flags. + }; + + using Eax5Props = EAX50FXSLOTPROPERTIES; + + struct Eax5State { + Eax5Props i; // Immediate. + EaxDirtyFlags df; // Dirty flags. + }; + + struct EaxRangeValidator { + template + void operator()( + const char* name, + const TValue& value, + const TValue& min_value, + const TValue& max_value) const + { + eax_validate_range(name, value, min_value, max_value); + } + }; + + struct Eax4GuidLoadEffectValidator { + void operator()(const GUID& guidLoadEffect) const + { + if (guidLoadEffect != EAX_NULL_GUID && + guidLoadEffect != EAX_REVERB_EFFECT && + guidLoadEffect != EAX_AGCCOMPRESSOR_EFFECT && + guidLoadEffect != EAX_AUTOWAH_EFFECT && + guidLoadEffect != EAX_CHORUS_EFFECT && + guidLoadEffect != EAX_DISTORTION_EFFECT && + guidLoadEffect != EAX_ECHO_EFFECT && + guidLoadEffect != EAX_EQUALIZER_EFFECT && + guidLoadEffect != EAX_FLANGER_EFFECT && + guidLoadEffect != EAX_FREQUENCYSHIFTER_EFFECT && + guidLoadEffect != EAX_VOCALMORPHER_EFFECT && + guidLoadEffect != EAX_PITCHSHIFTER_EFFECT && + guidLoadEffect != EAX_RINGMODULATOR_EFFECT) + { + eax_fail_unknown_effect_id(); + } + } + }; + + struct Eax4VolumeValidator { + void operator()(long lVolume) const + { + EaxRangeValidator{}( + "Volume", + lVolume, + EAXFXSLOT_MINVOLUME, + EAXFXSLOT_MAXVOLUME); + } + }; + + struct Eax4LockValidator { + void operator()(long lLock) const + { + EaxRangeValidator{}( + "Lock", + lLock, + EAXFXSLOT_MINLOCK, + EAXFXSLOT_MAXLOCK); + } + }; + + struct Eax4FlagsValidator { + void operator()(unsigned long ulFlags) const + { + EaxRangeValidator{}( + "Flags", + ulFlags, + 0UL, + ~EAX40FXSLOTFLAGS_RESERVED); + } + }; + + struct Eax4AllValidator { + void operator()(const EAX40FXSLOTPROPERTIES& all) const + { + Eax4GuidLoadEffectValidator{}(all.guidLoadEffect); + Eax4VolumeValidator{}(all.lVolume); + Eax4LockValidator{}(all.lLock); + Eax4FlagsValidator{}(all.ulFlags); + } + }; + + struct Eax5OcclusionValidator { + void operator()(long lOcclusion) const + { + EaxRangeValidator{}( + "Occlusion", + lOcclusion, + EAXFXSLOT_MINOCCLUSION, + EAXFXSLOT_MAXOCCLUSION); + } + }; + + struct Eax5OcclusionLfRatioValidator { + void operator()(float flOcclusionLFRatio) const + { + EaxRangeValidator{}( + "Occlusion LF Ratio", + flOcclusionLFRatio, + EAXFXSLOT_MINOCCLUSIONLFRATIO, + EAXFXSLOT_MAXOCCLUSIONLFRATIO); + } + }; + + struct Eax5FlagsValidator { + void operator()(unsigned long ulFlags) const + { + EaxRangeValidator{}( + "Flags", + ulFlags, + 0UL, + ~EAX50FXSLOTFLAGS_RESERVED); + } + }; + + struct Eax5AllValidator { + void operator()(const EAX50FXSLOTPROPERTIES& all) const + { + Eax4AllValidator{}(static_cast(all)); + Eax5OcclusionValidator{}(all.lOcclusion); + Eax5OcclusionLfRatioValidator{}(all.flOcclusionLFRatio); + } + }; + ALCcontext* eax_al_context_{}; EaxFxSlotIndexValue eax_fx_slot_index_{}; - - EAX50FXSLOTPROPERTIES eax_eax_fx_slot_{}; - + int eax_version_{}; // Current EAX version. EaxEffectUPtr eax_effect_{}; - bool eax_is_locked_{}; - - - [[noreturn]] - static void eax_fail( - const char* message); - - - GUID eax_get_eax_default_effect_guid() const noexcept; + Eax5State eax123_{}; // EAX1/EAX2/EAX3 state. + Eax4State eax4_{}; // EAX4 state. + Eax5State eax5_{}; // EAX5 state. + Eax5Props eax_{}; // Current EAX state. + + [[noreturn]] static void eax_fail(const char* message); + [[noreturn]] static void eax_fail_unknown_effect_id(); + [[noreturn]] static void eax_fail_unknown_property_id(); + [[noreturn]] static void eax_fail_unknown_version(); + + // Gets a new value from EAX call, + // validates it, + // sets a dirty flag only if the new value differs form the old one, + // and assigns the new value. + template + void eax_fx_slot_set(const EaxCall& call, TProperties& dst, EaxDirtyFlags& dirty_flags) + { + const auto& src = call.get_value(); + TValidator{}(src); + dirty_flags |= (dst != src ? TDirtyBit : EaxDirtyFlags{}); + dst = src; + } + + // Gets a new value from EAX call, + // validates it, + // sets a dirty flag without comparing the values, + // and assigns the new value. + template + void eax_fx_slot_set_dirty(const EaxCall& call, TProperties& dst, EaxDirtyFlags& dirty_flags) + { + const auto& src = call.get_value(); + TValidator{}(src); + dirty_flags |= TDirtyBit; + dst = src; + } + + constexpr bool eax4_fx_slot_is_legacy() const noexcept + { return eax_fx_slot_index_ < 2; } + + void eax4_fx_slot_ensure_unlocked() const; + + static ALenum eax_get_efx_effect_type(const GUID& guid); + const GUID& eax_get_eax_default_effect_guid() const noexcept; long eax_get_eax_default_lock() const noexcept; - void eax_set_eax_fx_slot_defaults(); - - void eax_initialize_eax(); - - void eax_initialize_lock(); - - - void eax_initialize_effects(const EaxCall& call); - - - void eax_get_fx_slot_all(const EaxCall& call) const; + void eax4_fx_slot_set_defaults(Eax4Props& props); + void eax4_fx_slot_set_defaults(); + void eax5_fx_slot_set_defaults(Eax5Props& props); + void eax5_fx_slot_set_defaults(); + void eax_fx_slot_set_defaults(); - void eax_get_fx_slot(const EaxCall& call) const; - - // [[nodiscard]] + void eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props) const; + void eax5_fx_slot_get(const EaxCall& call, const Eax5Props& props) const; + void eax_fx_slot_get(const EaxCall& call) const; + // Returns `true` if all sources should be updated, or `false` otherwise. bool eax_get(const EaxCall& call); - - void eax_set_fx_slot_effect(const EaxCall& call, ALenum effect_type); - - void eax_set_fx_slot_effect(const EaxCall& call); - - - void eax_set_efx_effect_slot_gain(); - - void eax_set_fx_slot_volume(); - - - void eax_set_effect_slot_send_auto(); - - void eax_set_fx_slot_flags(); - - - void eax_ensure_is_unlocked() const; - - void eax_validate_fx_slot_effect(const GUID& eax_effect_id); - void eax_validate_fx_slot_volume(long eax_volume); - void eax_validate_fx_slot_lock(long eax_lock); - void eax_validate_fx_slot_flags(const EaxCall& call, unsigned long eax_flags); - void eax_validate_fx_slot_occlusion(long eax_occlusion); - void eax_validate_fx_slot_occlusion_lf_ratio(float eax_occlusion_lf_ratio); - void eax_validate_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& fx_slot); - void eax_validate_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& fx_slot); - - void eax_set_fx_slot_effect(const EaxCall& call, const GUID& eax_effect_id); - - void eax_set_fx_slot_volume( - long eax_volume); - - void eax_set_fx_slot_lock( - long eax_lock); - - void eax_set_fx_slot_flags( - unsigned long eax_flags); - - // [[nodiscard]] - bool eax_set_fx_slot_occlusion( - long eax_occlusion); - - // [[nodiscard]] - bool eax_set_fx_slot_occlusion_lf_ratio( - float eax_occlusion_lf_ratio); - - void eax_set_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& eax_fx_slot); - - // [[nodiscard]] - bool eax_set_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& eax_fx_slot); - - - void eax_defer_fx_slot_effect(const EaxCall& call); - - void eax_defer_fx_slot_volume(const EaxCall& call); - - void eax_defer_fx_slot_lock(const EaxCall& call); - - void eax_defer_fx_slot_flags(const EaxCall& call); - - // [[nodiscard]] - bool eax_defer_fx_slot_occlusion(const EaxCall& call); - - // [[nodiscard]] - bool eax_defer_fx_slot_occlusion_lf_ratio(const EaxCall& call); - - // [[nodiscard]] - bool eax_defer_fx_slot_all(const EaxCall& call); - - bool eax_set_fx_slot(const EaxCall& call); - - void eax_apply_deferred(); - - // [[nodiscard]] + void eax_fx_slot_load_effect(); + void eax_fx_slot_set_volume(); + void eax_fx_slot_set_environment_flag(); + void eax_fx_slot_set_flags(); + + void eax4_fx_slot_set_all(const EaxCall& call); + void eax5_fx_slot_set_all(const EaxCall& call); + + // Returns `true` if all sources should be updated, or `false` otherwise. + bool eax4_fx_slot_set(const EaxCall& call); + // Returns `true` if all sources should be updated, or `false` otherwise. + bool eax5_fx_slot_set(const EaxCall& call); + // Returns `true` if all sources should be updated, or `false` otherwise. + bool eax_fx_slot_set(const EaxCall& call); + // Returns `true` if all sources should be updated, or `false` otherwise. bool eax_set(const EaxCall& call); + template< + EaxDirtyFlags TDirtyBit, + typename TMemberResult, + typename TProps, + typename TState> + void eax_fx_slot_commit_property( + TState& state, + EaxDirtyFlags& dst_df, + TMemberResult TProps::*member) noexcept + { + auto& src_i = state.i; + auto& src_df = state.df; + auto& dst_i = eax_; + + if ((src_df & TDirtyBit) != EaxDirtyFlags{}) { + dst_df |= TDirtyBit; + dst_i.*member = src_i.*member; + } + } + + void eax4_fx_slot_commit(EaxDirtyFlags& dst_df); + void eax5_fx_slot_commit(Eax5State& state, EaxDirtyFlags& dst_df); void eax_dispatch_effect(const EaxCall& call); - // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)` - void eax_set_effect_slot_effect(EaxEffect &effect); + void eax_set_efx_slot_effect(EaxEffect &effect); // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, value)` - void eax_set_effect_slot_send_auto(bool is_send_auto); + void eax_set_efx_slot_send_auto(bool is_send_auto); // `alAuxiliaryEffectSlotf(effect_slot, AL_EFFECTSLOT_GAIN, gain)` - void eax_set_effect_slot_gain(ALfloat gain); + void eax_set_efx_slot_gain(ALfloat gain); public: class EaxDeleter { public: void operator()(ALeffectslot *effect_slot); - }; // EaxAlEffectSlotDeleter + }; #endif // ALSOFT_EAX }; void UpdateAllEffectSlotProps(ALCcontext *context); #ifdef ALSOFT_EAX - using EaxAlEffectSlotUPtr = std::unique_ptr; - -EaxAlEffectSlotUPtr eax_create_al_effect_slot( - ALCcontext& context); - -void eax_delete_al_effect_slot( - ALCcontext& context, - ALeffectslot& effect_slot); +EaxAlEffectSlotUPtr eax_create_al_effect_slot(ALCcontext& context); +void eax_delete_al_effect_slot(ALCcontext& context, ALeffectslot& effect_slot); #endif // ALSOFT_EAX #endif diff --git a/al/eax/call.cpp b/al/eax/call.cpp index 1fd05968..f779c2b0 100644 --- a/al/eax/call.cpp +++ b/al/eax/call.cpp @@ -23,6 +23,7 @@ EaxCall::EaxCall( ALvoid* property_buffer, ALuint property_size) : type_{type}, version_{0}, property_set_id_{EaxCallPropertySetId::none} + , is_deferred_{(property_id & deferred_flag) != 0} , property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id} , property_buffer_{property_buffer}, property_size_{property_size} { diff --git a/al/eax/call.h b/al/eax/call.h index 9c2706c3..4c35551c 100644 --- a/al/eax/call.h +++ b/al/eax/call.h @@ -32,6 +32,7 @@ public: ALuint property_size); bool is_get() const noexcept { return type_ == EaxCallType::get; } + bool is_deferred() const noexcept { return is_deferred_; } int get_version() const noexcept { return version_; } EaxCallPropertySetId get_property_set_id() const noexcept { return property_set_id_; } ALuint get_property_id() const noexcept { return property_id_; } @@ -76,6 +77,7 @@ private: int version_; EaxFxSlotIndex fx_slot_index_; EaxCallPropertySetId property_set_id_; + bool is_deferred_; ALuint property_id_; ALuint property_source_id_; diff --git a/al/eax/effect.h b/al/eax/effect.h index b57bf240..f09a2520 100644 --- a/al/eax/effect.h +++ b/al/eax/effect.h @@ -35,8 +35,8 @@ template class EaxEffect4 : public EaxEffect { public: - EaxEffect4(ALenum type, const EaxCall& call) - : EaxEffect{type}, version_{clamp(call.get_version(), 4, 5)} + EaxEffect4(ALenum type, int eax_version) + : EaxEffect{type}, version_{clamp(eax_version, 4, 5)} {} void initialize() @@ -70,10 +70,10 @@ protected: Props d; // Deferred. }; // State - int version_; - Props props_; - State state4_; - State state5_; + int version_{}; + Props props_{}; + State state4_{}; + State state5_{}; template static void defer(const EaxCall& call, TProperty& property) @@ -149,25 +149,25 @@ using EaxEffectUPtr = std::unique_ptr; // Creates EAX4+ effect. template -EaxEffectUPtr eax_create_eax4_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax4_effect(int eax_version) { - auto effect = std::make_unique(call); + auto effect = std::make_unique(eax_version); effect->initialize(); return effect; } EaxEffectUPtr eax_create_eax_null_effect(); -EaxEffectUPtr eax_create_eax_chorus_effect(const EaxCall& call); -EaxEffectUPtr eax_create_eax_distortion_effect(const EaxCall& call); -EaxEffectUPtr eax_create_eax_echo_effect(const EaxCall& call); -EaxEffectUPtr eax_create_eax_flanger_effect(const EaxCall& call); -EaxEffectUPtr eax_create_eax_frequency_shifter_effect(const EaxCall& call); -EaxEffectUPtr eax_create_eax_vocal_morpher_effect(const EaxCall& call); -EaxEffectUPtr eax_create_eax_pitch_shifter_effect(const EaxCall& call); -EaxEffectUPtr eax_create_eax_ring_modulator_effect(const EaxCall& call); -EaxEffectUPtr eax_create_eax_auto_wah_effect(const EaxCall& call); -EaxEffectUPtr eax_create_eax_compressor_effect(const EaxCall& call); -EaxEffectUPtr eax_create_eax_equalizer_effect(const EaxCall& call); -EaxEffectUPtr eax_create_eax_reverb_effect(const EaxCall& call); +EaxEffectUPtr eax_create_eax_chorus_effect(int eax_version); +EaxEffectUPtr eax_create_eax_distortion_effect(int eax_version); +EaxEffectUPtr eax_create_eax_echo_effect(int eax_version); +EaxEffectUPtr eax_create_eax_flanger_effect(int eax_version); +EaxEffectUPtr eax_create_eax_frequency_shifter_effect(int eax_version); +EaxEffectUPtr eax_create_eax_vocal_morpher_effect(int eax_version); +EaxEffectUPtr eax_create_eax_pitch_shifter_effect(int eax_version); +EaxEffectUPtr eax_create_eax_ring_modulator_effect(int eax_version); +EaxEffectUPtr eax_create_eax_auto_wah_effect(int eax_version); +EaxEffectUPtr eax_create_eax_compressor_effect(int eax_version); +EaxEffectUPtr eax_create_eax_equalizer_effect(int eax_version); +EaxEffectUPtr eax_create_eax_reverb_effect(int eax_version); #endif // !EAX_EFFECT_INCLUDED diff --git a/al/eax/fx_slots.cpp b/al/eax/fx_slots.cpp index 671d2cfb..83de8f78 100644 --- a/al/eax/fx_slots.cpp +++ b/al/eax/fx_slots.cpp @@ -57,12 +57,6 @@ ALeffectslot& EaxFxSlots::get(EaxFxSlotIndex index) return *fx_slots_[index.value()]; } -void EaxFxSlots::unlock_legacy() noexcept -{ - fx_slots_[0]->eax_unlock_legacy(); - fx_slots_[1]->eax_unlock_legacy(); -} - [[noreturn]] void EaxFxSlots::fail( const char* message) diff --git a/al/eax/fx_slots.h b/al/eax/fx_slots.h index e7d1452e..cb7e0db4 100644 --- a/al/eax/fx_slots.h +++ b/al/eax/fx_slots.h @@ -33,9 +33,6 @@ public: ALeffectslot& get( EaxFxSlotIndex index); - void unlock_legacy() noexcept; - - private: using Items = std::array; diff --git a/al/eax/utils.h b/al/eax/utils.h index 2960c6d7..8ff75a18 100644 --- a/al/eax/utils.h +++ b/al/eax/utils.h @@ -6,6 +6,8 @@ #include #include +using EaxDirtyFlags = unsigned int; + struct EaxAlLowPassParam { float gain; float gain_hf; diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 7e0e34aa..3400f5a4 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -127,7 +127,7 @@ public: class EaxAutoWahEffect final : public EaxEffect4 { public: - EaxAutoWahEffect(const EaxCall& call); + EaxAutoWahEffect(int eax_version); private: struct AttackTimeValidator { @@ -197,8 +197,8 @@ private: bool commit_props(const Props& props) override; }; // EaxAutoWahEffect -EaxAutoWahEffect::EaxAutoWahEffect(const EaxCall& call) - : EaxEffect4{AL_EFFECT_AUTOWAH, call} +EaxAutoWahEffect::EaxAutoWahEffect(int eax_version) + : EaxEffect4{AL_EFFECT_AUTOWAH, eax_version} {} void EaxAutoWahEffect::set_defaults(Props& props) @@ -310,9 +310,9 @@ bool EaxAutoWahEffect::commit_props(const Props& props) } // namespace -EaxEffectUPtr eax_create_eax_auto_wah_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax_auto_wah_effect(int eax_version) { - return eax_create_eax4_effect(call); + return eax_create_eax4_effect(eax_version); } #endif // ALSOFT_EAX diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index 0d4283c9..1651ebb9 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -433,8 +433,8 @@ public: using typename Base::State; using Base::defer; - EaxChorusFlangerEffect(const EaxCall& call) - : Base{Traits::efx_effect(), call} + EaxChorusFlangerEffect(int eax_version) + : Base{Traits::efx_effect(), eax_version} {} private: @@ -712,23 +712,23 @@ private: }; // EaxChorusFlangerEffect template -EaxEffectUPtr eax_create_eax_chorus_flanger_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax_chorus_flanger_effect(int eax_version) { - return eax_create_eax4_effect>(call); + return eax_create_eax4_effect>(eax_version); } } // namespace // ========================================================================== -EaxEffectUPtr eax_create_eax_chorus_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax_chorus_effect(int eax_version) { - return eax_create_eax_chorus_flanger_effect(call); + return eax_create_eax_chorus_flanger_effect(eax_version); } -EaxEffectUPtr eax_create_eax_flanger_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax_flanger_effect(int eax_version) { - return eax_create_eax_chorus_flanger_effect(call); + return eax_create_eax_chorus_flanger_effect(eax_version); } #endif // ALSOFT_EAX diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp index 9824d11b..df318709 100644 --- a/al/effects/compressor.cpp +++ b/al/effects/compressor.cpp @@ -91,7 +91,7 @@ public: class EaxCompressorEffect final : public EaxEffect4 { public: - EaxCompressorEffect(const EaxCall& call); + EaxCompressorEffect(int eax_version); private: struct OnOffValidator { @@ -122,8 +122,8 @@ private: bool commit_props(const Props& props) override; }; // EaxCompressorEffect -EaxCompressorEffect::EaxCompressorEffect(const EaxCall& call) - : EaxEffect4{AL_EFFECT_COMPRESSOR, call} +EaxCompressorEffect::EaxCompressorEffect(int eax_version) + : EaxEffect4{AL_EFFECT_COMPRESSOR, eax_version} {} void EaxCompressorEffect::set_defaults(Props& props) @@ -182,9 +182,9 @@ bool EaxCompressorEffect::commit_props(const Props& props) } // namespace -EaxEffectUPtr eax_create_eax_compressor_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax_compressor_effect(int eax_version) { - return eax_create_eax4_effect(call); + return eax_create_eax4_effect(eax_version); } #endif // ALSOFT_EAX diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index b58412b9..80e5f46d 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -133,7 +133,7 @@ public: class EaxDistortionEffect final : public EaxEffect4 { public: - EaxDistortionEffect(const EaxCall& call); + EaxDistortionEffect(int eax_version); private: struct EdgeValidator { @@ -216,8 +216,8 @@ private: bool commit_props(const Props& props) override; }; // EaxDistortionEffect -EaxDistortionEffect::EaxDistortionEffect(const EaxCall& call) - : EaxEffect4{AL_EFFECT_DISTORTION, call} +EaxDistortionEffect::EaxDistortionEffect(int eax_version) + : EaxEffect4{AL_EFFECT_DISTORTION, eax_version} {} void EaxDistortionEffect::set_defaults(Props& props) @@ -347,9 +347,9 @@ bool EaxDistortionEffect::commit_props(const Props& props) } // namespace -EaxEffectUPtr eax_create_eax_distortion_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax_distortion_effect(int eax_version) { - return eax_create_eax4_effect(call); + return eax_create_eax4_effect(eax_version); } #endif // ALSOFT_EAX diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index f25c94bf..c0968676 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -130,7 +130,7 @@ public: class EaxEchoEffect final : public EaxEffect4 { public: - EaxEchoEffect(const EaxCall& call); + EaxEchoEffect(int eax_version); private: struct DelayValidator { @@ -213,8 +213,8 @@ private: bool commit_props(const Props& props) override; }; // EaxEchoEffect -EaxEchoEffect::EaxEchoEffect(const EaxCall& call) - : EaxEffect4{AL_EFFECT_ECHO, call} +EaxEchoEffect::EaxEchoEffect(int eax_version) + : EaxEffect4{AL_EFFECT_ECHO, eax_version} {} void EaxEchoEffect::set_defaults(Props& props) @@ -344,9 +344,9 @@ bool EaxEchoEffect::commit_props(const Props& props) } // namespace -EaxEffectUPtr eax_create_eax_echo_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax_echo_effect(int eax_version) { - return eax_create_eax4_effect(call); + return eax_create_eax4_effect(eax_version); } #endif // ALSOFT_EAX diff --git a/al/effects/effects.cpp b/al/effects/effects.cpp index e4e61231..7c8447e4 100644 --- a/al/effects/effects.cpp +++ b/al/effects/effects.cpp @@ -1,16 +1,12 @@ - #include "config.h" #ifdef ALSOFT_EAX -#include "effects.h" - #include - #include "AL/efx.h" +#include "effects.h" - -EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, const EaxCall& call) +EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, int eax_version) { #define EAX_PREFIX "[EAX_MAKE_EAX_EFFECT] " @@ -20,40 +16,40 @@ EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, const EaxCall& call) return eax_create_eax_null_effect(); case AL_EFFECT_CHORUS: - return eax_create_eax_chorus_effect(call); + return eax_create_eax_chorus_effect(eax_version); case AL_EFFECT_DISTORTION: - return eax_create_eax_distortion_effect(call); + return eax_create_eax_distortion_effect(eax_version); case AL_EFFECT_ECHO: - return eax_create_eax_echo_effect(call); + return eax_create_eax_echo_effect(eax_version); case AL_EFFECT_FLANGER: - return eax_create_eax_flanger_effect(call); + return eax_create_eax_flanger_effect(eax_version); case AL_EFFECT_FREQUENCY_SHIFTER: - return eax_create_eax_frequency_shifter_effect(call); + return eax_create_eax_frequency_shifter_effect(eax_version); case AL_EFFECT_VOCAL_MORPHER: - return eax_create_eax_vocal_morpher_effect(call); + return eax_create_eax_vocal_morpher_effect(eax_version); case AL_EFFECT_PITCH_SHIFTER: - return eax_create_eax_pitch_shifter_effect(call); + return eax_create_eax_pitch_shifter_effect(eax_version); case AL_EFFECT_RING_MODULATOR: - return eax_create_eax_ring_modulator_effect(call); + return eax_create_eax_ring_modulator_effect(eax_version); case AL_EFFECT_AUTOWAH: - return eax_create_eax_auto_wah_effect(call); + return eax_create_eax_auto_wah_effect(eax_version); case AL_EFFECT_COMPRESSOR: - return eax_create_eax_compressor_effect(call); + return eax_create_eax_compressor_effect(eax_version); case AL_EFFECT_EQUALIZER: - return eax_create_eax_equalizer_effect(call); + return eax_create_eax_equalizer_effect(eax_version); case AL_EFFECT_EAXREVERB: - return eax_create_eax_reverb_effect(call); + return eax_create_eax_reverb_effect(eax_version); default: assert(false && "Unsupported AL effect type."); diff --git a/al/effects/effects.h b/al/effects/effects.h index 164c0d19..acfeec6a 100644 --- a/al/effects/effects.h +++ b/al/effects/effects.h @@ -6,7 +6,6 @@ #include "core/except.h" #ifdef ALSOFT_EAX -#include "al/eax/call.h" #include "al/eax/effect.h" #endif // ALSOFT_EAX @@ -87,7 +86,7 @@ extern const EffectVtable ConvolutionEffectVtable; #ifdef ALSOFT_EAX -EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, const EaxCall& call); +EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, int eax_version); #endif // ALSOFT_EAX #endif /* AL_EFFECTS_EFFECTS_H */ diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index 80dd1c4b..0ee351f3 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -188,7 +188,7 @@ public: class EaxEqualizerEffect final : public EaxEffect4 { public: - EaxEqualizerEffect(const EaxCall& call); + EaxEqualizerEffect(int eax_version); private: struct LowGainValidator { @@ -336,8 +336,8 @@ private: bool commit_props(const Props& props) override; }; // EaxEqualizerEffect -EaxEqualizerEffect::EaxEqualizerEffect(const EaxCall& call) - : EaxEffect4{AL_EFFECT_EQUALIZER, call} +EaxEqualizerEffect::EaxEqualizerEffect(int eax_version) + : EaxEffect4{AL_EFFECT_EQUALIZER, eax_version} {} void EaxEqualizerEffect::set_defaults(Props& props) @@ -557,9 +557,9 @@ bool EaxEqualizerEffect::commit_props(const Props& props) } // namespace -EaxEffectUPtr eax_create_eax_equalizer_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax_equalizer_effect(int eax_version) { - return eax_create_eax4_effect(call); + return eax_create_eax4_effect(eax_version); } #endif // ALSOFT_EAX diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index 2b1710ad..400c0bf4 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -149,7 +149,7 @@ public: class EaxFrequencyShifterEffect final : public EaxEffect4 { public: - EaxFrequencyShifterEffect(const EaxCall& call); + EaxFrequencyShifterEffect(int eax_version); private: struct FrequencyValidator { @@ -207,8 +207,8 @@ private: }; // EaxFrequencyShifterEffect -EaxFrequencyShifterEffect::EaxFrequencyShifterEffect(const EaxCall& call) - : EaxEffect4{AL_EFFECT_FREQUENCY_SHIFTER, call} +EaxFrequencyShifterEffect::EaxFrequencyShifterEffect(int eax_version) + : EaxEffect4{AL_EFFECT_FREQUENCY_SHIFTER, eax_version} {} void EaxFrequencyShifterEffect::set_defaults(Props& props) @@ -308,9 +308,9 @@ bool EaxFrequencyShifterEffect::commit_props(const Props& props) } // namespace -EaxEffectUPtr eax_create_eax_frequency_shifter_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax_frequency_shifter_effect(int eax_version) { - return eax_create_eax4_effect(call); + return eax_create_eax4_effect(eax_version); } #endif // ALSOFT_EAX diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index 774fb767..e917e3a0 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -156,7 +156,7 @@ public: class EaxRingModulatorEffect final : public EaxEffect4 { public: - EaxRingModulatorEffect(const EaxCall& call); + EaxRingModulatorEffect(int eax_version); private: struct FrequencyValidator { @@ -213,8 +213,8 @@ private: bool commit_props(const Props& props) override; }; // EaxRingModulatorEffect -EaxRingModulatorEffect::EaxRingModulatorEffect(const EaxCall& call) - : EaxEffect4{AL_EFFECT_RING_MODULATOR, call} +EaxRingModulatorEffect::EaxRingModulatorEffect(int eax_version) + : EaxEffect4{AL_EFFECT_RING_MODULATOR, eax_version} {} void EaxRingModulatorEffect::set_defaults(Props& props) @@ -311,9 +311,9 @@ bool EaxRingModulatorEffect::commit_props(const Props& props) } // namespace -EaxEffectUPtr eax_create_eax_ring_modulator_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax_ring_modulator_effect(int eax_version) { - return eax_create_eax4_effect(call); + return eax_create_eax4_effect(eax_version); } #endif // ALSOFT_EAX diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp index 51dbdd8f..9711da28 100644 --- a/al/effects/pshifter.cpp +++ b/al/effects/pshifter.cpp @@ -102,7 +102,7 @@ public: class EaxPitchShifterEffect final : public EaxEffect4 { public: - EaxPitchShifterEffect(const EaxCall& call); + EaxPitchShifterEffect(int eax_version); private: struct CoarseTuneValidator { @@ -146,8 +146,8 @@ private: bool commit_props(const Props& old_i) override; }; // EaxPitchShifterEffect -EaxPitchShifterEffect::EaxPitchShifterEffect(const EaxCall& call) - : EaxEffect4{AL_EFFECT_PITCH_SHIFTER, call} +EaxPitchShifterEffect::EaxPitchShifterEffect(int eax_version) + : EaxEffect4{AL_EFFECT_PITCH_SHIFTER, eax_version} {} void EaxPitchShifterEffect::set_defaults(Props& props) @@ -223,9 +223,9 @@ bool EaxPitchShifterEffect::commit_props(const Props& props) } // namespace -EaxEffectUPtr eax_create_eax_pitch_shifter_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax_pitch_shifter_effect(int eax_version) { - return eax_create_eax4_effect(call); + return eax_create_eax4_effect(eax_version); } #endif // ALSOFT_EAX diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index 07d6dfcf..19b52d66 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -577,7 +577,7 @@ public: class EaxReverbEffect final : public EaxEffect { public: - EaxReverbEffect(const EaxCall& call) noexcept; + EaxReverbEffect(int eax_version) noexcept; void dispatch(const EaxCall& call) override; /*[[nodiscard]]*/ bool commit() override; @@ -1194,8 +1194,8 @@ private: static void translate(const Props2& src, Props3& dst) noexcept; }; // EaxReverbEffect -EaxReverbEffect::EaxReverbEffect(const EaxCall& call) noexcept - : EaxEffect{AL_EFFECT_EAXREVERB}, version_{call.get_version()} +EaxReverbEffect::EaxReverbEffect(int eax_version) noexcept + : EaxEffect{AL_EFFECT_EAXREVERB}, version_{eax_version} { set_defaults(); set_current_defaults(); @@ -1986,9 +1986,9 @@ void EaxReverbEffect::translate(const Props2& src, Props3& dst) noexcept } // namespace -EaxEffectUPtr eax_create_eax_reverb_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax_reverb_effect(int eax_version) { - return std::make_unique(call); + return std::make_unique(eax_version); } #endif // ALSOFT_EAX diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index 95f98db5..e1b7a698 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -267,7 +267,7 @@ public: class EaxVocalMorpherEffect final : public EaxEffect4 { public: - EaxVocalMorpherEffect(const EaxCall& call); + EaxVocalMorpherEffect(int eax_version); private: struct PhonemeAValidator { @@ -363,8 +363,8 @@ private: bool commit_props(const Props& props) override; }; // EaxVocalMorpherEffect -EaxVocalMorpherEffect::EaxVocalMorpherEffect(const EaxCall& call) - : EaxEffect4{AL_EFFECT_VOCAL_MORPHER, call} +EaxVocalMorpherEffect::EaxVocalMorpherEffect(int eax_version) + : EaxEffect4{AL_EFFECT_VOCAL_MORPHER, eax_version} {} void EaxVocalMorpherEffect::set_defaults(Props& props) @@ -570,9 +570,9 @@ bool EaxVocalMorpherEffect::commit_props(const Props& props) } // namespace -EaxEffectUPtr eax_create_eax_vocal_morpher_effect(const EaxCall& call) +EaxEffectUPtr eax_create_eax_vocal_morpher_effect(int eax_version) { - return eax_create_eax4_effect(call); + return eax_create_eax4_effect(eax_version); } #endif // ALSOFT_EAX diff --git a/alc/context.cpp b/alc/context.cpp index 9292926c..acd21a1d 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -339,7 +339,6 @@ ALenum ALCcontext::eax_eax_set( property_value_size); eax_version_ = call.get_version(); eax_initialize(call); - eax_unlock_legacy_fx_slots(call); switch (call.get_property_set_id()) { @@ -360,8 +359,7 @@ ALenum ALCcontext::eax_eax_set( eax_fail("Unsupported property set id."); } - static constexpr auto deferred_flag = 0x80000000u; - if(!(property_id&deferred_flag) && !mDeferUpdates) + if(!call.is_deferred() && !mDeferUpdates) applyAllUpdates(); return AL_NO_ERROR; @@ -383,7 +381,6 @@ ALenum ALCcontext::eax_eax_get( property_value_size); eax_version_ = call.get_version(); eax_initialize(call); - eax_unlock_legacy_fx_slots(call); switch (call.get_property_set_id()) { @@ -501,6 +498,9 @@ void ALCcontext::eax_initialize(const EaxCall& call) eax_initialize_sources(); eax_is_initialized_ = true; + + if(!mDeferUpdates) + applyAllUpdates(); } bool ALCcontext::eax_has_no_default_effect_slot() const noexcept @@ -603,15 +603,6 @@ void ALCcontext::eax_set_defaults() noexcept eax_d_ = eax_; } -void ALCcontext::eax_unlock_legacy_fx_slots(const EaxCall& call) noexcept -{ - if (call.get_version() != 5 || eax_are_legacy_fx_slots_unlocked_) - return; - - eax_are_legacy_fx_slots_unlocked_ = true; - eax_fx_slots_.unlock_legacy(); -} - void ALCcontext::eax_dispatch_fx_slot(const EaxCall& call) { const auto fx_slot_index = call.get_fx_slot_index(); diff --git a/alc/context.h b/alc/context.h index d30ee360..f107835f 100644 --- a/alc/context.h +++ b/alc/context.h @@ -251,7 +251,6 @@ private: bool eax_is_initialized_{}; bool eax_is_tried_{}; - bool eax_are_legacy_fx_slots_unlocked_{}; long eax_last_error_{}; unsigned long eax_speaker_config_{}; @@ -305,9 +304,6 @@ private: void eax_initialize_sources(); - void eax_unlock_legacy_fx_slots(const EaxCall& call) noexcept; - - void eax_dispatch_fx_slot(const EaxCall& call); void eax_dispatch_source(const EaxCall& call); -- cgit v1.2.3 From 5b3c27ea587d84c2a49150b032f5d4dec5eb50b9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 9 Mar 2023 19:58:42 -0800 Subject: Store the per-version EAX effect state in the base class This is the start of the refactoring for holding separable per-version EAX effects. Currently the effect state is stored in the effect object, which is instantiated per-type. This makes it impossible for different effects to be assigned on different EAX versions for a given effect slot (e.g. if the app sets a Chorus effect on EAX4 Slot0, it would fail to get or set the EAX1/2/3 reverb properties since it's a Chorus effect object). Seperate per-version effects will allow for switching the OpenAL effect by switching versions. This will provide an extra benefit in being able to delay OpenAL effect initialization until some EAX version has been set, avoiding an extraneous reverb and/or chorus processor for apps that only query some EAX properties but don't set anything (or which only use Slot0, leaving Slot1 with a defaulted Chorus effect running). --- al/eax/effect.h | 82 ++++++++++++++++------ al/effects/autowah.cpp | 64 ++++++++--------- al/effects/chorus.cpp | 90 +++++++++++++----------- al/effects/compressor.cpp | 34 ++++----- al/effects/distortion.cpp | 74 ++++++++++---------- al/effects/echo.cpp | 74 ++++++++++---------- al/effects/effects.cpp | 2 +- al/effects/equalizer.cpp | 124 ++++++++++++++++----------------- al/effects/fshifter.cpp | 54 +++++++-------- al/effects/modulator.cpp | 54 +++++++-------- al/effects/null.cpp | 10 +-- al/effects/pshifter.cpp | 44 ++++++------ al/effects/reverb.cpp | 172 +++++++++++++++++++--------------------------- al/effects/vmorpher.cpp | 84 +++++++++++----------- 14 files changed, 491 insertions(+), 471 deletions(-) (limited to 'al/effects/distortion.cpp') diff --git a/al/eax/effect.h b/al/eax/effect.h index f09a2520..2514e79d 100644 --- a/al/eax/effect.h +++ b/al/eax/effect.h @@ -16,14 +16,65 @@ struct EaxEffectErrorMessages static constexpr auto unknown_version() noexcept { return "Unknown version."; } }; // EaxEffectErrorMessages +union EaxEffectProps { + EAXREVERBPROPERTIES mReverb; + EAXCHORUSPROPERTIES mChorus; + EAXAUTOWAHPROPERTIES mAutowah; + EAXAGCCOMPRESSORPROPERTIES mCompressor; + EAXDISTORTIONPROPERTIES mDistortion; + EAXECHOPROPERTIES mEcho; + EAXEQUALIZERPROPERTIES mEqualizer; + EAXFLANGERPROPERTIES mFlanger; + EAXFREQUENCYSHIFTERPROPERTIES mFrequencyShifter; + EAXRINGMODULATORPROPERTIES mModulator; + EAXPITCHSHIFTERPROPERTIES mPitchShifter; + EAXVOCALMORPHERPROPERTIES mVocalMorpher; +}; + class EaxEffect { public: - EaxEffect(ALenum type) noexcept : al_effect_type_{type} { } + EaxEffect(ALenum type, int eax_version) noexcept + : al_effect_type_{type}, version_{eax_version} + { } virtual ~EaxEffect() = default; const ALenum al_effect_type_; EffectProps al_effect_props_{}; + using Props1 = EAX_REVERBPROPERTIES; + using Props2 = EAX20LISTENERPROPERTIES; + using Props3 = EAXREVERBPROPERTIES; + using Props4 = EaxEffectProps; + + struct State1 { + Props1 i; // Immediate. + Props1 d; // Deferred. + }; + + struct State2 { + Props2 i; // Immediate. + Props2 d; // Deferred. + }; + + struct State3 { + Props3 i; // Immediate. + Props3 d; // Deferred. + }; + + struct State4 { + Props4 i; // Immediate. + Props4 d; // Deferred. + }; + + int version_; + bool changed_{}; + Props4 props_{}; + State1 state1_{}; + State2 state2_{}; + State3 state3_{}; + State4 state4_{}; + State4 state5_{}; + virtual void dispatch(const EaxCall& call) = 0; // Returns "true" if any immediated property was changed. @@ -31,13 +82,13 @@ public: }; // EaxEffect // Base class for EAX4+ effects. -template +template class EaxEffect4 : public EaxEffect { public: EaxEffect4(ALenum type, int eax_version) - : EaxEffect{type}, version_{clamp(eax_version, 4, 5)} - {} + : EaxEffect{type, clamp(eax_version, 4, 5)} + { } void initialize() { @@ -63,17 +114,6 @@ public: protected: using Exception = TException; - using Props = TProps; - - struct State { - Props i; // Immediate. - Props d; // Deferred. - }; // State - - int version_{}; - Props props_{}; - State state4_{}; - State state5_{}; template static void defer(const EaxCall& call, TProperty& property) @@ -83,13 +123,13 @@ protected: property = value; } - virtual void set_defaults(Props& props) = 0; + virtual void set_defaults(Props4& props) = 0; virtual void set_efx_defaults() = 0; - virtual void get(const EaxCall& call, const Props& props) = 0; - virtual void set(const EaxCall& call, Props& props) = 0; + virtual void get(const EaxCall& call, const Props4& props) = 0; + virtual void set(const EaxCall& call, Props4& props) = 0; - virtual bool commit_props(const Props& props) = 0; + virtual bool commit_props(const Props4& props) = 0; [[noreturn]] static void fail(const char* message) { @@ -136,7 +176,7 @@ private: } } - bool commit_state(State& state) + bool commit_state(State4& state) { const auto props = props_; state.i = state.d; @@ -156,7 +196,7 @@ EaxEffectUPtr eax_create_eax4_effect(int eax_version) return effect; } -EaxEffectUPtr eax_create_eax_null_effect(); +EaxEffectUPtr eax_create_eax_null_effect(int eax_version); EaxEffectUPtr eax_create_eax_chorus_effect(int eax_version); EaxEffectUPtr eax_create_eax_distortion_effect(int eax_version); EaxEffectUPtr eax_create_eax_echo_effect(int eax_version); diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 3400f5a4..7b467e78 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -125,7 +125,7 @@ public: {} }; // EaxAutoWahEffectException -class EaxAutoWahEffect final : public EaxEffect4 { +class EaxAutoWahEffect final : public EaxEffect4 { public: EaxAutoWahEffect(int eax_version); @@ -175,7 +175,7 @@ private: }; // PeakLevelValidator struct AllValidator { - void operator()(const Props& all) const + void operator()(const EAXAUTOWAHPROPERTIES& all) const { AttackTimeValidator{}(all.flAttackTime); ReleaseTimeValidator{}(all.flReleaseTime); @@ -184,7 +184,7 @@ private: } }; // AllValidator - void set_defaults(Props& props) override; + void set_defaults(Props4& props) override; void set_efx_attack_time() noexcept; void set_efx_release_time() noexcept; @@ -192,27 +192,27 @@ private: void set_efx_peak_gain() noexcept; void set_efx_defaults() override; - void get(const EaxCall& call, const Props& props) override; - void set(const EaxCall& call, Props& props) override; - bool commit_props(const Props& props) override; + void get(const EaxCall& call, const Props4& props) override; + void set(const EaxCall& call, Props4& props) override; + bool commit_props(const Props4& props) override; }; // EaxAutoWahEffect EaxAutoWahEffect::EaxAutoWahEffect(int eax_version) : EaxEffect4{AL_EFFECT_AUTOWAH, eax_version} {} -void EaxAutoWahEffect::set_defaults(Props& props) +void EaxAutoWahEffect::set_defaults(Props4& props) { - props.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME; - props.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME; - props.lResonance = EAXAUTOWAH_DEFAULTRESONANCE; - props.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL; + props.mAutowah.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME; + props.mAutowah.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME; + props.mAutowah.lResonance = EAXAUTOWAH_DEFAULTRESONANCE; + props.mAutowah.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL; } void EaxAutoWahEffect::set_efx_attack_time() noexcept { al_effect_props_.Autowah.AttackTime = clamp( - props_.flAttackTime, + props_.mAutowah.flAttackTime, AL_AUTOWAH_MIN_ATTACK_TIME, AL_AUTOWAH_MAX_ATTACK_TIME); } @@ -220,7 +220,7 @@ void EaxAutoWahEffect::set_efx_attack_time() noexcept void EaxAutoWahEffect::set_efx_release_time() noexcept { al_effect_props_.Autowah.ReleaseTime = clamp( - props_.flReleaseTime, + props_.mAutowah.flReleaseTime, AL_AUTOWAH_MIN_RELEASE_TIME, AL_AUTOWAH_MAX_RELEASE_TIME); } @@ -228,7 +228,7 @@ void EaxAutoWahEffect::set_efx_release_time() noexcept void EaxAutoWahEffect::set_efx_resonance() noexcept { al_effect_props_.Autowah.Resonance = clamp( - level_mb_to_gain(static_cast(props_.lResonance)), + level_mb_to_gain(static_cast(props_.mAutowah.lResonance)), AL_AUTOWAH_MIN_RESONANCE, AL_AUTOWAH_MAX_RESONANCE); } @@ -236,7 +236,7 @@ void EaxAutoWahEffect::set_efx_resonance() noexcept void EaxAutoWahEffect::set_efx_peak_gain() noexcept { al_effect_props_.Autowah.PeakGain = clamp( - level_mb_to_gain(static_cast(props_.lPeakLevel)), + level_mb_to_gain(static_cast(props_.mAutowah.lPeakLevel)), AL_AUTOWAH_MIN_PEAK_GAIN, AL_AUTOWAH_MAX_PEAK_GAIN); } @@ -249,57 +249,57 @@ void EaxAutoWahEffect::set_efx_defaults() set_efx_peak_gain(); } -void EaxAutoWahEffect::get(const EaxCall& call, const Props& props) +void EaxAutoWahEffect::get(const EaxCall& call, const Props4& props) { switch (call.get_property_id()) { case EAXAUTOWAH_NONE: break; - case EAXAUTOWAH_ALLPARAMETERS: call.set_value(props); break; - case EAXAUTOWAH_ATTACKTIME: call.set_value(props.flAttackTime); break; - case EAXAUTOWAH_RELEASETIME: call.set_value(props.flReleaseTime); break; - case EAXAUTOWAH_RESONANCE: call.set_value(props.lResonance); break; - case EAXAUTOWAH_PEAKLEVEL: call.set_value(props.lPeakLevel); break; + case EAXAUTOWAH_ALLPARAMETERS: call.set_value(props.mAutowah); break; + case EAXAUTOWAH_ATTACKTIME: call.set_value(props.mAutowah.flAttackTime); break; + case EAXAUTOWAH_RELEASETIME: call.set_value(props.mAutowah.flReleaseTime); break; + case EAXAUTOWAH_RESONANCE: call.set_value(props.mAutowah.lResonance); break; + case EAXAUTOWAH_PEAKLEVEL: call.set_value(props.mAutowah.lPeakLevel); break; default: fail_unknown_property_id(); } } -void EaxAutoWahEffect::set(const EaxCall& call, Props& props) +void EaxAutoWahEffect::set(const EaxCall& call, Props4& props) { switch (call.get_property_id()) { case EAXAUTOWAH_NONE: break; - case EAXAUTOWAH_ALLPARAMETERS: defer(call, props); break; - case EAXAUTOWAH_ATTACKTIME: defer(call, props.flAttackTime); break; - case EAXAUTOWAH_RELEASETIME: defer(call, props.flReleaseTime); break; - case EAXAUTOWAH_RESONANCE: defer(call, props.lResonance); break; - case EAXAUTOWAH_PEAKLEVEL: defer(call, props.lPeakLevel); break; + case EAXAUTOWAH_ALLPARAMETERS: defer(call, props.mAutowah); break; + case EAXAUTOWAH_ATTACKTIME: defer(call, props.mAutowah.flAttackTime); break; + case EAXAUTOWAH_RELEASETIME: defer(call, props.mAutowah.flReleaseTime); break; + case EAXAUTOWAH_RESONANCE: defer(call, props.mAutowah.lResonance); break; + case EAXAUTOWAH_PEAKLEVEL: defer(call, props.mAutowah.lPeakLevel); break; default: fail_unknown_property_id(); } } -bool EaxAutoWahEffect::commit_props(const Props& props) +bool EaxAutoWahEffect::commit_props(const Props4& props) { auto is_dirty = false; - if (props_.flAttackTime != props.flAttackTime) + if (props_.mAutowah.flAttackTime != props.mAutowah.flAttackTime) { is_dirty = true; set_efx_attack_time(); } - if (props_.flReleaseTime != props.flReleaseTime) + if (props_.mAutowah.flReleaseTime != props.mAutowah.flReleaseTime) { is_dirty = true; set_efx_release_time(); } - if (props_.lResonance != props.lResonance) + if (props_.mAutowah.lResonance != props.mAutowah.lResonance) { is_dirty = true; set_efx_resonance(); } - if (props_.lPeakLevel != props.lPeakLevel) + if (props_.mAutowah.lPeakLevel != props.mAutowah.lPeakLevel) { is_dirty = true; set_efx_peak_gain(); diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index eec67d46..9fc5a44e 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -309,6 +309,7 @@ struct EaxChorusTraits { using Exception = EaxChorusEffectException; using Props = EAXCHORUSPROPERTIES; + static constexpr auto Field = &EaxEffectProps::mChorus; static constexpr auto efx_effect() { return AL_EFFECT_CHORUS; } @@ -368,6 +369,7 @@ struct EaxFlangerTraits { using Exception = EaxFlangerEffectException; using Props = EAXFLANGERPROPERTIES; + static constexpr auto Field = &EaxEffectProps::mFlanger; static constexpr auto efx_effect() { return AL_EFFECT_FLANGER; } @@ -424,15 +426,16 @@ struct EaxFlangerTraits }; // EaxFlangerTraits template -class EaxChorusFlangerEffect final : public EaxEffect4 { +class EaxChorusFlangerEffect final : public EaxEffect4 { public: using Traits = TTraits; - using Base = EaxEffect4; + using Base = EaxEffect4; using typename Base::Exception; - using typename Base::Props; - using typename Base::State; + using typename Base::Props4; using Base::defer; + static constexpr auto Field = Traits::Field; + EaxChorusFlangerEffect(int eax_version) : Base{Traits::efx_effect(), eax_version} {} @@ -505,7 +508,7 @@ private: }; // DelayValidator struct AllValidator { - void operator()(const Props& all) const + void operator()(const typename Traits::Props& all) const { WaveformValidator{}(all.ulWaveform); PhaseValidator{}(all.lPhase); @@ -516,20 +519,21 @@ private: } }; // AllValidator - void set_defaults(Props& props) override + void set_defaults(Props4& props) override { - props.ulWaveform = Traits::eax_default_waveform(); - props.lPhase = Traits::eax_default_phase(); - props.flRate = Traits::eax_default_rate(); - props.flDepth = Traits::eax_default_depth(); - props.flFeedback = Traits::eax_default_feedback(); - props.flDelay = Traits::eax_default_delay(); + auto&& all = props.*Field; + all.ulWaveform = Traits::eax_default_waveform(); + all.lPhase = Traits::eax_default_phase(); + all.flRate = Traits::eax_default_rate(); + all.flDepth = Traits::eax_default_depth(); + all.flFeedback = Traits::eax_default_feedback(); + all.flDelay = Traits::eax_default_delay(); } void set_efx_waveform() { const auto waveform = clamp( - static_cast(Base::props_.ulWaveform), + static_cast((Base::props_.*Field).ulWaveform), Traits::efx_min_waveform(), Traits::efx_max_waveform()); const auto efx_waveform = WaveformFromEnum(waveform); @@ -540,7 +544,7 @@ private: void set_efx_phase() noexcept { Base::al_effect_props_.Chorus.Phase = clamp( - static_cast(Base::props_.lPhase), + static_cast((Base::props_.*Field).lPhase), Traits::efx_min_phase(), Traits::efx_max_phase()); } @@ -548,7 +552,7 @@ private: void set_efx_rate() noexcept { Base::al_effect_props_.Chorus.Rate = clamp( - Base::props_.flRate, + (Base::props_.*Field).flRate, Traits::efx_min_rate(), Traits::efx_max_rate()); } @@ -556,7 +560,7 @@ private: void set_efx_depth() noexcept { Base::al_effect_props_.Chorus.Depth = clamp( - Base::props_.flDepth, + (Base::props_.*Field).flDepth, Traits::efx_min_depth(), Traits::efx_max_depth()); } @@ -564,7 +568,7 @@ private: void set_efx_feedback() noexcept { Base::al_effect_props_.Chorus.Feedback = clamp( - Base::props_.flFeedback, + (Base::props_.*Field).flFeedback, Traits::efx_min_feedback(), Traits::efx_max_feedback()); } @@ -572,7 +576,7 @@ private: void set_efx_delay() noexcept { Base::al_effect_props_.Chorus.Delay = clamp( - Base::props_.flDelay, + (Base::props_.*Field).flDelay, Traits::efx_min_delay(), Traits::efx_max_delay()); } @@ -587,39 +591,40 @@ private: set_efx_delay(); } - void get(const EaxCall& call, const Props& props) override + void get(const EaxCall& call, const Props4& props) override { + auto&& all = props.*Field; switch(call.get_property_id()) { case Traits::eax_none_param_id(): break; case Traits::eax_allparameters_param_id(): - call.template set_value(props); + call.template set_value(all); break; case Traits::eax_waveform_param_id(): - call.template set_value(props.ulWaveform); + call.template set_value(all.ulWaveform); break; case Traits::eax_phase_param_id(): - call.template set_value(props.lPhase); + call.template set_value(all.lPhase); break; case Traits::eax_rate_param_id(): - call.template set_value(props.flRate); + call.template set_value(all.flRate); break; case Traits::eax_depth_param_id(): - call.template set_value(props.flDepth); + call.template set_value(all.flDepth); break; case Traits::eax_feedback_param_id(): - call.template set_value(props.flFeedback); + call.template set_value(all.flFeedback); break; case Traits::eax_delay_param_id(): - call.template set_value(props.flDelay); + call.template set_value(all.flDelay); break; default: @@ -627,39 +632,40 @@ private: } } - void set(const EaxCall& call, Props& props) override + void set(const EaxCall& call, Props4& props) override { + auto&& all = props.*Field; switch(call.get_property_id()) { case Traits::eax_none_param_id(): break; case Traits::eax_allparameters_param_id(): - Base::template defer(call, props); + Base::template defer(call, all); break; case Traits::eax_waveform_param_id(): - Base::template defer(call, props.ulWaveform); + Base::template defer(call, all.ulWaveform); break; case Traits::eax_phase_param_id(): - Base::template defer(call, props.lPhase); + Base::template defer(call, all.lPhase); break; case Traits::eax_rate_param_id(): - Base::template defer(call, props.flRate); + Base::template defer(call, all.flRate); break; case Traits::eax_depth_param_id(): - Base::template defer(call, props.flDepth); + Base::template defer(call, all.flDepth); break; case Traits::eax_feedback_param_id(): - Base::template defer(call, props.flFeedback); + Base::template defer(call, all.flFeedback); break; case Traits::eax_delay_param_id(): - Base::template defer(call, props.flDelay); + Base::template defer(call, all.flDelay); break; default: @@ -667,41 +673,43 @@ private: } } - bool commit_props(const Props& props) override + bool commit_props(const Props4& props) override { auto is_dirty = false; + auto&& src = props.*Field; + auto&& dst = Base::props_.*Field; - if (Base::props_.ulWaveform != props.ulWaveform) + if (dst.ulWaveform != src.ulWaveform) { is_dirty = true; set_efx_waveform(); } - if (Base::props_.lPhase != props.lPhase) + if (dst.lPhase != src.lPhase) { is_dirty = true; set_efx_phase(); } - if (Base::props_.flRate != props.flRate) + if (dst.flRate != src.flRate) { is_dirty = true; set_efx_rate(); } - if (Base::props_.flDepth != props.flDepth) + if (dst.flDepth != src.flDepth) { is_dirty = true; set_efx_depth(); } - if (Base::props_.flFeedback != props.flFeedback) + if (dst.flFeedback != src.flFeedback) { is_dirty = true; set_efx_feedback(); } - if (Base::props_.flDelay != props.flDelay) + if (dst.flDelay != src.flDelay) { is_dirty = true; set_efx_delay(); diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp index df318709..38dca247 100644 --- a/al/effects/compressor.cpp +++ b/al/effects/compressor.cpp @@ -88,7 +88,7 @@ public: {} }; // EaxCompressorEffectException -class EaxCompressorEffect final : public EaxEffect4 +class EaxCompressorEffect final : public EaxEffect4 { public: EaxCompressorEffect(int eax_version); @@ -106,35 +106,35 @@ private: }; // OnOffValidator struct AllValidator { - void operator()(const Props& all) const + void operator()(const EAXAGCCOMPRESSORPROPERTIES& all) const { OnOffValidator{}(all.ulOnOff); } }; // AllValidator - void set_defaults(Props& props) override; + void set_defaults(Props4& props) override; void set_efx_on_off() noexcept; void set_efx_defaults() override; - void get(const EaxCall& call, const Props& props) override; - void set(const EaxCall& call, Props& props) override; - bool commit_props(const Props& props) override; + void get(const EaxCall& call, const Props4& props) override; + void set(const EaxCall& call, Props4& props) override; + bool commit_props(const Props4& props) override; }; // EaxCompressorEffect EaxCompressorEffect::EaxCompressorEffect(int eax_version) : EaxEffect4{AL_EFFECT_COMPRESSOR, eax_version} {} -void EaxCompressorEffect::set_defaults(Props& props) +void EaxCompressorEffect::set_defaults(Props4& props) { - props.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF; + props.mCompressor.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF; } void EaxCompressorEffect::set_efx_on_off() noexcept { const auto on_off = clamp( - static_cast(props_.ulOnOff), + static_cast(props_.mCompressor.ulOnOff), AL_COMPRESSOR_MIN_ONOFF, AL_COMPRESSOR_MAX_ONOFF); al_effect_props_.Compressor.OnOff = (on_off != AL_FALSE); @@ -145,33 +145,33 @@ void EaxCompressorEffect::set_efx_defaults() set_efx_on_off(); } -void EaxCompressorEffect::get(const EaxCall& call, const Props& props) +void EaxCompressorEffect::get(const EaxCall& call, const Props4& props) { switch(call.get_property_id()) { case EAXAGCCOMPRESSOR_NONE: break; - case EAXAGCCOMPRESSOR_ALLPARAMETERS: call.set_value(props); break; - case EAXAGCCOMPRESSOR_ONOFF: call.set_value(props.ulOnOff); break; + case EAXAGCCOMPRESSOR_ALLPARAMETERS: call.set_value(props.mCompressor); break; + case EAXAGCCOMPRESSOR_ONOFF: call.set_value(props.mCompressor.ulOnOff); break; default: fail_unknown_property_id(); } } -void EaxCompressorEffect::set(const EaxCall& call, Props& props) +void EaxCompressorEffect::set(const EaxCall& call, Props4& props) { switch(call.get_property_id()) { case EAXAGCCOMPRESSOR_NONE: break; - case EAXAGCCOMPRESSOR_ALLPARAMETERS: defer(call, props); break; - case EAXAGCCOMPRESSOR_ONOFF: defer(call, props.ulOnOff); break; + case EAXAGCCOMPRESSOR_ALLPARAMETERS: defer(call, props.mCompressor); break; + case EAXAGCCOMPRESSOR_ONOFF: defer(call, props.mCompressor.ulOnOff); break; default: fail_unknown_property_id(); } } -bool EaxCompressorEffect::commit_props(const Props& props) +bool EaxCompressorEffect::commit_props(const Props4& props) { auto is_dirty = false; - if (props_.ulOnOff != props.ulOnOff) + if (props_.mCompressor.ulOnOff != props.mCompressor.ulOnOff) { is_dirty = true; set_efx_on_off(); diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index 80e5f46d..f6f94775 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -130,7 +130,7 @@ public: {} }; // EaxDistortionEffectException -class EaxDistortionEffect final : public EaxEffect4 +class EaxDistortionEffect final : public EaxEffect4 { public: EaxDistortionEffect(int eax_version); @@ -192,7 +192,7 @@ private: }; // EqBandwidthValidator struct AllValidator { - void operator()(const Props& all) const + void operator()(const EAXDISTORTIONPROPERTIES& all) const { EdgeValidator{}(all.flEdge); GainValidator{}(all.lGain); @@ -202,7 +202,7 @@ private: } }; // AllValidator - void set_defaults(Props& props) override; + void set_defaults(Props4& props) override; void set_efx_edge() noexcept; void set_efx_gain() noexcept; @@ -211,28 +211,28 @@ private: void set_efx_eq_bandwidth() noexcept; void set_efx_defaults() override; - void get(const EaxCall& call, const Props& props) override; - void set(const EaxCall& call, Props& props) override; - bool commit_props(const Props& props) override; + void get(const EaxCall& call, const Props4& props) override; + void set(const EaxCall& call, Props4& props) override; + bool commit_props(const Props4& props) override; }; // EaxDistortionEffect EaxDistortionEffect::EaxDistortionEffect(int eax_version) : EaxEffect4{AL_EFFECT_DISTORTION, eax_version} {} -void EaxDistortionEffect::set_defaults(Props& props) +void EaxDistortionEffect::set_defaults(Props4& props) { - props.flEdge = EAXDISTORTION_DEFAULTEDGE; - props.lGain = EAXDISTORTION_DEFAULTGAIN; - props.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF; - props.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER; - props.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH; + props.mDistortion.flEdge = EAXDISTORTION_DEFAULTEDGE; + props.mDistortion.lGain = EAXDISTORTION_DEFAULTGAIN; + props.mDistortion.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF; + props.mDistortion.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER; + props.mDistortion.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH; } void EaxDistortionEffect::set_efx_edge() noexcept { al_effect_props_.Distortion.Edge = clamp( - props_.flEdge, + props_.mDistortion.flEdge, AL_DISTORTION_MIN_EDGE, AL_DISTORTION_MAX_EDGE); } @@ -240,7 +240,7 @@ void EaxDistortionEffect::set_efx_edge() noexcept void EaxDistortionEffect::set_efx_gain() noexcept { al_effect_props_.Distortion.Gain = clamp( - level_mb_to_gain(static_cast(props_.lGain)), + level_mb_to_gain(static_cast(props_.mDistortion.lGain)), AL_DISTORTION_MIN_GAIN, AL_DISTORTION_MAX_GAIN); } @@ -248,7 +248,7 @@ void EaxDistortionEffect::set_efx_gain() noexcept void EaxDistortionEffect::set_efx_lowpass_cutoff() noexcept { al_effect_props_.Distortion.LowpassCutoff = clamp( - props_.flLowPassCutOff, + props_.mDistortion.flLowPassCutOff, AL_DISTORTION_MIN_LOWPASS_CUTOFF, AL_DISTORTION_MAX_LOWPASS_CUTOFF); } @@ -256,7 +256,7 @@ void EaxDistortionEffect::set_efx_lowpass_cutoff() noexcept void EaxDistortionEffect::set_efx_eq_center() noexcept { al_effect_props_.Distortion.EQCenter = clamp( - props_.flEQCenter, + props_.mDistortion.flEQCenter, AL_DISTORTION_MIN_EQCENTER, AL_DISTORTION_MAX_EQCENTER); } @@ -264,7 +264,7 @@ void EaxDistortionEffect::set_efx_eq_center() noexcept void EaxDistortionEffect::set_efx_eq_bandwidth() noexcept { al_effect_props_.Distortion.EQBandwidth = clamp( - props_.flEdge, + props_.mDistortion.flEdge, AL_DISTORTION_MIN_EQBANDWIDTH, AL_DISTORTION_MAX_EQBANDWIDTH); } @@ -278,65 +278,65 @@ void EaxDistortionEffect::set_efx_defaults() set_efx_eq_bandwidth(); } -void EaxDistortionEffect::get(const EaxCall& call, const Props& props) +void EaxDistortionEffect::get(const EaxCall& call, const Props4& props) { switch(call.get_property_id()) { case EAXDISTORTION_NONE: break; - case EAXDISTORTION_ALLPARAMETERS: call.set_value(props); break; - case EAXDISTORTION_EDGE: call.set_value(props.flEdge); break; - case EAXDISTORTION_GAIN: call.set_value(props.lGain); break; - case EAXDISTORTION_LOWPASSCUTOFF: call.set_value(props.flLowPassCutOff); break; - case EAXDISTORTION_EQCENTER: call.set_value(props.flEQCenter); break; - case EAXDISTORTION_EQBANDWIDTH: call.set_value(props.flEQBandwidth); break; + case EAXDISTORTION_ALLPARAMETERS: call.set_value(props.mDistortion); break; + case EAXDISTORTION_EDGE: call.set_value(props.mDistortion.flEdge); break; + case EAXDISTORTION_GAIN: call.set_value(props.mDistortion.lGain); break; + case EAXDISTORTION_LOWPASSCUTOFF: call.set_value(props.mDistortion.flLowPassCutOff); break; + case EAXDISTORTION_EQCENTER: call.set_value(props.mDistortion.flEQCenter); break; + case EAXDISTORTION_EQBANDWIDTH: call.set_value(props.mDistortion.flEQBandwidth); break; default: fail_unknown_property_id(); } } -void EaxDistortionEffect::set(const EaxCall& call, Props& props) +void EaxDistortionEffect::set(const EaxCall& call, Props4& props) { switch(call.get_property_id()) { case EAXDISTORTION_NONE: break; - case EAXDISTORTION_ALLPARAMETERS: defer(call, props); break; - case EAXDISTORTION_EDGE: defer(call, props.flEdge); break; - case EAXDISTORTION_GAIN: defer(call, props.lGain); break; - case EAXDISTORTION_LOWPASSCUTOFF: defer(call, props.flLowPassCutOff); break; - case EAXDISTORTION_EQCENTER: defer(call, props.flEQCenter); break; - case EAXDISTORTION_EQBANDWIDTH: defer(call, props.flEQBandwidth); break; + case EAXDISTORTION_ALLPARAMETERS: defer(call, props.mDistortion); break; + case EAXDISTORTION_EDGE: defer(call, props.mDistortion.flEdge); break; + case EAXDISTORTION_GAIN: defer(call, props.mDistortion.lGain); break; + case EAXDISTORTION_LOWPASSCUTOFF: defer(call, props.mDistortion.flLowPassCutOff); break; + case EAXDISTORTION_EQCENTER: defer(call, props.mDistortion.flEQCenter); break; + case EAXDISTORTION_EQBANDWIDTH: defer(call, props.mDistortion.flEQBandwidth); break; default: fail_unknown_property_id(); } } -bool EaxDistortionEffect::commit_props(const Props& props) +bool EaxDistortionEffect::commit_props(const Props4& props) { auto is_dirty = false; - if (props_.flEdge != props.flEdge) + if (props_.mDistortion.flEdge != props.mDistortion.flEdge) { is_dirty = true; set_efx_edge(); } - if (props_.lGain != props.lGain) + if (props_.mDistortion.lGain != props.mDistortion.lGain) { is_dirty = true; set_efx_gain(); } - if (props_.flLowPassCutOff != props.flLowPassCutOff) + if (props_.mDistortion.flLowPassCutOff != props.mDistortion.flLowPassCutOff) { is_dirty = true; set_efx_lowpass_cutoff(); } - if (props_.flEQCenter != props.flEQCenter) + if (props_.mDistortion.flEQCenter != props.mDistortion.flEQCenter) { is_dirty = true; set_efx_eq_center(); } - if (props_.flEQBandwidth != props.flEQBandwidth) + if (props_.mDistortion.flEQBandwidth != props.mDistortion.flEQBandwidth) { is_dirty = true; set_efx_eq_bandwidth(); diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index c0968676..05218793 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -127,7 +127,7 @@ public: {} }; // EaxEchoEffectException -class EaxEchoEffect final : public EaxEffect4 +class EaxEchoEffect final : public EaxEffect4 { public: EaxEchoEffect(int eax_version); @@ -189,7 +189,7 @@ private: }; // SpreadValidator struct AllValidator { - void operator()(const Props& all) const + void operator()(const EAXECHOPROPERTIES& all) const { DelayValidator{}(all.flDelay); LrDelayValidator{}(all.flLRDelay); @@ -199,7 +199,7 @@ private: } }; // AllValidator - void set_defaults(Props& props) override; + void set_defaults(Props4& props) override; void set_efx_delay() noexcept; void set_efx_lr_delay() noexcept; @@ -208,28 +208,28 @@ private: void set_efx_spread() noexcept; void set_efx_defaults() override; - void get(const EaxCall& call, const Props& props) override; - void set(const EaxCall& call, Props& props) override; - bool commit_props(const Props& props) override; + void get(const EaxCall& call, const Props4& props) override; + void set(const EaxCall& call, Props4& props) override; + bool commit_props(const Props4& props) override; }; // EaxEchoEffect EaxEchoEffect::EaxEchoEffect(int eax_version) : EaxEffect4{AL_EFFECT_ECHO, eax_version} {} -void EaxEchoEffect::set_defaults(Props& props) +void EaxEchoEffect::set_defaults(Props4& props) { - props.flDelay = EAXECHO_DEFAULTDELAY; - props.flLRDelay = EAXECHO_DEFAULTLRDELAY; - props.flDamping = EAXECHO_DEFAULTDAMPING; - props.flFeedback = EAXECHO_DEFAULTFEEDBACK; - props.flSpread = EAXECHO_DEFAULTSPREAD; + props.mEcho.flDelay = EAXECHO_DEFAULTDELAY; + props.mEcho.flLRDelay = EAXECHO_DEFAULTLRDELAY; + props.mEcho.flDamping = EAXECHO_DEFAULTDAMPING; + props.mEcho.flFeedback = EAXECHO_DEFAULTFEEDBACK; + props.mEcho.flSpread = EAXECHO_DEFAULTSPREAD; } void EaxEchoEffect::set_efx_delay() noexcept { al_effect_props_.Echo.Delay = clamp( - props_.flDelay, + props_.mEcho.flDelay, AL_ECHO_MIN_DELAY, AL_ECHO_MAX_DELAY); } @@ -237,7 +237,7 @@ void EaxEchoEffect::set_efx_delay() noexcept void EaxEchoEffect::set_efx_lr_delay() noexcept { al_effect_props_.Echo.LRDelay = clamp( - props_.flLRDelay, + props_.mEcho.flLRDelay, AL_ECHO_MIN_LRDELAY, AL_ECHO_MAX_LRDELAY); } @@ -245,7 +245,7 @@ void EaxEchoEffect::set_efx_lr_delay() noexcept void EaxEchoEffect::set_efx_damping() noexcept { al_effect_props_.Echo.Damping = clamp( - props_.flDamping, + props_.mEcho.flDamping, AL_ECHO_MIN_DAMPING, AL_ECHO_MAX_DAMPING); } @@ -253,7 +253,7 @@ void EaxEchoEffect::set_efx_damping() noexcept void EaxEchoEffect::set_efx_feedback() noexcept { al_effect_props_.Echo.Feedback = clamp( - props_.flFeedback, + props_.mEcho.flFeedback, AL_ECHO_MIN_FEEDBACK, AL_ECHO_MAX_FEEDBACK); } @@ -261,7 +261,7 @@ void EaxEchoEffect::set_efx_feedback() noexcept void EaxEchoEffect::set_efx_spread() noexcept { al_effect_props_.Echo.Spread = clamp( - props_.flSpread, + props_.mEcho.flSpread, AL_ECHO_MIN_SPREAD, AL_ECHO_MAX_SPREAD); } @@ -275,65 +275,65 @@ void EaxEchoEffect::set_efx_defaults() set_efx_spread(); } -void EaxEchoEffect::get(const EaxCall& call, const Props& props) +void EaxEchoEffect::get(const EaxCall& call, const Props4& props) { switch(call.get_property_id()) { case EAXECHO_NONE: break; - case EAXECHO_ALLPARAMETERS: call.set_value(props); break; - case EAXECHO_DELAY: call.set_value(props.flDelay); break; - case EAXECHO_LRDELAY: call.set_value(props.flLRDelay); break; - case EAXECHO_DAMPING: call.set_value(props.flDamping); break; - case EAXECHO_FEEDBACK: call.set_value(props.flFeedback); break; - case EAXECHO_SPREAD: call.set_value(props.flSpread); break; + case EAXECHO_ALLPARAMETERS: call.set_value(props.mEcho); break; + case EAXECHO_DELAY: call.set_value(props.mEcho.flDelay); break; + case EAXECHO_LRDELAY: call.set_value(props.mEcho.flLRDelay); break; + case EAXECHO_DAMPING: call.set_value(props.mEcho.flDamping); break; + case EAXECHO_FEEDBACK: call.set_value(props.mEcho.flFeedback); break; + case EAXECHO_SPREAD: call.set_value(props.mEcho.flSpread); break; default: fail_unknown_property_id(); } } -void EaxEchoEffect::set(const EaxCall& call, Props& props) +void EaxEchoEffect::set(const EaxCall& call, Props4& props) { switch(call.get_property_id()) { case EAXECHO_NONE: break; - case EAXECHO_ALLPARAMETERS: defer(call, props); break; - case EAXECHO_DELAY: defer(call, props.flDelay); break; - case EAXECHO_LRDELAY: defer(call, props.flLRDelay); break; - case EAXECHO_DAMPING: defer(call, props.flDamping); break; - case EAXECHO_FEEDBACK: defer(call, props.flFeedback); break; - case EAXECHO_SPREAD: defer(call, props.flSpread); break; + case EAXECHO_ALLPARAMETERS: defer(call, props.mEcho); break; + case EAXECHO_DELAY: defer(call, props.mEcho.flDelay); break; + case EAXECHO_LRDELAY: defer(call, props.mEcho.flLRDelay); break; + case EAXECHO_DAMPING: defer(call, props.mEcho.flDamping); break; + case EAXECHO_FEEDBACK: defer(call, props.mEcho.flFeedback); break; + case EAXECHO_SPREAD: defer(call, props.mEcho.flSpread); break; default: fail_unknown_property_id(); } } -bool EaxEchoEffect::commit_props(const Props& props) +bool EaxEchoEffect::commit_props(const Props4& props) { auto is_dirty = false; - if (props_.flDelay != props.flDelay) + if (props_.mEcho.flDelay != props.mEcho.flDelay) { is_dirty = true; set_efx_delay(); } - if (props_.flLRDelay != props.flLRDelay) + if (props_.mEcho.flLRDelay != props.mEcho.flLRDelay) { is_dirty = true; set_efx_lr_delay(); } - if (props_.flDamping != props.flDamping) + if (props_.mEcho.flDamping != props.mEcho.flDamping) { is_dirty = true; set_efx_damping(); } - if (props_.flFeedback != props.flFeedback) + if (props_.mEcho.flFeedback != props.mEcho.flFeedback) { is_dirty = true; set_efx_feedback(); } - if (props_.flSpread != props.flSpread) + if (props_.mEcho.flSpread != props.mEcho.flSpread) { is_dirty = true; set_efx_spread(); diff --git a/al/effects/effects.cpp b/al/effects/effects.cpp index 7c8447e4..820f1517 100644 --- a/al/effects/effects.cpp +++ b/al/effects/effects.cpp @@ -13,7 +13,7 @@ EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, int eax_version) switch (al_effect_type) { case AL_EFFECT_NULL: - return eax_create_eax_null_effect(); + return eax_create_eax_null_effect(eax_version); case AL_EFFECT_CHORUS: return eax_create_eax_chorus_effect(eax_version); diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index 0ee351f3..7134e188 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -185,7 +185,7 @@ public: {} }; // EaxEqualizerEffectException -class EaxEqualizerEffect final : public EaxEffect4 +class EaxEqualizerEffect final : public EaxEffect4 { public: EaxEqualizerEffect(int eax_version); @@ -302,7 +302,7 @@ private: }; // HighCutOffValidator struct AllValidator { - void operator()(const Props& all) const + void operator()(const EAXEQUALIZERPROPERTIES& all) const { LowGainValidator{}(all.lLowGain); LowCutOffValidator{}(all.flLowCutOff); @@ -317,7 +317,7 @@ private: } }; // AllValidator - void set_defaults(Props& props) override; + void set_defaults(Props4& props) override; void set_efx_low_gain() noexcept; void set_efx_low_cutoff() noexcept; @@ -331,33 +331,33 @@ private: void set_efx_high_cutoff() noexcept; void set_efx_defaults() override; - void get(const EaxCall& call, const Props& props) override; - void set(const EaxCall& call, Props& props) override; - bool commit_props(const Props& props) override; + void get(const EaxCall& call, const Props4& props) override; + void set(const EaxCall& call, Props4& props) override; + bool commit_props(const Props4& props) override; }; // EaxEqualizerEffect EaxEqualizerEffect::EaxEqualizerEffect(int eax_version) : EaxEffect4{AL_EFFECT_EQUALIZER, eax_version} {} -void EaxEqualizerEffect::set_defaults(Props& props) +void EaxEqualizerEffect::set_defaults(Props4& props) { - props.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN; - props.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF; - props.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN; - props.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER; - props.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH; - props.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN; - props.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER; - props.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH; - props.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN; - props.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF; + props.mEqualizer.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN; + props.mEqualizer.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF; + props.mEqualizer.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN; + props.mEqualizer.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER; + props.mEqualizer.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH; + props.mEqualizer.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN; + props.mEqualizer.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER; + props.mEqualizer.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH; + props.mEqualizer.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN; + props.mEqualizer.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF; } void EaxEqualizerEffect::set_efx_low_gain() noexcept { al_effect_props_.Equalizer.LowGain = clamp( - level_mb_to_gain(static_cast(props_.lLowGain)), + level_mb_to_gain(static_cast(props_.mEqualizer.lLowGain)), AL_EQUALIZER_MIN_LOW_GAIN, AL_EQUALIZER_MAX_LOW_GAIN); } @@ -365,7 +365,7 @@ void EaxEqualizerEffect::set_efx_low_gain() noexcept void EaxEqualizerEffect::set_efx_low_cutoff() noexcept { al_effect_props_.Equalizer.LowCutoff = clamp( - props_.flLowCutOff, + props_.mEqualizer.flLowCutOff, AL_EQUALIZER_MIN_LOW_CUTOFF, AL_EQUALIZER_MAX_LOW_CUTOFF); } @@ -373,7 +373,7 @@ void EaxEqualizerEffect::set_efx_low_cutoff() noexcept void EaxEqualizerEffect::set_efx_mid1_gain() noexcept { al_effect_props_.Equalizer.Mid1Gain = clamp( - level_mb_to_gain(static_cast(props_.lMid1Gain)), + level_mb_to_gain(static_cast(props_.mEqualizer.lMid1Gain)), AL_EQUALIZER_MIN_MID1_GAIN, AL_EQUALIZER_MAX_MID1_GAIN); } @@ -381,7 +381,7 @@ void EaxEqualizerEffect::set_efx_mid1_gain() noexcept void EaxEqualizerEffect::set_efx_mid1_center() noexcept { al_effect_props_.Equalizer.Mid1Center = clamp( - props_.flMid1Center, + props_.mEqualizer.flMid1Center, AL_EQUALIZER_MIN_MID1_CENTER, AL_EQUALIZER_MAX_MID1_CENTER); } @@ -389,7 +389,7 @@ void EaxEqualizerEffect::set_efx_mid1_center() noexcept void EaxEqualizerEffect::set_efx_mid1_width() noexcept { al_effect_props_.Equalizer.Mid1Width = clamp( - props_.flMid1Width, + props_.mEqualizer.flMid1Width, AL_EQUALIZER_MIN_MID1_WIDTH, AL_EQUALIZER_MAX_MID1_WIDTH); } @@ -397,7 +397,7 @@ void EaxEqualizerEffect::set_efx_mid1_width() noexcept void EaxEqualizerEffect::set_efx_mid2_gain() noexcept { al_effect_props_.Equalizer.Mid2Gain = clamp( - level_mb_to_gain(static_cast(props_.lMid2Gain)), + level_mb_to_gain(static_cast(props_.mEqualizer.lMid2Gain)), AL_EQUALIZER_MIN_MID2_GAIN, AL_EQUALIZER_MAX_MID2_GAIN); } @@ -405,7 +405,7 @@ void EaxEqualizerEffect::set_efx_mid2_gain() noexcept void EaxEqualizerEffect::set_efx_mid2_center() noexcept { al_effect_props_.Equalizer.Mid2Center = clamp( - props_.flMid2Center, + props_.mEqualizer.flMid2Center, AL_EQUALIZER_MIN_MID2_CENTER, AL_EQUALIZER_MAX_MID2_CENTER); } @@ -413,7 +413,7 @@ void EaxEqualizerEffect::set_efx_mid2_center() noexcept void EaxEqualizerEffect::set_efx_mid2_width() noexcept { al_effect_props_.Equalizer.Mid2Width = clamp( - props_.flMid2Width, + props_.mEqualizer.flMid2Width, AL_EQUALIZER_MIN_MID2_WIDTH, AL_EQUALIZER_MAX_MID2_WIDTH); } @@ -421,7 +421,7 @@ void EaxEqualizerEffect::set_efx_mid2_width() noexcept void EaxEqualizerEffect::set_efx_high_gain() noexcept { al_effect_props_.Equalizer.HighGain = clamp( - level_mb_to_gain(static_cast(props_.lHighGain)), + level_mb_to_gain(static_cast(props_.mEqualizer.lHighGain)), AL_EQUALIZER_MIN_HIGH_GAIN, AL_EQUALIZER_MAX_HIGH_GAIN); } @@ -429,7 +429,7 @@ void EaxEqualizerEffect::set_efx_high_gain() noexcept void EaxEqualizerEffect::set_efx_high_cutoff() noexcept { al_effect_props_.Equalizer.HighCutoff = clamp( - props_.flHighCutOff, + props_.mEqualizer.flHighCutOff, AL_EQUALIZER_MIN_HIGH_CUTOFF, AL_EQUALIZER_MAX_HIGH_CUTOFF); } @@ -448,105 +448,105 @@ void EaxEqualizerEffect::set_efx_defaults() set_efx_high_cutoff(); } -void EaxEqualizerEffect::get(const EaxCall& call, const Props& props) +void EaxEqualizerEffect::get(const EaxCall& call, const Props4& props) { switch(call.get_property_id()) { case EAXEQUALIZER_NONE: break; - case EAXEQUALIZER_ALLPARAMETERS: call.set_value(props); break; - case EAXEQUALIZER_LOWGAIN: call.set_value(props.lLowGain); break; - case EAXEQUALIZER_LOWCUTOFF: call.set_value(props.flLowCutOff); break; - case EAXEQUALIZER_MID1GAIN: call.set_value(props.lMid1Gain); break; - case EAXEQUALIZER_MID1CENTER: call.set_value(props.flMid1Center); break; - case EAXEQUALIZER_MID1WIDTH: call.set_value(props.flMid1Width); break; - case EAXEQUALIZER_MID2GAIN: call.set_value(props.lMid2Gain); break; - case EAXEQUALIZER_MID2CENTER: call.set_value(props.flMid2Center); break; - case EAXEQUALIZER_MID2WIDTH: call.set_value(props.flMid2Width); break; - case EAXEQUALIZER_HIGHGAIN: call.set_value(props.lHighGain); break; - case EAXEQUALIZER_HIGHCUTOFF: call.set_value(props.flHighCutOff); break; + case EAXEQUALIZER_ALLPARAMETERS: call.set_value(props.mEqualizer); break; + case EAXEQUALIZER_LOWGAIN: call.set_value(props.mEqualizer.lLowGain); break; + case EAXEQUALIZER_LOWCUTOFF: call.set_value(props.mEqualizer.flLowCutOff); break; + case EAXEQUALIZER_MID1GAIN: call.set_value(props.mEqualizer.lMid1Gain); break; + case EAXEQUALIZER_MID1CENTER: call.set_value(props.mEqualizer.flMid1Center); break; + case EAXEQUALIZER_MID1WIDTH: call.set_value(props.mEqualizer.flMid1Width); break; + case EAXEQUALIZER_MID2GAIN: call.set_value(props.mEqualizer.lMid2Gain); break; + case EAXEQUALIZER_MID2CENTER: call.set_value(props.mEqualizer.flMid2Center); break; + case EAXEQUALIZER_MID2WIDTH: call.set_value(props.mEqualizer.flMid2Width); break; + case EAXEQUALIZER_HIGHGAIN: call.set_value(props.mEqualizer.lHighGain); break; + case EAXEQUALIZER_HIGHCUTOFF: call.set_value(props.mEqualizer.flHighCutOff); break; default: fail_unknown_property_id(); } } -void EaxEqualizerEffect::set(const EaxCall& call, Props& props) +void EaxEqualizerEffect::set(const EaxCall& call, Props4& props) { switch(call.get_property_id()) { case EAXEQUALIZER_NONE: break; - case EAXEQUALIZER_ALLPARAMETERS: defer(call, props); break; - case EAXEQUALIZER_LOWGAIN: defer(call, props.lLowGain); break; - case EAXEQUALIZER_LOWCUTOFF: defer(call, props.flLowCutOff); break; - case EAXEQUALIZER_MID1GAIN: defer(call, props.lMid1Gain); break; - case EAXEQUALIZER_MID1CENTER: defer(call, props.flMid1Center); break; - case EAXEQUALIZER_MID1WIDTH: defer(call, props.flMid1Width); break; - case EAXEQUALIZER_MID2GAIN: defer(call, props.lMid2Gain); break; - case EAXEQUALIZER_MID2CENTER: defer(call, props.flMid2Center); break; - case EAXEQUALIZER_MID2WIDTH: defer(call, props.flMid2Width); break; - case EAXEQUALIZER_HIGHGAIN: defer(call, props.lHighGain); break; - case EAXEQUALIZER_HIGHCUTOFF: defer(call, props.flHighCutOff); break; + case EAXEQUALIZER_ALLPARAMETERS: defer(call, props.mEqualizer); break; + case EAXEQUALIZER_LOWGAIN: defer(call, props.mEqualizer.lLowGain); break; + case EAXEQUALIZER_LOWCUTOFF: defer(call, props.mEqualizer.flLowCutOff); break; + case EAXEQUALIZER_MID1GAIN: defer(call, props.mEqualizer.lMid1Gain); break; + case EAXEQUALIZER_MID1CENTER: defer(call, props.mEqualizer.flMid1Center); break; + case EAXEQUALIZER_MID1WIDTH: defer(call, props.mEqualizer.flMid1Width); break; + case EAXEQUALIZER_MID2GAIN: defer(call, props.mEqualizer.lMid2Gain); break; + case EAXEQUALIZER_MID2CENTER: defer(call, props.mEqualizer.flMid2Center); break; + case EAXEQUALIZER_MID2WIDTH: defer(call, props.mEqualizer.flMid2Width); break; + case EAXEQUALIZER_HIGHGAIN: defer(call, props.mEqualizer.lHighGain); break; + case EAXEQUALIZER_HIGHCUTOFF: defer(call, props.mEqualizer.flHighCutOff); break; default: fail_unknown_property_id(); } } -bool EaxEqualizerEffect::commit_props(const Props& props) +bool EaxEqualizerEffect::commit_props(const Props4& props) { auto is_dirty = false; - if (props_.lLowGain != props.lLowGain) + if (props_.mEqualizer.lLowGain != props.mEqualizer.lLowGain) { is_dirty = true; set_efx_low_gain(); } - if (props_.flLowCutOff != props.flLowCutOff) + if (props_.mEqualizer.flLowCutOff != props.mEqualizer.flLowCutOff) { is_dirty = true; set_efx_low_cutoff(); } - if (props_.lMid1Gain != props.lMid1Gain) + if (props_.mEqualizer.lMid1Gain != props.mEqualizer.lMid1Gain) { is_dirty = true; set_efx_mid1_gain(); } - if (props_.flMid1Center != props.flMid1Center) + if (props_.mEqualizer.flMid1Center != props.mEqualizer.flMid1Center) { is_dirty = true; set_efx_mid1_center(); } - if (props_.flMid1Width != props.flMid1Width) + if (props_.mEqualizer.flMid1Width != props.mEqualizer.flMid1Width) { is_dirty = true; set_efx_mid1_width(); } - if (props_.lMid2Gain != props.lMid2Gain) + if (props_.mEqualizer.lMid2Gain != props.mEqualizer.lMid2Gain) { is_dirty = true; set_efx_mid2_gain(); } - if (props_.flMid2Center != props.flMid2Center) + if (props_.mEqualizer.flMid2Center != props.mEqualizer.flMid2Center) { is_dirty = true; set_efx_mid2_center(); } - if (props_.flMid2Width != props.flMid2Width) + if (props_.mEqualizer.flMid2Width != props.mEqualizer.flMid2Width) { is_dirty = true; set_efx_mid2_width(); } - if (props_.lHighGain != props.lHighGain) + if (props_.mEqualizer.lHighGain != props.mEqualizer.lHighGain) { is_dirty = true; set_efx_high_gain(); } - if (props_.flHighCutOff != props.flHighCutOff) + if (props_.mEqualizer.flHighCutOff != props.mEqualizer.flHighCutOff) { is_dirty = true; set_efx_high_cutoff(); diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index 9ca28775..1a97e339 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -147,7 +147,7 @@ public: {} }; // EaxFrequencyShifterEffectException -class EaxFrequencyShifterEffect final : public EaxEffect4 { +class EaxFrequencyShifterEffect final : public EaxEffect4 { public: EaxFrequencyShifterEffect(int eax_version); @@ -186,7 +186,7 @@ private: }; // RightDirectionValidator struct AllValidator { - void operator()(const Props& all) const + void operator()(const EAXFREQUENCYSHIFTERPROPERTIES& all) const { FrequencyValidator{}(all.flFrequency); LeftDirectionValidator{}(all.ulLeftDirection); @@ -194,16 +194,16 @@ private: } }; // AllValidator - void set_defaults(Props& props) override; + void set_defaults(Props4& props) override; void set_efx_frequency() noexcept; void set_efx_left_direction(); void set_efx_right_direction(); void set_efx_defaults() override; - void get(const EaxCall& call, const Props& props) override; - void set(const EaxCall& call, Props& props) override; - bool commit_props(const Props& props) override; + void get(const EaxCall& call, const Props4& props) override; + void set(const EaxCall& call, Props4& props) override; + bool commit_props(const Props4& props) override; }; // EaxFrequencyShifterEffect @@ -211,17 +211,17 @@ EaxFrequencyShifterEffect::EaxFrequencyShifterEffect(int eax_version) : EaxEffect4{AL_EFFECT_FREQUENCY_SHIFTER, eax_version} {} -void EaxFrequencyShifterEffect::set_defaults(Props& props) +void EaxFrequencyShifterEffect::set_defaults(Props4& props) { - props.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY; - props.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION; - props.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION; + props.mFrequencyShifter.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY; + props.mFrequencyShifter.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION; + props.mFrequencyShifter.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION; } void EaxFrequencyShifterEffect::set_efx_frequency() noexcept { al_effect_props_.Fshifter.Frequency = clamp( - props_.flFrequency, + props_.mFrequencyShifter.flFrequency, AL_FREQUENCY_SHIFTER_MIN_FREQUENCY, AL_FREQUENCY_SHIFTER_MAX_FREQUENCY); } @@ -229,7 +229,7 @@ void EaxFrequencyShifterEffect::set_efx_frequency() noexcept void EaxFrequencyShifterEffect::set_efx_left_direction() { const auto left_direction = clamp( - static_cast(props_.ulLeftDirection), + static_cast(props_.mFrequencyShifter.ulLeftDirection), AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION, AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION); const auto efx_left_direction = DirectionFromEmum(left_direction); @@ -240,7 +240,7 @@ void EaxFrequencyShifterEffect::set_efx_left_direction() void EaxFrequencyShifterEffect::set_efx_right_direction() { const auto right_direction = clamp( - static_cast(props_.ulRightDirection), + static_cast(props_.mFrequencyShifter.ulRightDirection), AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION, AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION); const auto efx_right_direction = DirectionFromEmum(right_direction); @@ -255,49 +255,49 @@ void EaxFrequencyShifterEffect::set_efx_defaults() set_efx_right_direction(); } -void EaxFrequencyShifterEffect::get(const EaxCall& call, const Props& props) +void EaxFrequencyShifterEffect::get(const EaxCall& call, const Props4& props) { switch(call.get_property_id()) { case EAXFREQUENCYSHIFTER_NONE: break; - case EAXFREQUENCYSHIFTER_ALLPARAMETERS: call.set_value(props); break; - case EAXFREQUENCYSHIFTER_FREQUENCY: call.set_value(props.flFrequency); break; - case EAXFREQUENCYSHIFTER_LEFTDIRECTION: call.set_value(props.ulLeftDirection); break; - case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: call.set_value(props.ulRightDirection); break; + case EAXFREQUENCYSHIFTER_ALLPARAMETERS: call.set_value(props.mFrequencyShifter); break; + case EAXFREQUENCYSHIFTER_FREQUENCY: call.set_value(props.mFrequencyShifter.flFrequency); break; + case EAXFREQUENCYSHIFTER_LEFTDIRECTION: call.set_value(props.mFrequencyShifter.ulLeftDirection); break; + case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: call.set_value(props.mFrequencyShifter.ulRightDirection); break; default: fail_unknown_property_id(); } } -void EaxFrequencyShifterEffect::set(const EaxCall& call, Props& props) +void EaxFrequencyShifterEffect::set(const EaxCall& call, Props4& props) { switch(call.get_property_id()) { case EAXFREQUENCYSHIFTER_NONE: break; - case EAXFREQUENCYSHIFTER_ALLPARAMETERS: defer(call, props); break; - case EAXFREQUENCYSHIFTER_FREQUENCY: defer(call, props.flFrequency); break; - case EAXFREQUENCYSHIFTER_LEFTDIRECTION: defer(call, props.ulLeftDirection); break; - case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: defer(call, props.ulRightDirection); break; + case EAXFREQUENCYSHIFTER_ALLPARAMETERS: defer(call, props.mFrequencyShifter); break; + case EAXFREQUENCYSHIFTER_FREQUENCY: defer(call, props.mFrequencyShifter.flFrequency); break; + case EAXFREQUENCYSHIFTER_LEFTDIRECTION: defer(call, props.mFrequencyShifter.ulLeftDirection); break; + case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: defer(call, props.mFrequencyShifter.ulRightDirection); break; default: fail_unknown_property_id(); } } -bool EaxFrequencyShifterEffect::commit_props(const Props& props) +bool EaxFrequencyShifterEffect::commit_props(const Props4& props) { auto is_dirty = false; - if (props_.flFrequency != props.flFrequency) + if (props_.mFrequencyShifter.flFrequency != props.mFrequencyShifter.flFrequency) { is_dirty = true; set_efx_frequency(); } - if (props_.ulLeftDirection != props.ulLeftDirection) + if (props_.mFrequencyShifter.ulLeftDirection != props.mFrequencyShifter.ulLeftDirection) { is_dirty = true; set_efx_left_direction(); } - if (props_.ulRightDirection != props.ulRightDirection) + if (props_.mFrequencyShifter.ulRightDirection != props.mFrequencyShifter.ulRightDirection) { is_dirty = true; set_efx_right_direction(); diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index 070b0998..a6a443f8 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -153,7 +153,7 @@ public: {} }; // EaxRingModulatorEffectException -class EaxRingModulatorEffect final : public EaxEffect4 +class EaxRingModulatorEffect final : public EaxEffect4 { public: EaxRingModulatorEffect(int eax_version); @@ -193,7 +193,7 @@ private: }; // WaveformValidator struct AllValidator { - void operator()(const Props& all) const + void operator()(const EAXRINGMODULATORPROPERTIES& all) const { FrequencyValidator{}(all.flFrequency); HighPassCutOffValidator{}(all.flHighPassCutOff); @@ -201,33 +201,33 @@ private: } }; // AllValidator - void set_defaults(Props& props) override; + void set_defaults(Props4& props) override; void set_efx_frequency() noexcept; void set_efx_high_pass_cutoff() noexcept; void set_efx_waveform(); void set_efx_defaults() override; - void get(const EaxCall& call, const Props& props) override; - void set(const EaxCall& call, Props& props) override; - bool commit_props(const Props& props) override; + void get(const EaxCall& call, const Props4& props) override; + void set(const EaxCall& call, Props4& props) override; + bool commit_props(const Props4& props) override; }; // EaxRingModulatorEffect EaxRingModulatorEffect::EaxRingModulatorEffect(int eax_version) : EaxEffect4{AL_EFFECT_RING_MODULATOR, eax_version} {} -void EaxRingModulatorEffect::set_defaults(Props& props) +void EaxRingModulatorEffect::set_defaults(Props4& props) { - props.flFrequency = EAXRINGMODULATOR_DEFAULTFREQUENCY; - props.flHighPassCutOff = EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF; - props.ulWaveform = EAXRINGMODULATOR_DEFAULTWAVEFORM; + props.mModulator.flFrequency = EAXRINGMODULATOR_DEFAULTFREQUENCY; + props.mModulator.flHighPassCutOff = EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF; + props.mModulator.ulWaveform = EAXRINGMODULATOR_DEFAULTWAVEFORM; } void EaxRingModulatorEffect::set_efx_frequency() noexcept { al_effect_props_.Modulator.Frequency = clamp( - props_.flFrequency, + props_.mModulator.flFrequency, AL_RING_MODULATOR_MIN_FREQUENCY, AL_RING_MODULATOR_MAX_FREQUENCY); } @@ -235,7 +235,7 @@ void EaxRingModulatorEffect::set_efx_frequency() noexcept void EaxRingModulatorEffect::set_efx_high_pass_cutoff() noexcept { al_effect_props_.Modulator.HighPassCutoff = clamp( - props_.flHighPassCutOff, + props_.mModulator.flHighPassCutOff, AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF, AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF); } @@ -243,7 +243,7 @@ void EaxRingModulatorEffect::set_efx_high_pass_cutoff() noexcept void EaxRingModulatorEffect::set_efx_waveform() { const auto waveform = clamp( - static_cast(props_.ulWaveform), + static_cast(props_.mModulator.ulWaveform), AL_RING_MODULATOR_MIN_WAVEFORM, AL_RING_MODULATOR_MAX_WAVEFORM); const auto efx_waveform = WaveformFromEmum(waveform); @@ -258,49 +258,49 @@ void EaxRingModulatorEffect::set_efx_defaults() set_efx_waveform(); } -void EaxRingModulatorEffect::get(const EaxCall& call, const Props& props) +void EaxRingModulatorEffect::get(const EaxCall& call, const Props4& props) { switch(call.get_property_id()) { case EAXRINGMODULATOR_NONE: break; - case EAXRINGMODULATOR_ALLPARAMETERS: call.set_value(props); break; - case EAXRINGMODULATOR_FREQUENCY: call.set_value(props.flFrequency); break; - case EAXRINGMODULATOR_HIGHPASSCUTOFF: call.set_value(props.flHighPassCutOff); break; - case EAXRINGMODULATOR_WAVEFORM: call.set_value(props.ulWaveform); break; + case EAXRINGMODULATOR_ALLPARAMETERS: call.set_value(props.mModulator); break; + case EAXRINGMODULATOR_FREQUENCY: call.set_value(props.mModulator.flFrequency); break; + case EAXRINGMODULATOR_HIGHPASSCUTOFF: call.set_value(props.mModulator.flHighPassCutOff); break; + case EAXRINGMODULATOR_WAVEFORM: call.set_value(props.mModulator.ulWaveform); break; default: fail_unknown_property_id(); } } -void EaxRingModulatorEffect::set(const EaxCall& call, Props& props) +void EaxRingModulatorEffect::set(const EaxCall& call, Props4& props) { switch (call.get_property_id()) { case EAXRINGMODULATOR_NONE: break; - case EAXRINGMODULATOR_ALLPARAMETERS: defer(call, props); break; - case EAXRINGMODULATOR_FREQUENCY: defer(call, props.flFrequency); break; - case EAXRINGMODULATOR_HIGHPASSCUTOFF: defer(call, props.flHighPassCutOff); break; - case EAXRINGMODULATOR_WAVEFORM: defer(call, props.ulWaveform); break; + case EAXRINGMODULATOR_ALLPARAMETERS: defer(call, props.mModulator); break; + case EAXRINGMODULATOR_FREQUENCY: defer(call, props.mModulator.flFrequency); break; + case EAXRINGMODULATOR_HIGHPASSCUTOFF: defer(call, props.mModulator.flHighPassCutOff); break; + case EAXRINGMODULATOR_WAVEFORM: defer(call, props.mModulator.ulWaveform); break; default: fail_unknown_property_id(); } } -bool EaxRingModulatorEffect::commit_props(const Props& props) +bool EaxRingModulatorEffect::commit_props(const Props4& props) { auto is_dirty = false; - if (props_.flFrequency != props.flFrequency) + if (props_.mModulator.flFrequency != props.mModulator.flFrequency) { is_dirty = true; set_efx_frequency(); } - if (props_.flHighPassCutOff != props.flHighPassCutOff) + if (props_.mModulator.flHighPassCutOff != props.mModulator.flHighPassCutOff) { is_dirty = true; set_efx_high_pass_cutoff(); } - if (props_.ulWaveform != props.ulWaveform) + if (props_.mModulator.ulWaveform != props.mModulator.ulWaveform) { is_dirty = true; set_efx_waveform(); diff --git a/al/effects/null.cpp b/al/effects/null.cpp index 2243dfe1..5bbcdd62 100644 --- a/al/effects/null.cpp +++ b/al/effects/null.cpp @@ -102,7 +102,7 @@ namespace { class EaxNullEffect final : public EaxEffect { public: - EaxNullEffect() noexcept; + EaxNullEffect(int eax_version) noexcept; void dispatch(const EaxCall& call) override; /*[[nodiscard]]*/ bool commit() override; @@ -117,8 +117,8 @@ public: {} }; // EaxNullEffectException -EaxNullEffect::EaxNullEffect() noexcept - : EaxEffect{AL_EFFECT_NULL} +EaxNullEffect::EaxNullEffect(int eax_version) noexcept + : EaxEffect{AL_EFFECT_NULL, eax_version} {} void EaxNullEffect::dispatch(const EaxCall& call) @@ -134,9 +134,9 @@ bool EaxNullEffect::commit() } // namespace -EaxEffectUPtr eax_create_eax_null_effect() +EaxEffectUPtr eax_create_eax_null_effect(int eax_version) { - return std::make_unique(); + return std::make_unique(eax_version); } #endif // ALSOFT_EAX diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp index 9711da28..ef3fe587 100644 --- a/al/effects/pshifter.cpp +++ b/al/effects/pshifter.cpp @@ -100,7 +100,7 @@ public: {} }; // EaxPitchShifterEffectException -class EaxPitchShifterEffect final : public EaxEffect4 { +class EaxPitchShifterEffect final : public EaxEffect4 { public: EaxPitchShifterEffect(int eax_version); @@ -128,38 +128,38 @@ private: }; // FineTuneValidator struct AllValidator { - void operator()(const Props& all) const + void operator()(const EAXPITCHSHIFTERPROPERTIES& all) const { CoarseTuneValidator{}(all.lCoarseTune); FineTuneValidator{}(all.lFineTune); } }; // AllValidator - void set_defaults(Props& props) override; + void set_defaults(Props4& props) override; void set_efx_coarse_tune() noexcept; void set_efx_fine_tune() noexcept; void set_efx_defaults() override; - void get(const EaxCall& call, const Props& props) override; - void set(const EaxCall& call, Props& props) override; - bool commit_props(const Props& old_i) override; + void get(const EaxCall& call, const Props4& props) override; + void set(const EaxCall& call, Props4& props) override; + bool commit_props(const Props4& old_i) override; }; // EaxPitchShifterEffect EaxPitchShifterEffect::EaxPitchShifterEffect(int eax_version) : EaxEffect4{AL_EFFECT_PITCH_SHIFTER, eax_version} {} -void EaxPitchShifterEffect::set_defaults(Props& props) +void EaxPitchShifterEffect::set_defaults(Props4& props) { - props.lCoarseTune = EAXPITCHSHIFTER_DEFAULTCOARSETUNE; - props.lFineTune = EAXPITCHSHIFTER_DEFAULTFINETUNE; + props.mPitchShifter.lCoarseTune = EAXPITCHSHIFTER_DEFAULTCOARSETUNE; + props.mPitchShifter.lFineTune = EAXPITCHSHIFTER_DEFAULTFINETUNE; } void EaxPitchShifterEffect::set_efx_coarse_tune() noexcept { al_effect_props_.Pshifter.CoarseTune = clamp( - static_cast(props_.lCoarseTune), + static_cast(props_.mPitchShifter.lCoarseTune), AL_PITCH_SHIFTER_MIN_COARSE_TUNE, AL_PITCH_SHIFTER_MAX_COARSE_TUNE); } @@ -167,7 +167,7 @@ void EaxPitchShifterEffect::set_efx_coarse_tune() noexcept void EaxPitchShifterEffect::set_efx_fine_tune() noexcept { al_effect_props_.Pshifter.FineTune = clamp( - static_cast(props_.lFineTune), + static_cast(props_.mPitchShifter.lFineTune), AL_PITCH_SHIFTER_MIN_FINE_TUNE, AL_PITCH_SHIFTER_MAX_FINE_TUNE); } @@ -178,41 +178,41 @@ void EaxPitchShifterEffect::set_efx_defaults() set_efx_fine_tune(); } -void EaxPitchShifterEffect::get(const EaxCall& call, const Props& props) +void EaxPitchShifterEffect::get(const EaxCall& call, const Props4& props) { switch(call.get_property_id()) { case EAXPITCHSHIFTER_NONE: break; - case EAXPITCHSHIFTER_ALLPARAMETERS: call.set_value(props); break; - case EAXPITCHSHIFTER_COARSETUNE: call.set_value(props.lCoarseTune); break; - case EAXPITCHSHIFTER_FINETUNE: call.set_value(props.lFineTune); break; + case EAXPITCHSHIFTER_ALLPARAMETERS: call.set_value(props.mPitchShifter); break; + case EAXPITCHSHIFTER_COARSETUNE: call.set_value(props.mPitchShifter.lCoarseTune); break; + case EAXPITCHSHIFTER_FINETUNE: call.set_value(props.mPitchShifter.lFineTune); break; default: fail_unknown_property_id(); } } -void EaxPitchShifterEffect::set(const EaxCall& call, Props& props) +void EaxPitchShifterEffect::set(const EaxCall& call, Props4& props) { switch(call.get_property_id()) { case EAXPITCHSHIFTER_NONE: break; - case EAXPITCHSHIFTER_ALLPARAMETERS: defer(call, props); break; - case EAXPITCHSHIFTER_COARSETUNE: defer(call, props.lCoarseTune); break; - case EAXPITCHSHIFTER_FINETUNE: defer(call, props.lFineTune); break; + case EAXPITCHSHIFTER_ALLPARAMETERS: defer(call, props.mPitchShifter); break; + case EAXPITCHSHIFTER_COARSETUNE: defer(call, props.mPitchShifter.lCoarseTune); break; + case EAXPITCHSHIFTER_FINETUNE: defer(call, props.mPitchShifter.lFineTune); break; default: fail_unknown_property_id(); } } -bool EaxPitchShifterEffect::commit_props(const Props& props) +bool EaxPitchShifterEffect::commit_props(const Props4& props) { auto is_dirty = false; - if (props_.lCoarseTune != props.lCoarseTune) + if (props_.mPitchShifter.lCoarseTune != props.mPitchShifter.lCoarseTune) { is_dirty = true; set_efx_coarse_tune(); } - if (props_.lFineTune != props.lFineTune) + if (props_.mPitchShifter.lFineTune != props.mPitchShifter.lFineTune) { is_dirty = true; set_efx_fine_tune(); diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index 656642e0..ba586254 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -587,28 +587,6 @@ private: using Exception = EaxReverbEffectException; - using Props1 = EAX_REVERBPROPERTIES; - using Props2 = EAX20LISTENERPROPERTIES; - using Props3 = EAXREVERBPROPERTIES; - - struct State1 - { - Props1 i; // Immediate. - Props1 d; // Deferred. - }; // State1 - - struct State2 - { - Props2 i; // Immediate. - Props2 d; // Deferred. - }; // State2 - - struct State3 - { - Props3 i; // Immediate. - Props3 d; // Deferred. - }; // State3 - struct EnvironmentValidator1 { void operator()(unsigned long ulEnvironment) const { @@ -654,7 +632,7 @@ private: }; // DampingValidator struct AllValidator1 { - void operator()(const Props1& all) const + void operator()(const EAX_REVERBPROPERTIES& all) const { EnvironmentValidator1{}(all.environment); VolumeValidator{}(all.fVolume); @@ -796,7 +774,7 @@ private: }; // FlagsValidator2 struct AllValidator2 { - void operator()(const Props2& all) const + void operator()(const EAX20LISTENERPROPERTIES& all) const { RoomValidator{}(all.lRoom); RoomHFValidator{}(all.lRoomHF); @@ -931,7 +909,7 @@ private: }; // FlagsValidator3 struct AllValidator3 { - void operator()(const Props3& all) const + void operator()(const EAXREVERBPROPERTIES& all) const { EnvironmentValidator3{}(all.ulEnvironment); EnvironmentSizeValidator{}(all.flEnvironmentSize); @@ -961,14 +939,14 @@ private: }; // AllValidator3 struct EnvironmentDeferrer2 { - void operator()(Props2& props, unsigned long dwEnvironment) const + void operator()(EAX20LISTENERPROPERTIES& props, unsigned long dwEnvironment) const { props = EAX2REVERB_PRESETS[dwEnvironment]; } }; // EnvironmentDeferrer2 struct EnvironmentSizeDeferrer2 { - void operator()(Props2& props, float flEnvironmentSize) const + void operator()(EAX20LISTENERPROPERTIES& props, float flEnvironmentSize) const { if (props.flEnvironmentSize == flEnvironmentSize) { @@ -1024,7 +1002,7 @@ private: }; // EnvironmentSizeDeferrer2 struct EnvironmentDeferrer3 { - void operator()(Props3& props, unsigned long ulEnvironment) const + void operator()(EAXREVERBPROPERTIES& props, unsigned long ulEnvironment) const { if (ulEnvironment == EAX_ENVIRONMENT_UNDEFINED) { @@ -1037,7 +1015,7 @@ private: }; // EnvironmentDeferrer3 struct EnvironmentSizeDeferrer3 { - void operator()(Props3& props, float flEnvironmentSize) const + void operator()(EAXREVERBPROPERTIES& props, float flEnvironmentSize) const { if (props.flEnvironmentSize == flEnvironmentSize) { @@ -1108,14 +1086,6 @@ private: } }; // EnvironmentSizeDeferrer3 - int version_; - bool changed_{}; - Props3 props_{}; - State1 state1_{}; - State2 state2_{}; - State3 state3_{}; - State3 state4_{}; - State3 state5_{}; [[noreturn]] static void fail(const char* message); [[noreturn]] static void fail_unknown_property_id(); @@ -1195,7 +1165,7 @@ private: }; // EaxReverbEffect EaxReverbEffect::EaxReverbEffect(int eax_version) noexcept - : EaxEffect{AL_EFFECT_EAXREVERB}, version_{eax_version} + : EaxEffect{AL_EFFECT_EAXREVERB, eax_version} { set_defaults(); set_current_defaults(); @@ -1246,17 +1216,19 @@ void EaxReverbEffect::set_defaults() noexcept set_defaults(state1_); set_defaults(state2_); set_defaults(state3_); - state4_ = state3_; - state5_ = state3_; + state4_.d.mReverb = state3_.d; + state4_.i.mReverb = state3_.i; + state5_.d.mReverb = state3_.d; + state5_.i.mReverb = state3_.i; } void EaxReverbEffect::set_current_defaults() { switch (version_) { - case 1: translate(state1_.i, props_); break; - case 2: translate(state2_.i, props_); break; - case 3: props_ = state3_.i; break; + case 1: translate(state1_.i, props_.mReverb); break; + case 2: translate(state2_.i, props_.mReverb); break; + case 3: props_.mReverb = state3_.i; break; case 4: props_ = state4_.i; break; case 5: props_ = state5_.i; break; default: fail_unknown_version(); @@ -1265,7 +1237,7 @@ void EaxReverbEffect::set_current_defaults() void EaxReverbEffect::set_efx_density_from_environment_size() noexcept { - const auto size = props_.flEnvironmentSize; + const auto size = props_.mReverb.flEnvironmentSize; const auto density = (size * size * size) / 16.0F; al_effect_props_.Reverb.Density = clamp( density, @@ -1276,7 +1248,7 @@ void EaxReverbEffect::set_efx_density_from_environment_size() noexcept void EaxReverbEffect::set_efx_diffusion() noexcept { al_effect_props_.Reverb.Diffusion = clamp( - props_.flEnvironmentDiffusion, + props_.mReverb.flEnvironmentDiffusion, AL_EAXREVERB_MIN_DIFFUSION, AL_EAXREVERB_MAX_DIFFUSION); } @@ -1284,7 +1256,7 @@ void EaxReverbEffect::set_efx_diffusion() noexcept void EaxReverbEffect::set_efx_gain() noexcept { al_effect_props_.Reverb.Gain = clamp( - level_mb_to_gain(static_cast(props_.lRoom)), + level_mb_to_gain(static_cast(props_.mReverb.lRoom)), AL_EAXREVERB_MIN_GAIN, AL_EAXREVERB_MAX_GAIN); } @@ -1292,7 +1264,7 @@ void EaxReverbEffect::set_efx_gain() noexcept void EaxReverbEffect::set_efx_gain_hf() noexcept { al_effect_props_.Reverb.GainHF = clamp( - level_mb_to_gain(static_cast(props_.lRoomHF)), + level_mb_to_gain(static_cast(props_.mReverb.lRoomHF)), AL_EAXREVERB_MIN_GAINHF, AL_EAXREVERB_MAX_GAINHF); } @@ -1300,7 +1272,7 @@ void EaxReverbEffect::set_efx_gain_hf() noexcept void EaxReverbEffect::set_efx_gain_lf() noexcept { al_effect_props_.Reverb.GainLF = clamp( - level_mb_to_gain(static_cast(props_.lRoomLF)), + level_mb_to_gain(static_cast(props_.mReverb.lRoomLF)), AL_EAXREVERB_MIN_GAINLF, AL_EAXREVERB_MAX_GAINLF); } @@ -1308,7 +1280,7 @@ void EaxReverbEffect::set_efx_gain_lf() noexcept void EaxReverbEffect::set_efx_decay_time() noexcept { al_effect_props_.Reverb.DecayTime = clamp( - props_.flDecayTime, + props_.mReverb.flDecayTime, AL_EAXREVERB_MIN_DECAY_TIME, AL_EAXREVERB_MAX_DECAY_TIME); } @@ -1316,7 +1288,7 @@ void EaxReverbEffect::set_efx_decay_time() noexcept void EaxReverbEffect::set_efx_decay_hf_ratio() noexcept { al_effect_props_.Reverb.DecayHFRatio = clamp( - props_.flDecayHFRatio, + props_.mReverb.flDecayHFRatio, AL_EAXREVERB_MIN_DECAY_HFRATIO, AL_EAXREVERB_MAX_DECAY_HFRATIO); } @@ -1324,7 +1296,7 @@ void EaxReverbEffect::set_efx_decay_hf_ratio() noexcept void EaxReverbEffect::set_efx_decay_lf_ratio() noexcept { al_effect_props_.Reverb.DecayLFRatio = clamp( - props_.flDecayLFRatio, + props_.mReverb.flDecayLFRatio, AL_EAXREVERB_MIN_DECAY_LFRATIO, AL_EAXREVERB_MAX_DECAY_LFRATIO); } @@ -1332,7 +1304,7 @@ void EaxReverbEffect::set_efx_decay_lf_ratio() noexcept void EaxReverbEffect::set_efx_reflections_gain() noexcept { al_effect_props_.Reverb.ReflectionsGain = clamp( - level_mb_to_gain(static_cast(props_.lReflections)), + level_mb_to_gain(static_cast(props_.mReverb.lReflections)), AL_EAXREVERB_MIN_REFLECTIONS_GAIN, AL_EAXREVERB_MAX_REFLECTIONS_GAIN); } @@ -1340,22 +1312,22 @@ void EaxReverbEffect::set_efx_reflections_gain() noexcept void EaxReverbEffect::set_efx_reflections_delay() noexcept { al_effect_props_.Reverb.ReflectionsDelay = clamp( - props_.flReflectionsDelay, + props_.mReverb.flReflectionsDelay, AL_EAXREVERB_MIN_REFLECTIONS_DELAY, AL_EAXREVERB_MAX_REFLECTIONS_DELAY); } void EaxReverbEffect::set_efx_reflections_pan() noexcept { - al_effect_props_.Reverb.ReflectionsPan[0] = props_.vReflectionsPan.x; - al_effect_props_.Reverb.ReflectionsPan[1] = props_.vReflectionsPan.y; - al_effect_props_.Reverb.ReflectionsPan[2] = props_.vReflectionsPan.z; + al_effect_props_.Reverb.ReflectionsPan[0] = props_.mReverb.vReflectionsPan.x; + al_effect_props_.Reverb.ReflectionsPan[1] = props_.mReverb.vReflectionsPan.y; + al_effect_props_.Reverb.ReflectionsPan[2] = props_.mReverb.vReflectionsPan.z; } void EaxReverbEffect::set_efx_late_reverb_gain() noexcept { al_effect_props_.Reverb.LateReverbGain = clamp( - level_mb_to_gain(static_cast(props_.lReverb)), + level_mb_to_gain(static_cast(props_.mReverb.lReverb)), AL_EAXREVERB_MIN_LATE_REVERB_GAIN, AL_EAXREVERB_MAX_LATE_REVERB_GAIN); } @@ -1363,22 +1335,22 @@ void EaxReverbEffect::set_efx_late_reverb_gain() noexcept void EaxReverbEffect::set_efx_late_reverb_delay() noexcept { al_effect_props_.Reverb.LateReverbDelay = clamp( - props_.flReverbDelay, + props_.mReverb.flReverbDelay, AL_EAXREVERB_MIN_LATE_REVERB_DELAY, AL_EAXREVERB_MAX_LATE_REVERB_DELAY); } void EaxReverbEffect::set_efx_late_reverb_pan() noexcept { - al_effect_props_.Reverb.LateReverbPan[0] = props_.vReverbPan.x; - al_effect_props_.Reverb.LateReverbPan[1] = props_.vReverbPan.y; - al_effect_props_.Reverb.LateReverbPan[2] = props_.vReverbPan.z; + al_effect_props_.Reverb.LateReverbPan[0] = props_.mReverb.vReverbPan.x; + al_effect_props_.Reverb.LateReverbPan[1] = props_.mReverb.vReverbPan.y; + al_effect_props_.Reverb.LateReverbPan[2] = props_.mReverb.vReverbPan.z; } void EaxReverbEffect::set_efx_echo_time() noexcept { al_effect_props_.Reverb.EchoTime = clamp( - props_.flEchoTime, + props_.mReverb.flEchoTime, AL_EAXREVERB_MIN_ECHO_TIME, AL_EAXREVERB_MAX_ECHO_TIME); } @@ -1386,7 +1358,7 @@ void EaxReverbEffect::set_efx_echo_time() noexcept void EaxReverbEffect::set_efx_echo_depth() noexcept { al_effect_props_.Reverb.EchoDepth = clamp( - props_.flEchoDepth, + props_.mReverb.flEchoDepth, AL_EAXREVERB_MIN_ECHO_DEPTH, AL_EAXREVERB_MAX_ECHO_DEPTH); } @@ -1394,7 +1366,7 @@ void EaxReverbEffect::set_efx_echo_depth() noexcept void EaxReverbEffect::set_efx_modulation_time() noexcept { al_effect_props_.Reverb.ModulationTime = clamp( - props_.flModulationTime, + props_.mReverb.flModulationTime, AL_EAXREVERB_MIN_MODULATION_TIME, AL_EAXREVERB_MAX_MODULATION_TIME); } @@ -1402,7 +1374,7 @@ void EaxReverbEffect::set_efx_modulation_time() noexcept void EaxReverbEffect::set_efx_modulation_depth() noexcept { al_effect_props_.Reverb.ModulationDepth = clamp( - props_.flModulationDepth, + props_.mReverb.flModulationDepth, AL_EAXREVERB_MIN_MODULATION_DEPTH, AL_EAXREVERB_MAX_MODULATION_DEPTH); } @@ -1410,7 +1382,7 @@ void EaxReverbEffect::set_efx_modulation_depth() noexcept void EaxReverbEffect::set_efx_air_absorption_gain_hf() noexcept { al_effect_props_.Reverb.AirAbsorptionGainHF = clamp( - level_mb_to_gain(props_.flAirAbsorptionHF), + level_mb_to_gain(props_.mReverb.flAirAbsorptionHF), AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF, AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF); } @@ -1418,7 +1390,7 @@ void EaxReverbEffect::set_efx_air_absorption_gain_hf() noexcept void EaxReverbEffect::set_efx_hf_reference() noexcept { al_effect_props_.Reverb.HFReference = clamp( - props_.flHFReference, + props_.mReverb.flHFReference, AL_EAXREVERB_MIN_HFREFERENCE, AL_EAXREVERB_MAX_HFREFERENCE); } @@ -1426,7 +1398,7 @@ void EaxReverbEffect::set_efx_hf_reference() noexcept void EaxReverbEffect::set_efx_lf_reference() noexcept { al_effect_props_.Reverb.LFReference = clamp( - props_.flLFReference, + props_.mReverb.flLFReference, AL_EAXREVERB_MIN_LFREFERENCE, AL_EAXREVERB_MAX_LFREFERENCE); } @@ -1434,14 +1406,14 @@ void EaxReverbEffect::set_efx_lf_reference() noexcept void EaxReverbEffect::set_efx_room_rolloff_factor() noexcept { al_effect_props_.Reverb.RoomRolloffFactor = clamp( - props_.flRoomRolloffFactor, + props_.mReverb.flRoomRolloffFactor, AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR, AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR); } void EaxReverbEffect::set_efx_flags() noexcept { - al_effect_props_.Reverb.DecayHFLimit = ((props_.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0); + al_effect_props_.Reverb.DecayHFLimit = ((props_.mReverb.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0); } void EaxReverbEffect::set_efx_defaults() noexcept @@ -1549,8 +1521,8 @@ void EaxReverbEffect::get(const EaxCall& call) case 1: get1(call, state1_.i); break; case 2: get2(call, state2_.i); break; case 3: get3(call, state3_.i); break; - case 4: get3(call, state4_.i); break; - case 5: get3(call, state5_.i); break; + case 4: get3(call, state4_.i.mReverb); break; + case 5: get3(call, state5_.i.mReverb); break; default: fail_unknown_version(); } } @@ -1566,15 +1538,15 @@ void EaxReverbEffect::get(const EaxCall& call) { case 1: state1_.i = state1_.d; - translate(state1_.d, props_); + translate(state1_.d, props_.mReverb); break; case 2: state2_.i = state2_.d; - translate(state2_.d, props_); + translate(state2_.d, props_.mReverb); break; case 3: state3_.i = state3_.d; - props_ = state3_.d; + props_.mReverb = state3_.d; break; case 4: state4_.i = state4_.d; @@ -1591,139 +1563,139 @@ void EaxReverbEffect::get(const EaxCall& call) auto is_dirty = false; - if (props_.flEnvironmentSize != props.flEnvironmentSize) + if (props_.mReverb.flEnvironmentSize != props.mReverb.flEnvironmentSize) { is_dirty = true; set_efx_density_from_environment_size(); } - if (props_.flEnvironmentDiffusion != props.flEnvironmentDiffusion) + if (props_.mReverb.flEnvironmentDiffusion != props.mReverb.flEnvironmentDiffusion) { is_dirty = true; set_efx_diffusion(); } - if (props_.lRoom != props.lRoom) + if (props_.mReverb.lRoom != props.mReverb.lRoom) { is_dirty = true; set_efx_gain(); } - if (props_.lRoomHF != props.lRoomHF) + if (props_.mReverb.lRoomHF != props.mReverb.lRoomHF) { is_dirty = true; set_efx_gain_hf(); } - if (props_.lRoomLF != props.lRoomLF) + if (props_.mReverb.lRoomLF != props.mReverb.lRoomLF) { is_dirty = true; set_efx_gain_lf(); } - if (props_.flDecayTime != props.flDecayTime) + if (props_.mReverb.flDecayTime != props.mReverb.flDecayTime) { is_dirty = true; set_efx_decay_time(); } - if (props_.flDecayHFRatio != props.flDecayHFRatio) + if (props_.mReverb.flDecayHFRatio != props.mReverb.flDecayHFRatio) { is_dirty = true; set_efx_decay_hf_ratio(); } - if (props_.flDecayLFRatio != props.flDecayLFRatio) + if (props_.mReverb.flDecayLFRatio != props.mReverb.flDecayLFRatio) { is_dirty = true; set_efx_decay_lf_ratio(); } - if (props_.lReflections != props.lReflections) + if (props_.mReverb.lReflections != props.mReverb.lReflections) { is_dirty = true; set_efx_reflections_gain(); } - if (props_.flReflectionsDelay != props.flReflectionsDelay) + if (props_.mReverb.flReflectionsDelay != props.mReverb.flReflectionsDelay) { is_dirty = true; set_efx_reflections_delay(); } - if (props_.vReflectionsPan != props.vReflectionsPan) + if (props_.mReverb.vReflectionsPan != props.mReverb.vReflectionsPan) { is_dirty = true; set_efx_reflections_pan(); } - if (props_.lReverb != props.lReverb) + if (props_.mReverb.lReverb != props.mReverb.lReverb) { is_dirty = true; set_efx_late_reverb_gain(); } - if (props_.flReverbDelay != props.flReverbDelay) + if (props_.mReverb.flReverbDelay != props.mReverb.flReverbDelay) { is_dirty = true; set_efx_late_reverb_delay(); } - if (props_.vReverbPan != props.vReverbPan) + if (props_.mReverb.vReverbPan != props.mReverb.vReverbPan) { is_dirty = true; set_efx_late_reverb_pan(); } - if (props_.flEchoTime != props.flEchoTime) + if (props_.mReverb.flEchoTime != props.mReverb.flEchoTime) { is_dirty = true; set_efx_echo_time(); } - if (props_.flEchoDepth != props.flEchoDepth) + if (props_.mReverb.flEchoDepth != props.mReverb.flEchoDepth) { is_dirty = true; set_efx_echo_depth(); } - if (props_.flModulationTime != props.flModulationTime) + if (props_.mReverb.flModulationTime != props.mReverb.flModulationTime) { is_dirty = true; set_efx_modulation_time(); } - if (props_.flModulationDepth != props.flModulationDepth) + if (props_.mReverb.flModulationDepth != props.mReverb.flModulationDepth) { is_dirty = true; set_efx_modulation_depth(); } - if (props_.flAirAbsorptionHF != props.flAirAbsorptionHF) + if (props_.mReverb.flAirAbsorptionHF != props.mReverb.flAirAbsorptionHF) { is_dirty = true; set_efx_air_absorption_gain_hf(); } - if (props_.flHFReference != props.flHFReference) + if (props_.mReverb.flHFReference != props.mReverb.flHFReference) { is_dirty = true; set_efx_hf_reference(); } - if (props_.flLFReference != props.flLFReference) + if (props_.mReverb.flLFReference != props.mReverb.flLFReference) { is_dirty = true; set_efx_lf_reference(); } - if (props_.flRoomRolloffFactor != props.flRoomRolloffFactor) + if (props_.mReverb.flRoomRolloffFactor != props.mReverb.flRoomRolloffFactor) { is_dirty = true; set_efx_room_rolloff_factor(); } - if (props_.ulFlags != props.ulFlags) + if (props_.mReverb.ulFlags != props.mReverb.ulFlags) { is_dirty = true; set_efx_flags(); @@ -1937,8 +1909,8 @@ void EaxReverbEffect::set(const EaxCall& call) case 1: set1(call, state1_.d); break; case 2: set2(call, state2_.d); break; case 3: set3(call, state3_.d); break; - case 4: set3(call, state4_.d); break; - case 5: set3(call, state5_.d); break; + case 4: set3(call, state4_.d.mReverb); break; + case 5: set3(call, state5_.d.mReverb); break; default: fail_unknown_version(); } changed_ = true; diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index e26c6fe3..b4820c86 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -265,7 +265,7 @@ public: {} }; // EaxVocalMorpherEffectException -class EaxVocalMorpherEffect final : public EaxEffect4 { +class EaxVocalMorpherEffect final : public EaxEffect4 { public: EaxVocalMorpherEffect(int eax_version); @@ -337,7 +337,7 @@ private: }; // RateValidator struct AllValidator { - void operator()(const Props& all) const + void operator()(const EAXVOCALMORPHERPROPERTIES& all) const { PhonemeAValidator{}(all.ulPhonemeA); PhonemeACoarseTuningValidator{}(all.lPhonemeACoarseTuning); @@ -348,7 +348,7 @@ private: } }; // AllValidator - void set_defaults(Props& props) override; + void set_defaults(Props4& props) override; void set_efx_phoneme_a(); void set_efx_phoneme_a_coarse_tuning() noexcept; @@ -358,29 +358,29 @@ private: void set_efx_rate() noexcept; void set_efx_defaults() override; - void get(const EaxCall& call, const Props& props) override; - void set(const EaxCall& call, Props& props) override; - bool commit_props(const Props& props) override; + void get(const EaxCall& call, const Props4& props) override; + void set(const EaxCall& call, Props4& props) override; + bool commit_props(const Props4& props) override; }; // EaxVocalMorpherEffect EaxVocalMorpherEffect::EaxVocalMorpherEffect(int eax_version) : EaxEffect4{AL_EFFECT_VOCAL_MORPHER, eax_version} {} -void EaxVocalMorpherEffect::set_defaults(Props& props) +void EaxVocalMorpherEffect::set_defaults(Props4& props) { - props.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA; - props.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING; - props.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB; - props.lPhonemeBCoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING; - props.ulWaveform = EAXVOCALMORPHER_DEFAULTWAVEFORM; - props.flRate = EAXVOCALMORPHER_DEFAULTRATE; + props.mVocalMorpher.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA; + props.mVocalMorpher.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING; + props.mVocalMorpher.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB; + props.mVocalMorpher.lPhonemeBCoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING; + props.mVocalMorpher.ulWaveform = EAXVOCALMORPHER_DEFAULTWAVEFORM; + props.mVocalMorpher.flRate = EAXVOCALMORPHER_DEFAULTRATE; } void EaxVocalMorpherEffect::set_efx_phoneme_a() { const auto phoneme_a = clamp( - static_cast(props_.ulPhonemeA), + static_cast(props_.mVocalMorpher.ulPhonemeA), AL_VOCAL_MORPHER_MIN_PHONEMEA, AL_VOCAL_MORPHER_MAX_PHONEMEA); const auto efx_phoneme_a = PhenomeFromEnum(phoneme_a); @@ -391,7 +391,7 @@ void EaxVocalMorpherEffect::set_efx_phoneme_a() void EaxVocalMorpherEffect::set_efx_phoneme_a_coarse_tuning() noexcept { const auto phoneme_a_coarse_tuning = clamp( - static_cast(props_.lPhonemeACoarseTuning), + static_cast(props_.mVocalMorpher.lPhonemeACoarseTuning), AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING, AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING); al_effect_props_.Vmorpher.PhonemeACoarseTuning = phoneme_a_coarse_tuning; @@ -400,7 +400,7 @@ void EaxVocalMorpherEffect::set_efx_phoneme_a_coarse_tuning() noexcept void EaxVocalMorpherEffect::set_efx_phoneme_b() { const auto phoneme_b = clamp( - static_cast(props_.ulPhonemeB), + static_cast(props_.mVocalMorpher.ulPhonemeB), AL_VOCAL_MORPHER_MIN_PHONEMEB, AL_VOCAL_MORPHER_MAX_PHONEMEB); const auto efx_phoneme_b = PhenomeFromEnum(phoneme_b); @@ -411,7 +411,7 @@ void EaxVocalMorpherEffect::set_efx_phoneme_b() void EaxVocalMorpherEffect::set_efx_phoneme_b_coarse_tuning() noexcept { al_effect_props_.Vmorpher.PhonemeBCoarseTuning = clamp( - static_cast(props_.lPhonemeBCoarseTuning), + static_cast(props_.mVocalMorpher.lPhonemeBCoarseTuning), AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING, AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING); } @@ -419,7 +419,7 @@ void EaxVocalMorpherEffect::set_efx_phoneme_b_coarse_tuning() noexcept void EaxVocalMorpherEffect::set_efx_waveform() { const auto waveform = clamp( - static_cast(props_.ulWaveform), + static_cast(props_.mVocalMorpher.ulWaveform), AL_VOCAL_MORPHER_MIN_WAVEFORM, AL_VOCAL_MORPHER_MAX_WAVEFORM); const auto wfx_waveform = WaveformFromEmum(waveform); @@ -430,7 +430,7 @@ void EaxVocalMorpherEffect::set_efx_waveform() void EaxVocalMorpherEffect::set_efx_rate() noexcept { al_effect_props_.Vmorpher.Rate = clamp( - props_.flRate, + props_.mVocalMorpher.flRate, AL_VOCAL_MORPHER_MIN_RATE, AL_VOCAL_MORPHER_MAX_RATE); } @@ -445,7 +445,7 @@ void EaxVocalMorpherEffect::set_efx_defaults() set_efx_rate(); } -void EaxVocalMorpherEffect::get(const EaxCall& call, const Props& props) +void EaxVocalMorpherEffect::get(const EaxCall& call, const Props4& props) { switch(call.get_property_id()) { @@ -453,31 +453,31 @@ void EaxVocalMorpherEffect::get(const EaxCall& call, const Props& props) break; case EAXVOCALMORPHER_ALLPARAMETERS: - call.set_value(props); + call.set_value(props.mVocalMorpher); break; case EAXVOCALMORPHER_PHONEMEA: - call.set_value(props.ulPhonemeA); + call.set_value(props.mVocalMorpher.ulPhonemeA); break; case EAXVOCALMORPHER_PHONEMEACOARSETUNING: - call.set_value(props.lPhonemeACoarseTuning); + call.set_value(props.mVocalMorpher.lPhonemeACoarseTuning); break; case EAXVOCALMORPHER_PHONEMEB: - call.set_value(props.ulPhonemeB); + call.set_value(props.mVocalMorpher.ulPhonemeB); break; case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: - call.set_value(props.lPhonemeBCoarseTuning); + call.set_value(props.mVocalMorpher.lPhonemeBCoarseTuning); break; case EAXVOCALMORPHER_WAVEFORM: - call.set_value(props.ulWaveform); + call.set_value(props.mVocalMorpher.ulWaveform); break; case EAXVOCALMORPHER_RATE: - call.set_value(props.flRate); + call.set_value(props.mVocalMorpher.flRate); break; default: @@ -485,7 +485,7 @@ void EaxVocalMorpherEffect::get(const EaxCall& call, const Props& props) } } -void EaxVocalMorpherEffect::set(const EaxCall& call, Props& props) +void EaxVocalMorpherEffect::set(const EaxCall& call, Props4& props) { switch(call.get_property_id()) { @@ -493,31 +493,31 @@ void EaxVocalMorpherEffect::set(const EaxCall& call, Props& props) break; case EAXVOCALMORPHER_ALLPARAMETERS: - defer(call, props); + defer(call, props.mVocalMorpher); break; case EAXVOCALMORPHER_PHONEMEA: - defer(call, props.ulPhonemeA); + defer(call, props.mVocalMorpher.ulPhonemeA); break; case EAXVOCALMORPHER_PHONEMEACOARSETUNING: - defer(call, props.lPhonemeACoarseTuning); + defer(call, props.mVocalMorpher.lPhonemeACoarseTuning); break; case EAXVOCALMORPHER_PHONEMEB: - defer(call, props.ulPhonemeB); + defer(call, props.mVocalMorpher.ulPhonemeB); break; case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: - defer(call, props.lPhonemeBCoarseTuning); + defer(call, props.mVocalMorpher.lPhonemeBCoarseTuning); break; case EAXVOCALMORPHER_WAVEFORM: - defer(call, props.ulWaveform); + defer(call, props.mVocalMorpher.ulWaveform); break; case EAXVOCALMORPHER_RATE: - defer(call, props.flRate); + defer(call, props.mVocalMorpher.flRate); break; default: @@ -525,41 +525,41 @@ void EaxVocalMorpherEffect::set(const EaxCall& call, Props& props) } } -bool EaxVocalMorpherEffect::commit_props(const Props& props) +bool EaxVocalMorpherEffect::commit_props(const Props4& props) { auto is_dirty = false; - if (props_.ulPhonemeA != props.ulPhonemeA) + if (props_.mVocalMorpher.ulPhonemeA != props.mVocalMorpher.ulPhonemeA) { is_dirty = true; set_efx_phoneme_a(); } - if (props_.lPhonemeACoarseTuning != props.lPhonemeACoarseTuning) + if (props_.mVocalMorpher.lPhonemeACoarseTuning != props.mVocalMorpher.lPhonemeACoarseTuning) { is_dirty = true; set_efx_phoneme_a_coarse_tuning(); } - if (props_.ulPhonemeB != props.ulPhonemeB) + if (props_.mVocalMorpher.ulPhonemeB != props.mVocalMorpher.ulPhonemeB) { is_dirty = true; set_efx_phoneme_b(); } - if (props_.lPhonemeBCoarseTuning != props.lPhonemeBCoarseTuning) + if (props_.mVocalMorpher.lPhonemeBCoarseTuning != props.mVocalMorpher.lPhonemeBCoarseTuning) { is_dirty = true; set_efx_phoneme_b_coarse_tuning(); } - if (props_.ulWaveform != props.ulWaveform) + if (props_.mVocalMorpher.ulWaveform != props.mVocalMorpher.ulWaveform) { is_dirty = true; set_efx_waveform(); } - if (props_.flRate != props.flRate) + if (props_.mVocalMorpher.flRate != props.mVocalMorpher.flRate) { is_dirty = true; set_efx_rate(); -- cgit v1.2.3 From 1ea8f7a9a1f1ec74bb162a704283f8e3c3ede96d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 9 Mar 2023 21:29:53 -0800 Subject: Add a type indicator to EaxEffectProps --- al/eax/effect.h | 34 ++++++++++------- al/effects/autowah.cpp | 1 + al/effects/chorus.cpp | 3 ++ al/effects/compressor.cpp | 1 + al/effects/distortion.cpp | 1 + al/effects/echo.cpp | 1 + al/effects/equalizer.cpp | 1 + al/effects/fshifter.cpp | 1 + al/effects/modulator.cpp | 1 + al/effects/pshifter.cpp | 1 + al/effects/reverb.cpp | 93 ++++++++++++++++++++++++++--------------------- al/effects/vmorpher.cpp | 1 + 12 files changed, 84 insertions(+), 55 deletions(-) (limited to 'al/effects/distortion.cpp') diff --git a/al/eax/effect.h b/al/eax/effect.h index 2514e79d..736ac058 100644 --- a/al/eax/effect.h +++ b/al/eax/effect.h @@ -16,19 +16,27 @@ struct EaxEffectErrorMessages static constexpr auto unknown_version() noexcept { return "Unknown version."; } }; // EaxEffectErrorMessages -union EaxEffectProps { - EAXREVERBPROPERTIES mReverb; - EAXCHORUSPROPERTIES mChorus; - EAXAUTOWAHPROPERTIES mAutowah; - EAXAGCCOMPRESSORPROPERTIES mCompressor; - EAXDISTORTIONPROPERTIES mDistortion; - EAXECHOPROPERTIES mEcho; - EAXEQUALIZERPROPERTIES mEqualizer; - EAXFLANGERPROPERTIES mFlanger; - EAXFREQUENCYSHIFTERPROPERTIES mFrequencyShifter; - EAXRINGMODULATORPROPERTIES mModulator; - EAXPITCHSHIFTERPROPERTIES mPitchShifter; - EAXVOCALMORPHERPROPERTIES mVocalMorpher; +/* TODO: Use std::variant (C++17). */ +enum class EaxEffectType { + None, Reverb, Chorus, Autowah, Compressor, Distortion, Echo, Equalizer, Flanger, + FrequencyShifter, Modulator, PitchShifter, VocalMorpher +}; +struct EaxEffectProps { + EaxEffectType mType; + union { + EAXREVERBPROPERTIES mReverb; + EAXCHORUSPROPERTIES mChorus; + EAXAUTOWAHPROPERTIES mAutowah; + EAXAGCCOMPRESSORPROPERTIES mCompressor; + EAXDISTORTIONPROPERTIES mDistortion; + EAXECHOPROPERTIES mEcho; + EAXEQUALIZERPROPERTIES mEqualizer; + EAXFLANGERPROPERTIES mFlanger; + EAXFREQUENCYSHIFTERPROPERTIES mFrequencyShifter; + EAXRINGMODULATORPROPERTIES mModulator; + EAXPITCHSHIFTERPROPERTIES mPitchShifter; + EAXVOCALMORPHERPROPERTIES mVocalMorpher; + }; }; class EaxEffect { diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 7b467e78..22c3ab9f 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -203,6 +203,7 @@ EaxAutoWahEffect::EaxAutoWahEffect(int eax_version) void EaxAutoWahEffect::set_defaults(Props4& props) { + props.mType = EaxEffectType::Autowah; props.mAutowah.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME; props.mAutowah.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME; props.mAutowah.lResonance = EAXAUTOWAH_DEFAULTRESONANCE; diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index 9fc5a44e..47be502d 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -311,6 +311,7 @@ struct EaxChorusTraits using Props = EAXCHORUSPROPERTIES; static constexpr auto Field = &EaxEffectProps::mChorus; + static constexpr auto eax_effect_type() { return EaxEffectType::Chorus; } static constexpr auto efx_effect() { return AL_EFFECT_CHORUS; } static constexpr auto eax_none_param_id() { return EAXCHORUS_NONE; } @@ -371,6 +372,7 @@ struct EaxFlangerTraits using Props = EAXFLANGERPROPERTIES; static constexpr auto Field = &EaxEffectProps::mFlanger; + static constexpr auto eax_effect_type() { return EaxEffectType::Flanger; } static constexpr auto efx_effect() { return AL_EFFECT_FLANGER; } static constexpr auto eax_none_param_id() { return EAXFLANGER_NONE; } @@ -522,6 +524,7 @@ private: void set_defaults(Props4& props) override { auto&& all = props.*Field; + props.mType = Traits::eax_effect_type(); all.ulWaveform = Traits::eax_default_waveform(); all.lPhase = Traits::eax_default_phase(); all.flRate = Traits::eax_default_rate(); diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp index 38dca247..7a4fb028 100644 --- a/al/effects/compressor.cpp +++ b/al/effects/compressor.cpp @@ -128,6 +128,7 @@ EaxCompressorEffect::EaxCompressorEffect(int eax_version) void EaxCompressorEffect::set_defaults(Props4& props) { + props.mType = EaxEffectType::Compressor; props.mCompressor.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF; } diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index f6f94775..5f1206ab 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -222,6 +222,7 @@ EaxDistortionEffect::EaxDistortionEffect(int eax_version) void EaxDistortionEffect::set_defaults(Props4& props) { + props.mType = EaxEffectType::Distortion; props.mDistortion.flEdge = EAXDISTORTION_DEFAULTEDGE; props.mDistortion.lGain = EAXDISTORTION_DEFAULTGAIN; props.mDistortion.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF; diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index 05218793..1a89dffb 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -219,6 +219,7 @@ EaxEchoEffect::EaxEchoEffect(int eax_version) void EaxEchoEffect::set_defaults(Props4& props) { + props.mType = EaxEffectType::Echo; props.mEcho.flDelay = EAXECHO_DEFAULTDELAY; props.mEcho.flLRDelay = EAXECHO_DEFAULTLRDELAY; props.mEcho.flDamping = EAXECHO_DEFAULTDAMPING; diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index 7134e188..fa60d8a1 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -342,6 +342,7 @@ EaxEqualizerEffect::EaxEqualizerEffect(int eax_version) void EaxEqualizerEffect::set_defaults(Props4& props) { + props.mType = EaxEffectType::Equalizer; props.mEqualizer.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN; props.mEqualizer.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF; props.mEqualizer.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN; diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index 1a97e339..ae2b4f4e 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -213,6 +213,7 @@ EaxFrequencyShifterEffect::EaxFrequencyShifterEffect(int eax_version) void EaxFrequencyShifterEffect::set_defaults(Props4& props) { + props.mType = EaxEffectType::FrequencyShifter; props.mFrequencyShifter.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY; props.mFrequencyShifter.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION; props.mFrequencyShifter.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION; diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index a6a443f8..f1d01ddc 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -219,6 +219,7 @@ EaxRingModulatorEffect::EaxRingModulatorEffect(int eax_version) void EaxRingModulatorEffect::set_defaults(Props4& props) { + props.mType = EaxEffectType::Modulator; props.mModulator.flFrequency = EAXRINGMODULATOR_DEFAULTFREQUENCY; props.mModulator.flHighPassCutOff = EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF; props.mModulator.ulWaveform = EAXRINGMODULATOR_DEFAULTWAVEFORM; diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp index ef3fe587..524585a2 100644 --- a/al/effects/pshifter.cpp +++ b/al/effects/pshifter.cpp @@ -152,6 +152,7 @@ EaxPitchShifterEffect::EaxPitchShifterEffect(int eax_version) void EaxPitchShifterEffect::set_defaults(Props4& props) { + props.mType = EaxEffectType::PitchShifter; props.mPitchShifter.lCoarseTune = EAXPITCHSHIFTER_DEFAULTCOARSETUNE; props.mPitchShifter.lFineTune = EAXPITCHSHIFTER_DEFAULTFINETUNE; } diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index ba586254..acd2fd06 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -1160,8 +1160,9 @@ private: static void set3(const EaxCall& call, Props3& props); void set(const EaxCall& call); - static void translate(const Props1& src, Props3& dst) noexcept; - static void translate(const Props2& src, Props3& dst) noexcept; + static void translate(const Props1& src, Props4& dst) noexcept; + static void translate(const Props2& src, Props4& dst) noexcept; + static void translate(const Props3& src, Props4& dst) noexcept; }; // EaxReverbEffect EaxReverbEffect::EaxReverbEffect(int eax_version) noexcept @@ -1216,19 +1217,19 @@ void EaxReverbEffect::set_defaults() noexcept set_defaults(state1_); set_defaults(state2_); set_defaults(state3_); - state4_.d.mReverb = state3_.d; - state4_.i.mReverb = state3_.i; - state5_.d.mReverb = state3_.d; - state5_.i.mReverb = state3_.i; + translate(state3_.i, state4_.i); + state4_.d = state4_.i; + translate(state3_.i, state5_.i); + state5_.d = state5_.i; } void EaxReverbEffect::set_current_defaults() { switch (version_) { - case 1: translate(state1_.i, props_.mReverb); break; - case 2: translate(state2_.i, props_.mReverb); break; - case 3: props_.mReverb = state3_.i; break; + case 1: translate(state1_.i, props_); break; + case 2: translate(state2_.i, props_); break; + case 3: translate(state3_.i, props_); break; case 4: props_ = state4_.i; break; case 5: props_ = state5_.i; break; default: fail_unknown_version(); @@ -1538,15 +1539,15 @@ void EaxReverbEffect::get(const EaxCall& call) { case 1: state1_.i = state1_.d; - translate(state1_.d, props_.mReverb); + translate(state1_.d, props_); break; case 2: state2_.i = state2_.d; - translate(state2_.d, props_.mReverb); + translate(state2_.d, props_); break; case 3: state3_.i = state3_.d; - props_.mReverb = state3_.d; + translate(state3_.d, props_); break; case 4: state4_.i = state4_.d; @@ -1917,43 +1918,51 @@ void EaxReverbEffect::set(const EaxCall& call) version_ = version; } -void EaxReverbEffect::translate(const Props1& src, Props3& dst) noexcept +void EaxReverbEffect::translate(const Props1& src, Props4& dst) noexcept { assert(src.environment <= EAX1REVERB_MAXENVIRONMENT); - dst = EAXREVERB_PRESETS[src.environment]; - dst.flDecayTime = src.fDecayTime_sec; - dst.flDecayHFRatio = src.fDamping; - dst.lReverb = mini(static_cast(gain_to_level_mb(src.fVolume)), 0); + dst.mType = EaxEffectType::Reverb; + dst.mReverb = EAXREVERB_PRESETS[src.environment]; + dst.mReverb.flDecayTime = src.fDecayTime_sec; + dst.mReverb.flDecayHFRatio = src.fDamping; + dst.mReverb.lReverb = mini(static_cast(gain_to_level_mb(src.fVolume)), 0); } -void EaxReverbEffect::translate(const Props2& src, Props3& dst) noexcept +void EaxReverbEffect::translate(const Props2& src, Props4& dst) noexcept { assert(src.dwEnvironment <= EAX1REVERB_MAXENVIRONMENT); const auto& env = EAXREVERB_PRESETS[src.dwEnvironment]; - dst.ulEnvironment = src.dwEnvironment; - dst.flEnvironmentSize = src.flEnvironmentSize; - dst.flEnvironmentDiffusion = src.flEnvironmentDiffusion; - dst.lRoom = src.lRoom; - dst.lRoomHF = src.lRoomHF; - dst.lRoomLF = env.lRoomLF; - dst.flDecayTime = src.flDecayTime; - dst.flDecayHFRatio = src.flDecayHFRatio; - dst.flDecayLFRatio = env.flDecayLFRatio; - dst.lReflections = src.lReflections; - dst.flReflectionsDelay = src.flReflectionsDelay; - dst.vReflectionsPan = env.vReflectionsPan; - dst.lReverb = src.lReverb; - dst.flReverbDelay = src.flReverbDelay; - dst.vReverbPan = env.vReverbPan; - dst.flEchoTime = env.flEchoTime; - dst.flEchoDepth = env.flEchoDepth; - dst.flModulationTime = env.flModulationTime; - dst.flModulationDepth = env.flModulationDepth; - dst.flAirAbsorptionHF = src.flAirAbsorptionHF; - dst.flHFReference = env.flHFReference; - dst.flLFReference = env.flLFReference; - dst.flRoomRolloffFactor = src.flRoomRolloffFactor; - dst.ulFlags = src.dwFlags; + dst.mType = EaxEffectType::Reverb; + dst.mReverb.ulEnvironment = src.dwEnvironment; + dst.mReverb.flEnvironmentSize = src.flEnvironmentSize; + dst.mReverb.flEnvironmentDiffusion = src.flEnvironmentDiffusion; + dst.mReverb.lRoom = src.lRoom; + dst.mReverb.lRoomHF = src.lRoomHF; + dst.mReverb.lRoomLF = env.lRoomLF; + dst.mReverb.flDecayTime = src.flDecayTime; + dst.mReverb.flDecayHFRatio = src.flDecayHFRatio; + dst.mReverb.flDecayLFRatio = env.flDecayLFRatio; + dst.mReverb.lReflections = src.lReflections; + dst.mReverb.flReflectionsDelay = src.flReflectionsDelay; + dst.mReverb.vReflectionsPan = env.vReflectionsPan; + dst.mReverb.lReverb = src.lReverb; + dst.mReverb.flReverbDelay = src.flReverbDelay; + dst.mReverb.vReverbPan = env.vReverbPan; + dst.mReverb.flEchoTime = env.flEchoTime; + dst.mReverb.flEchoDepth = env.flEchoDepth; + dst.mReverb.flModulationTime = env.flModulationTime; + dst.mReverb.flModulationDepth = env.flModulationDepth; + dst.mReverb.flAirAbsorptionHF = src.flAirAbsorptionHF; + dst.mReverb.flHFReference = env.flHFReference; + dst.mReverb.flLFReference = env.flLFReference; + dst.mReverb.flRoomRolloffFactor = src.flRoomRolloffFactor; + dst.mReverb.ulFlags = src.dwFlags; +} + +void EaxReverbEffect::translate(const Props3& src, Props4& dst) noexcept +{ + dst.mType = EaxEffectType::Reverb; + dst.mReverb = src; } } // namespace diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index b4820c86..d8d74b94 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -369,6 +369,7 @@ EaxVocalMorpherEffect::EaxVocalMorpherEffect(int eax_version) void EaxVocalMorpherEffect::set_defaults(Props4& props) { + props.mType = EaxEffectType::VocalMorpher; props.mVocalMorpher.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA; props.mVocalMorpher.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING; props.mVocalMorpher.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB; -- cgit v1.2.3 From 1d112eee0fb5bfe358dc9a7627a64679292a3df5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 11 Mar 2023 00:16:32 -0800 Subject: Convert the EAX Autowah and Compressor effects --- al/auxeffectslot.h | 8 +- al/eax/effect.h | 14 ++ al/effects/autowah.cpp | 283 +++++++++++++++++---------------------- al/effects/distortion.cpp | 329 ++++++++++++++++++++-------------------------- 4 files changed, 278 insertions(+), 356 deletions(-) (limited to 'al/effects/distortion.cpp') diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index cfb8a0f2..71d05ef3 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -133,10 +133,10 @@ private: { if (guidLoadEffect != EAX_NULL_GUID && guidLoadEffect != EAX_REVERB_EFFECT && - guidLoadEffect != EAX_AGCCOMPRESSOR_EFFECT /*&& - guidLoadEffect != EAX_AUTOWAH_EFFECT*/ && - guidLoadEffect != EAX_CHORUS_EFFECT /*&& - guidLoadEffect != EAX_DISTORTION_EFFECT && + guidLoadEffect != EAX_AGCCOMPRESSOR_EFFECT && + guidLoadEffect != EAX_AUTOWAH_EFFECT && + guidLoadEffect != EAX_CHORUS_EFFECT && + guidLoadEffect != EAX_DISTORTION_EFFECT /*&& guidLoadEffect != EAX_ECHO_EFFECT && guidLoadEffect != EAX_EQUALIZER_EFFECT*/ && guidLoadEffect != EAX_FLANGER_EFFECT /*&& diff --git a/al/eax/effect.h b/al/eax/effect.h index a8dc903a..bf03fea3 100644 --- a/al/eax/effect.h +++ b/al/eax/effect.h @@ -165,12 +165,18 @@ struct EaxCommitter { static void Set(const EaxCall &call, EaxEffectProps &props); }; +struct EaxAutowahCommitter : public EaxCommitter { + using EaxCommitter::EaxCommitter; +}; struct EaxChorusCommitter : public EaxCommitter { using EaxCommitter::EaxCommitter; }; struct EaxCompressorCommitter : public EaxCommitter { using EaxCommitter::EaxCommitter; }; +struct EaxDistortionCommitter : public EaxCommitter { + using EaxCommitter::EaxCommitter; +}; struct EaxFlangerCommitter : public EaxCommitter { using EaxCommitter::EaxCommitter; }; @@ -236,8 +242,12 @@ public: return call_set_defaults(props); if(altype == AL_EFFECT_CHORUS) return call_set_defaults(props); + if(altype == AL_EFFECT_AUTOWAH) + return call_set_defaults(props); if(altype == AL_EFFECT_COMPRESSOR) return call_set_defaults(props); + if(altype == AL_EFFECT_DISTORTION) + return call_set_defaults(props); if(altype == AL_EFFECT_FLANGER) return call_set_defaults(props); return call_set_defaults(props); @@ -277,8 +287,12 @@ public: return Callable(__VA_ARGS__); \ if(T == EaxEffectType::Chorus) \ return Callable(__VA_ARGS__); \ + if(T == EaxEffectType::Autowah) \ + return Callable(__VA_ARGS__); \ if(T == EaxEffectType::Compressor) \ return Callable(__VA_ARGS__); \ + if(T == EaxEffectType::Distortion) \ + return Callable(__VA_ARGS__); \ if(T == EaxEffectType::Flanger) \ return Callable(__VA_ARGS__); \ return Callable(__VA_ARGS__) diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 22c3ab9f..532d7276 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -118,202 +118,161 @@ const EffectProps AutowahEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -class EaxAutoWahEffectException : public EaxException { -public: - explicit EaxAutoWahEffectException(const char* message) - : EaxException{"EAX_AUTO_WAH_EFFECT", message} - {} -}; // EaxAutoWahEffectException - -class EaxAutoWahEffect final : public EaxEffect4 { -public: - EaxAutoWahEffect(int eax_version); - -private: - struct AttackTimeValidator { - void operator()(float flAttackTime) const - { - eax_validate_range( - "Attack Time", - flAttackTime, - EAXAUTOWAH_MINATTACKTIME, - EAXAUTOWAH_MAXATTACKTIME); - } - }; // AttackTimeValidator - - struct ReleaseTimeValidator { - void operator()(float flReleaseTime) const - { - eax_validate_range( - "Release Time", - flReleaseTime, - EAXAUTOWAH_MINRELEASETIME, - EAXAUTOWAH_MAXRELEASETIME); - } - }; // ReleaseTimeValidator - - struct ResonanceValidator { - void operator()(long lResonance) const - { - eax_validate_range( - "Resonance", - lResonance, - EAXAUTOWAH_MINRESONANCE, - EAXAUTOWAH_MAXRESONANCE); - } - }; // ResonanceValidator - - struct PeakLevelValidator { - void operator()(long lPeakLevel) const - { - eax_validate_range( - "Peak Level", - lPeakLevel, - EAXAUTOWAH_MINPEAKLEVEL, - EAXAUTOWAH_MAXPEAKLEVEL); - } - }; // PeakLevelValidator - - struct AllValidator { - void operator()(const EAXAUTOWAHPROPERTIES& all) const - { - AttackTimeValidator{}(all.flAttackTime); - ReleaseTimeValidator{}(all.flReleaseTime); - ResonanceValidator{}(all.lResonance); - PeakLevelValidator{}(all.lPeakLevel); - } - }; // AllValidator - - void set_defaults(Props4& props) override; - - void set_efx_attack_time() noexcept; - void set_efx_release_time() noexcept; - void set_efx_resonance() noexcept; - void set_efx_peak_gain() noexcept; - void set_efx_defaults() override; - - void get(const EaxCall& call, const Props4& props) override; - void set(const EaxCall& call, Props4& props) override; - bool commit_props(const Props4& props) override; -}; // EaxAutoWahEffect - -EaxAutoWahEffect::EaxAutoWahEffect(int eax_version) - : EaxEffect4{AL_EFFECT_AUTOWAH, eax_version} -{} - -void EaxAutoWahEffect::set_defaults(Props4& props) -{ - props.mType = EaxEffectType::Autowah; - props.mAutowah.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME; - props.mAutowah.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME; - props.mAutowah.lResonance = EAXAUTOWAH_DEFAULTRESONANCE; - props.mAutowah.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL; -} - -void EaxAutoWahEffect::set_efx_attack_time() noexcept -{ - al_effect_props_.Autowah.AttackTime = clamp( - props_.mAutowah.flAttackTime, - AL_AUTOWAH_MIN_ATTACK_TIME, - AL_AUTOWAH_MAX_ATTACK_TIME); -} - -void EaxAutoWahEffect::set_efx_release_time() noexcept -{ - al_effect_props_.Autowah.ReleaseTime = clamp( - props_.mAutowah.flReleaseTime, - AL_AUTOWAH_MIN_RELEASE_TIME, - AL_AUTOWAH_MAX_RELEASE_TIME); -} +using AutowahCommitter = EaxCommitter; -void EaxAutoWahEffect::set_efx_resonance() noexcept -{ - al_effect_props_.Autowah.Resonance = clamp( - level_mb_to_gain(static_cast(props_.mAutowah.lResonance)), - AL_AUTOWAH_MIN_RESONANCE, - AL_AUTOWAH_MAX_RESONANCE); -} +struct AttackTimeValidator { + void operator()(float flAttackTime) const + { + eax_validate_range( + "Attack Time", + flAttackTime, + EAXAUTOWAH_MINATTACKTIME, + EAXAUTOWAH_MAXATTACKTIME); + } +}; // AttackTimeValidator -void EaxAutoWahEffect::set_efx_peak_gain() noexcept -{ - al_effect_props_.Autowah.PeakGain = clamp( - level_mb_to_gain(static_cast(props_.mAutowah.lPeakLevel)), - AL_AUTOWAH_MIN_PEAK_GAIN, - AL_AUTOWAH_MAX_PEAK_GAIN); -} +struct ReleaseTimeValidator { + void operator()(float flReleaseTime) const + { + eax_validate_range( + "Release Time", + flReleaseTime, + EAXAUTOWAH_MINRELEASETIME, + EAXAUTOWAH_MAXRELEASETIME); + } +}; // ReleaseTimeValidator -void EaxAutoWahEffect::set_efx_defaults() -{ - set_efx_attack_time(); - set_efx_release_time(); - set_efx_resonance(); - set_efx_peak_gain(); -} +struct ResonanceValidator { + void operator()(long lResonance) const + { + eax_validate_range( + "Resonance", + lResonance, + EAXAUTOWAH_MINRESONANCE, + EAXAUTOWAH_MAXRESONANCE); + } +}; // ResonanceValidator -void EaxAutoWahEffect::get(const EaxCall& call, const Props4& props) -{ - switch (call.get_property_id()) +struct PeakLevelValidator { + void operator()(long lPeakLevel) const { - case EAXAUTOWAH_NONE: break; - case EAXAUTOWAH_ALLPARAMETERS: call.set_value(props.mAutowah); break; - case EAXAUTOWAH_ATTACKTIME: call.set_value(props.mAutowah.flAttackTime); break; - case EAXAUTOWAH_RELEASETIME: call.set_value(props.mAutowah.flReleaseTime); break; - case EAXAUTOWAH_RESONANCE: call.set_value(props.mAutowah.lResonance); break; - case EAXAUTOWAH_PEAKLEVEL: call.set_value(props.mAutowah.lPeakLevel); break; - default: fail_unknown_property_id(); + eax_validate_range( + "Peak Level", + lPeakLevel, + EAXAUTOWAH_MINPEAKLEVEL, + EAXAUTOWAH_MAXPEAKLEVEL); } -} +}; // PeakLevelValidator -void EaxAutoWahEffect::set(const EaxCall& call, Props4& props) -{ - switch (call.get_property_id()) +struct AllValidator { + void operator()(const EAXAUTOWAHPROPERTIES& all) const { - case EAXAUTOWAH_NONE: break; - case EAXAUTOWAH_ALLPARAMETERS: defer(call, props.mAutowah); break; - case EAXAUTOWAH_ATTACKTIME: defer(call, props.mAutowah.flAttackTime); break; - case EAXAUTOWAH_RELEASETIME: defer(call, props.mAutowah.flReleaseTime); break; - case EAXAUTOWAH_RESONANCE: defer(call, props.mAutowah.lResonance); break; - case EAXAUTOWAH_PEAKLEVEL: defer(call, props.mAutowah.lPeakLevel); break; - default: fail_unknown_property_id(); + AttackTimeValidator{}(all.flAttackTime); + ReleaseTimeValidator{}(all.flReleaseTime); + ResonanceValidator{}(all.lResonance); + PeakLevelValidator{}(all.lPeakLevel); } +}; // AllValidator + +} // namespace + +template<> +struct AutowahCommitter::Exception : public EaxException +{ + explicit Exception(const char *message) : EaxException{"EAX_AUTOWAH_EFFECT", message} + { } +}; + +template<> +[[noreturn]] void AutowahCommitter::fail(const char *message) +{ + throw Exception{message}; } -bool EaxAutoWahEffect::commit_props(const Props4& props) +template<> +bool AutowahCommitter::commit(const EaxEffectProps &props) { - auto is_dirty = false; + const auto orig = props_; + props_ = props; - if (props_.mAutowah.flAttackTime != props.mAutowah.flAttackTime) + auto is_dirty = bool{orig.mType != props_.mType}; + if(props_.mAutowah.flAttackTime != props.mAutowah.flAttackTime) { is_dirty = true; - set_efx_attack_time(); + al_effect_props_.Autowah.AttackTime = clamp( + props_.mAutowah.flAttackTime, + AL_AUTOWAH_MIN_ATTACK_TIME, + AL_AUTOWAH_MAX_ATTACK_TIME); } - if (props_.mAutowah.flReleaseTime != props.mAutowah.flReleaseTime) + if(props_.mAutowah.flReleaseTime != props.mAutowah.flReleaseTime) { is_dirty = true; - set_efx_release_time(); + al_effect_props_.Autowah.ReleaseTime = clamp( + props_.mAutowah.flReleaseTime, + AL_AUTOWAH_MIN_RELEASE_TIME, + AL_AUTOWAH_MAX_RELEASE_TIME); } - if (props_.mAutowah.lResonance != props.mAutowah.lResonance) + if(props_.mAutowah.lResonance != props.mAutowah.lResonance) { is_dirty = true; - set_efx_resonance(); + al_effect_props_.Autowah.Resonance = clamp( + level_mb_to_gain(static_cast(props_.mAutowah.lResonance)), + AL_AUTOWAH_MIN_RESONANCE, + AL_AUTOWAH_MAX_RESONANCE); } - if (props_.mAutowah.lPeakLevel != props.mAutowah.lPeakLevel) + if(props_.mAutowah.lPeakLevel != props.mAutowah.lPeakLevel) { is_dirty = true; - set_efx_peak_gain(); + al_effect_props_.Autowah.PeakGain = clamp( + level_mb_to_gain(static_cast(props_.mAutowah.lPeakLevel)), + AL_AUTOWAH_MIN_PEAK_GAIN, + AL_AUTOWAH_MAX_PEAK_GAIN); } return is_dirty; } -} // namespace +template<> +void AutowahCommitter::SetDefaults(EaxEffectProps &props) +{ + props.mType = EaxEffectType::Autowah; + props.mAutowah.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME; + props.mAutowah.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME; + props.mAutowah.lResonance = EAXAUTOWAH_DEFAULTRESONANCE; + props.mAutowah.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL; +} + +template<> +void AutowahCommitter::Get(const EaxCall &call, const EaxEffectProps &props) +{ + switch(call.get_property_id()) + { + case EAXAUTOWAH_NONE: break; + case EAXAUTOWAH_ALLPARAMETERS: call.set_value(props.mAutowah); break; + case EAXAUTOWAH_ATTACKTIME: call.set_value(props.mAutowah.flAttackTime); break; + case EAXAUTOWAH_RELEASETIME: call.set_value(props.mAutowah.flReleaseTime); break; + case EAXAUTOWAH_RESONANCE: call.set_value(props.mAutowah.lResonance); break; + case EAXAUTOWAH_PEAKLEVEL: call.set_value(props.mAutowah.lPeakLevel); break; + default: fail_unknown_property_id(); + } +} -EaxEffectUPtr eax_create_eax_auto_wah_effect(int eax_version) +template<> +void AutowahCommitter::Set(const EaxCall &call, EaxEffectProps &props) { - return eax_create_eax4_effect(eax_version); + switch(call.get_property_id()) + { + case EAXAUTOWAH_NONE: break; + case EAXAUTOWAH_ALLPARAMETERS: defer(call, props.mAutowah); break; + case EAXAUTOWAH_ATTACKTIME: defer(call, props.mAutowah.flAttackTime); break; + case EAXAUTOWAH_RELEASETIME: defer(call, props.mAutowah.flReleaseTime); break; + case EAXAUTOWAH_RESONANCE: defer(call, props.mAutowah.lResonance); break; + case EAXAUTOWAH_PEAKLEVEL: defer(call, props.mAutowah.lPeakLevel); break; + default: fail_unknown_property_id(); + } } #endif // ALSOFT_EAX diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index 5f1206ab..f91314de 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -122,235 +122,184 @@ const EffectProps DistortionEffectProps{genDefaultProps()}; #ifdef ALSOFT_EAX namespace { -class EaxDistortionEffectException : public EaxException -{ -public: - explicit EaxDistortionEffectException(const char* message) - : EaxException{"EAX_DISTORTION_EFFECT", message} - {} -}; // EaxDistortionEffectException - -class EaxDistortionEffect final : public EaxEffect4 -{ -public: - EaxDistortionEffect(int eax_version); - -private: - struct EdgeValidator { - void operator()(float flEdge) const - { - eax_validate_range( - "Edge", - flEdge, - EAXDISTORTION_MINEDGE, - EAXDISTORTION_MAXEDGE); - } - }; // EdgeValidator - - struct GainValidator { - void operator()(long lGain) const - { - eax_validate_range( - "Gain", - lGain, - EAXDISTORTION_MINGAIN, - EAXDISTORTION_MAXGAIN); - } - }; // GainValidator - - struct LowPassCutOffValidator { - void operator()(float flLowPassCutOff) const - { - eax_validate_range( - "Low-pass Cut-off", - flLowPassCutOff, - EAXDISTORTION_MINLOWPASSCUTOFF, - EAXDISTORTION_MAXLOWPASSCUTOFF); - } - }; // LowPassCutOffValidator - - struct EqCenterValidator { - void operator()(float flEQCenter) const - { - eax_validate_range( - "EQ Center", - flEQCenter, - EAXDISTORTION_MINEQCENTER, - EAXDISTORTION_MAXEQCENTER); - } - }; // EqCenterValidator - - struct EqBandwidthValidator { - void operator()(float flEQBandwidth) const - { - eax_validate_range( - "EQ Bandwidth", - flEQBandwidth, - EAXDISTORTION_MINEQBANDWIDTH, - EAXDISTORTION_MAXEQBANDWIDTH); - } - }; // EqBandwidthValidator - - struct AllValidator { - void operator()(const EAXDISTORTIONPROPERTIES& all) const - { - EdgeValidator{}(all.flEdge); - GainValidator{}(all.lGain); - LowPassCutOffValidator{}(all.flLowPassCutOff); - EqCenterValidator{}(all.flEQCenter); - EqBandwidthValidator{}(all.flEQBandwidth); - } - }; // AllValidator - - void set_defaults(Props4& props) override; - - void set_efx_edge() noexcept; - void set_efx_gain() noexcept; - void set_efx_lowpass_cutoff() noexcept; - void set_efx_eq_center() noexcept; - void set_efx_eq_bandwidth() noexcept; - void set_efx_defaults() override; - - void get(const EaxCall& call, const Props4& props) override; - void set(const EaxCall& call, Props4& props) override; - bool commit_props(const Props4& props) override; -}; // EaxDistortionEffect - -EaxDistortionEffect::EaxDistortionEffect(int eax_version) - : EaxEffect4{AL_EFFECT_DISTORTION, eax_version} -{} - -void EaxDistortionEffect::set_defaults(Props4& props) -{ - props.mType = EaxEffectType::Distortion; - props.mDistortion.flEdge = EAXDISTORTION_DEFAULTEDGE; - props.mDistortion.lGain = EAXDISTORTION_DEFAULTGAIN; - props.mDistortion.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF; - props.mDistortion.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER; - props.mDistortion.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH; -} - -void EaxDistortionEffect::set_efx_edge() noexcept -{ - al_effect_props_.Distortion.Edge = clamp( - props_.mDistortion.flEdge, - AL_DISTORTION_MIN_EDGE, - AL_DISTORTION_MAX_EDGE); -} +using DistortionCommitter = EaxCommitter; -void EaxDistortionEffect::set_efx_gain() noexcept -{ - al_effect_props_.Distortion.Gain = clamp( - level_mb_to_gain(static_cast(props_.mDistortion.lGain)), - AL_DISTORTION_MIN_GAIN, - AL_DISTORTION_MAX_GAIN); -} - -void EaxDistortionEffect::set_efx_lowpass_cutoff() noexcept -{ - al_effect_props_.Distortion.LowpassCutoff = clamp( - props_.mDistortion.flLowPassCutOff, - AL_DISTORTION_MIN_LOWPASS_CUTOFF, - AL_DISTORTION_MAX_LOWPASS_CUTOFF); -} +struct EdgeValidator { + void operator()(float flEdge) const + { + eax_validate_range( + "Edge", + flEdge, + EAXDISTORTION_MINEDGE, + EAXDISTORTION_MAXEDGE); + } +}; // EdgeValidator -void EaxDistortionEffect::set_efx_eq_center() noexcept -{ - al_effect_props_.Distortion.EQCenter = clamp( - props_.mDistortion.flEQCenter, - AL_DISTORTION_MIN_EQCENTER, - AL_DISTORTION_MAX_EQCENTER); -} +struct GainValidator { + void operator()(long lGain) const + { + eax_validate_range( + "Gain", + lGain, + EAXDISTORTION_MINGAIN, + EAXDISTORTION_MAXGAIN); + } +}; // GainValidator -void EaxDistortionEffect::set_efx_eq_bandwidth() noexcept -{ - al_effect_props_.Distortion.EQBandwidth = clamp( - props_.mDistortion.flEdge, - AL_DISTORTION_MIN_EQBANDWIDTH, - AL_DISTORTION_MAX_EQBANDWIDTH); -} +struct LowPassCutOffValidator { + void operator()(float flLowPassCutOff) const + { + eax_validate_range( + "Low-pass Cut-off", + flLowPassCutOff, + EAXDISTORTION_MINLOWPASSCUTOFF, + EAXDISTORTION_MAXLOWPASSCUTOFF); + } +}; // LowPassCutOffValidator -void EaxDistortionEffect::set_efx_defaults() -{ - set_efx_edge(); - set_efx_gain(); - set_efx_lowpass_cutoff(); - set_efx_eq_center(); - set_efx_eq_bandwidth(); -} +struct EqCenterValidator { + void operator()(float flEQCenter) const + { + eax_validate_range( + "EQ Center", + flEQCenter, + EAXDISTORTION_MINEQCENTER, + EAXDISTORTION_MAXEQCENTER); + } +}; // EqCenterValidator -void EaxDistortionEffect::get(const EaxCall& call, const Props4& props) -{ - switch(call.get_property_id()) +struct EqBandwidthValidator { + void operator()(float flEQBandwidth) const { - case EAXDISTORTION_NONE: break; - case EAXDISTORTION_ALLPARAMETERS: call.set_value(props.mDistortion); break; - case EAXDISTORTION_EDGE: call.set_value(props.mDistortion.flEdge); break; - case EAXDISTORTION_GAIN: call.set_value(props.mDistortion.lGain); break; - case EAXDISTORTION_LOWPASSCUTOFF: call.set_value(props.mDistortion.flLowPassCutOff); break; - case EAXDISTORTION_EQCENTER: call.set_value(props.mDistortion.flEQCenter); break; - case EAXDISTORTION_EQBANDWIDTH: call.set_value(props.mDistortion.flEQBandwidth); break; - default: fail_unknown_property_id(); + eax_validate_range( + "EQ Bandwidth", + flEQBandwidth, + EAXDISTORTION_MINEQBANDWIDTH, + EAXDISTORTION_MAXEQBANDWIDTH); } -} +}; // EqBandwidthValidator -void EaxDistortionEffect::set(const EaxCall& call, Props4& props) -{ - switch(call.get_property_id()) +struct AllValidator { + void operator()(const EAXDISTORTIONPROPERTIES& all) const { - case EAXDISTORTION_NONE: break; - case EAXDISTORTION_ALLPARAMETERS: defer(call, props.mDistortion); break; - case EAXDISTORTION_EDGE: defer(call, props.mDistortion.flEdge); break; - case EAXDISTORTION_GAIN: defer(call, props.mDistortion.lGain); break; - case EAXDISTORTION_LOWPASSCUTOFF: defer(call, props.mDistortion.flLowPassCutOff); break; - case EAXDISTORTION_EQCENTER: defer(call, props.mDistortion.flEQCenter); break; - case EAXDISTORTION_EQBANDWIDTH: defer(call, props.mDistortion.flEQBandwidth); break; - default: fail_unknown_property_id(); + EdgeValidator{}(all.flEdge); + GainValidator{}(all.lGain); + LowPassCutOffValidator{}(all.flLowPassCutOff); + EqCenterValidator{}(all.flEQCenter); + EqBandwidthValidator{}(all.flEQBandwidth); } +}; // AllValidator + +} // namespace + +template<> +struct DistortionCommitter::Exception : public EaxException { + explicit Exception(const char *message) : EaxException{"EAX_DISTORTION_EFFECT", message} + { } +}; + +template<> +[[noreturn]] void DistortionCommitter::fail(const char *message) +{ + throw Exception{message}; } -bool EaxDistortionEffect::commit_props(const Props4& props) +template<> +bool DistortionCommitter::commit(const EaxEffectProps &props) { - auto is_dirty = false; + const auto orig = props_; + props_ = props; - if (props_.mDistortion.flEdge != props.mDistortion.flEdge) + auto is_dirty = bool{orig.mType != props_.mType}; + if(props_.mDistortion.flEdge != props.mDistortion.flEdge) { is_dirty = true; - set_efx_edge(); + al_effect_props_.Distortion.Edge = clamp( + props_.mDistortion.flEdge, + AL_DISTORTION_MIN_EDGE, + AL_DISTORTION_MAX_EDGE); } - if (props_.mDistortion.lGain != props.mDistortion.lGain) + if(props_.mDistortion.lGain != props.mDistortion.lGain) { is_dirty = true; - set_efx_gain(); + al_effect_props_.Distortion.Gain = clamp( + level_mb_to_gain(static_cast(props_.mDistortion.lGain)), + AL_DISTORTION_MIN_GAIN, + AL_DISTORTION_MAX_GAIN); } - if (props_.mDistortion.flLowPassCutOff != props.mDistortion.flLowPassCutOff) + if(props_.mDistortion.flLowPassCutOff != props.mDistortion.flLowPassCutOff) { is_dirty = true; - set_efx_lowpass_cutoff(); + al_effect_props_.Distortion.LowpassCutoff = clamp( + props_.mDistortion.flLowPassCutOff, + AL_DISTORTION_MIN_LOWPASS_CUTOFF, + AL_DISTORTION_MAX_LOWPASS_CUTOFF); } - if (props_.mDistortion.flEQCenter != props.mDistortion.flEQCenter) + if(props_.mDistortion.flEQCenter != props.mDistortion.flEQCenter) { is_dirty = true; - set_efx_eq_center(); + al_effect_props_.Distortion.EQCenter = clamp( + props_.mDistortion.flEQCenter, + AL_DISTORTION_MIN_EQCENTER, + AL_DISTORTION_MAX_EQCENTER); } - if (props_.mDistortion.flEQBandwidth != props.mDistortion.flEQBandwidth) + if(props_.mDistortion.flEQBandwidth != props.mDistortion.flEQBandwidth) { is_dirty = true; - set_efx_eq_bandwidth(); + al_effect_props_.Distortion.EQBandwidth = clamp( + props_.mDistortion.flEdge, + AL_DISTORTION_MIN_EQBANDWIDTH, + AL_DISTORTION_MAX_EQBANDWIDTH); } return is_dirty; } -} // namespace +template<> +void DistortionCommitter::SetDefaults(EaxEffectProps &props) +{ + props.mType = EaxEffectType::Distortion; + props.mDistortion.flEdge = EAXDISTORTION_DEFAULTEDGE; + props.mDistortion.lGain = EAXDISTORTION_DEFAULTGAIN; + props.mDistortion.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF; + props.mDistortion.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER; + props.mDistortion.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH; +} -EaxEffectUPtr eax_create_eax_distortion_effect(int eax_version) +template<> +void DistortionCommitter::Get(const EaxCall &call, const EaxEffectProps &props) { - return eax_create_eax4_effect(eax_version); + switch(call.get_property_id()) + { + case EAXDISTORTION_NONE: break; + case EAXDISTORTION_ALLPARAMETERS: call.set_value(props.mDistortion); break; + case EAXDISTORTION_EDGE: call.set_value(props.mDistortion.flEdge); break; + case EAXDISTORTION_GAIN: call.set_value(props.mDistortion.lGain); break; + case EAXDISTORTION_LOWPASSCUTOFF: call.set_value(props.mDistortion.flLowPassCutOff); break; + case EAXDISTORTION_EQCENTER: call.set_value(props.mDistortion.flEQCenter); break; + case EAXDISTORTION_EQBANDWIDTH: call.set_value(props.mDistortion.flEQBandwidth); break; + default: fail_unknown_property_id(); + } +} + +template<> +void DistortionCommitter::Set(const EaxCall &call, EaxEffectProps &props) +{ + switch(call.get_property_id()) + { + case EAXDISTORTION_NONE: break; + case EAXDISTORTION_ALLPARAMETERS: defer(call, props.mDistortion); break; + case EAXDISTORTION_EDGE: defer(call, props.mDistortion.flEdge); break; + case EAXDISTORTION_GAIN: defer(call, props.mDistortion.lGain); break; + case EAXDISTORTION_LOWPASSCUTOFF: defer(call, props.mDistortion.flLowPassCutOff); break; + case EAXDISTORTION_EQCENTER: defer(call, props.mDistortion.flEQCenter); break; + case EAXDISTORTION_EQBANDWIDTH: defer(call, props.mDistortion.flEQBandwidth); break; + default: fail_unknown_property_id(); + } } #endif // ALSOFT_EAX -- cgit v1.2.3 From 96b3d98ac330a29e34f4161f9c0e9d1daa05994e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 11 Mar 2023 15:03:18 -0800 Subject: Simplify committing EAX effect properties There's no need to explicitly clamp to EFX limits when they're the same as or more lenient than EAX, which were already validated when set, or when it's within tolerance of the effect implementation. Also it's generally better to check once all properties for changes and apply them all if one is different, rather than checking and setting each member individually. --- al/effects/autowah.cpp | 50 ++++++---------------- al/effects/chorus.cpp | 41 ++++++------------ al/effects/distortion.cpp | 61 ++++++-------------------- al/effects/echo.cpp | 61 ++++++-------------------- al/effects/equalizer.cpp | 107 +++++++++++----------------------------------- 5 files changed, 78 insertions(+), 242 deletions(-) (limited to 'al/effects/distortion.cpp') diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 532d7276..7434b62c 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -195,44 +195,18 @@ bool AutowahCommitter::commit(const EaxEffectProps &props) const auto orig = props_; props_ = props; - auto is_dirty = bool{orig.mType != props_.mType}; - if(props_.mAutowah.flAttackTime != props.mAutowah.flAttackTime) - { - is_dirty = true; - al_effect_props_.Autowah.AttackTime = clamp( - props_.mAutowah.flAttackTime, - AL_AUTOWAH_MIN_ATTACK_TIME, - AL_AUTOWAH_MAX_ATTACK_TIME); - } - - if(props_.mAutowah.flReleaseTime != props.mAutowah.flReleaseTime) - { - is_dirty = true; - al_effect_props_.Autowah.ReleaseTime = clamp( - props_.mAutowah.flReleaseTime, - AL_AUTOWAH_MIN_RELEASE_TIME, - AL_AUTOWAH_MAX_RELEASE_TIME); - } - - if(props_.mAutowah.lResonance != props.mAutowah.lResonance) - { - is_dirty = true; - al_effect_props_.Autowah.Resonance = clamp( - level_mb_to_gain(static_cast(props_.mAutowah.lResonance)), - AL_AUTOWAH_MIN_RESONANCE, - AL_AUTOWAH_MAX_RESONANCE); - } - - if(props_.mAutowah.lPeakLevel != props.mAutowah.lPeakLevel) - { - is_dirty = true; - al_effect_props_.Autowah.PeakGain = clamp( - level_mb_to_gain(static_cast(props_.mAutowah.lPeakLevel)), - AL_AUTOWAH_MIN_PEAK_GAIN, - AL_AUTOWAH_MAX_PEAK_GAIN); - } - - return is_dirty; + if(orig.mType == props_.mType && props_.mAutowah.flAttackTime == props.mAutowah.flAttackTime + && props_.mAutowah.flReleaseTime == props.mAutowah.flReleaseTime + && props_.mAutowah.lResonance == props.mAutowah.lResonance + && props_.mAutowah.lPeakLevel == props.mAutowah.lPeakLevel) + return false; + + al_effect_props_.Autowah.AttackTime = props_.mAutowah.flAttackTime; + al_effect_props_.Autowah.ReleaseTime = props_.mAutowah.flReleaseTime; + al_effect_props_.Autowah.Resonance = level_mb_to_gain(static_cast(props_.mAutowah.lResonance)); + al_effect_props_.Autowah.PeakGain = level_mb_to_gain(static_cast(props_.mAutowah.lPeakLevel)); + + return true; } template<> diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index a9088157..a6845ee8 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -350,14 +350,11 @@ struct EaxChorusTraits { static constexpr auto efx_default_feedback() { return AL_CHORUS_DEFAULT_FEEDBACK; } static constexpr auto efx_default_delay() { return AL_CHORUS_DEFAULT_DELAY; } - static al::optional eax_waveform(unsigned long type) + static ChorusWaveform eax_waveform(unsigned long type) { - switch(type) - { - case EAX_CHORUS_SINUSOID: return ChorusWaveform::Sinusoid; - case EAX_CHORUS_TRIANGLE: return ChorusWaveform::Triangle; - } - return al::nullopt; + if(type == EAX_CHORUS_SINUSOID) return ChorusWaveform::Sinusoid; + if(type == EAX_CHORUS_TRIANGLE) return ChorusWaveform::Triangle; + return ChorusWaveform::Sinusoid; } }; // EaxChorusTraits @@ -420,14 +417,11 @@ struct EaxFlangerTraits { static constexpr auto efx_default_feedback() { return AL_FLANGER_DEFAULT_FEEDBACK; } static constexpr auto efx_default_delay() { return AL_FLANGER_DEFAULT_DELAY; } - static al::optional eax_waveform(unsigned long type) + static ChorusWaveform eax_waveform(unsigned long type) { - switch(type) - { - case EAX_FLANGER_SINUSOID: return ChorusWaveform::Sinusoid; - case EAX_FLANGER_TRIANGLE: return ChorusWaveform::Triangle; - } - return al::nullopt; + if(type == EAX_FLANGER_SINUSOID) return ChorusWaveform::Sinusoid; + if(type == EAX_FLANGER_TRIANGLE) return ChorusWaveform::Triangle; + return ChorusWaveform::Sinusoid; } }; // EaxFlangerTraits @@ -626,19 +620,12 @@ public: && dst.flFeedback == src.flFeedback && dst.flDelay == src.flDelay) return false; - const auto efx_waveform = Traits::eax_waveform(dst.ulWaveform); - assert(efx_waveform.has_value()); - al_effect_props_.Chorus.Waveform = *efx_waveform; - al_effect_props_.Chorus.Phase = clamp(static_cast(dst.lPhase), - Traits::efx_min_phase(), Traits::efx_max_phase()); - al_effect_props_.Chorus.Rate = clamp(dst.flRate, - Traits::efx_min_rate(), Traits::efx_max_rate()); - al_effect_props_.Chorus.Depth = clamp(dst.flDepth, - Traits::efx_min_depth(), Traits::efx_max_depth()); - al_effect_props_.Chorus.Feedback = clamp(dst.flFeedback, - Traits::efx_min_feedback(), Traits::efx_max_feedback()); - al_effect_props_.Chorus.Delay = clamp(dst.flDelay, - Traits::efx_min_delay(), Traits::efx_max_delay()); + al_effect_props_.Chorus.Waveform = Traits::eax_waveform(dst.ulWaveform); + al_effect_props_.Chorus.Phase = static_cast(dst.lPhase); + al_effect_props_.Chorus.Rate = dst.flRate; + al_effect_props_.Chorus.Depth = dst.flDepth; + al_effect_props_.Chorus.Feedback = dst.flFeedback; + al_effect_props_.Chorus.Delay = dst.flDelay; return true; } diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index f91314de..a0f4d924 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -210,53 +210,20 @@ bool DistortionCommitter::commit(const EaxEffectProps &props) const auto orig = props_; props_ = props; - auto is_dirty = bool{orig.mType != props_.mType}; - if(props_.mDistortion.flEdge != props.mDistortion.flEdge) - { - is_dirty = true; - al_effect_props_.Distortion.Edge = clamp( - props_.mDistortion.flEdge, - AL_DISTORTION_MIN_EDGE, - AL_DISTORTION_MAX_EDGE); - } - - if(props_.mDistortion.lGain != props.mDistortion.lGain) - { - is_dirty = true; - al_effect_props_.Distortion.Gain = clamp( - level_mb_to_gain(static_cast(props_.mDistortion.lGain)), - AL_DISTORTION_MIN_GAIN, - AL_DISTORTION_MAX_GAIN); - } - - if(props_.mDistortion.flLowPassCutOff != props.mDistortion.flLowPassCutOff) - { - is_dirty = true; - al_effect_props_.Distortion.LowpassCutoff = clamp( - props_.mDistortion.flLowPassCutOff, - AL_DISTORTION_MIN_LOWPASS_CUTOFF, - AL_DISTORTION_MAX_LOWPASS_CUTOFF); - } - - if(props_.mDistortion.flEQCenter != props.mDistortion.flEQCenter) - { - is_dirty = true; - al_effect_props_.Distortion.EQCenter = clamp( - props_.mDistortion.flEQCenter, - AL_DISTORTION_MIN_EQCENTER, - AL_DISTORTION_MAX_EQCENTER); - } - - if(props_.mDistortion.flEQBandwidth != props.mDistortion.flEQBandwidth) - { - is_dirty = true; - al_effect_props_.Distortion.EQBandwidth = clamp( - props_.mDistortion.flEdge, - AL_DISTORTION_MIN_EQBANDWIDTH, - AL_DISTORTION_MAX_EQBANDWIDTH); - } - - return is_dirty; + if(orig.mType == props_.mType && props_.mDistortion.flEdge == props.mDistortion.flEdge + && props_.mDistortion.lGain == props.mDistortion.lGain + && props_.mDistortion.flLowPassCutOff == props.mDistortion.flLowPassCutOff + && props_.mDistortion.flEQCenter == props.mDistortion.flEQCenter + && props_.mDistortion.flEQBandwidth == props.mDistortion.flEQBandwidth) + return false; + + al_effect_props_.Distortion.Edge = props_.mDistortion.flEdge; + al_effect_props_.Distortion.Gain = level_mb_to_gain(static_cast(props_.mDistortion.lGain)); + al_effect_props_.Distortion.LowpassCutoff = props_.mDistortion.flLowPassCutOff; + al_effect_props_.Distortion.EQCenter = props_.mDistortion.flEQCenter; + al_effect_props_.Distortion.EQBandwidth = props_.mDistortion.flEdge; + + return true; } template<> diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index 98fa5541..3a83b24f 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -207,53 +207,20 @@ bool EchoCommitter::commit(const EaxEffectProps &props) const auto orig = props_; props_ = props; - auto is_dirty = bool{orig.mType != props_.mType}; - if(props_.mEcho.flDelay != props.mEcho.flDelay) - { - is_dirty = true; - al_effect_props_.Echo.Delay = clamp( - props_.mEcho.flDelay, - AL_ECHO_MIN_DELAY, - AL_ECHO_MAX_DELAY); - } - - if(props_.mEcho.flLRDelay != props.mEcho.flLRDelay) - { - is_dirty = true; - al_effect_props_.Echo.LRDelay = clamp( - props_.mEcho.flLRDelay, - AL_ECHO_MIN_LRDELAY, - AL_ECHO_MAX_LRDELAY); - } - - if(props_.mEcho.flDamping != props.mEcho.flDamping) - { - is_dirty = true; - al_effect_props_.Echo.Damping = clamp( - props_.mEcho.flDamping, - AL_ECHO_MIN_DAMPING, - AL_ECHO_MAX_DAMPING); - } - - if(props_.mEcho.flFeedback != props.mEcho.flFeedback) - { - is_dirty = true; - al_effect_props_.Echo.Feedback = clamp( - props_.mEcho.flFeedback, - AL_ECHO_MIN_FEEDBACK, - AL_ECHO_MAX_FEEDBACK); - } - - if(props_.mEcho.flSpread != props.mEcho.flSpread) - { - is_dirty = true; - al_effect_props_.Echo.Spread = clamp( - props_.mEcho.flSpread, - AL_ECHO_MIN_SPREAD, - AL_ECHO_MAX_SPREAD); - } - - return is_dirty; + if(orig.mType == props_.mType && props_.mEcho.flDelay == props.mEcho.flDelay + && props_.mEcho.flLRDelay == props.mEcho.flLRDelay + && props_.mEcho.flDamping == props.mEcho.flDamping + && props_.mEcho.flFeedback == props.mEcho.flFeedback + && props_.mEcho.flSpread == props.mEcho.flSpread) + return false; + + al_effect_props_.Echo.Delay = props_.mEcho.flDelay; + al_effect_props_.Echo.LRDelay = props_.mEcho.flLRDelay; + al_effect_props_.Echo.Damping = props_.mEcho.flDamping; + al_effect_props_.Echo.Feedback = props_.mEcho.flFeedback; + al_effect_props_.Echo.Spread = props_.mEcho.flSpread; + + return true; } template<> diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index d9d52e1a..2ef048f9 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -325,89 +325,30 @@ bool EqualizerCommitter::commit(const EaxEffectProps &props) const auto orig = props_; props_ = props; - auto is_dirty = bool{orig.mType != props_.mType}; - if(props_.mEqualizer.lLowGain != props.mEqualizer.lLowGain) - { - is_dirty = true; - al_effect_props_.Equalizer.LowGain = clamp( - level_mb_to_gain(static_cast(props_.mEqualizer.lLowGain)), - AL_EQUALIZER_MIN_LOW_GAIN, - AL_EQUALIZER_MAX_LOW_GAIN); - } - if(props_.mEqualizer.flLowCutOff != props.mEqualizer.flLowCutOff) - { - is_dirty = true; - al_effect_props_.Equalizer.LowCutoff = clamp( - props_.mEqualizer.flLowCutOff, - AL_EQUALIZER_MIN_LOW_CUTOFF, - AL_EQUALIZER_MAX_LOW_CUTOFF); - } - if(props_.mEqualizer.lMid1Gain != props.mEqualizer.lMid1Gain) - { - is_dirty = true; - al_effect_props_.Equalizer.Mid1Gain = clamp( - level_mb_to_gain(static_cast(props_.mEqualizer.lMid1Gain)), - AL_EQUALIZER_MIN_MID1_GAIN, - AL_EQUALIZER_MAX_MID1_GAIN); - } - if(props_.mEqualizer.flMid1Center != props.mEqualizer.flMid1Center) - { - is_dirty = true; - al_effect_props_.Equalizer.Mid1Center = clamp( - props_.mEqualizer.flMid1Center, - AL_EQUALIZER_MIN_MID1_CENTER, - AL_EQUALIZER_MAX_MID1_CENTER); - } - if(props_.mEqualizer.flMid1Width != props.mEqualizer.flMid1Width) - { - is_dirty = true; - al_effect_props_.Equalizer.Mid1Width = clamp( - props_.mEqualizer.flMid1Width, - AL_EQUALIZER_MIN_MID1_WIDTH, - AL_EQUALIZER_MAX_MID1_WIDTH); - } - if(props_.mEqualizer.lMid2Gain != props.mEqualizer.lMid2Gain) - { - is_dirty = true; - al_effect_props_.Equalizer.Mid2Gain = clamp( - level_mb_to_gain(static_cast(props_.mEqualizer.lMid2Gain)), - AL_EQUALIZER_MIN_MID2_GAIN, - AL_EQUALIZER_MAX_MID2_GAIN); - } - if(props_.mEqualizer.flMid2Center != props.mEqualizer.flMid2Center) - { - is_dirty = true; - al_effect_props_.Equalizer.Mid2Center = clamp( - props_.mEqualizer.flMid2Center, - AL_EQUALIZER_MIN_MID2_CENTER, - AL_EQUALIZER_MAX_MID2_CENTER); - } - if(props_.mEqualizer.flMid2Width != props.mEqualizer.flMid2Width) - { - is_dirty = true; - al_effect_props_.Equalizer.Mid2Width = clamp( - props_.mEqualizer.flMid2Width, - AL_EQUALIZER_MIN_MID2_WIDTH, - AL_EQUALIZER_MAX_MID2_WIDTH); - } - if(props_.mEqualizer.lHighGain != props.mEqualizer.lHighGain) - { - is_dirty = true; - al_effect_props_.Equalizer.HighGain = clamp( - level_mb_to_gain(static_cast(props_.mEqualizer.lHighGain)), - AL_EQUALIZER_MIN_HIGH_GAIN, - AL_EQUALIZER_MAX_HIGH_GAIN); - } - if(props_.mEqualizer.flHighCutOff != props.mEqualizer.flHighCutOff) - { - is_dirty = true; - al_effect_props_.Equalizer.HighCutoff = clamp( - props_.mEqualizer.flHighCutOff, - AL_EQUALIZER_MIN_HIGH_CUTOFF, - AL_EQUALIZER_MAX_HIGH_CUTOFF); - } - - return is_dirty; + if(orig.mType == props_.mType && props_.mEqualizer.lLowGain == props.mEqualizer.lLowGain + && props_.mEqualizer.flLowCutOff == props.mEqualizer.flLowCutOff + && props_.mEqualizer.lMid1Gain == props.mEqualizer.lMid1Gain + && props_.mEqualizer.flMid1Center == props.mEqualizer.flMid1Center + && props_.mEqualizer.flMid1Width == props.mEqualizer.flMid1Width + && props_.mEqualizer.lMid2Gain == props.mEqualizer.lMid2Gain + && props_.mEqualizer.flMid2Center == props.mEqualizer.flMid2Center + && props_.mEqualizer.flMid2Width == props.mEqualizer.flMid2Width + && props_.mEqualizer.lHighGain == props.mEqualizer.lHighGain + && props_.mEqualizer.flHighCutOff == props.mEqualizer.flHighCutOff) + return false; + + al_effect_props_.Equalizer.LowGain = level_mb_to_gain(static_cast(props_.mEqualizer.lLowGain)); + al_effect_props_.Equalizer.LowCutoff = props_.mEqualizer.flLowCutOff; + al_effect_props_.Equalizer.Mid1Gain = level_mb_to_gain(static_cast(props_.mEqualizer.lMid1Gain)); + al_effect_props_.Equalizer.Mid1Center = props_.mEqualizer.flMid1Center; + al_effect_props_.Equalizer.Mid1Width = props_.mEqualizer.flMid1Width; + al_effect_props_.Equalizer.Mid2Gain = level_mb_to_gain(static_cast(props_.mEqualizer.lMid2Gain)); + al_effect_props_.Equalizer.Mid2Center = props_.mEqualizer.flMid2Center; + al_effect_props_.Equalizer.Mid2Width = props_.mEqualizer.flMid2Width; + al_effect_props_.Equalizer.HighGain = level_mb_to_gain(static_cast(props_.mEqualizer.lHighGain)); + al_effect_props_.Equalizer.HighCutoff = props_.mEqualizer.flHighCutOff; + + return true; } template<> -- cgit v1.2.3 From 86d4a77e62857205586caf95580980f29e06eb9f Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 11 Mar 2023 17:03:51 -0800 Subject: Rename some struct members for clarity --- al/eax/effect.h | 12 ++++---- al/effects/autowah.cpp | 23 ++++++++------- al/effects/chorus.cpp | 4 +-- al/effects/compressor.cpp | 8 ++--- al/effects/distortion.cpp | 26 ++++++++--------- al/effects/echo.cpp | 26 ++++++++--------- al/effects/equalizer.cpp | 46 ++++++++++++++--------------- al/effects/fshifter.cpp | 18 ++++++------ al/effects/modulator.cpp | 17 ++++++----- al/effects/null.cpp | 4 +-- al/effects/pshifter.cpp | 14 ++++----- al/effects/reverb.cpp | 74 +++++++++++++++++++++++------------------------ al/effects/vmorpher.cpp | 32 ++++++++++---------- 13 files changed, 153 insertions(+), 151 deletions(-) (limited to 'al/effects/distortion.cpp') diff --git a/al/eax/effect.h b/al/eax/effect.h index 2de768b7..c90ccbe6 100644 --- a/al/eax/effect.h +++ b/al/eax/effect.h @@ -64,11 +64,11 @@ struct EaxReverbCommitter { struct Exception; EaxReverbCommitter(EaxEffectProps &eaxprops, EffectProps &alprops) - : props_{eaxprops}, al_effect_props_{alprops} + : mEaxProps{eaxprops}, mAlProps{alprops} { } - EaxEffectProps &props_; - EffectProps &al_effect_props_; + EaxEffectProps &mEaxProps; + EffectProps &mAlProps; [[noreturn]] static void fail(const char* message); [[noreturn]] static void fail_unknown_property_id() @@ -132,11 +132,11 @@ struct EaxCommitter { struct Exception; EaxCommitter(EaxEffectProps &eaxprops, EffectProps &alprops) - : props_{eaxprops}, al_effect_props_{alprops} + : mEaxProps{eaxprops}, mAlProps{alprops} { } - EaxEffectProps &props_; - EffectProps &al_effect_props_; + EaxEffectProps &mEaxProps; + EffectProps &mAlProps; template static void defer(const EaxCall& call, TProperty& property) diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 7434b62c..596157f0 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -192,19 +192,20 @@ template<> template<> bool AutowahCommitter::commit(const EaxEffectProps &props) { - const auto orig = props_; - props_ = props; - - if(orig.mType == props_.mType && props_.mAutowah.flAttackTime == props.mAutowah.flAttackTime - && props_.mAutowah.flReleaseTime == props.mAutowah.flReleaseTime - && props_.mAutowah.lResonance == props.mAutowah.lResonance - && props_.mAutowah.lPeakLevel == props.mAutowah.lPeakLevel) + const auto orig = mEaxProps; + mEaxProps = props; + + if(orig.mType == mEaxProps.mType + && mEaxProps.mAutowah.flAttackTime == props.mAutowah.flAttackTime + && mEaxProps.mAutowah.flReleaseTime == props.mAutowah.flReleaseTime + && mEaxProps.mAutowah.lResonance == props.mAutowah.lResonance + && mEaxProps.mAutowah.lPeakLevel == props.mAutowah.lPeakLevel) return false; - al_effect_props_.Autowah.AttackTime = props_.mAutowah.flAttackTime; - al_effect_props_.Autowah.ReleaseTime = props_.mAutowah.flReleaseTime; - al_effect_props_.Autowah.Resonance = level_mb_to_gain(static_cast(props_.mAutowah.lResonance)); - al_effect_props_.Autowah.PeakGain = level_mb_to_gain(static_cast(props_.mAutowah.lPeakLevel)); + mAlProps.Autowah.AttackTime = mEaxProps.mAutowah.flAttackTime; + mAlProps.Autowah.ReleaseTime = mEaxProps.mAutowah.flReleaseTime; + mAlProps.Autowah.Resonance = level_mb_to_gain(static_cast(mEaxProps.mAutowah.lResonance)); + mAlProps.Autowah.PeakGain = level_mb_to_gain(static_cast(mEaxProps.mAutowah.lPeakLevel)); return true; } diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index a6845ee8..c8b32aed 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -654,7 +654,7 @@ template<> bool ChorusCommitter::commit(const EaxEffectProps &props) { using Committer = ChorusFlangerEffect; - return Committer::Commit(props, props_, al_effect_props_); + return Committer::Commit(props, mEaxProps, mAlProps); } template<> @@ -695,7 +695,7 @@ template<> bool FlangerCommitter::commit(const EaxEffectProps &props) { using Committer = ChorusFlangerEffect; - return Committer::Commit(props, props_, al_effect_props_); + return Committer::Commit(props, mEaxProps, mAlProps); } template<> diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp index ecd43f2f..2d219df6 100644 --- a/al/effects/compressor.cpp +++ b/al/effects/compressor.cpp @@ -118,12 +118,12 @@ template<> template<> bool CompressorCommitter::commit(const EaxEffectProps &props) { - const auto orig = props_; - props_ = props; - if(orig.mType == props_.mType && orig.mCompressor.ulOnOff == props_.mCompressor.ulOnOff) + const auto orig = mEaxProps; + mEaxProps = props; + if(orig.mType == mEaxProps.mType && orig.mCompressor.ulOnOff == mEaxProps.mCompressor.ulOnOff) return false; - al_effect_props_.Compressor.OnOff = (props_.mCompressor.ulOnOff != 0); + mAlProps.Compressor.OnOff = (mEaxProps.mCompressor.ulOnOff != 0); return true; } diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index a0f4d924..6125c2a4 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -207,21 +207,21 @@ template<> template<> bool DistortionCommitter::commit(const EaxEffectProps &props) { - const auto orig = props_; - props_ = props; - - if(orig.mType == props_.mType && props_.mDistortion.flEdge == props.mDistortion.flEdge - && props_.mDistortion.lGain == props.mDistortion.lGain - && props_.mDistortion.flLowPassCutOff == props.mDistortion.flLowPassCutOff - && props_.mDistortion.flEQCenter == props.mDistortion.flEQCenter - && props_.mDistortion.flEQBandwidth == props.mDistortion.flEQBandwidth) + const auto orig = mEaxProps; + mEaxProps = props; + + if(orig.mType == mEaxProps.mType && mEaxProps.mDistortion.flEdge == props.mDistortion.flEdge + && mEaxProps.mDistortion.lGain == props.mDistortion.lGain + && mEaxProps.mDistortion.flLowPassCutOff == props.mDistortion.flLowPassCutOff + && mEaxProps.mDistortion.flEQCenter == props.mDistortion.flEQCenter + && mEaxProps.mDistortion.flEQBandwidth == props.mDistortion.flEQBandwidth) return false; - al_effect_props_.Distortion.Edge = props_.mDistortion.flEdge; - al_effect_props_.Distortion.Gain = level_mb_to_gain(static_cast(props_.mDistortion.lGain)); - al_effect_props_.Distortion.LowpassCutoff = props_.mDistortion.flLowPassCutOff; - al_effect_props_.Distortion.EQCenter = props_.mDistortion.flEQCenter; - al_effect_props_.Distortion.EQBandwidth = props_.mDistortion.flEdge; + mAlProps.Distortion.Edge = mEaxProps.mDistortion.flEdge; + mAlProps.Distortion.Gain = level_mb_to_gain(static_cast(mEaxProps.mDistortion.lGain)); + mAlProps.Distortion.LowpassCutoff = mEaxProps.mDistortion.flLowPassCutOff; + mAlProps.Distortion.EQCenter = mEaxProps.mDistortion.flEQCenter; + mAlProps.Distortion.EQBandwidth = mEaxProps.mDistortion.flEdge; return true; } diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index 3a83b24f..be12c621 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -204,21 +204,21 @@ template<> template<> bool EchoCommitter::commit(const EaxEffectProps &props) { - const auto orig = props_; - props_ = props; - - if(orig.mType == props_.mType && props_.mEcho.flDelay == props.mEcho.flDelay - && props_.mEcho.flLRDelay == props.mEcho.flLRDelay - && props_.mEcho.flDamping == props.mEcho.flDamping - && props_.mEcho.flFeedback == props.mEcho.flFeedback - && props_.mEcho.flSpread == props.mEcho.flSpread) + const auto orig = mEaxProps; + mEaxProps = props; + + if(orig.mType == mEaxProps.mType && mEaxProps.mEcho.flDelay == props.mEcho.flDelay + && mEaxProps.mEcho.flLRDelay == props.mEcho.flLRDelay + && mEaxProps.mEcho.flDamping == props.mEcho.flDamping + && mEaxProps.mEcho.flFeedback == props.mEcho.flFeedback + && mEaxProps.mEcho.flSpread == props.mEcho.flSpread) return false; - al_effect_props_.Echo.Delay = props_.mEcho.flDelay; - al_effect_props_.Echo.LRDelay = props_.mEcho.flLRDelay; - al_effect_props_.Echo.Damping = props_.mEcho.flDamping; - al_effect_props_.Echo.Feedback = props_.mEcho.flFeedback; - al_effect_props_.Echo.Spread = props_.mEcho.flSpread; + mAlProps.Echo.Delay = mEaxProps.mEcho.flDelay; + mAlProps.Echo.LRDelay = mEaxProps.mEcho.flLRDelay; + mAlProps.Echo.Damping = mEaxProps.mEcho.flDamping; + mAlProps.Echo.Feedback = mEaxProps.mEcho.flFeedback; + mAlProps.Echo.Spread = mEaxProps.mEcho.flSpread; return true; } diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index 2ef048f9..5eea9e6d 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -322,31 +322,31 @@ template<> template<> bool EqualizerCommitter::commit(const EaxEffectProps &props) { - const auto orig = props_; - props_ = props; - - if(orig.mType == props_.mType && props_.mEqualizer.lLowGain == props.mEqualizer.lLowGain - && props_.mEqualizer.flLowCutOff == props.mEqualizer.flLowCutOff - && props_.mEqualizer.lMid1Gain == props.mEqualizer.lMid1Gain - && props_.mEqualizer.flMid1Center == props.mEqualizer.flMid1Center - && props_.mEqualizer.flMid1Width == props.mEqualizer.flMid1Width - && props_.mEqualizer.lMid2Gain == props.mEqualizer.lMid2Gain - && props_.mEqualizer.flMid2Center == props.mEqualizer.flMid2Center - && props_.mEqualizer.flMid2Width == props.mEqualizer.flMid2Width - && props_.mEqualizer.lHighGain == props.mEqualizer.lHighGain - && props_.mEqualizer.flHighCutOff == props.mEqualizer.flHighCutOff) + const auto orig = mEaxProps; + mEaxProps = props; + + if(orig.mType == mEaxProps.mType && mEaxProps.mEqualizer.lLowGain == props.mEqualizer.lLowGain + && mEaxProps.mEqualizer.flLowCutOff == props.mEqualizer.flLowCutOff + && mEaxProps.mEqualizer.lMid1Gain == props.mEqualizer.lMid1Gain + && mEaxProps.mEqualizer.flMid1Center == props.mEqualizer.flMid1Center + && mEaxProps.mEqualizer.flMid1Width == props.mEqualizer.flMid1Width + && mEaxProps.mEqualizer.lMid2Gain == props.mEqualizer.lMid2Gain + && mEaxProps.mEqualizer.flMid2Center == props.mEqualizer.flMid2Center + && mEaxProps.mEqualizer.flMid2Width == props.mEqualizer.flMid2Width + && mEaxProps.mEqualizer.lHighGain == props.mEqualizer.lHighGain + && mEaxProps.mEqualizer.flHighCutOff == props.mEqualizer.flHighCutOff) return false; - al_effect_props_.Equalizer.LowGain = level_mb_to_gain(static_cast(props_.mEqualizer.lLowGain)); - al_effect_props_.Equalizer.LowCutoff = props_.mEqualizer.flLowCutOff; - al_effect_props_.Equalizer.Mid1Gain = level_mb_to_gain(static_cast(props_.mEqualizer.lMid1Gain)); - al_effect_props_.Equalizer.Mid1Center = props_.mEqualizer.flMid1Center; - al_effect_props_.Equalizer.Mid1Width = props_.mEqualizer.flMid1Width; - al_effect_props_.Equalizer.Mid2Gain = level_mb_to_gain(static_cast(props_.mEqualizer.lMid2Gain)); - al_effect_props_.Equalizer.Mid2Center = props_.mEqualizer.flMid2Center; - al_effect_props_.Equalizer.Mid2Width = props_.mEqualizer.flMid2Width; - al_effect_props_.Equalizer.HighGain = level_mb_to_gain(static_cast(props_.mEqualizer.lHighGain)); - al_effect_props_.Equalizer.HighCutoff = props_.mEqualizer.flHighCutOff; + mAlProps.Equalizer.LowGain = level_mb_to_gain(static_cast(mEaxProps.mEqualizer.lLowGain)); + mAlProps.Equalizer.LowCutoff = mEaxProps.mEqualizer.flLowCutOff; + mAlProps.Equalizer.Mid1Gain = level_mb_to_gain(static_cast(mEaxProps.mEqualizer.lMid1Gain)); + mAlProps.Equalizer.Mid1Center = mEaxProps.mEqualizer.flMid1Center; + mAlProps.Equalizer.Mid1Width = mEaxProps.mEqualizer.flMid1Width; + mAlProps.Equalizer.Mid2Gain = level_mb_to_gain(static_cast(mEaxProps.mEqualizer.lMid2Gain)); + mAlProps.Equalizer.Mid2Center = mEaxProps.mEqualizer.flMid2Center; + mAlProps.Equalizer.Mid2Width = mEaxProps.mEqualizer.flMid2Width; + mAlProps.Equalizer.HighGain = level_mb_to_gain(static_cast(mEaxProps.mEqualizer.lHighGain)); + mAlProps.Equalizer.HighCutoff = mEaxProps.mEqualizer.flHighCutOff; return true; } diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index f4c42bf7..983e83ee 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -200,13 +200,13 @@ template<> template<> bool FrequencyShifterCommitter::commit(const EaxEffectProps &props) { - const auto orig = props_; - props_ = props; + const auto orig = mEaxProps; + mEaxProps = props; - if(orig.mType == props_.mType - && props_.mFrequencyShifter.flFrequency == props.mFrequencyShifter.flFrequency - && props_.mFrequencyShifter.ulLeftDirection == props.mFrequencyShifter.ulLeftDirection - && props_.mFrequencyShifter.ulRightDirection == props.mFrequencyShifter.ulRightDirection) + if(orig.mType == mEaxProps.mType + && mEaxProps.mFrequencyShifter.flFrequency == props.mFrequencyShifter.flFrequency + && mEaxProps.mFrequencyShifter.ulLeftDirection == props.mFrequencyShifter.ulLeftDirection + && mEaxProps.mFrequencyShifter.ulRightDirection == props.mFrequencyShifter.ulRightDirection) return false; auto get_direction = [](unsigned long dir) noexcept @@ -218,9 +218,9 @@ bool FrequencyShifterCommitter::commit(const EaxEffectProps &props) return FShifterDirection::Off; }; - al_effect_props_.Fshifter.Frequency = props_.mFrequencyShifter.flFrequency; - al_effect_props_.Fshifter.LeftDirection = get_direction(props_.mFrequencyShifter.ulLeftDirection); - al_effect_props_.Fshifter.RightDirection = get_direction(props_.mFrequencyShifter.ulRightDirection); + mAlProps.Fshifter.Frequency = mEaxProps.mFrequencyShifter.flFrequency; + mAlProps.Fshifter.LeftDirection = get_direction(mEaxProps.mFrequencyShifter.ulLeftDirection); + mAlProps.Fshifter.RightDirection = get_direction(mEaxProps.mFrequencyShifter.ulRightDirection); return true; } diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index f3e43c52..8b6b1045 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -206,12 +206,13 @@ template<> template<> bool ModulatorCommitter::commit(const EaxEffectProps &props) { - const auto orig = props_; - props_ = props; + const auto orig = mEaxProps; + mEaxProps = props; - if(orig.mType == props_.mType && props_.mModulator.flFrequency == props.mModulator.flFrequency - && props_.mModulator.flHighPassCutOff == props.mModulator.flHighPassCutOff - && props_.mModulator.ulWaveform == props.mModulator.ulWaveform) + if(orig.mType == mEaxProps.mType + && mEaxProps.mModulator.flFrequency == props.mModulator.flFrequency + && mEaxProps.mModulator.flHighPassCutOff == props.mModulator.flHighPassCutOff + && mEaxProps.mModulator.ulWaveform == props.mModulator.ulWaveform) return false; auto get_waveform = [](unsigned long form) @@ -225,9 +226,9 @@ bool ModulatorCommitter::commit(const EaxEffectProps &props) return ModulatorWaveform::Sinusoid; }; - al_effect_props_.Modulator.Frequency = props_.mModulator.flFrequency; - al_effect_props_.Modulator.HighPassCutoff = props_.mModulator.flHighPassCutOff; - al_effect_props_.Modulator.Waveform = get_waveform(props_.mModulator.ulWaveform); + mAlProps.Modulator.Frequency = mEaxProps.mModulator.flFrequency; + mAlProps.Modulator.HighPassCutoff = mEaxProps.mModulator.flHighPassCutOff; + mAlProps.Modulator.Waveform = get_waveform(mEaxProps.mModulator.ulWaveform); return true; } diff --git a/al/effects/null.cpp b/al/effects/null.cpp index e80ab9f8..0bbc183a 100644 --- a/al/effects/null.cpp +++ b/al/effects/null.cpp @@ -120,8 +120,8 @@ template<> template<> bool NullCommitter::commit(const EaxEffectProps &props) { - const bool ret{props.mType != props_.mType}; - props_ = props; + const bool ret{props.mType != mEaxProps.mType}; + mEaxProps = props; return ret; } diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp index 53115edb..7c9f0b0e 100644 --- a/al/effects/pshifter.cpp +++ b/al/effects/pshifter.cpp @@ -141,16 +141,16 @@ template<> template<> bool PitchShifterCommitter::commit(const EaxEffectProps &props) { - const auto orig = props_; - props_ = props; + const auto orig = mEaxProps; + mEaxProps = props; - if(orig.mType == props_.mType - && props_.mPitchShifter.lCoarseTune == props.mPitchShifter.lCoarseTune - && props_.mPitchShifter.lFineTune == props.mPitchShifter.lFineTune) + if(orig.mType == mEaxProps.mType + && mEaxProps.mPitchShifter.lCoarseTune == props.mPitchShifter.lCoarseTune + && mEaxProps.mPitchShifter.lFineTune == props.mPitchShifter.lFineTune) return false; - al_effect_props_.Pshifter.CoarseTune = static_cast(props_.mPitchShifter.lCoarseTune); - al_effect_props_.Pshifter.FineTune = static_cast(props_.mPitchShifter.lFineTune); + mAlProps.Pshifter.CoarseTune = static_cast(mEaxProps.mPitchShifter.lCoarseTune); + mAlProps.Pshifter.FineTune = static_cast(mEaxProps.mPitchShifter.lFineTune); return true; } diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index b154e3ff..3b04d86c 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -1156,66 +1156,66 @@ bool EaxReverbCommitter::commit(const EAXREVERBPROPERTIES &props) bool EaxReverbCommitter::commit(const EaxEffectProps &props) { - const auto orig = props_; - props_ = props; - if(orig.mType == props_.mType && memcmp(&orig.mReverb, &props_.mReverb, sizeof(props_.mReverb)) == 0) + const auto orig = mEaxProps; + mEaxProps = props; + if(orig.mType == mEaxProps.mType && memcmp(&orig.mReverb, &mEaxProps.mReverb, sizeof(mEaxProps.mReverb)) == 0) return false; - const auto size = props_.mReverb.flEnvironmentSize; + const auto size = mEaxProps.mReverb.flEnvironmentSize; const auto density = (size * size * size) / 16.0F; - al_effect_props_.Reverb.Density = clamp(density, + mAlProps.Reverb.Density = clamp(density, AL_EAXREVERB_MIN_DENSITY, AL_EAXREVERB_MAX_DENSITY); - al_effect_props_.Reverb.Diffusion = clamp(props_.mReverb.flEnvironmentDiffusion, + mAlProps.Reverb.Diffusion = clamp(mEaxProps.mReverb.flEnvironmentDiffusion, AL_EAXREVERB_MIN_DIFFUSION, AL_EAXREVERB_MAX_DIFFUSION); - al_effect_props_.Reverb.Gain = clamp( - level_mb_to_gain(static_cast(props_.mReverb.lRoom)), + mAlProps.Reverb.Gain = clamp( + level_mb_to_gain(static_cast(mEaxProps.mReverb.lRoom)), AL_EAXREVERB_MIN_GAIN, AL_EAXREVERB_MAX_GAIN); - al_effect_props_.Reverb.GainHF = clamp( - level_mb_to_gain(static_cast(props_.mReverb.lRoomHF)), + mAlProps.Reverb.GainHF = clamp( + level_mb_to_gain(static_cast(mEaxProps.mReverb.lRoomHF)), AL_EAXREVERB_MIN_GAINHF, AL_EAXREVERB_MAX_GAINHF); - al_effect_props_.Reverb.GainLF = clamp( - level_mb_to_gain(static_cast(props_.mReverb.lRoomLF)), + mAlProps.Reverb.GainLF = clamp( + level_mb_to_gain(static_cast(mEaxProps.mReverb.lRoomLF)), AL_EAXREVERB_MIN_GAINLF, AL_EAXREVERB_MAX_GAINLF); - al_effect_props_.Reverb.DecayTime = clamp(props_.mReverb.flDecayTime, + mAlProps.Reverb.DecayTime = clamp(mEaxProps.mReverb.flDecayTime, AL_EAXREVERB_MIN_DECAY_TIME, AL_EAXREVERB_MAX_DECAY_TIME); - al_effect_props_.Reverb.DecayHFRatio = clamp(props_.mReverb.flDecayHFRatio, + mAlProps.Reverb.DecayHFRatio = clamp(mEaxProps.mReverb.flDecayHFRatio, AL_EAXREVERB_MIN_DECAY_HFRATIO, AL_EAXREVERB_MAX_DECAY_HFRATIO); - al_effect_props_.Reverb.DecayLFRatio = clamp(props_.mReverb.flDecayLFRatio, + mAlProps.Reverb.DecayLFRatio = clamp(mEaxProps.mReverb.flDecayLFRatio, AL_EAXREVERB_MIN_DECAY_LFRATIO, AL_EAXREVERB_MAX_DECAY_LFRATIO); - al_effect_props_.Reverb.ReflectionsGain = clamp( - level_mb_to_gain(static_cast(props_.mReverb.lReflections)), + mAlProps.Reverb.ReflectionsGain = clamp( + level_mb_to_gain(static_cast(mEaxProps.mReverb.lReflections)), AL_EAXREVERB_MIN_REFLECTIONS_GAIN, AL_EAXREVERB_MAX_REFLECTIONS_GAIN); - al_effect_props_.Reverb.ReflectionsDelay = clamp(props_.mReverb.flReflectionsDelay, + mAlProps.Reverb.ReflectionsDelay = clamp(mEaxProps.mReverb.flReflectionsDelay, AL_EAXREVERB_MIN_REFLECTIONS_DELAY, AL_EAXREVERB_MAX_REFLECTIONS_DELAY); - al_effect_props_.Reverb.ReflectionsPan[0] = props_.mReverb.vReflectionsPan.x; - al_effect_props_.Reverb.ReflectionsPan[1] = props_.mReverb.vReflectionsPan.y; - al_effect_props_.Reverb.ReflectionsPan[2] = props_.mReverb.vReflectionsPan.z; - al_effect_props_.Reverb.LateReverbGain = clamp( - level_mb_to_gain(static_cast(props_.mReverb.lReverb)), + mAlProps.Reverb.ReflectionsPan[0] = mEaxProps.mReverb.vReflectionsPan.x; + mAlProps.Reverb.ReflectionsPan[1] = mEaxProps.mReverb.vReflectionsPan.y; + mAlProps.Reverb.ReflectionsPan[2] = mEaxProps.mReverb.vReflectionsPan.z; + mAlProps.Reverb.LateReverbGain = clamp( + level_mb_to_gain(static_cast(mEaxProps.mReverb.lReverb)), AL_EAXREVERB_MIN_LATE_REVERB_GAIN, AL_EAXREVERB_MAX_LATE_REVERB_GAIN); - al_effect_props_.Reverb.LateReverbDelay = clamp(props_.mReverb.flReverbDelay, + mAlProps.Reverb.LateReverbDelay = clamp(mEaxProps.mReverb.flReverbDelay, AL_EAXREVERB_MIN_LATE_REVERB_DELAY, AL_EAXREVERB_MAX_LATE_REVERB_DELAY); - al_effect_props_.Reverb.LateReverbPan[0] = props_.mReverb.vReverbPan.x; - al_effect_props_.Reverb.LateReverbPan[1] = props_.mReverb.vReverbPan.y; - al_effect_props_.Reverb.LateReverbPan[2] = props_.mReverb.vReverbPan.z; - al_effect_props_.Reverb.EchoTime = clamp(props_.mReverb.flEchoTime, + mAlProps.Reverb.LateReverbPan[0] = mEaxProps.mReverb.vReverbPan.x; + mAlProps.Reverb.LateReverbPan[1] = mEaxProps.mReverb.vReverbPan.y; + mAlProps.Reverb.LateReverbPan[2] = mEaxProps.mReverb.vReverbPan.z; + mAlProps.Reverb.EchoTime = clamp(mEaxProps.mReverb.flEchoTime, AL_EAXREVERB_MIN_ECHO_TIME, AL_EAXREVERB_MAX_ECHO_TIME); - al_effect_props_.Reverb.EchoDepth = clamp(props_.mReverb.flEchoDepth, + mAlProps.Reverb.EchoDepth = clamp(mEaxProps.mReverb.flEchoDepth, AL_EAXREVERB_MIN_ECHO_DEPTH, AL_EAXREVERB_MAX_ECHO_DEPTH); - al_effect_props_.Reverb.ModulationTime = clamp(props_.mReverb.flModulationTime, + mAlProps.Reverb.ModulationTime = clamp(mEaxProps.mReverb.flModulationTime, AL_EAXREVERB_MIN_MODULATION_TIME, AL_EAXREVERB_MAX_MODULATION_TIME); - al_effect_props_.Reverb.ModulationDepth = clamp(props_.mReverb.flModulationDepth, + mAlProps.Reverb.ModulationDepth = clamp(mEaxProps.mReverb.flModulationDepth, AL_EAXREVERB_MIN_MODULATION_DEPTH, AL_EAXREVERB_MAX_MODULATION_DEPTH); - al_effect_props_.Reverb.AirAbsorptionGainHF = clamp( - level_mb_to_gain(props_.mReverb.flAirAbsorptionHF), + mAlProps.Reverb.AirAbsorptionGainHF = clamp( + level_mb_to_gain(mEaxProps.mReverb.flAirAbsorptionHF), AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF, AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF); - al_effect_props_.Reverb.HFReference = clamp(props_.mReverb.flHFReference, + mAlProps.Reverb.HFReference = clamp(mEaxProps.mReverb.flHFReference, AL_EAXREVERB_MIN_HFREFERENCE, AL_EAXREVERB_MAX_HFREFERENCE); - al_effect_props_.Reverb.LFReference = clamp(props_.mReverb.flLFReference, + mAlProps.Reverb.LFReference = clamp(mEaxProps.mReverb.flLFReference, AL_EAXREVERB_MIN_LFREFERENCE, AL_EAXREVERB_MAX_LFREFERENCE); - al_effect_props_.Reverb.RoomRolloffFactor = clamp(props_.mReverb.flRoomRolloffFactor, + mAlProps.Reverb.RoomRolloffFactor = clamp(mEaxProps.mReverb.flRoomRolloffFactor, AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR, AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR); - al_effect_props_.Reverb.DecayHFLimit = ((props_.mReverb.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0); + mAlProps.Reverb.DecayHFLimit = ((mEaxProps.mReverb.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0); return true; } diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index f8be5856..856fc6b3 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -355,16 +355,16 @@ template<> template<> bool VocalMorpherCommitter::commit(const EaxEffectProps &props) { - const auto orig = props_; - props_ = props; - - if(orig.mType == props_.mType - && props_.mVocalMorpher.ulPhonemeA == props.mVocalMorpher.ulPhonemeA - && props_.mVocalMorpher.lPhonemeACoarseTuning == props.mVocalMorpher.lPhonemeACoarseTuning - && props_.mVocalMorpher.ulPhonemeB == props.mVocalMorpher.ulPhonemeB - && props_.mVocalMorpher.lPhonemeBCoarseTuning == props.mVocalMorpher.lPhonemeBCoarseTuning - && props_.mVocalMorpher.ulWaveform == props.mVocalMorpher.ulWaveform - && props_.mVocalMorpher.flRate == props.mVocalMorpher.flRate) + const auto orig = mEaxProps; + mEaxProps = props; + + if(orig.mType == mEaxProps.mType + && mEaxProps.mVocalMorpher.ulPhonemeA == props.mVocalMorpher.ulPhonemeA + && mEaxProps.mVocalMorpher.lPhonemeACoarseTuning == props.mVocalMorpher.lPhonemeACoarseTuning + && mEaxProps.mVocalMorpher.ulPhonemeB == props.mVocalMorpher.ulPhonemeB + && mEaxProps.mVocalMorpher.lPhonemeBCoarseTuning == props.mVocalMorpher.lPhonemeBCoarseTuning + && mEaxProps.mVocalMorpher.ulWaveform == props.mVocalMorpher.ulWaveform + && mEaxProps.mVocalMorpher.flRate == props.mVocalMorpher.flRate) return false; auto get_phoneme = [](unsigned long phoneme) noexcept @@ -414,12 +414,12 @@ bool VocalMorpherCommitter::commit(const EaxEffectProps &props) return VMorpherWaveform::Sinusoid; }; - al_effect_props_.Vmorpher.PhonemeA = get_phoneme(props_.mVocalMorpher.ulPhonemeA); - al_effect_props_.Vmorpher.PhonemeACoarseTuning = static_cast(props_.mVocalMorpher.lPhonemeACoarseTuning); - al_effect_props_.Vmorpher.PhonemeB = get_phoneme(props_.mVocalMorpher.ulPhonemeB); - al_effect_props_.Vmorpher.PhonemeBCoarseTuning = static_cast(props_.mVocalMorpher.lPhonemeBCoarseTuning); - al_effect_props_.Vmorpher.Waveform = get_waveform(props_.mVocalMorpher.ulWaveform); - al_effect_props_.Vmorpher.Rate = props_.mVocalMorpher.flRate; + mAlProps.Vmorpher.PhonemeA = get_phoneme(mEaxProps.mVocalMorpher.ulPhonemeA); + mAlProps.Vmorpher.PhonemeACoarseTuning = static_cast(mEaxProps.mVocalMorpher.lPhonemeACoarseTuning); + mAlProps.Vmorpher.PhonemeB = get_phoneme(mEaxProps.mVocalMorpher.ulPhonemeB); + mAlProps.Vmorpher.PhonemeBCoarseTuning = static_cast(mEaxProps.mVocalMorpher.lPhonemeBCoarseTuning); + mAlProps.Vmorpher.Waveform = get_waveform(mEaxProps.mVocalMorpher.ulWaveform); + mAlProps.Vmorpher.Rate = mEaxProps.mVocalMorpher.flRate; return true; } -- cgit v1.2.3 From 3f45b3c0c900a6b513d8917cc4df00ca100a7c09 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 11 Mar 2023 18:15:59 -0800 Subject: Avoid copying to a temporary --- al/effects/autowah.cpp | 15 ++++++------ al/effects/chorus.cpp | 36 +++++++++++++++-------------- al/effects/compressor.cpp | 9 ++++---- al/effects/distortion.cpp | 17 +++++++------- al/effects/echo.cpp | 17 +++++++------- al/effects/equalizer.cpp | 27 +++++++++++----------- al/effects/fshifter.cpp | 13 +++++------ al/effects/modulator.cpp | 13 +++++------ al/effects/pshifter.cpp | 11 ++++----- al/effects/reverb.cpp | 59 ++++++++++++++++++++++++----------------------- al/effects/vmorpher.cpp | 19 ++++++++------- 11 files changed, 116 insertions(+), 120 deletions(-) (limited to 'al/effects/distortion.cpp') diff --git a/al/effects/autowah.cpp b/al/effects/autowah.cpp index 596157f0..129318f4 100644 --- a/al/effects/autowah.cpp +++ b/al/effects/autowah.cpp @@ -192,20 +192,19 @@ template<> template<> bool AutowahCommitter::commit(const EaxEffectProps &props) { - const auto orig = mEaxProps; - mEaxProps = props; - - if(orig.mType == mEaxProps.mType + if(props.mType == mEaxProps.mType && mEaxProps.mAutowah.flAttackTime == props.mAutowah.flAttackTime && mEaxProps.mAutowah.flReleaseTime == props.mAutowah.flReleaseTime && mEaxProps.mAutowah.lResonance == props.mAutowah.lResonance && mEaxProps.mAutowah.lPeakLevel == props.mAutowah.lPeakLevel) return false; - mAlProps.Autowah.AttackTime = mEaxProps.mAutowah.flAttackTime; - mAlProps.Autowah.ReleaseTime = mEaxProps.mAutowah.flReleaseTime; - mAlProps.Autowah.Resonance = level_mb_to_gain(static_cast(mEaxProps.mAutowah.lResonance)); - mAlProps.Autowah.PeakGain = level_mb_to_gain(static_cast(mEaxProps.mAutowah.lPeakLevel)); + mEaxProps = props; + + mAlProps.Autowah.AttackTime = props.mAutowah.flAttackTime; + mAlProps.Autowah.ReleaseTime = props.mAutowah.flReleaseTime; + mAlProps.Autowah.Resonance = level_mb_to_gain(static_cast(props.mAutowah.lResonance)); + mAlProps.Autowah.PeakGain = level_mb_to_gain(static_cast(props.mAutowah.lPeakLevel)); return true; } diff --git a/al/effects/chorus.cpp b/al/effects/chorus.cpp index c8b32aed..305259a4 100644 --- a/al/effects/chorus.cpp +++ b/al/effects/chorus.cpp @@ -607,25 +607,27 @@ public: } } - static bool Commit(const EaxEffectProps &props, EaxEffectProps &props_, - EffectProps &al_effect_props_) + static bool Commit(const EaxEffectProps &props, EaxEffectProps &props_, EffectProps &al_props_) { - const auto orig = props_; - props_ = props; + if(props.mType == props_.mType) + { + auto&& src = props_.*Field; + auto&& dst = props.*Field; + if(dst.ulWaveform == src.ulWaveform && dst.lPhase == src.lPhase + && dst.flRate == src.flRate && dst.flDepth == src.flDepth + && dst.flFeedback == src.flFeedback && dst.flDelay == src.flDelay) + return false; + } - auto&& src = orig.*Field; - auto&& dst = props_.*Field; - if(orig.mType == props_.mType && dst.ulWaveform == src.ulWaveform - && dst.lPhase == src.lPhase && dst.flRate == src.flRate && dst.flDepth == src.flDepth - && dst.flFeedback == src.flFeedback && dst.flDelay == src.flDelay) - return false; - - al_effect_props_.Chorus.Waveform = Traits::eax_waveform(dst.ulWaveform); - al_effect_props_.Chorus.Phase = static_cast(dst.lPhase); - al_effect_props_.Chorus.Rate = dst.flRate; - al_effect_props_.Chorus.Depth = dst.flDepth; - al_effect_props_.Chorus.Feedback = dst.flFeedback; - al_effect_props_.Chorus.Delay = dst.flDelay; + props_ = props; + auto&& dst = props.*Field; + + al_props_.Chorus.Waveform = Traits::eax_waveform(dst.ulWaveform); + al_props_.Chorus.Phase = static_cast(dst.lPhase); + al_props_.Chorus.Rate = dst.flRate; + al_props_.Chorus.Depth = dst.flDepth; + al_props_.Chorus.Feedback = dst.flFeedback; + al_props_.Chorus.Delay = dst.flDelay; return true; } diff --git a/al/effects/compressor.cpp b/al/effects/compressor.cpp index 2d219df6..a4aa8e77 100644 --- a/al/effects/compressor.cpp +++ b/al/effects/compressor.cpp @@ -118,12 +118,13 @@ template<> template<> bool CompressorCommitter::commit(const EaxEffectProps &props) { - const auto orig = mEaxProps; - mEaxProps = props; - if(orig.mType == mEaxProps.mType && orig.mCompressor.ulOnOff == mEaxProps.mCompressor.ulOnOff) + if(props.mType == mEaxProps.mType + && props.mCompressor.ulOnOff == mEaxProps.mCompressor.ulOnOff) return false; - mAlProps.Compressor.OnOff = (mEaxProps.mCompressor.ulOnOff != 0); + mEaxProps = props; + + mAlProps.Compressor.OnOff = (props.mCompressor.ulOnOff != 0); return true; } diff --git a/al/effects/distortion.cpp b/al/effects/distortion.cpp index 6125c2a4..ee298ddf 100644 --- a/al/effects/distortion.cpp +++ b/al/effects/distortion.cpp @@ -207,21 +207,20 @@ template<> template<> bool DistortionCommitter::commit(const EaxEffectProps &props) { - const auto orig = mEaxProps; - mEaxProps = props; - - if(orig.mType == mEaxProps.mType && mEaxProps.mDistortion.flEdge == props.mDistortion.flEdge + if(props.mType == mEaxProps.mType && mEaxProps.mDistortion.flEdge == props.mDistortion.flEdge && mEaxProps.mDistortion.lGain == props.mDistortion.lGain && mEaxProps.mDistortion.flLowPassCutOff == props.mDistortion.flLowPassCutOff && mEaxProps.mDistortion.flEQCenter == props.mDistortion.flEQCenter && mEaxProps.mDistortion.flEQBandwidth == props.mDistortion.flEQBandwidth) return false; - mAlProps.Distortion.Edge = mEaxProps.mDistortion.flEdge; - mAlProps.Distortion.Gain = level_mb_to_gain(static_cast(mEaxProps.mDistortion.lGain)); - mAlProps.Distortion.LowpassCutoff = mEaxProps.mDistortion.flLowPassCutOff; - mAlProps.Distortion.EQCenter = mEaxProps.mDistortion.flEQCenter; - mAlProps.Distortion.EQBandwidth = mEaxProps.mDistortion.flEdge; + mEaxProps = props; + + mAlProps.Distortion.Edge = props.mDistortion.flEdge; + mAlProps.Distortion.Gain = level_mb_to_gain(static_cast(props.mDistortion.lGain)); + mAlProps.Distortion.LowpassCutoff = props.mDistortion.flLowPassCutOff; + mAlProps.Distortion.EQCenter = props.mDistortion.flEQCenter; + mAlProps.Distortion.EQBandwidth = props.mDistortion.flEdge; return true; } diff --git a/al/effects/echo.cpp b/al/effects/echo.cpp index be12c621..2eb37603 100644 --- a/al/effects/echo.cpp +++ b/al/effects/echo.cpp @@ -204,21 +204,20 @@ template<> template<> bool EchoCommitter::commit(const EaxEffectProps &props) { - const auto orig = mEaxProps; - mEaxProps = props; - - if(orig.mType == mEaxProps.mType && mEaxProps.mEcho.flDelay == props.mEcho.flDelay + if(props.mType == mEaxProps.mType && mEaxProps.mEcho.flDelay == props.mEcho.flDelay && mEaxProps.mEcho.flLRDelay == props.mEcho.flLRDelay && mEaxProps.mEcho.flDamping == props.mEcho.flDamping && mEaxProps.mEcho.flFeedback == props.mEcho.flFeedback && mEaxProps.mEcho.flSpread == props.mEcho.flSpread) return false; - mAlProps.Echo.Delay = mEaxProps.mEcho.flDelay; - mAlProps.Echo.LRDelay = mEaxProps.mEcho.flLRDelay; - mAlProps.Echo.Damping = mEaxProps.mEcho.flDamping; - mAlProps.Echo.Feedback = mEaxProps.mEcho.flFeedback; - mAlProps.Echo.Spread = mEaxProps.mEcho.flSpread; + mEaxProps = props; + + mAlProps.Echo.Delay = props.mEcho.flDelay; + mAlProps.Echo.LRDelay = props.mEcho.flLRDelay; + mAlProps.Echo.Damping = props.mEcho.flDamping; + mAlProps.Echo.Feedback = props.mEcho.flFeedback; + mAlProps.Echo.Spread = props.mEcho.flSpread; return true; } diff --git a/al/effects/equalizer.cpp b/al/effects/equalizer.cpp index 5eea9e6d..7dc703db 100644 --- a/al/effects/equalizer.cpp +++ b/al/effects/equalizer.cpp @@ -322,10 +322,7 @@ template<> template<> bool EqualizerCommitter::commit(const EaxEffectProps &props) { - const auto orig = mEaxProps; - mEaxProps = props; - - if(orig.mType == mEaxProps.mType && mEaxProps.mEqualizer.lLowGain == props.mEqualizer.lLowGain + if(props.mType == mEaxProps.mType && mEaxProps.mEqualizer.lLowGain == props.mEqualizer.lLowGain && mEaxProps.mEqualizer.flLowCutOff == props.mEqualizer.flLowCutOff && mEaxProps.mEqualizer.lMid1Gain == props.mEqualizer.lMid1Gain && mEaxProps.mEqualizer.flMid1Center == props.mEqualizer.flMid1Center @@ -337,16 +334,18 @@ bool EqualizerCommitter::commit(const EaxEffectProps &props) && mEaxProps.mEqualizer.flHighCutOff == props.mEqualizer.flHighCutOff) return false; - mAlProps.Equalizer.LowGain = level_mb_to_gain(static_cast(mEaxProps.mEqualizer.lLowGain)); - mAlProps.Equalizer.LowCutoff = mEaxProps.mEqualizer.flLowCutOff; - mAlProps.Equalizer.Mid1Gain = level_mb_to_gain(static_cast(mEaxProps.mEqualizer.lMid1Gain)); - mAlProps.Equalizer.Mid1Center = mEaxProps.mEqualizer.flMid1Center; - mAlProps.Equalizer.Mid1Width = mEaxProps.mEqualizer.flMid1Width; - mAlProps.Equalizer.Mid2Gain = level_mb_to_gain(static_cast(mEaxProps.mEqualizer.lMid2Gain)); - mAlProps.Equalizer.Mid2Center = mEaxProps.mEqualizer.flMid2Center; - mAlProps.Equalizer.Mid2Width = mEaxProps.mEqualizer.flMid2Width; - mAlProps.Equalizer.HighGain = level_mb_to_gain(static_cast(mEaxProps.mEqualizer.lHighGain)); - mAlProps.Equalizer.HighCutoff = mEaxProps.mEqualizer.flHighCutOff; + mEaxProps = props; + + mAlProps.Equalizer.LowGain = level_mb_to_gain(static_cast(props.mEqualizer.lLowGain)); + mAlProps.Equalizer.LowCutoff = props.mEqualizer.flLowCutOff; + mAlProps.Equalizer.Mid1Gain = level_mb_to_gain(static_cast(props.mEqualizer.lMid1Gain)); + mAlProps.Equalizer.Mid1Center = props.mEqualizer.flMid1Center; + mAlProps.Equalizer.Mid1Width = props.mEqualizer.flMid1Width; + mAlProps.Equalizer.Mid2Gain = level_mb_to_gain(static_cast(props.mEqualizer.lMid2Gain)); + mAlProps.Equalizer.Mid2Center = props.mEqualizer.flMid2Center; + mAlProps.Equalizer.Mid2Width = props.mEqualizer.flMid2Width; + mAlProps.Equalizer.HighGain = level_mb_to_gain(static_cast(props.mEqualizer.lHighGain)); + mAlProps.Equalizer.HighCutoff = props.mEqualizer.flHighCutOff; return true; } diff --git a/al/effects/fshifter.cpp b/al/effects/fshifter.cpp index 983e83ee..949db203 100644 --- a/al/effects/fshifter.cpp +++ b/al/effects/fshifter.cpp @@ -200,15 +200,14 @@ template<> template<> bool FrequencyShifterCommitter::commit(const EaxEffectProps &props) { - const auto orig = mEaxProps; - mEaxProps = props; - - if(orig.mType == mEaxProps.mType + if(props.mType == mEaxProps.mType && mEaxProps.mFrequencyShifter.flFrequency == props.mFrequencyShifter.flFrequency && mEaxProps.mFrequencyShifter.ulLeftDirection == props.mFrequencyShifter.ulLeftDirection && mEaxProps.mFrequencyShifter.ulRightDirection == props.mFrequencyShifter.ulRightDirection) return false; + mEaxProps = props; + auto get_direction = [](unsigned long dir) noexcept { if(dir == EAX_FREQUENCYSHIFTER_DOWN) @@ -218,9 +217,9 @@ bool FrequencyShifterCommitter::commit(const EaxEffectProps &props) return FShifterDirection::Off; }; - mAlProps.Fshifter.Frequency = mEaxProps.mFrequencyShifter.flFrequency; - mAlProps.Fshifter.LeftDirection = get_direction(mEaxProps.mFrequencyShifter.ulLeftDirection); - mAlProps.Fshifter.RightDirection = get_direction(mEaxProps.mFrequencyShifter.ulRightDirection); + mAlProps.Fshifter.Frequency = props.mFrequencyShifter.flFrequency; + mAlProps.Fshifter.LeftDirection = get_direction(props.mFrequencyShifter.ulLeftDirection); + mAlProps.Fshifter.RightDirection = get_direction(props.mFrequencyShifter.ulRightDirection); return true; } diff --git a/al/effects/modulator.cpp b/al/effects/modulator.cpp index 8b6b1045..5f37d08f 100644 --- a/al/effects/modulator.cpp +++ b/al/effects/modulator.cpp @@ -206,15 +206,14 @@ template<> template<> bool ModulatorCommitter::commit(const EaxEffectProps &props) { - const auto orig = mEaxProps; - mEaxProps = props; - - if(orig.mType == mEaxProps.mType + if(props.mType == mEaxProps.mType && mEaxProps.mModulator.flFrequency == props.mModulator.flFrequency && mEaxProps.mModulator.flHighPassCutOff == props.mModulator.flHighPassCutOff && mEaxProps.mModulator.ulWaveform == props.mModulator.ulWaveform) return false; + mEaxProps = props; + auto get_waveform = [](unsigned long form) { if(form == EAX_RINGMODULATOR_SINUSOID) @@ -226,9 +225,9 @@ bool ModulatorCommitter::commit(const EaxEffectProps &props) return ModulatorWaveform::Sinusoid; }; - mAlProps.Modulator.Frequency = mEaxProps.mModulator.flFrequency; - mAlProps.Modulator.HighPassCutoff = mEaxProps.mModulator.flHighPassCutOff; - mAlProps.Modulator.Waveform = get_waveform(mEaxProps.mModulator.ulWaveform); + mAlProps.Modulator.Frequency = props.mModulator.flFrequency; + mAlProps.Modulator.HighPassCutoff = props.mModulator.flHighPassCutOff; + mAlProps.Modulator.Waveform = get_waveform(props.mModulator.ulWaveform); return true; } diff --git a/al/effects/pshifter.cpp b/al/effects/pshifter.cpp index 7c9f0b0e..634eb186 100644 --- a/al/effects/pshifter.cpp +++ b/al/effects/pshifter.cpp @@ -141,16 +141,15 @@ template<> template<> bool PitchShifterCommitter::commit(const EaxEffectProps &props) { - const auto orig = mEaxProps; - mEaxProps = props; - - if(orig.mType == mEaxProps.mType + if(props.mType == mEaxProps.mType && mEaxProps.mPitchShifter.lCoarseTune == props.mPitchShifter.lCoarseTune && mEaxProps.mPitchShifter.lFineTune == props.mPitchShifter.lFineTune) return false; - mAlProps.Pshifter.CoarseTune = static_cast(mEaxProps.mPitchShifter.lCoarseTune); - mAlProps.Pshifter.FineTune = static_cast(mEaxProps.mPitchShifter.lFineTune); + mEaxProps = props; + + mAlProps.Pshifter.CoarseTune = static_cast(mEaxProps.mPitchShifter.lCoarseTune); + mAlProps.Pshifter.FineTune = static_cast(mEaxProps.mPitchShifter.lFineTune); return true; } diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp index 2ba16ebd..7f0be980 100644 --- a/al/effects/reverb.cpp +++ b/al/effects/reverb.cpp @@ -1156,40 +1156,41 @@ bool EaxReverbCommitter::commit(const EAXREVERBPROPERTIES &props) bool EaxReverbCommitter::commit(const EaxEffectProps &props) { - const auto orig = mEaxProps; - mEaxProps = props; - if(orig.mType == mEaxProps.mType && memcmp(&orig.mReverb, &mEaxProps.mReverb, sizeof(mEaxProps.mReverb)) == 0) + if(props.mType == mEaxProps.mType + && memcmp(&props.mReverb, &mEaxProps.mReverb, sizeof(mEaxProps.mReverb)) == 0) return false; - const auto size = mEaxProps.mReverb.flEnvironmentSize; + mEaxProps = props; + + const auto size = props.mReverb.flEnvironmentSize; const auto density = (size * size * size) / 16.0F; mAlProps.Reverb.Density = std::min(density, AL_EAXREVERB_MAX_DENSITY); - mAlProps.Reverb.Diffusion = mEaxProps.mReverb.flEnvironmentDiffusion; - mAlProps.Reverb.Gain = level_mb_to_gain(static_cast(mEaxProps.mReverb.lRoom)); - mAlProps.Reverb.GainHF = level_mb_to_gain(static_cast(mEaxProps.mReverb.lRoomHF)); - mAlProps.Reverb.GainLF = level_mb_to_gain(static_cast(mEaxProps.mReverb.lRoomLF)); - mAlProps.Reverb.DecayTime = mEaxProps.mReverb.flDecayTime; - mAlProps.Reverb.DecayHFRatio = mEaxProps.mReverb.flDecayHFRatio; + mAlProps.Reverb.Diffusion = props.mReverb.flEnvironmentDiffusion; + mAlProps.Reverb.Gain = level_mb_to_gain(static_cast(props.mReverb.lRoom)); + mAlProps.Reverb.GainHF = level_mb_to_gain(static_cast(props.mReverb.lRoomHF)); + mAlProps.Reverb.GainLF = level_mb_to_gain(static_cast(props.mReverb.lRoomLF)); + mAlProps.Reverb.DecayTime = props.mReverb.flDecayTime; + mAlProps.Reverb.DecayHFRatio = props.mReverb.flDecayHFRatio; mAlProps.Reverb.DecayLFRatio = mEaxProps.mReverb.flDecayLFRatio; - mAlProps.Reverb.ReflectionsGain = level_mb_to_gain(static_cast(mEaxProps.mReverb.lReflections)); - mAlProps.Reverb.ReflectionsDelay = mEaxProps.mReverb.flReflectionsDelay; - mAlProps.Reverb.ReflectionsPan[0] = mEaxProps.mReverb.vReflectionsPan.x; - mAlProps.Reverb.ReflectionsPan[1] = mEaxProps.mReverb.vReflectionsPan.y; - mAlProps.Reverb.ReflectionsPan[2] = mEaxProps.mReverb.vReflectionsPan.z; - mAlProps.Reverb.LateReverbGain = level_mb_to_gain(static_cast(mEaxProps.mReverb.lReverb)); - mAlProps.Reverb.LateReverbDelay = mEaxProps.mReverb.flReverbDelay; - mAlProps.Reverb.LateReverbPan[0] = mEaxProps.mReverb.vReverbPan.x; - mAlProps.Reverb.LateReverbPan[1] = mEaxProps.mReverb.vReverbPan.y; - mAlProps.Reverb.LateReverbPan[2] = mEaxProps.mReverb.vReverbPan.z; - mAlProps.Reverb.EchoTime = mEaxProps.mReverb.flEchoTime; - mAlProps.Reverb.EchoDepth = mEaxProps.mReverb.flEchoDepth; - mAlProps.Reverb.ModulationTime = mEaxProps.mReverb.flModulationTime; - mAlProps.Reverb.ModulationDepth = mEaxProps.mReverb.flModulationDepth; - mAlProps.Reverb.AirAbsorptionGainHF = level_mb_to_gain(mEaxProps.mReverb.flAirAbsorptionHF); - mAlProps.Reverb.HFReference = mEaxProps.mReverb.flHFReference; - mAlProps.Reverb.LFReference = mEaxProps.mReverb.flLFReference; - mAlProps.Reverb.RoomRolloffFactor = mEaxProps.mReverb.flRoomRolloffFactor; - mAlProps.Reverb.DecayHFLimit = ((mEaxProps.mReverb.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0); + mAlProps.Reverb.ReflectionsGain = level_mb_to_gain(static_cast(props.mReverb.lReflections)); + mAlProps.Reverb.ReflectionsDelay = props.mReverb.flReflectionsDelay; + mAlProps.Reverb.ReflectionsPan[0] = props.mReverb.vReflectionsPan.x; + mAlProps.Reverb.ReflectionsPan[1] = props.mReverb.vReflectionsPan.y; + mAlProps.Reverb.ReflectionsPan[2] = props.mReverb.vReflectionsPan.z; + mAlProps.Reverb.LateReverbGain = level_mb_to_gain(static_cast(props.mReverb.lReverb)); + mAlProps.Reverb.LateReverbDelay = props.mReverb.flReverbDelay; + mAlProps.Reverb.LateReverbPan[0] = props.mReverb.vReverbPan.x; + mAlProps.Reverb.LateReverbPan[1] = props.mReverb.vReverbPan.y; + mAlProps.Reverb.LateReverbPan[2] = props.mReverb.vReverbPan.z; + mAlProps.Reverb.EchoTime = props.mReverb.flEchoTime; + mAlProps.Reverb.EchoDepth = props.mReverb.flEchoDepth; + mAlProps.Reverb.ModulationTime = props.mReverb.flModulationTime; + mAlProps.Reverb.ModulationDepth = props.mReverb.flModulationDepth; + mAlProps.Reverb.AirAbsorptionGainHF = level_mb_to_gain(props.mReverb.flAirAbsorptionHF); + mAlProps.Reverb.HFReference = props.mReverb.flHFReference; + mAlProps.Reverb.LFReference = props.mReverb.flLFReference; + mAlProps.Reverb.RoomRolloffFactor = props.mReverb.flRoomRolloffFactor; + mAlProps.Reverb.DecayHFLimit = ((props.mReverb.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0); return true; } diff --git a/al/effects/vmorpher.cpp b/al/effects/vmorpher.cpp index 856fc6b3..21ea3680 100644 --- a/al/effects/vmorpher.cpp +++ b/al/effects/vmorpher.cpp @@ -355,10 +355,7 @@ template<> template<> bool VocalMorpherCommitter::commit(const EaxEffectProps &props) { - const auto orig = mEaxProps; - mEaxProps = props; - - if(orig.mType == mEaxProps.mType + if(props.mType == mEaxProps.mType && mEaxProps.mVocalMorpher.ulPhonemeA == props.mVocalMorpher.ulPhonemeA && mEaxProps.mVocalMorpher.lPhonemeACoarseTuning == props.mVocalMorpher.lPhonemeACoarseTuning && mEaxProps.mVocalMorpher.ulPhonemeB == props.mVocalMorpher.ulPhonemeB @@ -367,6 +364,8 @@ bool VocalMorpherCommitter::commit(const EaxEffectProps &props) && mEaxProps.mVocalMorpher.flRate == props.mVocalMorpher.flRate) return false; + mEaxProps = props; + auto get_phoneme = [](unsigned long phoneme) noexcept { #define HANDLE_PHENOME(x) case x: return VMorpherPhenome::x @@ -414,12 +413,12 @@ bool VocalMorpherCommitter::commit(const EaxEffectProps &props) return VMorpherWaveform::Sinusoid; }; - mAlProps.Vmorpher.PhonemeA = get_phoneme(mEaxProps.mVocalMorpher.ulPhonemeA); - mAlProps.Vmorpher.PhonemeACoarseTuning = static_cast(mEaxProps.mVocalMorpher.lPhonemeACoarseTuning); - mAlProps.Vmorpher.PhonemeB = get_phoneme(mEaxProps.mVocalMorpher.ulPhonemeB); - mAlProps.Vmorpher.PhonemeBCoarseTuning = static_cast(mEaxProps.mVocalMorpher.lPhonemeBCoarseTuning); - mAlProps.Vmorpher.Waveform = get_waveform(mEaxProps.mVocalMorpher.ulWaveform); - mAlProps.Vmorpher.Rate = mEaxProps.mVocalMorpher.flRate; + mAlProps.Vmorpher.PhonemeA = get_phoneme(props.mVocalMorpher.ulPhonemeA); + mAlProps.Vmorpher.PhonemeACoarseTuning = static_cast(props.mVocalMorpher.lPhonemeACoarseTuning); + mAlProps.Vmorpher.PhonemeB = get_phoneme(props.mVocalMorpher.ulPhonemeB); + mAlProps.Vmorpher.PhonemeBCoarseTuning = static_cast(props.mVocalMorpher.lPhonemeBCoarseTuning); + mAlProps.Vmorpher.Waveform = get_waveform(props.mVocalMorpher.ulWaveform); + mAlProps.Vmorpher.Rate = props.mVocalMorpher.flRate; return true; } -- cgit v1.2.3