aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--al/eax/api.cpp3
-rw-r--r--al/eax/api.h27
-rw-r--r--alc/context.cpp901
-rw-r--r--alc/context.h402
4 files changed, 630 insertions, 703 deletions
diff --git a/al/eax/api.cpp b/al/eax/api.cpp
index 1eb5b20d..f0809df1 100644
--- a/al/eax/api.cpp
+++ b/al/eax/api.cpp
@@ -269,7 +269,8 @@ const GUID EAX_RINGMODULATOR_EFFECT =
};
-const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX40_FXSlot0;
+const GUID EAX40CONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX40_FXSlot0;
+const GUID EAX50CONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX50_FXSlot0;
const EAX40ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID = EAX40ACTIVEFXSLOTS
{{
diff --git a/al/eax/api.h b/al/eax/api.h
index a436acb2..3d78c90b 100644
--- a/al/eax/api.h
+++ b/al/eax/api.h
@@ -287,21 +287,19 @@ 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
-};
+constexpr auto HEADPHONES = 0UL;
+constexpr auto SPEAKERS_2 = 1UL;
+constexpr auto SPEAKERS_4 = 2UL;
+constexpr auto SPEAKERS_5 = 3UL; // 5.1 speakers
+constexpr auto SPEAKERS_6 = 4UL; // 6.1 speakers
+constexpr auto SPEAKERS_7 = 5UL; // 7.1 speakers
+
+constexpr auto EAXCONTEXT_MINSPEAKERCONFIG = HEADPHONES;
+constexpr auto EAXCONTEXT_MAXSPEAKERCONFIG = SPEAKERS_7;
// EAX50
-enum : unsigned long {
- EAX_40 = 5, // EAX 4.0
- EAX_50 = 6, // EAX 5.0
-};
+constexpr auto EAX_40 = 5UL; // EAX 4.0
+constexpr auto EAX_50 = 6UL; // EAX 5.0
constexpr auto EAXCONTEXT_MINEAXSESSION = EAX_40;
constexpr auto EAXCONTEXT_MAXEAXSESSION = EAX_50;
@@ -370,7 +368,8 @@ extern const GUID EAXPROPERTYID_EAX50_FXSlot2;
extern const GUID EAXPROPERTYID_EAX40_FXSlot3;
extern const GUID EAXPROPERTYID_EAX50_FXSlot3;
-extern const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID;
+extern const GUID EAX40CONTEXT_DEFAULTPRIMARYFXSLOTID;
+extern const GUID EAX50CONTEXT_DEFAULTPRIMARYFXSLOTID;
enum EAXFXSLOT_PROPERTY : unsigned int {
EAXFXSLOT_PARAMETER = 0,
diff --git a/alc/context.cpp b/alc/context.cpp
index acd21a1d..f2dcb088 100644
--- a/alc/context.cpp
+++ b/alc/context.cpp
@@ -30,11 +30,8 @@
#include "vecmat.h"
#ifdef ALSOFT_EAX
-#include <cassert>
#include <cstring>
-
#include "alstring.h"
-#include "al/eax/exception.h"
#include "al/eax/globals.h"
#endif // ALSOFT_EAX
@@ -257,7 +254,7 @@ void ALCcontext::applyAllUpdates()
}
#ifdef ALSOFT_EAX
- eax_apply_deferred();
+ eax_commit();
#endif
if(std::exchange(mPropsDirty, false))
UpdateContextProps(this);
@@ -273,19 +270,6 @@ void ALCcontext::applyAllUpdates()
#ifdef ALSOFT_EAX
namespace {
-class ContextException :
- public EaxException
-{
-public:
- explicit ContextException(
- const char* message)
- :
- EaxException{"EAX_CONTEXT", message}
- {
- }
-}; // ContextException
-
-
template<typename F>
void ForEachSource(ALCcontext *context, F func)
{
@@ -312,14 +296,11 @@ bool ALCcontext::eax_is_capable() const noexcept
void ALCcontext::eax_uninitialize() noexcept
{
- if (!eax_is_initialized_)
- {
+ if(!eax_is_initialized_)
return;
- }
- eax_is_initialized_ = true;
+ eax_is_initialized_ = false;
eax_is_tried_ = false;
-
eax_fx_slots_.uninitialize();
}
@@ -337,26 +318,31 @@ ALenum ALCcontext::eax_eax_set(
property_source_id,
property_value,
property_value_size);
- eax_version_ = call.get_version();
- eax_initialize(call);
+ const auto eax_version = call.get_version();
- switch (call.get_property_set_id())
- {
- case EaxCallPropertySetId::context:
- eax_set(call);
- break;
-
- case EaxCallPropertySetId::fx_slot:
- case EaxCallPropertySetId::fx_slot_effect:
- eax_dispatch_fx_slot(call);
- break;
+ if(eax_version != eax_version_) {
+ eax123_.df = ~EaxDirtyFlags();
+ eax4_.df = ~EaxDirtyFlags();
+ eax5_.df = ~EaxDirtyFlags();
+ }
- case EaxCallPropertySetId::source:
- eax_dispatch_source(call);
- break;
+ eax_version_ = eax_version;
+ eax_initialize(call);
- default:
- eax_fail("Unsupported property set id.");
+ switch(call.get_property_set_id())
+ {
+ case EaxCallPropertySetId::context:
+ eax_set(call);
+ break;
+ case EaxCallPropertySetId::fx_slot:
+ case EaxCallPropertySetId::fx_slot_effect:
+ eax_dispatch_fx_slot(call);
+ break;
+ case EaxCallPropertySetId::source:
+ eax_dispatch_source(call);
+ break;
+ default:
+ eax_fail_unknown_property_set_id();
}
if(!call.is_deferred() && !mDeferUpdates)
@@ -382,23 +368,20 @@ ALenum ALCcontext::eax_eax_get(
eax_version_ = call.get_version();
eax_initialize(call);
- switch (call.get_property_set_id())
+ switch(call.get_property_set_id())
{
- case EaxCallPropertySetId::context:
- eax_get(call);
- break;
-
- case EaxCallPropertySetId::fx_slot:
- case EaxCallPropertySetId::fx_slot_effect:
- eax_dispatch_fx_slot(call);
- break;
-
- case EaxCallPropertySetId::source:
- eax_dispatch_source(call);
- break;
-
- default:
- eax_fail("Unsupported property set id.");
+ case EaxCallPropertySetId::context:
+ eax_get(call);
+ break;
+ case EaxCallPropertySetId::fx_slot:
+ case EaxCallPropertySetId::fx_slot_effect:
+ eax_dispatch_fx_slot(call);
+ break;
+ case EaxCallPropertySetId::source:
+ eax_dispatch_source(call);
+ break;
+ default:
+ eax_fail_unknown_property_set_id();
}
return AL_NO_ERROR;
@@ -420,19 +403,35 @@ void ALCcontext::eax_set_last_error() noexcept
eax_last_error_ = EAXERR_INVALID_OPERATION;
}
-[[noreturn]]
-void ALCcontext::eax_fail(
- const char* message)
+[[noreturn]] void ALCcontext::eax_fail(const char* message)
{
throw ContextException{message};
}
+[[noreturn]] void ALCcontext::eax_fail_unknown_property_set_id()
+{
+ eax_fail("Unknown property ID.");
+}
+
+[[noreturn]] void ALCcontext::eax_fail_unknown_primary_fx_slot_id()
+{
+ eax_fail("Unknown primary FX Slot ID.");
+}
+
+[[noreturn]] void ALCcontext::eax_fail_unknown_property_id()
+{
+ eax_fail("Unknown property ID.");
+}
+
+[[noreturn]] void ALCcontext::eax_fail_unknown_version()
+{
+ eax_fail("Unknown version.");
+}
+
void ALCcontext::eax_initialize_extensions()
{
- if (!eax_g_is_enabled)
- {
+ if(!eax_g_is_enabled)
return;
- }
const auto string_max_capacity =
std::strlen(mExtensionList) + 1 +
@@ -441,13 +440,11 @@ void ALCcontext::eax_initialize_extensions()
std::strlen(eax3_ext_name) + 1 +
std::strlen(eax4_ext_name) + 1 +
std::strlen(eax5_ext_name) + 1 +
- std::strlen(eax_x_ram_ext_name) + 1 +
- 0;
+ std::strlen(eax_x_ram_ext_name) + 1;
eax_extension_list_.reserve(string_max_capacity);
- if (eax_is_capable())
- {
+ if(eax_is_capable()) {
eax_extension_list_ += eax1_ext_name;
eax_extension_list_ += ' ';
@@ -473,31 +470,26 @@ void ALCcontext::eax_initialize_extensions()
void ALCcontext::eax_initialize(const EaxCall& call)
{
- if (eax_is_initialized_)
- {
+ if(eax_is_initialized_)
return;
- }
- if (eax_is_tried_)
- {
+ if(eax_is_tried_)
eax_fail("No EAX.");
- }
eax_is_tried_ = true;
- if (!eax_g_is_enabled)
- {
+ if(!eax_g_is_enabled)
eax_fail("EAX disabled by a configuration.");
- }
eax_ensure_compatibility();
eax_set_defaults();
- eax_set_air_absorbtion_hf();
+ eax_context_commit_air_absorbtion_hf();
eax_update_speaker_configuration();
eax_initialize_fx_slots(call);
eax_initialize_sources();
eax_is_initialized_ = true;
+ mPropsDirty = true;
if(!mDeferUpdates)
applyAllUpdates();
@@ -510,10 +502,8 @@ bool ALCcontext::eax_has_no_default_effect_slot() const noexcept
void ALCcontext::eax_ensure_no_default_effect_slot() const
{
- if (!eax_has_no_default_effect_slot())
- {
+ 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
@@ -523,10 +513,8 @@ bool ALCcontext::eax_has_enough_aux_sends() const noexcept
void ALCcontext::eax_ensure_enough_aux_sends() const
{
- if (!eax_has_enough_aux_sends())
- {
+ if(!eax_has_enough_aux_sends())
eax_fail("Not enough aux sends.");
- }
}
void ALCcontext::eax_ensure_compatibility()
@@ -580,27 +568,56 @@ void ALCcontext::eax_set_last_error_defaults() noexcept
eax_last_error_ = EAX_OK;
}
-void ALCcontext::eax_set_session_defaults() noexcept
+void ALCcontext::eax_session_set_defaults() noexcept
{
- eax_session_.ulEAXVersion = EAXCONTEXT_MINEAXSESSION;
+ eax_session_.ulEAXVersion = EAXCONTEXT_DEFAULTEAXSESSION;
eax_session_.ulMaxActiveSends = EAXCONTEXT_DEFAULTMAXACTIVESENDS;
}
-void ALCcontext::eax_set_context_defaults() noexcept
+void ALCcontext::eax4_context_set_defaults(Eax4Props& props) noexcept
+{
+ props.guidPrimaryFXSlotID = EAX40CONTEXT_DEFAULTPRIMARYFXSLOTID;
+ props.flDistanceFactor = EAXCONTEXT_DEFAULTDISTANCEFACTOR;
+ props.flAirAbsorptionHF = EAXCONTEXT_DEFAULTAIRABSORPTIONHF;
+ props.flHFReference = EAXCONTEXT_DEFAULTHFREFERENCE;
+}
+
+void ALCcontext::eax4_context_set_defaults(Eax4State& state) noexcept
+{
+ eax4_context_set_defaults(state.i);
+ state.d = state.i;
+ state.df = ~EaxDirtyFlags{};
+}
+
+void ALCcontext::eax5_context_set_defaults(Eax5Props& props) noexcept
{
- eax_.context.guidPrimaryFXSlotID = EAXCONTEXT_DEFAULTPRIMARYFXSLOTID;
- eax_.context.flDistanceFactor = EAXCONTEXT_DEFAULTDISTANCEFACTOR;
- eax_.context.flAirAbsorptionHF = EAXCONTEXT_DEFAULTAIRABSORPTIONHF;
- eax_.context.flHFReference = EAXCONTEXT_DEFAULTHFREFERENCE;
+ props.guidPrimaryFXSlotID = EAX50CONTEXT_DEFAULTPRIMARYFXSLOTID;
+ props.flDistanceFactor = EAXCONTEXT_DEFAULTDISTANCEFACTOR;
+ props.flAirAbsorptionHF = EAXCONTEXT_DEFAULTAIRABSORPTIONHF;
+ props.flHFReference = EAXCONTEXT_DEFAULTHFREFERENCE;
+ props.flMacroFXFactor = EAXCONTEXT_DEFAULTMACROFXFACTOR;
+}
+
+void ALCcontext::eax5_context_set_defaults(Eax5State& state) noexcept
+{
+ eax5_context_set_defaults(state.i);
+ state.d = state.i;
+ state.df = ~EaxDirtyFlags{};
+}
+
+void ALCcontext::eax_context_set_defaults() noexcept
+{
+ eax5_context_set_defaults(eax123_);
+ eax4_context_set_defaults(eax4_);
+ eax5_context_set_defaults(eax5_);
+ eax_ = eax5_.i;
}
void ALCcontext::eax_set_defaults() noexcept
{
eax_set_last_error_defaults();
- eax_set_session_defaults();
- eax_set_context_defaults();
-
- eax_d_ = eax_;
+ eax_session_set_defaults();
+ eax_context_set_defaults();
}
void ALCcontext::eax_dispatch_fx_slot(const EaxCall& call)
@@ -629,152 +646,128 @@ void ALCcontext::eax_dispatch_source(const EaxCall& call)
source->eax_dispatch(call);
}
-void ALCcontext::eax_get_primary_fx_slot_id(const EaxCall& call)
+void ALCcontext::eax_get_misc(const EaxCall& call)
{
- call.set_value<ContextException>(eax_.context.guidPrimaryFXSlotID);
-}
-
-void ALCcontext::eax_get_distance_factor(const EaxCall& call)
-{
- call.set_value<ContextException>(eax_.context.flDistanceFactor);
-}
-
-void ALCcontext::eax_get_air_absorption_hf(const EaxCall& call)
-{
- call.set_value<ContextException>(eax_.context.flAirAbsorptionHF);
-}
-
-void ALCcontext::eax_get_hf_reference(const EaxCall& call)
-{
- call.set_value<ContextException>(eax_.context.flHFReference);
-}
-
-void ALCcontext::eax_get_last_error(const EaxCall& call)
-{
- const auto eax_last_error = eax_last_error_;
- eax_last_error_ = EAX_OK;
- call.set_value<ContextException>(eax_last_error);
-}
-
-void ALCcontext::eax_get_speaker_config(const EaxCall& call)
-{
- call.set_value<ContextException>(eax_speaker_config_);
-}
-
-void ALCcontext::eax_get_session(const EaxCall& call)
-{
- call.set_value<ContextException>(eax_session_);
+ switch(call.get_property_id())
+ {
+ case EAXCONTEXT_NONE:
+ break;
+ case EAXCONTEXT_LASTERROR:
+ call.set_value<ContextException>(eax_last_error_);
+ break;
+ case EAXCONTEXT_SPEAKERCONFIG:
+ call.set_value<ContextException>(eax_speaker_config_);
+ break;
+ case EAXCONTEXT_EAXSESSION:
+ call.set_value<ContextException>(eax_session_);
+ break;
+ default:
+ eax_fail_unknown_property_id();
+ }
}
-void ALCcontext::eax_get_macro_fx_factor(const EaxCall& call)
+void ALCcontext::eax4_get(const EaxCall& call, const Eax4Props& props)
{
- call.set_value<ContextException>(eax_.context.flMacroFXFactor);
+ switch(call.get_property_id())
+ {
+ case EAXCONTEXT_ALLPARAMETERS:
+ call.set_value<ContextException>(props);
+ break;
+ case EAXCONTEXT_PRIMARYFXSLOTID:
+ call.set_value<ContextException>(props.guidPrimaryFXSlotID);
+ break;
+ case EAXCONTEXT_DISTANCEFACTOR:
+ call.set_value<ContextException>(props.flDistanceFactor);
+ break;
+ case EAXCONTEXT_AIRABSORPTIONHF:
+ call.set_value<ContextException>(props.flAirAbsorptionHF);
+ break;
+ case EAXCONTEXT_HFREFERENCE:
+ call.set_value<ContextException>(props.flHFReference);
+ break;
+ default:
+ eax_get_misc(call);
+ break;
+ }
}
-void ALCcontext::eax_get_context_all(const EaxCall& call)
+void ALCcontext::eax5_get(const EaxCall& call, const Eax5Props& props)
{
- switch (call.get_version())
+ switch(call.get_property_id())
{
- case 4:
- call.set_value<ContextException>(static_cast<const EAX40CONTEXTPROPERTIES&>(eax_.context));
- break;
-
- case 5:
- call.set_value<ContextException>(static_cast<const EAX50CONTEXTPROPERTIES&>(eax_.context));
- break;
-
- default:
- eax_fail("Unsupported EAX version.");
+ case EAXCONTEXT_ALLPARAMETERS:
+ call.set_value<ContextException>(props);
+ break;
+ case EAXCONTEXT_PRIMARYFXSLOTID:
+ call.set_value<ContextException>(props.guidPrimaryFXSlotID);
+ break;
+ case EAXCONTEXT_DISTANCEFACTOR:
+ call.set_value<ContextException>(props.flDistanceFactor);
+ break;
+ case EAXCONTEXT_AIRABSORPTIONHF:
+ call.set_value<ContextException>(props.flAirAbsorptionHF);
+ break;
+ case EAXCONTEXT_HFREFERENCE:
+ call.set_value<ContextException>(props.flHFReference);
+ break;
+ case EAXCONTEXT_MACROFXFACTOR:
+ call.set_value<ContextException>(props.flMacroFXFactor);
+ break;
+ default:
+ eax_get_misc(call);
+ break;
}
}
void ALCcontext::eax_get(const EaxCall& call)
{
- switch (call.get_property_id())
+ switch(call.get_version())
{
- case EAXCONTEXT_NONE:
- break;
-
- case EAXCONTEXT_ALLPARAMETERS:
- eax_get_context_all(call);
- break;
-
- case EAXCONTEXT_PRIMARYFXSLOTID:
- eax_get_primary_fx_slot_id(call);
- break;
-
- case EAXCONTEXT_DISTANCEFACTOR:
- eax_get_distance_factor(call);
- break;
-
- case EAXCONTEXT_AIRABSORPTIONHF:
- eax_get_air_absorption_hf(call);
- break;
-
- case EAXCONTEXT_HFREFERENCE:
- eax_get_hf_reference(call);
- break;
-
- case EAXCONTEXT_LASTERROR:
- eax_get_last_error(call);
- break;
-
- case EAXCONTEXT_SPEAKERCONFIG:
- eax_get_speaker_config(call);
- break;
-
- case EAXCONTEXT_EAXSESSION:
- eax_get_session(call);
- break;
-
- case EAXCONTEXT_MACROFXFACTOR:
- eax_get_macro_fx_factor(call);
- break;
-
- default:
- eax_fail("Unsupported property id.");
+ case 4: eax4_get(call, eax4_.i); break;
+ case 5: eax5_get(call, eax5_.i); break;
+ default: eax_fail_unknown_version();
}
}
-void ALCcontext::eax_set_primary_fx_slot_id()
+void ALCcontext::eax_context_commit_primary_fx_slot_id()
{
- eax_primary_fx_slot_index_ = eax_.context.guidPrimaryFXSlotID;
+ eax_primary_fx_slot_index_ = eax_.guidPrimaryFXSlotID;
}
-void ALCcontext::eax_set_distance_factor()
+void ALCcontext::eax_context_commit_distance_factor()
{
- mListener.mMetersPerUnit = eax_.context.flDistanceFactor;
+ if(mListener.mMetersPerUnit == eax_.flDistanceFactor)
+ return;
+
+ mListener.mMetersPerUnit = eax_.flDistanceFactor;
mPropsDirty = true;
}
-void ALCcontext::eax_set_air_absorbtion_hf()
+void ALCcontext::eax_context_commit_air_absorbtion_hf()
{
- mAirAbsorptionGainHF = level_mb_to_gain(eax_.context.flAirAbsorptionHF);
+ const auto new_value = level_mb_to_gain(eax_.flAirAbsorptionHF);
+
+ if(mAirAbsorptionGainHF == new_value)
+ return;
+
+ mAirAbsorptionGainHF = new_value;
mPropsDirty = true;
}
-void ALCcontext::eax_set_hf_reference()
+void ALCcontext::eax_context_commit_hf_reference()
{
// TODO
}
-void ALCcontext::eax_set_macro_fx_factor()
+void ALCcontext::eax_context_commit_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(const EaxCall& call)
{
eax_fx_slots_.initialize(call, *this);
- eax_primary_fx_slot_index_ = eax_.context.guidPrimaryFXSlotID;
+ eax_primary_fx_slot_index_ = eax_.guidPrimaryFXSlotID;
}
void ALCcontext::eax_initialize_sources()
@@ -793,408 +786,250 @@ void ALCcontext::eax_update_sources()
ForEachSource(this, update_source);
}
-void ALCcontext::eax_validate_primary_fx_slot_id(
- const GUID& primary_fx_slot_id)
+void ALCcontext::eax_set_misc(const EaxCall& call)
{
- 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)
+ switch(call.get_property_id())
{
- eax_fail("Unsupported primary FX slot id.");
+ case EAXCONTEXT_NONE:
+ break;
+ case EAXCONTEXT_SPEAKERCONFIG:
+ eax_set<Eax5SpeakerConfigValidator>(call, eax_speaker_config_);
+ break;
+ case EAXCONTEXT_EAXSESSION:
+ eax_set<Eax5SessionAllValidator>(call, eax_session_);
+ break;
+ default:
+ eax_fail_unknown_property_id();
}
}
-void ALCcontext::eax_validate_distance_factor(
- float distance_factor)
+void ALCcontext::eax4_defer_all(const EaxCall& call, Eax4State& state)
{
- eax_validate_range<ContextException>(
- "Distance Factor",
- distance_factor,
- EAXCONTEXT_MINDISTANCEFACTOR,
- EAXCONTEXT_MAXDISTANCEFACTOR);
-}
+ const auto& src = call.get_value<ContextException, const EAX40CONTEXTPROPERTIES>();
+ Eax4AllValidator{}(src);
+ const auto& dst_i = state.i;
+ auto& dst_d = state.d;
+ dst_d = src;
-void ALCcontext::eax_validate_air_absorption_hf(
- float air_absorption_hf)
-{
- eax_validate_range<ContextException>(
- "Air Absorption HF",
- air_absorption_hf,
- EAXCONTEXT_MINAIRABSORPTIONHF,
- EAXCONTEXT_MAXAIRABSORPTIONHF);
-}
+ if(dst_i.guidPrimaryFXSlotID != dst_d.guidPrimaryFXSlotID)
+ state.df |= eax_primary_fx_slot_id_dirty_bit;
-void ALCcontext::eax_validate_hf_reference(
- float hf_reference)
-{
- eax_validate_range<ContextException>(
- "HF Reference",
- hf_reference,
- EAXCONTEXT_MINHFREFERENCE,
- EAXCONTEXT_MAXHFREFERENCE);
-}
+ if(dst_i.flDistanceFactor != dst_d.flDistanceFactor)
+ state.df |= eax_distance_factor_dirty_bit;
-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.");
- }
+ if(dst_i.flAirAbsorptionHF != dst_d.flAirAbsorptionHF)
+ state.df |= eax_air_absorption_hf_dirty_bit;
+
+ if(dst_i.flHFReference != dst_d.flHFReference)
+ state.df |= eax_hf_reference_dirty_bit;
}
-void ALCcontext::eax_validate_session_eax_version(
- unsigned long eax_version)
+void ALCcontext::eax4_defer(const EaxCall& call, Eax4State& state)
{
- switch (eax_version)
+ switch(call.get_property_id())
{
- case EAX_40:
- case EAX_50:
- break;
-
- default:
- eax_fail("Unsupported session EAX version.");
+ case EAXCONTEXT_ALLPARAMETERS:
+ eax4_defer_all(call, state);
+ break;
+ case EAXCONTEXT_PRIMARYFXSLOTID:
+ eax_defer<Eax4PrimaryFxSlotIdValidator, eax_primary_fx_slot_id_dirty_bit>(
+ call, state, &EAX40CONTEXTPROPERTIES::guidPrimaryFXSlotID);
+ break;
+ case EAXCONTEXT_DISTANCEFACTOR:
+ eax_defer<Eax4DistanceFactorValidator, eax_distance_factor_dirty_bit>(
+ call, state, &EAX40CONTEXTPROPERTIES::flDistanceFactor);
+ break;
+ case EAXCONTEXT_AIRABSORPTIONHF:
+ eax_defer<Eax4AirAbsorptionHfValidator, eax_air_absorption_hf_dirty_bit>(
+ call, state, &EAX40CONTEXTPROPERTIES::flAirAbsorptionHF);
+ break;
+ case EAXCONTEXT_HFREFERENCE:
+ eax_defer<Eax4HfReferenceValidator, eax_hf_reference_dirty_bit>(
+ call, state, &EAX40CONTEXTPROPERTIES::flHFReference);
+ break;
+ default:
+ eax_set_misc(call);
+ break;
}
}
-void ALCcontext::eax_validate_session_max_active_sends(
- unsigned long max_active_sends)
-{
- eax_validate_range<ContextException>(
- "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<ContextException>(
- "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<const EAX40CONTEXTPROPERTIES>(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)
+void ALCcontext::eax5_defer_all(const EaxCall& call, Eax5State& state)
{
- eax_d_.context.flDistanceFactor = distance_factor;
+ const auto& src = call.get_value<ContextException, const EAX50CONTEXTPROPERTIES>();
+ Eax4AllValidator{}(src);
+ const auto& dst_i = state.i;
+ auto& dst_d = state.d;
+ dst_d = src;
- eax_context_dirty_flags_.flDistanceFactor =
- (eax_.context.flDistanceFactor != eax_d_.context.flDistanceFactor);
-}
+ if(dst_i.guidPrimaryFXSlotID != dst_d.guidPrimaryFXSlotID)
+ state.df |= eax_primary_fx_slot_id_dirty_bit;
-void ALCcontext::eax_defer_air_absorption_hf(
- float air_absorption_hf)
-{
- eax_d_.context.flAirAbsorptionHF = air_absorption_hf;
+ if(dst_i.flDistanceFactor != dst_d.flDistanceFactor)
+ state.df |= eax_distance_factor_dirty_bit;
- eax_context_dirty_flags_.flAirAbsorptionHF =
- (eax_.context.flAirAbsorptionHF != eax_d_.context.flAirAbsorptionHF);
-}
+ if(dst_i.flAirAbsorptionHF != dst_d.flAirAbsorptionHF)
+ state.df |= eax_air_absorption_hf_dirty_bit;
-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;
+ if(dst_i.flHFReference != dst_d.flHFReference)
+ state.df |= eax_hf_reference_dirty_bit;
- eax_context_dirty_flags_.flMacroFXFactor =
- (eax_.context.flMacroFXFactor != eax_d_.context.flMacroFXFactor);
+ if(dst_i.flMacroFXFactor != dst_d.flMacroFXFactor)
+ state.df |= eax_macro_fx_factor_dirty_bit;
}
-void ALCcontext::eax_defer_context_all(
- const EAX40CONTEXTPROPERTIES& context_all)
+void ALCcontext::eax5_defer(const EaxCall& call, Eax5State& state)
{
- 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<const EAX40CONTEXTPROPERTIES&>(context_all));
- eax_defer_macro_fx_factor(context_all.flMacroFXFactor);
-}
-
-void ALCcontext::eax_defer_context_all(const EaxCall& call)
-{
- switch(call.get_version())
+ switch(call.get_property_id())
{
- case 4:
- {
- const auto& context_all =
- call.get_value<ContextException, EAX40CONTEXTPROPERTIES>();
-
- eax_validate_context_all(context_all);
- eax_defer_context_all(context_all);
- }
+ case EAXCONTEXT_ALLPARAMETERS:
+ eax5_defer_all(call, state);
break;
-
- case 5:
- {
- const auto& context_all =
- call.get_value<ContextException, EAX50CONTEXTPROPERTIES>();
-
- eax_validate_context_all(context_all);
- eax_defer_context_all(context_all);
- }
+ case EAXCONTEXT_PRIMARYFXSLOTID:
+ eax_defer<Eax5PrimaryFxSlotIdValidator, eax_primary_fx_slot_id_dirty_bit>(
+ call, state, &EAX50CONTEXTPROPERTIES::guidPrimaryFXSlotID);
+ break;
+ case EAXCONTEXT_DISTANCEFACTOR:
+ eax_defer<Eax4DistanceFactorValidator, eax_distance_factor_dirty_bit>(
+ call, state, &EAX50CONTEXTPROPERTIES::flDistanceFactor);
+ break;
+ case EAXCONTEXT_AIRABSORPTIONHF:
+ eax_defer<Eax4AirAbsorptionHfValidator, eax_air_absorption_hf_dirty_bit>(
+ call, state, &EAX50CONTEXTPROPERTIES::flAirAbsorptionHF);
+ break;
+ case EAXCONTEXT_HFREFERENCE:
+ eax_defer<Eax4HfReferenceValidator, eax_hf_reference_dirty_bit>(
+ call, state, &EAX50CONTEXTPROPERTIES::flHFReference);
+ break;
+ case EAXCONTEXT_MACROFXFACTOR:
+ eax_defer<Eax5MacroFxFactorValidator, eax_macro_fx_factor_dirty_bit>(
+ call, state, &EAX50CONTEXTPROPERTIES::flMacroFXFactor);
break;
-
default:
- eax_fail("Unsupported EAX version.");
+ eax_set_misc(call);
+ break;
}
}
-void ALCcontext::eax_defer_primary_fx_slot_id(const EaxCall& call)
-{
- const auto& primary_fx_slot_id =
- call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::guidPrimaryFXSlotID)>();
-
- 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 EaxCall& call)
+void ALCcontext::eax_set(const EaxCall& call)
{
- const auto& distance_factor =
- call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::flDistanceFactor)>();
-
- eax_validate_distance_factor(distance_factor);
- eax_defer_distance_factor(distance_factor);
+ switch(call.get_version())
+ {
+ case 4: eax4_defer(call, eax4_); break;
+ case 5: eax5_defer(call, eax5_); break;
+ default: eax_fail_unknown_version();
+ }
}
-void ALCcontext::eax_defer_air_absorption_hf(const EaxCall& call)
+void ALCcontext::eax4_context_commit(Eax4State& state, EaxDirtyFlags& dst_df)
{
- const auto& air_absorption_hf =
- call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::flAirAbsorptionHF)>();
+ if(state.df == EaxDirtyFlags{})
+ return;
- eax_validate_air_absorption_hf(air_absorption_hf);
- eax_defer_air_absorption_hf(air_absorption_hf);
-}
+ eax_context_commit_property<eax_primary_fx_slot_id_dirty_bit>(
+ state, dst_df, &EAX40CONTEXTPROPERTIES::guidPrimaryFXSlotID);
+ eax_context_commit_property<eax_distance_factor_dirty_bit>(
+ state, dst_df, &EAX40CONTEXTPROPERTIES::flDistanceFactor);
+ eax_context_commit_property<eax_air_absorption_hf_dirty_bit>(
+ state, dst_df, &EAX40CONTEXTPROPERTIES::flAirAbsorptionHF);
+ eax_context_commit_property<eax_hf_reference_dirty_bit>(
+ state, dst_df, &EAX40CONTEXTPROPERTIES::flHFReference);
-void ALCcontext::eax_defer_hf_reference(const EaxCall& call)
-{
- const auto& hf_reference =
- call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::flHFReference)>();
-
- eax_validate_hf_reference(hf_reference);
- eax_defer_hf_reference(hf_reference);
+ state.df = EaxDirtyFlags{};
}
-void ALCcontext::eax_set_session(const EaxCall& call)
+void ALCcontext::eax5_context_commit(Eax5State& state, EaxDirtyFlags& dst_df)
{
- const auto& eax_session =
- call.get_value<ContextException, const EAXSESSIONPROPERTIES>();
+ if(state.df == EaxDirtyFlags{})
+ return;
- eax_validate_session(eax_session);
+ eax_context_commit_property<eax_primary_fx_slot_id_dirty_bit>(
+ state, dst_df, &EAX50CONTEXTPROPERTIES::guidPrimaryFXSlotID);
+ eax_context_commit_property<eax_distance_factor_dirty_bit>(
+ state, dst_df, &EAX50CONTEXTPROPERTIES::flDistanceFactor);
+ eax_context_commit_property<eax_air_absorption_hf_dirty_bit>(
+ state, dst_df, &EAX50CONTEXTPROPERTIES::flAirAbsorptionHF);
+ eax_context_commit_property<eax_hf_reference_dirty_bit>(
+ state, dst_df, &EAX50CONTEXTPROPERTIES::flHFReference);
+ eax_context_commit_property<eax_macro_fx_factor_dirty_bit>(
+ state, dst_df, &EAX50CONTEXTPROPERTIES::flMacroFXFactor);
- eax_session_ = eax_session;
+ state.df = EaxDirtyFlags{};
}
-void ALCcontext::eax_defer_macro_fx_factor(const EaxCall& call)
+void ALCcontext::eax_context_commit()
{
- const auto& macro_fx_factor =
- call.get_value<ContextException, const decltype(EAX50CONTEXTPROPERTIES::flMacroFXFactor)>();
-
- eax_validate_macro_fx_factor(macro_fx_factor);
- eax_defer_macro_fx_factor(macro_fx_factor);
-}
+ auto dst_df = EaxDirtyFlags{};
-void ALCcontext::eax_set(const EaxCall& call)
-{
- switch (call.get_property_id())
+ switch(eax_version_)
{
- case EAXCONTEXT_NONE:
- break;
-
- case EAXCONTEXT_ALLPARAMETERS:
- eax_defer_context_all(call);
- break;
-
- case EAXCONTEXT_PRIMARYFXSLOTID:
- eax_defer_primary_fx_slot_id(call);
- break;
-
- case EAXCONTEXT_DISTANCEFACTOR:
- eax_defer_distance_factor(call);
- break;
-
- case EAXCONTEXT_AIRABSORPTIONHF:
- eax_defer_air_absorption_hf(call);
- break;
-
- case EAXCONTEXT_HFREFERENCE:
- eax_defer_hf_reference(call);
- break;
-
- case EAXCONTEXT_LASTERROR:
- eax_fail("Last error is read-only.");
-
- case EAXCONTEXT_SPEAKERCONFIG:
- eax_fail("Speaker configuration is read-only.");
-
- case EAXCONTEXT_EAXSESSION:
- eax_set_session(call);
- break;
-
- case EAXCONTEXT_MACROFXFACTOR:
- eax_defer_macro_fx_factor(call);
- break;
-
- default:
- eax_fail("Unsupported property id.");
+ case 1:
+ case 2:
+ case 3:
+ eax5_context_commit(eax123_, dst_df);
+ break;
+ case 4:
+ eax4_context_commit(eax4_, dst_df);
+ break;
+ case 5:
+ eax5_context_commit(eax5_, dst_df);
+ break;
+ default:
+ eax_fail_unknown_version();
}
-}
-void ALCcontext::eax_apply_deferred()
-{
- if (eax_context_dirty_flags_ == ContextDirtyFlags{})
- {
+ if(dst_df == EaxDirtyFlags{})
return;
- }
- eax_ = eax_d_;
+ if((dst_df & eax_primary_fx_slot_id_dirty_bit) != EaxDirtyFlags{})
+ eax_context_commit_primary_fx_slot_id();
- if (eax_context_dirty_flags_.guidPrimaryFXSlotID)
- {
- eax_set_primary_fx_slot_id();
- }
+ if((dst_df & eax_distance_factor_dirty_bit) != EaxDirtyFlags{})
+ eax_context_commit_distance_factor();
- if (eax_context_dirty_flags_.flDistanceFactor)
- {
- eax_set_distance_factor();
- }
+ if((dst_df & eax_air_absorption_hf_dirty_bit) != EaxDirtyFlags{})
+ eax_context_commit_air_absorbtion_hf();
- if (eax_context_dirty_flags_.flAirAbsorptionHF)
- {
- eax_set_air_absorbtion_hf();
- }
+ if((dst_df & eax_hf_reference_dirty_bit) != EaxDirtyFlags{})
+ eax_context_commit_hf_reference();
- if (eax_context_dirty_flags_.flHFReference)
- {
- eax_set_hf_reference();
- }
+ if((dst_df & eax_macro_fx_factor_dirty_bit) != EaxDirtyFlags{})
+ eax_context_commit_macro_fx_factor();
- if (eax_context_dirty_flags_.flMacroFXFactor)
- {
- eax_set_macro_fx_factor();
- }
-
- if (eax_context_dirty_flags_.guidPrimaryFXSlotID)
- {
+ if((dst_df & eax_primary_fx_slot_id_dirty_bit) != EaxDirtyFlags{})
eax_update_sources();
- }
-
- eax_context_dirty_flags_ = ContextDirtyFlags{};
}
-
-namespace
+void ALCcontext::eax_commit()
{
+ eax_context_commit();
+}
+namespace {
-class EaxSetException :
- public EaxException
-{
+class EaxSetException : public EaxException {
public:
- explicit EaxSetException(
- const char* message)
- :
- EaxException{"EAX_SET", message}
- {
- }
-}; // EaxSetException
-
+ explicit EaxSetException(const char* message)
+ : EaxException{"EAX_SET", message}
+ {}
+};
-[[noreturn]]
-void eax_fail_set(
- const char* message)
+[[noreturn]] void eax_fail_set(const char* message)
{
throw EaxSetException{message};
}
-
-class EaxGetException :
- public EaxException
-{
+class EaxGetException : public EaxException {
public:
- explicit EaxGetException(
- const char* message)
- :
- EaxException{"EAX_GET", message}
- {
- }
-}; // EaxGetException
+ explicit EaxGetException(const char* message)
+ : EaxException{"EAX_GET", message}
+ {}
+};
-
-[[noreturn]]
-void eax_fail_get(
- const char* message)
+[[noreturn]] void eax_fail_get(const char* message)
{
throw EaxGetException{message};
}
-
} // namespace
@@ -1208,10 +1043,8 @@ try
{
auto context = GetContextRef();
- if (!context)
- {
+ if(!context)
eax_fail_set("No current context.");
- }
std::lock_guard<std::mutex> prop_lock{context->mPropLock};
@@ -1220,8 +1053,7 @@ try
property_id,
property_source_id,
property_value,
- property_value_size
- );
+ property_value_size);
}
catch (...)
{
@@ -1239,10 +1071,8 @@ try
{
auto context = GetContextRef();
- if (!context)
- {
+ if(!context)
eax_fail_get("No current context.");
- }
std::lock_guard<std::mutex> prop_lock{context->mPropLock};
@@ -1251,8 +1081,7 @@ try
property_id,
property_source_id,
property_value,
- property_value_size
- );
+ property_value_size);
}
catch (...)
{
diff --git a/alc/context.h b/alc/context.h
index f107835f..9317455d 100644
--- a/alc/context.h
+++ b/alc/context.h
@@ -21,22 +21,10 @@
#ifdef ALSOFT_EAX
#include "al/eax/call.h"
+#include "al/eax/exception.h"
#include "al/eax/fx_slot_index.h"
#include "al/eax/fx_slots.h"
#include "al/eax/utils.h"
-
-
-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
#endif // ALSOFT_EAX
struct ALeffect;
@@ -200,14 +188,11 @@ public:
#ifdef ALSOFT_EAX
public:
bool has_eax() const noexcept { return eax_is_initialized_; }
-
bool eax_is_capable() const noexcept;
-
+ int eax_get_version() const noexcept { return eax_version_; }
void eax_uninitialize() noexcept;
- int eax_get_version() const noexcept { return eax_version_; }
-
ALenum eax_eax_set(
const GUID* property_set_id,
ALuint property_id,
@@ -222,15 +207,10 @@ public:
ALvoid* property_value,
ALuint property_value_size);
-
void eax_update_filters();
-
void eax_commit_and_update_sources();
-
-
void eax_set_last_error() noexcept;
-
EaxFxSlotIndex eax_get_primary_fx_slot_index() const noexcept
{ return eax_primary_fx_slot_index_; }
@@ -243,11 +223,169 @@ public:
{ eax_fx_slots_.commit(); }
private:
- struct Eax
+ static constexpr auto eax_primary_fx_slot_id_dirty_bit = EaxDirtyFlags{1} << 0;
+ static constexpr auto eax_distance_factor_dirty_bit = EaxDirtyFlags{1} << 1;
+ static constexpr auto eax_air_absorption_hf_dirty_bit = EaxDirtyFlags{1} << 2;
+ static constexpr auto eax_hf_reference_dirty_bit = EaxDirtyFlags{1} << 3;
+ static constexpr auto eax_macro_fx_factor_dirty_bit = EaxDirtyFlags{1} << 4;
+
+ using Eax4Props = EAX40CONTEXTPROPERTIES;
+
+ struct Eax4State {
+ Eax4Props i; // Immediate.
+ Eax4Props d; // Deferred.
+ EaxDirtyFlags df; // Dirty flags.
+ };
+
+ using Eax5Props = EAX50CONTEXTPROPERTIES;
+
+ struct Eax5State {
+ Eax5Props i; // Immediate.
+ Eax5Props d; // Deferred.
+ EaxDirtyFlags df; // Dirty flags.
+ };
+
+ class ContextException : public EaxException
{
- EAX50CONTEXTPROPERTIES context{};
- }; // Eax
+ public:
+ explicit ContextException(const char* message)
+ : EaxException{"EAX_CONTEXT", message}
+ {}
+ };
+ struct Eax4PrimaryFxSlotIdValidator {
+ void operator()(const GUID& guidPrimaryFXSlotID) const
+ {
+ if(guidPrimaryFXSlotID != EAX_NULL_GUID &&
+ guidPrimaryFXSlotID != EAXPROPERTYID_EAX40_FXSlot0 &&
+ guidPrimaryFXSlotID != EAXPROPERTYID_EAX40_FXSlot1 &&
+ guidPrimaryFXSlotID != EAXPROPERTYID_EAX40_FXSlot2 &&
+ guidPrimaryFXSlotID != EAXPROPERTYID_EAX40_FXSlot3)
+ {
+ eax_fail_unknown_primary_fx_slot_id();
+ }
+ }
+ };
+
+ struct Eax4DistanceFactorValidator {
+ void operator()(float flDistanceFactor) const
+ {
+ eax_validate_range<ContextException>(
+ "Distance Factor",
+ flDistanceFactor,
+ EAXCONTEXT_MINDISTANCEFACTOR,
+ EAXCONTEXT_MAXDISTANCEFACTOR);
+ }
+ };
+
+ struct Eax4AirAbsorptionHfValidator {
+ void operator()(float flAirAbsorptionHF) const
+ {
+ eax_validate_range<ContextException>(
+ "Air Absorption HF",
+ flAirAbsorptionHF,
+ EAXCONTEXT_MINAIRABSORPTIONHF,
+ EAXCONTEXT_MAXAIRABSORPTIONHF);
+ }
+ };
+
+ struct Eax4HfReferenceValidator {
+ void operator()(float flHFReference) const
+ {
+ eax_validate_range<ContextException>(
+ "HF Reference",
+ flHFReference,
+ EAXCONTEXT_MINHFREFERENCE,
+ EAXCONTEXT_MAXHFREFERENCE);
+ }
+ };
+
+ struct Eax4AllValidator {
+ void operator()(const EAX40CONTEXTPROPERTIES& all) const
+ {
+ Eax4PrimaryFxSlotIdValidator{}(all.guidPrimaryFXSlotID);
+ Eax4DistanceFactorValidator{}(all.flDistanceFactor);
+ Eax4AirAbsorptionHfValidator{}(all.flAirAbsorptionHF);
+ Eax4HfReferenceValidator{}(all.flHFReference);
+ }
+ };
+
+ struct Eax5PrimaryFxSlotIdValidator {
+ void operator()(const GUID& guidPrimaryFXSlotID) const
+ {
+ if(guidPrimaryFXSlotID != EAX_NULL_GUID &&
+ guidPrimaryFXSlotID != EAXPROPERTYID_EAX50_FXSlot0 &&
+ guidPrimaryFXSlotID != EAXPROPERTYID_EAX50_FXSlot1 &&
+ guidPrimaryFXSlotID != EAXPROPERTYID_EAX50_FXSlot2 &&
+ guidPrimaryFXSlotID != EAXPROPERTYID_EAX50_FXSlot3)
+ {
+ eax_fail_unknown_primary_fx_slot_id();
+ }
+ }
+ };
+
+ struct Eax5MacroFxFactorValidator {
+ void operator()(float flMacroFXFactor) const
+ {
+ eax_validate_range<ContextException>(
+ "Macro FX Factor",
+ flMacroFXFactor,
+ EAXCONTEXT_MINMACROFXFACTOR,
+ EAXCONTEXT_MAXMACROFXFACTOR);
+ }
+ };
+
+ struct Eax5AllValidator {
+ void operator()(const EAX50CONTEXTPROPERTIES& all) const
+ {
+ Eax5PrimaryFxSlotIdValidator{}(all.guidPrimaryFXSlotID);
+ Eax4DistanceFactorValidator{}(all.flDistanceFactor);
+ Eax4AirAbsorptionHfValidator{}(all.flAirAbsorptionHF);
+ Eax4HfReferenceValidator{}(all.flHFReference);
+ Eax5MacroFxFactorValidator{}(all.flMacroFXFactor);
+ }
+ };
+
+ struct Eax5EaxVersionValidator {
+ void operator()(unsigned long ulEAXVersion) const
+ {
+ eax_validate_range<ContextException>(
+ "EAX version",
+ ulEAXVersion,
+ EAXCONTEXT_MINEAXSESSION,
+ EAXCONTEXT_MAXEAXSESSION);
+ }
+ };
+
+ struct Eax5MaxActiveSendsValidator {
+ void operator()(unsigned long ulMaxActiveSends) const
+ {
+ eax_validate_range<ContextException>(
+ "Max Active Sends",
+ ulMaxActiveSends,
+ EAXCONTEXT_MINMAXACTIVESENDS,
+ EAXCONTEXT_MAXMAXACTIVESENDS);
+ }
+ };
+
+ struct Eax5SessionAllValidator {
+ void operator()(const EAXSESSIONPROPERTIES& all) const
+ {
+ Eax5EaxVersionValidator{}(all.ulEAXVersion);
+ Eax5MaxActiveSendsValidator{}(all.ulMaxActiveSends);
+ }
+ };
+
+ struct Eax5SpeakerConfigValidator {
+ void operator()(unsigned long ulSpeakerConfig) const
+ {
+ eax_validate_range<ContextException>(
+ "Speaker Config",
+ ulSpeakerConfig,
+ EAXCONTEXT_MINSPEAKERCONFIG,
+ EAXCONTEXT_MAXSPEAKERCONFIG);
+ }
+ };
bool eax_is_initialized_{};
bool eax_is_tried_{};
@@ -258,169 +396,129 @@ private:
EaxFxSlotIndex eax_primary_fx_slot_index_{};
EaxFxSlots eax_fx_slots_{};
- int eax_version_{};
- Eax eax_{};
- Eax eax_d_{};
+ int eax_version_{}; // Current EAX version.
+ Eax5State eax123_{}; // EAX1/EAX2/EAX3 state.
+ Eax4State eax4_{}; // EAX4 state.
+ Eax5State eax5_{}; // EAX5 state.
+ Eax5Props eax_{}; // Current EAX state.
EAXSESSIONPROPERTIES eax_session_{};
- ContextDirtyFlags eax_context_dirty_flags_{};
-
std::string eax_extension_list_{};
+ [[noreturn]] static void eax_fail(const char* message);
+ [[noreturn]] static void eax_fail_unknown_property_set_id();
+ [[noreturn]] static void eax_fail_unknown_primary_fx_slot_id();
+ [[noreturn]] static void eax_fail_unknown_property_id();
+ [[noreturn]] static void eax_fail_unknown_version();
+
+ // Gets a value from EAX call,
+ // validates it,
+ // and updates the current value.
+ template<typename TValidator, typename TProperty>
+ static void eax_set(const EaxCall& call, TProperty& property)
+ {
+ const auto& value = call.get_value<ContextException, const TProperty>();
+ TValidator{}(value);
+ property = value;
+ }
- [[noreturn]]
- static void eax_fail(
- const char* message);
+ // Gets a new value from EAX call,
+ // validates it,
+ // updates the deferred value,
+ // updates a dirty flag.
+ template<
+ typename TValidator,
+ EaxDirtyFlags TDirtyBit,
+ typename TMemberResult,
+ typename TProps,
+ typename TState>
+ static void eax_defer(
+ const EaxCall& call,
+ TState& state,
+ TMemberResult TProps::*member) noexcept
+ {
+ const auto& src = call.get_value<ContextException, const TMemberResult>();
+ TValidator{}(src);
+ const auto& dst_i = state.i.*member;
+ auto& dst_d = state.d.*member;
+ dst_d = src;
+
+ if(dst_i != dst_d)
+ state.df |= TDirtyBit;
+ }
+ template<
+ EaxDirtyFlags TDirtyBit,
+ typename TMemberResult,
+ typename TProps,
+ typename TState>
+ void eax_context_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 eax_initialize_extensions();
-
void eax_initialize(const EaxCall& call);
-
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;
-
void eax_ensure_compatibility();
-
unsigned long eax_detect_speaker_configuration() const;
void eax_update_speaker_configuration();
-
void eax_set_last_error_defaults() noexcept;
-
- void eax_set_session_defaults() noexcept;
-
- void eax_set_context_defaults() noexcept;
-
+ void eax_session_set_defaults() noexcept;
+ static void eax4_context_set_defaults(Eax4Props& props) noexcept;
+ static void eax4_context_set_defaults(Eax4State& state) noexcept;
+ static void eax5_context_set_defaults(Eax5Props& props) noexcept;
+ static void eax5_context_set_defaults(Eax5State& state) noexcept;
+ void eax_context_set_defaults() noexcept;
void eax_set_defaults() noexcept;
void eax_initialize_sources();
-
void eax_dispatch_fx_slot(const EaxCall& call);
-
void eax_dispatch_source(const EaxCall& call);
-
- void eax_get_primary_fx_slot_id(const EaxCall& call);
-
- void eax_get_distance_factor(const EaxCall& call);
-
- void eax_get_air_absorption_hf(const EaxCall& call);
-
- void eax_get_hf_reference(const EaxCall& call);
-
- void eax_get_last_error(const EaxCall& call);
-
- void eax_get_speaker_config(const EaxCall& call);
-
- void eax_get_session(const EaxCall& call);
-
- void eax_get_macro_fx_factor(const EaxCall& call);
-
- void eax_get_context_all(const EaxCall& call);
-
+ void eax_get_misc(const EaxCall& call);
+ void eax4_get(const EaxCall& call, const Eax4Props& props);
+ void eax5_get(const EaxCall& call, const Eax5Props& props);
void eax_get(const EaxCall& 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_context_commit_primary_fx_slot_id();
+ void eax_context_commit_distance_factor();
+ void eax_context_commit_air_absorbtion_hf();
+ void eax_context_commit_hf_reference();
+ void eax_context_commit_macro_fx_factor();
void eax_initialize_fx_slots(const EaxCall& call);
-
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 EaxCall& call);
-
- void eax_defer_primary_fx_slot_id(const EaxCall& call);
-
- void eax_defer_distance_factor(const EaxCall& call);
-
- void eax_defer_air_absorption_hf(const EaxCall& call);
-
- void eax_defer_hf_reference(const EaxCall& call);
-
- void eax_set_session(const EaxCall& call);
-
- void eax_defer_macro_fx_factor(const EaxCall& call);
-
+ void eax_set_misc(const EaxCall& call);
+ void eax4_defer_all(const EaxCall& call, Eax4State& state);
+ void eax4_defer(const EaxCall& call, Eax4State& state);
+ void eax5_defer_all(const EaxCall& call, Eax5State& state);
+ void eax5_defer(const EaxCall& call, Eax5State& state);
void eax_set(const EaxCall& call);
- void eax_apply_deferred();
+ void eax4_context_commit(Eax4State& state, EaxDirtyFlags& dst_df);
+ void eax5_context_commit(Eax5State& state, EaxDirtyFlags& dst_df);
+ void eax_context_commit();
+ void eax_commit();
#endif // ALSOFT_EAX
};