aboutsummaryrefslogtreecommitdiffstats
path: root/al/effects
diff options
context:
space:
mode:
authorBoris I. Bendovsky <[email protected]>2022-02-22 05:39:06 +0200
committerGitHub <[email protected]>2022-02-21 19:39:06 -0800
commit4ffba10d510de4d50b2948920ea4f4c8ea168efa (patch)
tree9750883c4fe23a8aee44a2efabe71795618f2188 /al/effects
parent6c643e59e94ee14d6c8509d46a39ed6a53f72a76 (diff)
Implement EAX v1.0 (#664)
Diffstat (limited to 'al/effects')
-rw-r--r--al/effects/reverb.cpp320
1 files changed, 284 insertions, 36 deletions
diff --git a/al/effects/reverb.cpp b/al/effects/reverb.cpp
index ef23f869..ac0cf17c 100644
--- a/al/effects/reverb.cpp
+++ b/al/effects/reverb.cpp
@@ -11,9 +11,8 @@
#ifdef ALSOFT_EAX
#include <tuple>
-
#include "alnumeric.h"
-
+#include "AL/efx-presets.h"
#include "al/eax_exception.h"
#include "al/eax_utils.h"
#endif // ALSOFT_EAX
@@ -567,6 +566,8 @@ const EffectProps StdReverbEffectProps{genDefaultStdProps()};
#ifdef ALSOFT_EAX
namespace {
+extern const EFXEAXREVERBPROPERTIES eax_efx_reverb_presets[];
+
using EaxReverbEffectDirtyFlagsValue = std::uint_least32_t;
struct EaxReverbEffectDirtyFlags
@@ -599,6 +600,17 @@ struct EaxReverbEffectDirtyFlags
EaxReverbEffectDirtyFlagsValue ulFlags : 1;
}; // EaxReverbEffectDirtyFlags
+using Eax1ReverbEffectDirtyFlagsValue = std::uint_least8_t;
+
+struct Eax1ReverbEffectDirtyFlags
+{
+ using EaxIsBitFieldStruct = bool;
+
+ EaxReverbEffectDirtyFlagsValue environment : 1;
+ EaxReverbEffectDirtyFlagsValue volume : 1;
+ EaxReverbEffectDirtyFlagsValue decay_time : 1;
+ EaxReverbEffectDirtyFlagsValue damping : 1;
+}; // Eax1ReverbEffectDirtyFlags
class EaxReverbEffect final :
public EaxEffect
@@ -611,15 +623,18 @@ public:
const EaxEaxCall& eax_call) override;
private:
+ EAX_REVERBPROPERTIES eax1_{};
EAXREVERBPROPERTIES eax_{};
EAXREVERBPROPERTIES eax_d_{};
+ Eax1ReverbEffectDirtyFlags eax1_dirty_flags_{};
EaxReverbEffectDirtyFlags eax_dirty_flags_{};
+ [[noreturn]] static void eax_fail(const char* message);
void set_eax_defaults();
- void set_efx_density();
+ void set_efx_density_from_environment_size();
void set_efx_diffusion();
@@ -668,6 +683,8 @@ private:
void set_efx_defaults();
+ bool v1_get(const EaxEaxCall& eax_call) const;
+
void get_all(
const EaxEaxCall& eax_call) const;
@@ -676,85 +693,91 @@ private:
const EaxEaxCall& eax_call) const;
- void validate_environment(
+ 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);
+
+ static void validate_environment(
unsigned long ulEnvironment,
int version,
bool is_standalone);
- void validate_environment_size(
+ static void validate_environment_size(
float flEnvironmentSize);
- void validate_environment_diffusion(
+ static void validate_environment_diffusion(
float flEnvironmentDiffusion);
- void validate_room(
+ static void validate_room(
long lRoom);
- void validate_room_hf(
+ static void validate_room_hf(
long lRoomHF);
- void validate_room_lf(
+ static void validate_room_lf(
long lRoomLF);
- void validate_decay_time(
+ static void validate_decay_time(
float flDecayTime);
- void validate_decay_hf_ratio(
+ static void validate_decay_hf_ratio(
float flDecayHFRatio);
- void validate_decay_lf_ratio(
+ static void validate_decay_lf_ratio(
float flDecayLFRatio);
- void validate_reflections(
+ static void validate_reflections(
long lReflections);
- void validate_reflections_delay(
+ static void validate_reflections_delay(
float flReflectionsDelay);
- void validate_reflections_pan(
+ static void validate_reflections_pan(
const EAXVECTOR& vReflectionsPan);
- void validate_reverb(
+ static void validate_reverb(
long lReverb);
- void validate_reverb_delay(
+ static void validate_reverb_delay(
float flReverbDelay);
- void validate_reverb_pan(
+ static void validate_reverb_pan(
const EAXVECTOR& vReverbPan);
- void validate_echo_time(
+ static void validate_echo_time(
float flEchoTime);
- void validate_echo_depth(
+ static void validate_echo_depth(
float flEchoDepth);
- void validate_modulation_time(
+ static void validate_modulation_time(
float flModulationTime);
- void validate_modulation_depth(
+ static void validate_modulation_depth(
float flModulationDepth);
- void validate_air_absorbtion_hf(
+ static void validate_air_absorbtion_hf(
float air_absorbtion_hf);
- void validate_hf_reference(
+ static void validate_hf_reference(
float flHFReference);
- void validate_lf_reference(
+ static void validate_lf_reference(
float flLFReference);
- void validate_room_rolloff_factor(
+ static void validate_room_rolloff_factor(
float flRoomRolloffFactor);
- void validate_flags(
+ static void validate_flags(
unsigned long ulFlags);
- void validate_all(
+ static void validate_all(
const EAX20LISTENERPROPERTIES& all,
int version);
- void validate_all(
+ static void validate_all(
const EAXREVERBPROPERTIES& all,
int version);
@@ -914,6 +937,14 @@ private:
const EaxEaxCall& eax_call);
+ void v1_set_efx();
+ bool v1_set_environment(const EaxEaxCall& eax_call);
+ bool v1_set_volume(const EaxEaxCall& eax_call);
+ bool v1_set_decay_time(const EaxEaxCall& eax_call);
+ bool v1_set_damping(const EaxEaxCall& eax_call);
+ bool v1_set_all(const EaxEaxCall& eax_call);
+ bool v1_set(const EaxEaxCall& eax_call);
+
// [[nodiscard]]
bool apply_deferred();
@@ -950,14 +981,19 @@ bool EaxReverbEffect::dispatch(
return eax_call.is_get() ? get(eax_call) : set(eax_call);
}
+[[noreturn]] void EaxReverbEffect::eax_fail(const char* message)
+{
+ throw EaxReverbEffectException{message};
+}
+
void EaxReverbEffect::set_eax_defaults()
{
+ eax1_ = EAX1REVERB_PRESETS[EAX_ENVIRONMENT_GENERIC];
eax_ = EAXREVERB_PRESETS[EAX_ENVIRONMENT_GENERIC];
-
eax_d_ = eax_;
}
-void EaxReverbEffect::set_efx_density()
+void EaxReverbEffect::set_efx_density_from_environment_size()
{
const auto eax_environment_size = eax_.flEnvironmentSize;
@@ -1180,7 +1216,7 @@ void EaxReverbEffect::set_efx_flags()
void EaxReverbEffect::set_efx_defaults()
{
- set_efx_density();
+ set_efx_density_from_environment_size();
set_efx_diffusion();
set_efx_gain();
set_efx_gain_hf();
@@ -1205,6 +1241,37 @@ void EaxReverbEffect::set_efx_defaults()
set_efx_flags();
}
+bool EaxReverbEffect::v1_get(const EaxEaxCall& eax_call) const
+{
+ switch (eax_call.get_property_id())
+ {
+ case DSPROPERTY_EAX_ALL:
+ eax_call.set_value<EaxReverbEffectException>(eax1_);
+ break;
+
+ case DSPROPERTY_EAX_ENVIRONMENT:
+ eax_call.set_value<EaxReverbEffectException>(eax1_.environment);
+ break;
+
+ case DSPROPERTY_EAX_VOLUME:
+ eax_call.set_value<EaxReverbEffectException>(eax1_.fVolume);
+ break;
+
+ case DSPROPERTY_EAX_DECAYTIME:
+ eax_call.set_value<EaxReverbEffectException>(eax1_.fDecayTime_sec);
+ break;
+
+ case DSPROPERTY_EAX_DAMPING:
+ eax_call.set_value<EaxReverbEffectException>(eax1_.fDamping);
+ break;
+
+ default:
+ eax_fail("Unsupported property id.");
+ }
+
+ return false;
+}
+
void EaxReverbEffect::get_all(
const EaxEaxCall& eax_call) const
{
@@ -1236,6 +1303,9 @@ void EaxReverbEffect::get_all(
bool EaxReverbEffect::get(
const EaxEaxCall& eax_call) const
{
+ if (eax_call.get_version() == 1)
+ return v1_get(eax_call);
+
switch (eax_call.get_property_id())
{
case EAXREVERB_NONE:
@@ -1342,12 +1412,40 @@ bool EaxReverbEffect::get(
break;
default:
- throw EaxReverbEffectException{"Unsupported property id."};
+ eax_fail("Unsupported property id.");
}
return false;
}
+void EaxReverbEffect::v1_validate_environment(unsigned long environment)
+{
+ validate_environment(environment, 1, true);
+}
+
+void EaxReverbEffect::v1_validate_volume(float volume)
+{
+ eax_validate_range<EaxReverbEffectException>("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<EaxReverbEffectException>("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,
@@ -1357,7 +1455,7 @@ void EaxReverbEffect::validate_environment(
"Environment",
ulEnvironment,
EAXREVERB_MINENVIRONMENT,
- (version == 2 || is_standalone) ? EAX20REVERB_MAXENVIRONMENT : EAX30REVERB_MAXENVIRONMENT);
+ (version <= 2 || is_standalone) ? EAX1REVERB_MAXENVIRONMENT : EAX30REVERB_MAXENVIRONMENT);
}
void EaxReverbEffect::validate_environment_size(
@@ -1630,6 +1728,42 @@ void EaxReverbEffect::validate_all(
validate_flags(lReverb.ulFlags);
}
+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)
{
@@ -2200,6 +2334,87 @@ void EaxReverbEffect::defer_all(
}
}
+bool EaxReverbEffect::v1_set_environment(const EaxEaxCall& eax_call)
+{
+ const auto environment = eax_call.get_value<EaxReverbEffectException, const decltype(EAX_REVERBPROPERTIES::environment)>();
+ v1_validate_environment(environment);
+
+ if (eax1_.environment == environment)
+ return false;
+
+ eax1_.environment = environment;
+ v1_set_efx();
+ return true;
+}
+
+bool EaxReverbEffect::v1_set_volume(const EaxEaxCall& eax_call)
+{
+ const auto volume = eax_call.get_value<EaxReverbEffectException, const decltype(EAX_REVERBPROPERTIES::fVolume)>();
+ v1_validate_volume(volume);
+
+ if (eax1_.fVolume == volume)
+ return false;
+
+ eax1_.fVolume = volume;
+ v1_set_efx();
+ return true;
+}
+
+bool EaxReverbEffect::v1_set_decay_time(const EaxEaxCall& eax_call)
+{
+ const auto decay_time = eax_call.get_value<EaxReverbEffectException, const decltype(EAX_REVERBPROPERTIES::fDecayTime_sec)>();
+ v1_validate_decay_time(decay_time);
+
+ if (eax1_.fDecayTime_sec == decay_time)
+ return false;
+
+ eax1_.fDecayTime_sec = decay_time;
+ v1_set_efx();
+ return true;
+}
+
+bool EaxReverbEffect::v1_set_damping(const EaxEaxCall& eax_call)
+{
+ const auto damping = eax_call.get_value<EaxReverbEffectException, const decltype(EAX_REVERBPROPERTIES::fDamping)>();
+ v1_validate_damping(damping);
+
+ if (eax1_.fDamping == damping)
+ return false;
+
+ eax1_.fDamping = damping;
+ v1_set_efx();
+ return true;
+}
+
+bool EaxReverbEffect::v1_set_all(const EaxEaxCall& eax_call)
+{
+ const auto& all = eax_call.get_value<EaxReverbEffectException, const EAX_REVERBPROPERTIES>();
+ v1_validate_all(all);
+
+ if (eax1_ == all)
+ return false;
+
+ eax1_.environment = all.environment;
+ eax1_.fVolume = all.fVolume;
+ eax1_.fDecayTime_sec = all.fDecayTime_sec;
+ eax1_.fDamping = all.fDamping;
+ v1_set_efx();
+ return true;
+}
+
+bool EaxReverbEffect::v1_set(const EaxEaxCall& eax_call)
+{
+ switch (eax_call.get_property_id())
+ {
+ case DSPROPERTY_EAX_ALL: return v1_set_all(eax_call);
+ case DSPROPERTY_EAX_ENVIRONMENT: return v1_set_environment(eax_call);
+ case DSPROPERTY_EAX_VOLUME: return v1_set_volume(eax_call);
+ case DSPROPERTY_EAX_DECAYTIME: return v1_set_decay_time(eax_call);
+ case DSPROPERTY_EAX_DAMPING: return v1_set_damping(eax_call);
+ default: eax_fail("Unsupported property id.");
+ }
+}
+
// [[nodiscard]]
bool EaxReverbEffect::apply_deferred()
{
@@ -2216,7 +2431,7 @@ bool EaxReverbEffect::apply_deferred()
if (eax_dirty_flags_.flEnvironmentSize)
{
- set_efx_density();
+ set_efx_density_from_environment_size();
}
if (eax_dirty_flags_.flEnvironmentDiffusion)
@@ -2338,6 +2553,9 @@ bool EaxReverbEffect::apply_deferred()
bool EaxReverbEffect::set(
const EaxEaxCall& eax_call)
{
+ if (eax_call.get_version() == 1)
+ return v1_set(eax_call);
+
switch (eax_call.get_property_id())
{
case EAXREVERB_NONE:
@@ -2444,7 +2662,7 @@ bool EaxReverbEffect::set(
break;
default:
- throw EaxReverbEffectException{"Unsupported property id."};
+ eax_fail("Unsupported property id.");
}
if (!eax_call.is_deferred())
@@ -2455,6 +2673,36 @@ bool EaxReverbEffect::set(
return false;
}
+const EFXEAXREVERBPROPERTIES eax_efx_reverb_presets[EAX1_ENVIRONMENT_COUNT] =
+{
+ 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
+
} // namespace
EaxEffectUPtr eax_create_eax_reverb_effect()