aboutsummaryrefslogtreecommitdiffstats
path: root/al
diff options
context:
space:
mode:
authorBoris I. Bendovsky <[email protected]>2022-06-18 23:36:42 +0300
committerGitHub <[email protected]>2022-06-18 13:36:42 -0700
commitd21ff67554d494ec53dcb4747b828478f8d5690a (patch)
tree5a8c39eeba176e4cfd539a9548af4bcc41557d5b /al
parent0e7d5736c0b66d0639beb395b512416d252d28fb (diff)
[EAX] Add separate source state for each version (#720)
Diffstat (limited to 'al')
-rw-r--r--al/eax/api.cpp2
-rw-r--r--al/eax/api.h19
-rw-r--r--al/eax/call.h17
-rw-r--r--al/eax/utils.h69
-rw-r--r--al/source.cpp2782
-rw-r--r--al/source.h1333
6 files changed, 1656 insertions, 2566 deletions
diff --git a/al/eax/api.cpp b/al/eax/api.cpp
index 34ba554f..a1e9d3e1 100644
--- a/al/eax/api.cpp
+++ b/al/eax/api.cpp
@@ -313,7 +313,7 @@ bool operator==(
lhs.flOcclusionLFRatio == rhs.flOcclusionLFRatio;
}
-const EAX50ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS
+const EAX40ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID = EAX40ACTIVEFXSLOTS
{{
EAX_NULL_GUID,
EAXPROPERTYID_EAX40_FXSlot0,
diff --git a/al/eax/api.h b/al/eax/api.h
index f4419ddb..a9b0a50f 100644
--- a/al/eax/api.h
+++ b/al/eax/api.h
@@ -275,6 +275,10 @@ struct EAX20BUFFERPROPERTIES
unsigned long dwFlags; // modifies the behavior of properties
}; // EAX20BUFFERPROPERTIES
+inline bool operator==(const EAX20BUFFERPROPERTIES& lhs, const EAX20BUFFERPROPERTIES& rhs) noexcept
+{
+ return std::memcmp(&lhs, &rhs, sizeof(EAX20BUFFERPROPERTIES)) == 0;
+}
extern const GUID DSPROPSETID_EAX30_ListenerProperties;
@@ -707,12 +711,21 @@ struct EAX30SOURCEPROPERTIES
unsigned long ulFlags; // modifies the behavior of properties
}; // EAX30SOURCEPROPERTIES
-struct EAX50SOURCEPROPERTIES :
- public EAX30SOURCEPROPERTIES
+inline bool operator==(const EAX30SOURCEPROPERTIES& lhs, const EAX30SOURCEPROPERTIES& rhs) noexcept
+{
+ return std::memcmp(&lhs, &rhs, sizeof(EAX30SOURCEPROPERTIES)) == 0;
+}
+
+struct EAX50SOURCEPROPERTIES : public EAX30SOURCEPROPERTIES
{
float flMacroFXFactor;
}; // EAX50SOURCEPROPERTIES
+inline bool operator==(const EAX50SOURCEPROPERTIES& lhs, const EAX50SOURCEPROPERTIES& rhs) noexcept
+{
+ return std::memcmp(&lhs, &rhs, sizeof(EAX50SOURCEPROPERTIES)) == 0;
+}
+
struct EAXSOURCEALLSENDPROPERTIES
{
GUID guidReceivingFXSlotID;
@@ -808,7 +821,7 @@ struct EAXSOURCEEXCLUSIONSENDPROPERTIES
float flExclusionLFRatio;
}; // EAXSOURCEEXCLUSIONSENDPROPERTIES
-extern const EAX50ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID;
+extern const EAX40ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID;
extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID;
diff --git a/al/eax/call.h b/al/eax/call.h
index d491d6f9..9c2706c3 100644
--- a/al/eax/call.h
+++ b/al/eax/call.h
@@ -2,6 +2,7 @@
#define EAX_EAX_CALL_INCLUDED
#include "AL/al.h"
+#include "alnumeric.h"
#include "alspan.h"
#include "api.h"
#include "fx_slot_index.h"
@@ -48,18 +49,22 @@ public:
return *static_cast<TValue*>(property_buffer_);
}
- template<typename TException, typename TValue>
- al::span<TValue> get_values() const
+ template<typename TValue>
+ al::span<TValue> get_values(size_t max_count) const
{
- if (property_size_ < static_cast<ALuint>(sizeof(TValue)))
- {
+ if (max_count == 0 || property_size_ < static_cast<ALuint>(sizeof(TValue)))
fail_too_small();
- }
- const auto count = property_size_ / sizeof(TValue);
+ const auto count = minz(property_size_ / sizeof(TValue), max_count);
return al::span<TValue>{static_cast<TValue*>(property_buffer_), count};
}
+ template<typename TValue>
+ al::span<TValue> get_values() const
+ {
+ return get_values<TValue>(~size_t{});
+ }
+
template<typename TException, typename TValue>
void set_value(const TValue& value) const
{
diff --git a/al/eax/utils.h b/al/eax/utils.h
index d3d4a196..5a8fdd64 100644
--- a/al/eax/utils.h
+++ b/al/eax/utils.h
@@ -6,22 +6,14 @@
#include <string>
#include <type_traits>
-
-struct EaxAlLowPassParam
-{
+struct EaxAlLowPassParam {
float gain;
float gain_hf;
-}; // EaxAlLowPassParam
-
+};
-void eax_log_exception(
- const char* message = nullptr) noexcept;
+void eax_log_exception(const char* message = nullptr) noexcept;
-
-template<
- typename TException,
- typename TValue
->
+template<typename TException, typename TValue>
void eax_validate_range(
const char* value_name,
const TValue& value,
@@ -29,9 +21,7 @@ void eax_validate_range(
const TValue& max_value)
{
if (value >= min_value && value <= max_value)
- {
return;
- }
const auto message =
std::string{value_name} +
@@ -43,60 +33,38 @@ void eax_validate_range(
throw TException{message.c_str()};
}
+namespace detail {
-namespace detail
-{
-
-
-template<
- typename T
->
-struct EaxIsBitFieldStruct
-{
+template<typename T>
+struct EaxIsBitFieldStruct {
private:
using yes = std::true_type;
using no = std::false_type;
- template<
- typename U
- >
+ template<typename U>
static auto test(int) -> decltype(std::declval<typename U::EaxIsBitFieldStruct>(), yes{});
- template<
- typename
- >
+ template<typename>
static no test(...);
-
public:
static constexpr auto value = std::is_same<decltype(test<T>(0)), yes>::value;
-}; // EaxIsBitFieldStruct
-
+};
-template<
- typename T,
- typename TValue
->
-inline bool eax_bit_fields_are_equal(
- const T& lhs,
- const T& rhs) noexcept
+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<const TValue&>(lhs) == reinterpret_cast<const TValue&>(rhs);
}
-
} // namespace detail
-
template<
typename T,
std::enable_if_t<detail::EaxIsBitFieldStruct<T>::value, int> = 0
>
-inline bool operator==(
- const T& lhs,
- const T& rhs) noexcept
+inline bool operator==(const T& lhs, const T& rhs) noexcept
{
using Value = std::conditional_t<
sizeof(T) == 1,
@@ -107,13 +75,9 @@ inline bool operator==(
std::conditional_t<
sizeof(T) == 4,
std::uint32_t,
- void
- >
- >
- >;
+ void>>>;
static_assert(!std::is_same<Value, void>::value, "Unsupported type.");
-
return detail::eax_bit_fields_are_equal<T, Value>(lhs, rhs);
}
@@ -121,12 +85,9 @@ template<
typename T,
std::enable_if_t<detail::EaxIsBitFieldStruct<T>::value, int> = 0
>
-inline bool operator!=(
- const T& lhs,
- const T& rhs) noexcept
+inline bool operator!=(const T& lhs, const T& rhs) noexcept
{
return !(lhs == rhs);
}
-
#endif // !EAX_UTILS_INCLUDED
diff --git a/al/source.cpp b/al/source.cpp
index f2c7e2f8..475f3cf8 100644
--- a/al/source.cpp
+++ b/al/source.cpp
@@ -73,7 +73,7 @@
#include "threads.h"
#ifdef ALSOFT_EAX
-#include "eax/exception.h"
+#include <cassert>
#endif // ALSOFT_EAX
namespace {
@@ -3640,13 +3640,7 @@ void UpdateAllSourceProps(ALCcontext *context)
usemask &= ~(1_u64 << idx);
ALsource *source{sublist.Sources + idx};
- source->eax_commit();
-
- if(Voice *voice{GetSourceVoice(source, context)})
- {
- if(std::exchange(source->mPropsDirty, false))
- UpdateSourceProps(source, voice, context);
- }
+ source->eax_commit_and_update();
}
}
}
@@ -3685,45 +3679,6 @@ SourceSubList::~SourceSubList()
#ifdef 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 EaxUpdateSourceVoice(ALsource *source, ALCcontext *context)
{
if(Voice *voice{GetSourceVoice(source, context)})
@@ -3733,2350 +3688,1158 @@ void EaxUpdateSourceVoice(ALsource *source, ALCcontext *context)
}
}
+constexpr const ALsource::EaxFxSlotIds ALsource::eax4_fx_slot_ids;
+constexpr const ALsource::EaxFxSlotIds ALsource::eax5_fx_slot_ids;
void ALsource::eax_initialize(ALCcontext *context) noexcept
{
- assert(context);
+ assert(context != nullptr);
eax_al_context_ = context;
+ eax_primary_fx_slot_id_ = eax_al_context_->eax_get_primary_fx_slot_index();
+ eax_version_ = eax_al_context_->eax_get_version();
eax_set_defaults();
- eax_initialize_fx_slots();
-
- eax_d_ = eax_;
+ eax_commit(EaxCommitType::forced);
}
-void ALsource::eax_update_filters()
+void ALsource::eax_dispatch(const EaxCall& call)
{
- eax_update_filters_internal();
+ const auto eax_version = call.get_version();
+ eax_is_version_changed_ |= (eax_version_ == eax_version);
+ eax_version_ = eax_version;
+ call.is_get() ? eax_get(call) : eax_set(call);
}
-void ALsource::eax_update(EaxContextSharedDirtyFlags)
+void ALsource::eax_commit()
{
- /* NOTE: EaxContextSharedDirtyFlags only has one flag (primary_fx_slot_id),
- * which must be true for this to be called.
- */
- if(eax_uses_primary_id_)
- eax_update_primary_fx_slot_id();
+ eax_commit(EaxCommitType::normal);
}
void ALsource::eax_commit_and_update()
{
- eax_apply_deferred();
+ eax_commit();
EaxUpdateSourceVoice(this, eax_al_context_);
}
-ALsource* ALsource::eax_lookup_source(
- ALCcontext& al_context,
- ALuint source_id) noexcept
+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_set_source_defaults() noexcept
+[[noreturn]] void ALsource::eax_fail(const char* message)
{
- eax1_.fMix = EAX_REVERBMIX_USEDISTANCE;
-
- 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;
- eax_.source.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR;
+ throw Exception{message};
}
-void ALsource::eax_set_active_fx_slots_defaults() noexcept
+[[noreturn]] void ALsource::eax_fail_unknown_property_id()
{
- eax_.active_fx_slots = EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID;
+ eax_fail("Unknown property id.");
}
-void ALsource::eax_set_send_defaults(EAXSOURCEALLSENDPROPERTIES& eax_send) noexcept
+[[noreturn]] void ALsource::eax_fail_unknown_version()
{
- 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;
+ eax_fail("Unknown version.");
}
-void ALsource::eax_set_sends_defaults() noexcept
+[[noreturn]] void ALsource::eax_fail_unknown_active_fx_slot_id()
{
- for (auto& eax_send : eax_.sends)
- {
- eax_set_send_defaults(eax_send);
- }
+ eax_fail("Unknown active FX slot ID.");
}
-void ALsource::eax_set_speaker_levels_defaults() noexcept
+[[noreturn]] void ALsource::eax_fail_unknown_receiving_fx_slot_id()
{
- std::fill(eax_.speaker_levels.begin(), eax_.speaker_levels.end(), EAXSOURCE_DEFAULTSPEAKERLEVEL);
+ eax_fail("Unknown receiving FX slot ID.");
}
-void ALsource::eax_set_defaults() noexcept
+void ALsource::eax_set_sends_defaults(EaxSends& sends, const EaxFxSlotIds& ids) noexcept
{
- 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<float>(src_occlusion_mb) * ratio;
-
- return dst_occlustion_mb;
-}
-
-EaxAlLowPassParam ALsource::eax_create_direct_filter_param() const noexcept
-{
- auto gain_mb =
- static_cast<float>(eax_.source.lDirect) +
-
- (static_cast<float>(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<float>(eax_.source.lDirectHF) +
-
- static_cast<float>(eax_.source.lObstruction) +
-
- (static_cast<float>(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<float>(send.lOcclusion) * send.flOcclusionDirectRatio;
- }
+ for (auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i) {
+ auto& send = sends[i];
+ send.guidReceivingFXSlotID = *(ids[i]);
+ send.lSend = EAXSOURCE_DEFAULTSEND;
+ send.lSendHF = EAXSOURCE_DEFAULTSENDHF;
+ send.lOcclusion = EAXSOURCE_DEFAULTOCCLUSION;
+ send.flOcclusionLFRatio = EAXSOURCE_DEFAULTOCCLUSIONLFRATIO;
+ send.flOcclusionRoomRatio = EAXSOURCE_DEFAULTOCCLUSIONROOMRATIO;
+ send.flOcclusionDirectRatio = EAXSOURCE_DEFAULTOCCLUSIONDIRECTRATIO;
+ send.lExclusion = EAXSOURCE_DEFAULTEXCLUSION;
+ send.flExclusionLFRatio = EAXSOURCE_DEFAULTEXCLUSIONLFRATIO;
}
-
- const auto al_low_pass_param = EaxAlLowPassParam
- {
- level_mb_to_gain(gain_mb),
- minf(level_mb_to_gain(gain_hf_mb), 1.0f)
- };
-
- return al_low_pass_param;
}
-EaxAlLowPassParam ALsource::eax_create_room_filter_param(
- const ALeffectslot& fx_slot,
- const EAXSOURCEALLSENDPROPERTIES& send) const noexcept
+void ALsource::eax1_set_defaults(Eax1Props& props) noexcept
{
- const auto& fx_slot_eax = fx_slot.eax_get_eax_fx_slot();
-
- const auto gain_mb =
- static_cast<float>(
- 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<float>(eax_.source.lExclusion) * eax_.source.flExclusionLFRatio) +
- (static_cast<float>(send.lExclusion) * send.flExclusionLFRatio) +
-
- 0.0F;
-
- const auto gain_hf_mb =
- static_cast<float>(
- eax_.source.lRoomHF +
- send.lSendHF) +
-
- (static_cast<float>(fx_slot_eax.lOcclusion + eax_.source.lOcclusion) * eax_.source.flOcclusionRoomRatio) +
- (static_cast<float>(send.lOcclusion) * send.flOcclusionRoomRatio) +
-
- static_cast<float>(
- eax_.source.lExclusion +
- send.lExclusion) +
-
- 0.0F;
-
- const auto al_low_pass_param = EaxAlLowPassParam
- {
- level_mb_to_gain(gain_mb),
- minf(level_mb_to_gain(gain_hf_mb), 1.0f)
- };
-
- return al_low_pass_param;
+ props.fMix = EAX_REVERBMIX_USEDISTANCE;
}
-void ALsource::eax_set_fx_slots()
+void ALsource::eax1_set_defaults() noexcept
{
- eax_uses_primary_id_ = false;
- eax_has_active_fx_slots_ = false;
- eax_active_fx_slots_.fill(false);
-
- for(const auto& eax_active_fx_slot_id : eax_.active_fx_slots.guidActiveFXSlots)
- {
- 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 = 0u;i < eax_active_fx_slots_.size();++i)
- {
- if(!eax_active_fx_slots_[i])
- eax_set_al_source_send(nullptr, i, EaxAlLowPassParam{1.0f, 1.0f});
- }
+ eax1_set_defaults(eax1_.i);
+ eax1_.d = eax1_.i;
}
-void ALsource::eax_initialize_fx_slots()
+void ALsource::eax2_set_defaults(Eax2Props& props) noexcept
{
- eax_set_fx_slots();
- eax_update_filters_internal();
+ props.lDirect = EAXSOURCE_DEFAULTDIRECT;
+ props.lDirectHF = EAXSOURCE_DEFAULTDIRECTHF;
+ props.lRoom = EAXSOURCE_DEFAULTROOM;
+ props.lRoomHF = EAXSOURCE_DEFAULTROOMHF;
+ props.flRoomRolloffFactor = EAXSOURCE_DEFAULTROOMROLLOFFFACTOR;
+ props.lObstruction = EAXSOURCE_DEFAULTOBSTRUCTION;
+ props.flObstructionLFRatio = EAXSOURCE_DEFAULTOBSTRUCTIONLFRATIO;
+ props.lOcclusion = EAXSOURCE_DEFAULTOCCLUSION;
+ props.flOcclusionLFRatio = EAXSOURCE_DEFAULTOCCLUSIONLFRATIO;
+ props.flOcclusionRoomRatio = EAXSOURCE_DEFAULTOCCLUSIONROOMRATIO;
+ props.lOutsideVolumeHF = EAXSOURCE_DEFAULTOUTSIDEVOLUMEHF;
+ props.flAirAbsorptionFactor = EAXSOURCE_DEFAULTAIRABSORPTIONFACTOR;
+ props.dwFlags = EAXSOURCE_DEFAULTFLAGS;
}
-void ALsource::eax_update_direct_filter_internal()
+void ALsource::eax2_set_defaults() noexcept
{
- const auto& direct_param = eax_create_direct_filter_param();
-
- Direct.Gain = direct_param.gain;
- Direct.GainHF = direct_param.gain_hf;
- Direct.HFReference = LOWPASSFREQREF;
- Direct.GainLF = 1.0f;
- Direct.LFReference = HIGHPASSFREQREF;
- mPropsDirty = true;
+ eax2_set_defaults(eax2_.i);
+ eax2_.d = eax2_.i;
}
-void ALsource::eax_update_room_filters_internal()
+void ALsource::eax3_set_defaults(Eax3Props& props) noexcept
{
- if (!eax_has_active_fx_slots_)
- {
- return;
- }
-
- for (auto i = 0u; i < EAX_MAX_FXSLOTS; ++i)
- {
- if (eax_active_fx_slots_[i])
- {
- auto& fx_slot = eax_al_context_->eax_get_fx_slot(static_cast<std::size_t>(i));
- const auto& send = eax_.sends[i];
- const auto& room_param = eax_create_room_filter_param(fx_slot, send);
-
- eax_set_al_source_send(&fx_slot, i, room_param);
- }
- }
+ props.lDirect = EAXSOURCE_DEFAULTDIRECT;
+ props.lDirectHF = EAXSOURCE_DEFAULTDIRECTHF;
+ props.lRoom = EAXSOURCE_DEFAULTROOM;
+ props.lRoomHF = EAXSOURCE_DEFAULTROOMHF;
+ props.lObstruction = EAXSOURCE_DEFAULTOBSTRUCTION;
+ props.flObstructionLFRatio = EAXSOURCE_DEFAULTOBSTRUCTIONLFRATIO;
+ props.lOcclusion = EAXSOURCE_DEFAULTOCCLUSION;
+ props.flOcclusionLFRatio = EAXSOURCE_DEFAULTOCCLUSIONLFRATIO;
+ props.flOcclusionRoomRatio = EAXSOURCE_DEFAULTOCCLUSIONROOMRATIO;
+ props.flOcclusionDirectRatio = EAXSOURCE_DEFAULTOCCLUSIONDIRECTRATIO;
+ props.lExclusion = EAXSOURCE_DEFAULTEXCLUSION;
+ props.flExclusionLFRatio = EAXSOURCE_DEFAULTEXCLUSIONLFRATIO;
+ props.lOutsideVolumeHF = EAXSOURCE_DEFAULTOUTSIDEVOLUMEHF;
+ props.flDopplerFactor = EAXSOURCE_DEFAULTDOPPLERFACTOR;
+ props.flRolloffFactor = EAXSOURCE_DEFAULTROLLOFFFACTOR;
+ props.flRoomRolloffFactor = EAXSOURCE_DEFAULTROOMROLLOFFFACTOR;
+ props.flAirAbsorptionFactor = EAXSOURCE_DEFAULTAIRABSORPTIONFACTOR;
+ props.ulFlags = EAXSOURCE_DEFAULTFLAGS;
}
-void ALsource::eax_update_filters_internal()
+void ALsource::eax3_set_defaults() noexcept
{
- eax_update_direct_filter_internal();
- eax_update_room_filters_internal();
+ eax3_set_defaults(eax3_.i);
+ eax3_.d = eax3_.i;
}
-void ALsource::eax_update_primary_fx_slot_id()
+void ALsource::eax4_set_sends_defaults(EaxSends& sends) noexcept
{
- 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.value();
- eax_active_fx_slots_[fx_slot_index] = false;
-
- eax_set_al_source_send(nullptr, fx_slot_index, EaxAlLowPassParam{1.0f, 1.0f});
- }
-
- if (primary_fx_slot_index.has_value())
- {
- const auto fx_slot_index = primary_fx_slot_index.value();
- eax_active_fx_slots_[fx_slot_index] = true;
-
- 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_source_send(&fx_slot, fx_slot_index, room_param);
- }
-
- eax_has_active_fx_slots_ = std::any_of(
- eax_active_fx_slots_.cbegin(),
- eax_active_fx_slots_.cend(),
- [](const auto& item)
- {
- return item;
- }
- );
+ eax_set_sends_defaults(sends, eax4_fx_slot_ids);
}
-void ALsource::eax_defer_active_fx_slots(
- const EaxCall& call)
+void ALsource::eax4_set_active_fx_slots_defaults(EAX40ACTIVEFXSLOTS& slots) noexcept
{
- const auto active_fx_slots_span =
- call.get_values<EaxSourceActiveFxSlotsException, const GUID>();
-
- 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);
+ slots = EAX40SOURCE_DEFAULTACTIVEFXSLOTID;
}
-
-const char* ALsource::eax_get_exclusion_name() noexcept
+void ALsource::eax4_set_defaults() noexcept
{
- return "Exclusion";
+ eax3_set_defaults(eax4_.i.source);
+ eax4_set_sends_defaults(eax4_.i.sends);
+ eax4_set_active_fx_slots_defaults(eax4_.i.active_fx_slots);
+ eax4_.d = eax4_.i;
}
-const char* ALsource::eax_get_exclusion_lf_ratio_name() noexcept
+void ALsource::eax5_set_source_defaults(EAX50SOURCEPROPERTIES& props) noexcept
{
- return "Exclusion LF Ratio";
+ eax3_set_defaults(static_cast<Eax3Props&>(props));
+ props.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR;
}
-const char* ALsource::eax_get_occlusion_name() noexcept
+void ALsource::eax5_set_sends_defaults(EaxSends& sends) noexcept
{
- return "Occlusion";
+ eax_set_sends_defaults(sends, eax5_fx_slot_ids);
}
-const char* ALsource::eax_get_occlusion_lf_ratio_name() noexcept
+void ALsource::eax5_set_active_fx_slots_defaults(EAX50ACTIVEFXSLOTS& slots) noexcept
{
- return "Occlusion LF Ratio";
+ slots = EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID;
}
-const char* ALsource::eax_get_occlusion_direct_ratio_name() noexcept
+void ALsource::eax5_set_speaker_levels_defaults(EaxSpeakerLevels& speaker_levels) noexcept
{
- return "Occlusion Direct Ratio";
-}
-
-const char* ALsource::eax_get_occlusion_room_ratio_name() noexcept
-{
- return "Occlusion Room Ratio";
-}
-
-void ALsource::eax1_validate_reverb_mix(float reverb_mix)
-{
- if (reverb_mix == EAX_REVERBMIX_USEDISTANCE)
- return;
-
- eax_validate_range<EaxSourceSendException>("Reverb Mix", reverb_mix, EAX_BUFFER_MINREVERBMIX, EAX_BUFFER_MAXREVERBMIX);
-}
-
-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."};
+ for (auto i = size_t{}; i < eax_max_speakers; ++i) {
+ auto& speaker_level = speaker_levels[i];
+ speaker_level.lSpeakerID = static_cast<long>(EAXSPEAKER_FRONT_LEFT + i);
+ speaker_level.lLevel = EAXSOURCE_DEFAULTSPEAKERLEVEL;
}
}
-void ALsource::eax_validate_send_send(
- long lSend)
+void ALsource::eax5_set_defaults(Eax5Props& props) noexcept
{
- eax_validate_range<EaxSourceSendException>(
- "Send",
- lSend,
- EAXSOURCE_MINSEND,
- EAXSOURCE_MAXSEND);
+ eax5_set_source_defaults(props.source);
+ eax5_set_sends_defaults(props.sends);
+ eax5_set_active_fx_slots_defaults(props.active_fx_slots);
+ eax5_set_speaker_levels_defaults(props.speaker_levels);
}
-void ALsource::eax_validate_send_send_hf(
- long lSendHF)
+void ALsource::eax5_set_defaults() noexcept
{
- eax_validate_range<EaxSourceSendException>(
- "Send HF",
- lSendHF,
- EAXSOURCE_MINSENDHF,
- EAXSOURCE_MAXSENDHF);
+ eax5_set_defaults(eax5_.i);
+ eax5_.d = eax5_.i;
}
-void ALsource::eax_validate_send_occlusion(
- long lOcclusion)
-{
- eax_validate_range<EaxSourceSendException>(
- eax_get_occlusion_name(),
- lOcclusion,
- EAXSOURCE_MINOCCLUSION,
- EAXSOURCE_MAXOCCLUSION);
-}
-
-void ALsource::eax_validate_send_occlusion_lf_ratio(
- float flOcclusionLFRatio)
-{
- eax_validate_range<EaxSourceSendException>(
- eax_get_occlusion_lf_ratio_name(),
- flOcclusionLFRatio,
- EAXSOURCE_MINOCCLUSIONLFRATIO,
- EAXSOURCE_MAXOCCLUSIONLFRATIO);
-}
-
-void ALsource::eax_validate_send_occlusion_room_ratio(
- float flOcclusionRoomRatio)
-{
- eax_validate_range<EaxSourceSendException>(
- eax_get_occlusion_room_ratio_name(),
- flOcclusionRoomRatio,
- EAXSOURCE_MINOCCLUSIONROOMRATIO,
- EAXSOURCE_MAXOCCLUSIONROOMRATIO);
-}
-
-void ALsource::eax_validate_send_occlusion_direct_ratio(
- float flOcclusionDirectRatio)
-{
- eax_validate_range<EaxSourceSendException>(
- eax_get_occlusion_direct_ratio_name(),
- flOcclusionDirectRatio,
- EAXSOURCE_MINOCCLUSIONDIRECTRATIO,
- EAXSOURCE_MAXOCCLUSIONDIRECTRATIO);
-}
-
-void ALsource::eax_validate_send_exclusion(
- long lExclusion)
-{
- eax_validate_range<EaxSourceSendException>(
- eax_get_exclusion_name(),
- lExclusion,
- EAXSOURCE_MINEXCLUSION,
- EAXSOURCE_MAXEXCLUSION);
-}
-
-void ALsource::eax_validate_send_exclusion_lf_ratio(
- float flExclusionLFRatio)
-{
- eax_validate_range<EaxSourceSendException>(
- 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)
+void ALsource::eax_set_defaults() noexcept
{
- 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);
+ eax1_set_defaults();
+ eax2_set_defaults();
+ eax3_set_defaults();
+ eax4_set_defaults();
+ eax5_set_defaults();
}
-void ALsource::eax_validate_send_all(
- const EAXSOURCEALLSENDPROPERTIES& all)
+void ALsource::eax1_translate(const Eax1Props& src, Eax5Props& dst) noexcept
{
- 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);
-}
+ eax5_set_defaults(dst);
-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;
- }
+ if (src.fMix == EAX_REVERBMIX_USEDISTANCE)
+ dst.source.ulFlags |= EAXSOURCEFLAGS_ROOMAUTO;
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);
-}
+ dst.source.ulFlags &= ~EAXSOURCEFLAGS_ROOMAUTO;
-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);
+ dst.sends[0].lSendHF = clamp(
+ static_cast<long>(gain_to_level_mb(src.fMix)),
+ EAXSOURCE_MINSENDHF,
+ EAXSOURCE_MAXSENDHF);
}
-void ALsource::eax_defer_send(
- const EaxCall& call)
-{
- const auto eax_all_span =
- call.get_values<EaxSourceException, const EAXSOURCESENDPROPERTIES>();
-
- 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);
+void ALsource::eax2_translate(const Eax2Props& src, Eax5Props& dst) noexcept
+{
+ // Source.
+ //
+ dst.source.lDirect = src.lDirect;
+ dst.source.lDirectHF = src.lDirectHF;
+ dst.source.lRoom = src.lRoom;
+ dst.source.lRoomHF = src.lRoomHF;
+ dst.source.lObstruction = src.lObstruction;
+ dst.source.flObstructionLFRatio = src.flObstructionLFRatio;
+ dst.source.lOcclusion = src.lOcclusion;
+ dst.source.flOcclusionLFRatio = src.flOcclusionLFRatio;
+ dst.source.flOcclusionRoomRatio = src.flOcclusionRoomRatio;
+ dst.source.flOcclusionDirectRatio = EAXSOURCE_DEFAULTOCCLUSIONDIRECTRATIO;
+ dst.source.lExclusion = EAXSOURCE_DEFAULTEXCLUSION;
+ dst.source.flExclusionLFRatio = EAXSOURCE_DEFAULTEXCLUSIONLFRATIO;
+ dst.source.lOutsideVolumeHF = src.lOutsideVolumeHF;
+ dst.source.flDopplerFactor = EAXSOURCE_DEFAULTDOPPLERFACTOR;
+ dst.source.flRolloffFactor = EAXSOURCE_DEFAULTROLLOFFFACTOR;
+ dst.source.flRoomRolloffFactor = src.flRoomRolloffFactor;
+ dst.source.flAirAbsorptionFactor = src.flAirAbsorptionFactor;
+ dst.source.ulFlags = src.dwFlags;
+ dst.source.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR;
+
+ // Set everyting else to defaults.
+ //
+ eax5_set_sends_defaults(dst.sends);
+ eax5_set_active_fx_slots_defaults(dst.active_fx_slots);
+ eax5_set_speaker_levels_defaults(dst.speaker_levels);
+}
+
+void ALsource::eax3_translate(const Eax3Props& src, Eax5Props& dst) noexcept
+{
+ // Source.
+ //
+ static_cast<Eax3Props&>(dst.source) = src;
+ dst.source.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR;
+
+ // Set everyting else to defaults.
+ //
+ eax5_set_sends_defaults(dst.sends);
+ eax5_set_active_fx_slots_defaults(dst.active_fx_slots);
+ eax5_set_speaker_levels_defaults(dst.speaker_levels);
+}
+
+void ALsource::eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept
+{
+ // Source.
+ //
+ static_cast<Eax3Props&>(dst.source) = src.source;
+ dst.source.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR;
+
+ // Sends.
+ //
+ dst.sends = src.sends;
+
+ for (auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i)
+ dst.sends[i].guidReceivingFXSlotID = *(eax5_fx_slot_ids[i]);
+
+ // Active FX slots.
+ //
+ for (auto i = 0; i < EAX50_MAX_ACTIVE_FXSLOTS; ++i) {
+ auto& dst_id = dst.active_fx_slots.guidActiveFXSlots[i];
+
+ if (i < EAX40_MAX_ACTIVE_FXSLOTS) {
+ const auto& src_id = src.active_fx_slots.guidActiveFXSlots[i];
+
+ if (src_id == EAX_NULL_GUID)
+ dst_id = EAX_NULL_GUID;
+ else if (src_id == EAX_PrimaryFXSlotID)
+ dst_id = EAX_PrimaryFXSlotID;
+ else if (src_id == EAXPROPERTYID_EAX40_FXSlot0)
+ dst_id = EAXPROPERTYID_EAX50_FXSlot0;
+ else if (src_id == EAXPROPERTYID_EAX40_FXSlot1)
+ dst_id = EAXPROPERTYID_EAX50_FXSlot1;
+ else if (src_id == EAXPROPERTYID_EAX40_FXSlot2)
+ dst_id = EAXPROPERTYID_EAX50_FXSlot2;
+ else if (src_id == EAXPROPERTYID_EAX40_FXSlot3)
+ dst_id = EAXPROPERTYID_EAX50_FXSlot3;
+ else
+ assert(false && "Unknown active FX slot ID.");
+ } else
+ dst_id = EAX_NULL_GUID;
}
- 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);
- }
+ // Speaker levels.
+ //
+ eax5_set_speaker_levels_defaults(dst.speaker_levels);
}
-void ALsource::eax_defer_send_exclusion_all(
- const EaxCall& call)
+float ALsource::eax_calculate_dst_occlusion_mb(
+ long src_occlusion_mb,
+ float path_ratio,
+ float lf_ratio) noexcept
{
- const auto eax_all_span =
- call.get_values<EaxSourceException, const EAXSOURCEEXCLUSIONSENDPROPERTIES>();
-
- 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);
- }
+ 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<float>(src_occlusion_mb) * ratio;
+ return dst_occlustion_mb;
}
-void ALsource::eax_defer_send_occlusion_all(
- const EaxCall& call)
+EaxAlLowPassParam ALsource::eax_create_direct_filter_param() const noexcept
{
- const auto eax_all_span =
- call.get_values<EaxSourceException, const EAXSOURCEOCCLUSIONSENDPROPERTIES>();
-
- const auto count = eax_all_span.size();
-
- if (count <= 0 || count > EAX_MAX_FXSLOTS)
- {
- throw EaxSourceSendException{"Send occlusion all count out of range."};
- }
+ auto gain_mb =
+ static_cast<float>(eax_.source.lDirect) +
+ (static_cast<float>(eax_.source.lObstruction) * eax_.source.flObstructionLFRatio) +
+ eax_calculate_dst_occlusion_mb(
+ eax_.source.lOcclusion,
+ eax_.source.flOcclusionDirectRatio,
+ eax_.source.flOcclusionLFRatio);
- for (auto i = std::size_t{}; i < count; ++i)
- {
- const auto& all = eax_all_span[i];
- eax_validate_send_occlusion_all(all);
- }
+ auto gain_hf_mb =
+ static_cast<float>(eax_.source.lDirectHF) +
+ static_cast<float>(eax_.source.lObstruction) +
+ (static_cast<float>(eax_.source.lOcclusion) * eax_.source.flOcclusionDirectRatio);
- for (auto i = std::size_t{}; i < count; ++i)
+ for (auto i = std::size_t{}; i < EAX_MAX_FXSLOTS; ++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 EaxCall& call)
-{
- const auto eax_all_span =
- call.get_values<EaxSourceException, const EAXSOURCEALLSENDPROPERTIES>();
-
- const auto count = eax_all_span.size();
+ if (!eax_active_fx_slots_[i])
+ {
+ continue;
+ }
- if (count <= 0 || count > EAX_MAX_FXSLOTS)
- {
- throw EaxSourceSendException{"Send all count out of range."};
- }
+ const auto& send = eax_.sends[i];
- for (auto i = std::size_t{}; i < count; ++i)
- {
- const auto& all = eax_all_span[i];
- eax_validate_send_all(all);
- }
+ gain_mb += eax_calculate_dst_occlusion_mb(
+ send.lOcclusion,
+ send.flOcclusionDirectRatio,
+ send.flOcclusionLFRatio);
- 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);
+ gain_hf_mb += static_cast<float>(send.lOcclusion) * send.flOcclusionDirectRatio;
}
-}
+ const auto al_low_pass_param = EaxAlLowPassParam{
+ level_mb_to_gain(gain_mb),
+ minf(level_mb_to_gain(gain_hf_mb), 1.0f)};
-void ALsource::eax_validate_source_direct(
- long direct)
-{
- eax_validate_range<EaxSourceException>(
- "Direct",
- direct,
- EAXSOURCE_MINDIRECT,
- EAXSOURCE_MAXDIRECT);
-}
-
-void ALsource::eax_validate_source_direct_hf(
- long direct_hf)
-{
- eax_validate_range<EaxSourceException>(
- "Direct HF",
- direct_hf,
- EAXSOURCE_MINDIRECTHF,
- EAXSOURCE_MAXDIRECTHF);
-}
-
-void ALsource::eax_validate_source_room(
- long room)
-{
- eax_validate_range<EaxSourceException>(
- "Room",
- room,
- EAXSOURCE_MINROOM,
- EAXSOURCE_MAXROOM);
-}
-
-void ALsource::eax_validate_source_room_hf(
- long room_hf)
-{
- eax_validate_range<EaxSourceException>(
- "Room HF",
- room_hf,
- EAXSOURCE_MINROOMHF,
- EAXSOURCE_MAXROOMHF);
-}
-
-void ALsource::eax_validate_source_obstruction(
- long obstruction)
-{
- eax_validate_range<EaxSourceException>(
- "Obstruction",
- obstruction,
- EAXSOURCE_MINOBSTRUCTION,
- EAXSOURCE_MAXOBSTRUCTION);
-}
-
-void ALsource::eax_validate_source_obstruction_lf_ratio(
- float obstruction_lf_ratio)
-{
- eax_validate_range<EaxSourceException>(
- "Obstruction LF Ratio",
- obstruction_lf_ratio,
- EAXSOURCE_MINOBSTRUCTIONLFRATIO,
- EAXSOURCE_MAXOBSTRUCTIONLFRATIO);
-}
-
-void ALsource::eax_validate_source_occlusion(
- long occlusion)
-{
- eax_validate_range<EaxSourceException>(
- eax_get_occlusion_name(),
- occlusion,
- EAXSOURCE_MINOCCLUSION,
- EAXSOURCE_MAXOCCLUSION);
-}
-
-void ALsource::eax_validate_source_occlusion_lf_ratio(
- float occlusion_lf_ratio)
-{
- eax_validate_range<EaxSourceException>(
- 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<EaxSourceException>(
- 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<EaxSourceException>(
- eax_get_occlusion_direct_ratio_name(),
- occlusion_direct_ratio,
- EAXSOURCE_MINOCCLUSIONDIRECTRATIO,
- EAXSOURCE_MAXOCCLUSIONDIRECTRATIO);
-}
-
-void ALsource::eax_validate_source_exclusion(
- long exclusion)
-{
- eax_validate_range<EaxSourceException>(
- eax_get_exclusion_name(),
- exclusion,
- EAXSOURCE_MINEXCLUSION,
- EAXSOURCE_MAXEXCLUSION);
-}
-
-void ALsource::eax_validate_source_exclusion_lf_ratio(
- float exclusion_lf_ratio)
-{
- eax_validate_range<EaxSourceException>(
- 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<EaxSourceException>(
- "Outside Volume HF",
- outside_volume_hf,
- EAXSOURCE_MINOUTSIDEVOLUMEHF,
- EAXSOURCE_MAXOUTSIDEVOLUMEHF);
-}
-
-void ALsource::eax_validate_source_doppler_factor(
- float doppler_factor)
-{
- eax_validate_range<EaxSourceException>(
- "Doppler Factor",
- doppler_factor,
- EAXSOURCE_MINDOPPLERFACTOR,
- EAXSOURCE_MAXDOPPLERFACTOR);
-}
-
-void ALsource::eax_validate_source_rolloff_factor(
- float rolloff_factor)
-{
- eax_validate_range<EaxSourceException>(
- "Rolloff Factor",
- rolloff_factor,
- EAXSOURCE_MINROLLOFFFACTOR,
- EAXSOURCE_MAXROLLOFFFACTOR);
-}
-
-void ALsource::eax_validate_source_room_rolloff_factor(
- float room_rolloff_factor)
-{
- eax_validate_range<EaxSourceException>(
- "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<EaxSourceException>(
- "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<EaxSourceException>(
- "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<EaxSourceException>(
- "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<EAX30SOURCEPROPERTIES>(all), eax_version);
- eax_validate_source_macro_fx_factor(all.flMacroFXFactor);
-}
-
-void ALsource::eax_validate_source_speaker_id(
- long speaker_id)
-{
- eax_validate_range<EaxSourceException>(
- "Speaker Id",
- speaker_id,
- static_cast<long>(EAXSPEAKER_FRONT_LEFT),
- static_cast<long>(EAXSPEAKER_LOW_FREQUENCY));
-}
-
-void ALsource::eax_validate_source_speaker_level(
- long speaker_level)
-{
- eax_validate_range<EaxSourceException>(
- "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);
+ return al_low_pass_param;
}
-void ALsource::eax_defer_source_all(
- const EAX30SOURCEPROPERTIES& all)
+EaxAlLowPassParam ALsource::eax_create_room_filter_param(
+ const ALeffectslot& fx_slot,
+ const EAXSOURCEALLSENDPROPERTIES& send) const noexcept
{
- 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);
-}
+ const auto& fx_slot_eax = fx_slot.eax_get_eax_fx_slot();
-void ALsource::eax_defer_source_all(
- const EAX50SOURCEPROPERTIES& all)
-{
- eax_defer_source_all(static_cast<const EAX30SOURCEPROPERTIES&>(all));
- eax_defer_source_macro_fx_factor(all.flMacroFXFactor);
-}
+ const auto gain_mb =
+ static_cast<float>(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<float>(eax_.source.lExclusion) * eax_.source.flExclusionLFRatio) +
+ (static_cast<float>(send.lExclusion) * send.flExclusionLFRatio);
-void ALsource::eax_defer_source_speaker_level_all(
- const EAXSPEAKERLEVELPROPERTIES& all)
-{
- const auto speaker_index = static_cast<std::size_t>(all.lSpeakerID - 1);
- auto& speaker_level_d = eax_d_.speaker_levels[speaker_index];
- const auto& speaker_level = eax_.speaker_levels[speaker_index];
+ const auto gain_hf_mb =
+ static_cast<float>(eax_.source.lRoomHF + send.lSendHF) +
+ (static_cast<float>(fx_slot_eax.lOcclusion + eax_.source.lOcclusion) * eax_.source.flOcclusionRoomRatio) +
+ (static_cast<float>(send.lOcclusion) * send.flOcclusionRoomRatio) +
+ static_cast<float>(eax_.source.lExclusion + send.lExclusion);
- if (speaker_level != speaker_level_d)
- {
- eax_source_dirty_misc_flags_.speaker_levels = true;
- }
-}
+ const auto al_low_pass_param = EaxAlLowPassParam{
+ level_mb_to_gain(gain_mb),
+ minf(level_mb_to_gain(gain_hf_mb), 1.0f)};
-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.");
- }
+ return al_low_pass_param;
}
-void ALsource::eax1_set_efx()
+void ALsource::eax_update_direct_filter()
{
- const auto primary_fx_slot_index = eax_al_context_->eax_get_primary_fx_slot_index();
-
- if (!primary_fx_slot_index.has_value())
- return;
-
- WetGainAuto = (eax1_.fMix == EAX_REVERBMIX_USEDISTANCE);
- const auto filter_gain = (WetGainAuto ? 1.0F : eax1_.fMix);
- auto& fx_slot = eax_al_context_->eax_get_fx_slot(*primary_fx_slot_index);
- eax_set_al_source_send(&fx_slot, *primary_fx_slot_index, EaxAlLowPassParam{filter_gain, 1.0F});
+ const auto& direct_param = eax_create_direct_filter_param();
+ Direct.Gain = direct_param.gain;
+ Direct.GainHF = direct_param.gain_hf;
+ Direct.HFReference = LOWPASSFREQREF;
+ Direct.GainLF = 1.0f;
+ Direct.LFReference = HIGHPASSFREQREF;
mPropsDirty = true;
}
-void ALsource::eax1_set_reverb_mix(const EaxCall& call)
-{
- const auto reverb_mix = call.get_value<EaxSourceException, const decltype(EAXBUFFER_REVERBPROPERTIES::fMix)>();
- eax1_validate_reverb_mix(reverb_mix);
-
- if (eax1_.fMix == reverb_mix)
- return;
-
- eax1_.fMix = reverb_mix;
- eax1_set_efx();
-}
-
-void ALsource::eax_defer_source_direct(
- const EaxCall& call)
-{
- const auto direct =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lDirect)>();
-
- eax_validate_source_direct(direct);
- eax_defer_source_direct(direct);
-}
-
-void ALsource::eax_defer_source_direct_hf(
- const EaxCall& call)
-{
- const auto direct_hf =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lDirectHF)>();
-
- eax_validate_source_direct_hf(direct_hf);
- eax_defer_source_direct_hf(direct_hf);
-}
-
-void ALsource::eax_defer_source_room(
- const EaxCall& call)
-{
- const auto room =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lRoom)>();
-
- eax_validate_source_room(room);
- eax_defer_source_room(room);
-}
-
-void ALsource::eax_defer_source_room_hf(
- const EaxCall& call)
-{
- const auto room_hf =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lRoomHF)>();
-
- eax_validate_source_room_hf(room_hf);
- eax_defer_source_room_hf(room_hf);
-}
-
-void ALsource::eax_defer_source_obstruction(
- const EaxCall& call)
-{
- const auto obstruction =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lObstruction)>();
-
- eax_validate_source_obstruction(obstruction);
- eax_defer_source_obstruction(obstruction);
-}
-
-void ALsource::eax_defer_source_obstruction_lf_ratio(
- const EaxCall& call)
-{
- const auto obstruction_lf_ratio =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flObstructionLFRatio)>();
-
- 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 EaxCall& call)
-{
- const auto occlusion =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lOcclusion)>();
-
- eax_validate_source_occlusion(occlusion);
- eax_defer_source_occlusion(occlusion);
-}
-
-void ALsource::eax_defer_source_occlusion_lf_ratio(
- const EaxCall& call)
-{
- const auto occlusion_lf_ratio =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flOcclusionLFRatio)>();
-
- 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 EaxCall& call)
-{
- const auto occlusion_room_ratio =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flOcclusionRoomRatio)>();
-
- 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 EaxCall& call)
-{
- const auto occlusion_direct_ratio =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flOcclusionDirectRatio)>();
-
- 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 EaxCall& call)
-{
- const auto exclusion =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lExclusion)>();
-
- eax_validate_source_exclusion(exclusion);
- eax_defer_source_exclusion(exclusion);
-}
-
-void ALsource::eax_defer_source_exclusion_lf_ratio(
- const EaxCall& call)
-{
- const auto exclusion_lf_ratio =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flExclusionLFRatio)>();
-
- 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 EaxCall& call)
-{
- const auto outside_volume_hf =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lOutsideVolumeHF)>();
-
- 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 EaxCall& call)
-{
- const auto doppler_factor =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flDopplerFactor)>();
-
- eax_validate_source_doppler_factor(doppler_factor);
- eax_defer_source_doppler_factor(doppler_factor);
-}
-
-void ALsource::eax_defer_source_rolloff_factor(
- const EaxCall& call)
+void ALsource::eax_update_room_filters()
{
- const auto rolloff_factor =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flRolloffFactor)>();
-
- eax_validate_source_rolloff_factor(rolloff_factor);
- eax_defer_source_rolloff_factor(rolloff_factor);
-}
-
-void ALsource::eax_defer_source_room_rolloff_factor(
- const EaxCall& call)
-{
- const auto room_rolloff_factor =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flRoomRolloffFactor)>();
-
- 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 EaxCall& call)
-{
- const auto air_absorption_factor =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::flAirAbsorptionFactor)>();
-
- 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 EaxCall& call)
-{
- const auto flags =
- call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::ulFlags)>();
-
- eax_validate_source_flags(flags, call.get_version());
- eax_defer_source_flags(flags);
-}
-
-void ALsource::eax_defer_source_macro_fx_factor(
- const EaxCall& call)
-{
- const auto macro_fx_factor =
- call.get_value<EaxSourceException, const decltype(EAX50SOURCEPROPERTIES::flMacroFXFactor)>();
-
- 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 EaxCall& call)
-{
- const auto all = call.get_value<EaxSourceException, const EAXSOURCE2DPROPERTIES>();
-
- eax_validate_source_2d_all(all, call.get_version());
- eax_defer_source_2d_all(all);
-}
-
-void ALsource::eax_defer_source_obstruction_all(
- const EaxCall& call)
-{
- const auto all = call.get_value<EaxSourceException, const EAXOBSTRUCTIONPROPERTIES>();
-
- eax_validate_source_obstruction_all(all);
- eax_defer_source_obstruction_all(all);
-}
-
-void ALsource::eax_defer_source_exclusion_all(
- const EaxCall& call)
-{
- const auto all = call.get_value<EaxSourceException, const EAXEXCLUSIONPROPERTIES>();
-
- eax_validate_source_exclusion_all(all);
- eax_defer_source_exclusion_all(all);
-}
-
-void ALsource::eax_defer_source_occlusion_all(
- const EaxCall& call)
-{
- const auto all = call.get_value<EaxSourceException, const EAXOCCLUSIONPROPERTIES>();
-
- eax_validate_source_occlusion_all(all);
- eax_defer_source_occlusion_all(all);
-}
-
-void ALsource::eax_defer_source_all(
- const EaxCall& call)
-{
- const auto eax_version = call.get_version();
-
- if (eax_version == 2)
- {
- const auto all = call.get_value<EaxSourceException, const EAX20BUFFERPROPERTIES>();
-
- eax_validate_source_all(all, eax_version);
- eax_defer_source_all(all);
- }
- else if (eax_version < 5)
- {
- const auto all = call.get_value<EaxSourceException, const EAX30SOURCEPROPERTIES>();
-
- eax_validate_source_all(all, eax_version);
- eax_defer_source_all(all);
- }
- else
- {
- const auto all = call.get_value<EaxSourceException, const EAX50SOURCEPROPERTIES>();
+ for (auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i) {
+ if (!eax_active_fx_slots_[i])
+ continue;
- eax_validate_source_all(all, eax_version);
- eax_defer_source_all(all);
+ auto& fx_slot = eax_al_context_->eax_get_fx_slot(i);
+ const auto& send = eax_.sends[i];
+ const auto& room_param = eax_create_room_filter_param(fx_slot, send);
+ eax_set_al_source_send(&fx_slot, i, room_param);
}
}
-void ALsource::eax_defer_source_speaker_level_all(
- const EaxCall& call)
-{
- const auto speaker_level_properties = call.get_value<EaxSourceException, const EAXSPEAKERLEVELPROPERTIES>();
-
- 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()
+void ALsource::eax_set_efx_outer_gain_hf()
{
- const auto efx_gain_hf = clamp(
+ OuterGainHF = clamp(
level_mb_to_gain(static_cast<float>(eax_.source.lOutsideVolumeHF)),
AL_MIN_CONE_OUTER_GAINHF,
- AL_MAX_CONE_OUTER_GAINHF
- );
-
- OuterGainHF = efx_gain_hf;
+ AL_MAX_CONE_OUTER_GAINHF);
}
-void ALsource::eax_set_doppler_factor()
+void ALsource::eax_set_efx_doppler_factor()
{
DopplerFactor = eax_.source.flDopplerFactor;
}
-void ALsource::eax_set_rolloff_factor()
+void ALsource::eax_set_efx_rolloff_factor()
{
RolloffFactor2 = eax_.source.flRolloffFactor;
}
-void ALsource::eax_set_room_rolloff_factor()
+void ALsource::eax_set_efx_room_rolloff_factor()
{
RoomRolloffFactor = eax_.source.flRoomRolloffFactor;
}
-void ALsource::eax_set_air_absorption_factor()
+void ALsource::eax_set_efx_air_absorption_factor()
{
AirAbsorptionFactor = eax_.source.flAirAbsorptionFactor;
}
-void ALsource::eax_set_direct_hf_auto_flag()
-{
- const auto is_enable = (eax_.source.ulFlags & EAXSOURCEFLAGS_DIRECTHFAUTO) != 0;
-
- DryGainHFAuto = is_enable;
-}
-
-void ALsource::eax_set_room_auto_flag()
-{
- const auto is_enable = (eax_.source.ulFlags & EAXSOURCEFLAGS_ROOMAUTO) != 0;
-
- WetGainAuto = is_enable;
-}
-
-void ALsource::eax_set_room_hf_auto_flag()
-{
- const auto is_enable = (eax_.source.ulFlags & EAXSOURCEFLAGS_ROOMHFAUTO) != 0;
-
- WetGainHFAuto = is_enable;
-}
-
-void ALsource::eax_set_flags()
+void ALsource::eax_set_efx_dry_gain_hf_auto()
{
- eax_set_direct_hf_auto_flag();
- eax_set_room_auto_flag();
- eax_set_room_hf_auto_flag();
- eax_set_speaker_levels();
+ DryGainHFAuto = ((eax_.source.ulFlags & EAXSOURCEFLAGS_DIRECTHFAUTO) != 0);
}
-void ALsource::eax_set_macro_fx_factor()
+void ALsource::eax_set_efx_wet_gain_auto()
{
- // TODO
+ WetGainAuto = ((eax_.source.ulFlags & EAXSOURCEFLAGS_ROOMAUTO) != 0);
}
-void ALsource::eax_set_speaker_levels()
+void ALsource::eax_set_efx_wet_gain_hf_auto()
{
- // TODO
+ WetGainHFAuto = ((eax_.source.ulFlags & EAXSOURCEFLAGS_ROOMHFAUTO) != 0);
}
-void ALsource::eax1_set(const EaxCall& call)
+void ALsource::eax1_set(const EaxCall& call, Eax1Props& props)
{
- switch (call.get_property_id())
- {
+ switch (call.get_property_id()) {
case DSPROPERTY_EAXBUFFER_ALL:
+ eax_defer<Eax1SourceAllValidator>(call, props);
+ break;
+
case DSPROPERTY_EAXBUFFER_REVERBMIX:
- eax1_set_reverb_mix(call);
+ eax_defer<Eax1SourceReverbMixValidator>(call, props.fMix);
break;
default:
- eax_fail("Unsupported property id.");
+ eax_fail_unknown_property_id();
}
}
-void ALsource::eax_apply_deferred()
+void ALsource::eax2_set(const EaxCall& call, Eax2Props& props)
{
- 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;
- }
+ switch (call.get_property_id()) {
+ case DSPROPERTY_EAX20BUFFER_NONE:
+ break;
- eax_ = eax_d_;
+ case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS:
+ eax_defer<Eax2SourceAllValidator>(call, props);
+ break;
- 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;
- }
- }
- }
- }
- }
+ case DSPROPERTY_EAX20BUFFER_DIRECT:
+ eax_defer<Eax2SourceDirectValidator>(call, props.lDirect);
+ break;
- if (eax_source_dirty_misc_flags_ != EaxSourceSourceMiscDirtyFlags{})
- {
- if (eax_source_dirty_misc_flags_.lOutsideVolumeHF)
- {
- eax_set_outside_volume_hf();
- }
+ case DSPROPERTY_EAX20BUFFER_DIRECTHF:
+ eax_defer<Eax2SourceDirectHfValidator>(call, props.lDirectHF);
+ break;
- if (eax_source_dirty_misc_flags_.flDopplerFactor)
- {
- eax_set_doppler_factor();
- }
+ case DSPROPERTY_EAX20BUFFER_ROOM:
+ eax_defer<Eax2SourceRoomValidator>(call, props.lRoom);
+ break;
- if (eax_source_dirty_misc_flags_.flRolloffFactor)
- {
- eax_set_rolloff_factor();
- }
+ case DSPROPERTY_EAX20BUFFER_ROOMHF:
+ eax_defer<Eax2SourceRoomHfValidator>(call, props.lRoomHF);
+ break;
- if (eax_source_dirty_misc_flags_.flRoomRolloffFactor)
- {
- eax_set_room_rolloff_factor();
- }
+ case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR:
+ eax_defer<Eax2SourceRoomRolloffFactorValidator>(call, props.flRoomRolloffFactor);
+ break;
- if (eax_source_dirty_misc_flags_.flAirAbsorptionFactor)
- {
- eax_set_air_absorption_factor();
- }
+ case DSPROPERTY_EAX20BUFFER_OBSTRUCTION:
+ eax_defer<Eax2SourceObstructionValidator>(call, props.lObstruction);
+ break;
- if (eax_source_dirty_misc_flags_.ulFlags)
- {
- eax_set_flags();
- }
+ case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO:
+ eax_defer<Eax2SourceObstructionLfRatioValidator>(call, props.flObstructionLFRatio);
+ break;
- if (eax_source_dirty_misc_flags_.flMacroFXFactor)
- {
- eax_set_macro_fx_factor();
- }
+ case DSPROPERTY_EAX20BUFFER_OCCLUSION:
+ eax_defer<Eax2SourceOcclusionValidator>(call, props.lOcclusion);
+ break;
- mPropsDirty = true;
+ case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO:
+ eax_defer<Eax2SourceOcclusionLfRatioValidator>(call, props.flOcclusionLFRatio);
+ break;
- eax_source_dirty_misc_flags_ = EaxSourceSourceMiscDirtyFlags{};
- }
+ case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO:
+ eax_defer<Eax2SourceOcclusionRoomRatioValidator>(call, props.flOcclusionRoomRatio);
+ break;
- eax_sends_dirty_flags_ = EaxSourceSendsDirtyFlags{};
- eax_source_dirty_filter_flags_ = EaxSourceSourceFilterDirtyFlags{};
-}
+ case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF:
+ eax_defer<Eax2SourceOutsideVolumeHfValidator>(call, props.lOutsideVolumeHF);
+ break;
-void ALsource::eax_set(
- const EaxCall& call)
-{
- const auto version = call.get_version();
+ case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR:
+ eax_defer<Eax2SourceAirAbsorptionFactorValidator>(call, props.flAirAbsorptionFactor);
+ break;
- if (version == 1)
- {
- eax1_set(call);
- return;
- }
+ case DSPROPERTY_EAX20BUFFER_FLAGS:
+ eax_defer<Eax2SourceFlagsValidator>(call, props.dwFlags);
+ break;
- const auto property_id = (version == 2 ? eax2_translate_property_id(call) : call.get_property_id());
+ default:
+ eax_fail_unknown_property_id();
+ }
+}
- switch (property_id)
- {
+void ALsource::eax3_set(const EaxCall& call, Eax3Props& props)
+{
+ switch (call.get_property_id()) {
case EAXSOURCE_NONE:
break;
case EAXSOURCE_ALLPARAMETERS:
- eax_defer_source_all(call);
+ eax_defer<Eax3SourceAllValidator>(call, props);
break;
case EAXSOURCE_OBSTRUCTIONPARAMETERS:
- eax_defer_source_obstruction_all(call);
+ eax_defer_sub<Eax4ObstructionValidator, EAXOBSTRUCTIONPROPERTIES>(call, props.lObstruction);
break;
case EAXSOURCE_OCCLUSIONPARAMETERS:
- eax_defer_source_occlusion_all(call);
+ eax_defer_sub<Eax4OcclusionValidator, EAXOCCLUSIONPROPERTIES>(call, props.lOcclusion);
break;
case EAXSOURCE_EXCLUSIONPARAMETERS:
- eax_defer_source_exclusion_all(call);
+ eax_defer_sub<Eax4ExclusionValidator, EAXEXCLUSIONPROPERTIES>(call, props.lExclusion);
break;
case EAXSOURCE_DIRECT:
- eax_defer_source_direct(call);
+ eax_defer<Eax2SourceDirectValidator>(call, props.lDirect);
break;
case EAXSOURCE_DIRECTHF:
- eax_defer_source_direct_hf(call);
+ eax_defer<Eax2SourceDirectHfValidator>(call, props.lDirectHF);
break;
case EAXSOURCE_ROOM:
- eax_defer_source_room(call);
+ eax_defer<Eax2SourceRoomValidator>(call, props.lRoom);
break;
case EAXSOURCE_ROOMHF:
- eax_defer_source_room_hf(call);
+ eax_defer<Eax2SourceRoomHfValidator>(call, props.lRoomHF);
break;
case EAXSOURCE_OBSTRUCTION:
- eax_defer_source_obstruction(call);
+ eax_defer<Eax2SourceObstructionValidator>(call, props.lObstruction);
break;
case EAXSOURCE_OBSTRUCTIONLFRATIO:
- eax_defer_source_obstruction_lf_ratio(call);
+ eax_defer<Eax2SourceObstructionLfRatioValidator>(call, props.flObstructionLFRatio);
break;
case EAXSOURCE_OCCLUSION:
- eax_defer_source_occlusion(call);
+ eax_defer<Eax2SourceOcclusionValidator>(call, props.lOcclusion);
break;
case EAXSOURCE_OCCLUSIONLFRATIO:
- eax_defer_source_occlusion_lf_ratio(call);
+ eax_defer<Eax2SourceOcclusionLfRatioValidator>(call, props.flOcclusionLFRatio);
break;
case EAXSOURCE_OCCLUSIONROOMRATIO:
- eax_defer_source_occlusion_room_ratio(call);
+ eax_defer<Eax2SourceOcclusionRoomRatioValidator>(call, props.flOcclusionRoomRatio);
break;
case EAXSOURCE_OCCLUSIONDIRECTRATIO:
- eax_defer_source_occlusion_direct_ratio(call);
+ eax_defer<Eax3SourceOcclusionDirectRatioValidator>(call, props.flOcclusionDirectRatio);
break;
case EAXSOURCE_EXCLUSION:
- eax_defer_source_exclusion(call);
+ eax_defer<Eax3SourceExclusionValidator>(call, props.lExclusion);
break;
case EAXSOURCE_EXCLUSIONLFRATIO:
- eax_defer_source_exclusion_lf_ratio(call);
+ eax_defer<Eax3SourceExclusionLfRatioValidator>(call, props.flExclusionLFRatio);
break;
case EAXSOURCE_OUTSIDEVOLUMEHF:
- eax_defer_source_outside_volume_hf(call);
+ eax_defer<Eax2SourceOutsideVolumeHfValidator>(call, props.lOutsideVolumeHF);
break;
case EAXSOURCE_DOPPLERFACTOR:
- eax_defer_source_doppler_factor(call);
+ eax_defer<Eax3SourceDopplerFactorValidator>(call, props.flDopplerFactor);
break;
case EAXSOURCE_ROLLOFFFACTOR:
- eax_defer_source_rolloff_factor(call);
+ eax_defer<Eax3SourceRolloffFactorValidator>(call, props.flRolloffFactor);
break;
case EAXSOURCE_ROOMROLLOFFFACTOR:
- eax_defer_source_room_rolloff_factor(call);
+ eax_defer<Eax2SourceRoomRolloffFactorValidator>(call, props.flRoomRolloffFactor);
break;
case EAXSOURCE_AIRABSORPTIONFACTOR:
- eax_defer_source_air_absorption_factor(call);
+ eax_defer<Eax2SourceAirAbsorptionFactorValidator>(call, props.flAirAbsorptionFactor);
+ break;
+
+ case EAXSOURCE_FLAGS:
+ eax_defer<Eax2SourceFlagsValidator>(call, props.ulFlags);
break;
+ default:
+ eax_fail_unknown_property_id();
+ }
+}
+
+void ALsource::eax4_set(const EaxCall& call, Eax4Props& props)
+{
+ switch (call.get_property_id()) {
+ case EAXSOURCE_NONE:
+ case EAXSOURCE_ALLPARAMETERS:
+ case EAXSOURCE_OBSTRUCTIONPARAMETERS:
+ case EAXSOURCE_OCCLUSIONPARAMETERS:
+ case EAXSOURCE_EXCLUSIONPARAMETERS:
+ case EAXSOURCE_DIRECT:
+ case EAXSOURCE_DIRECTHF:
+ case EAXSOURCE_ROOM:
+ case EAXSOURCE_ROOMHF:
+ case EAXSOURCE_OBSTRUCTION:
+ case EAXSOURCE_OBSTRUCTIONLFRATIO:
+ case EAXSOURCE_OCCLUSION:
+ case EAXSOURCE_OCCLUSIONLFRATIO:
+ case EAXSOURCE_OCCLUSIONROOMRATIO:
+ case EAXSOURCE_OCCLUSIONDIRECTRATIO:
+ case EAXSOURCE_EXCLUSION:
+ case EAXSOURCE_EXCLUSIONLFRATIO:
+ case EAXSOURCE_OUTSIDEVOLUMEHF:
+ case EAXSOURCE_DOPPLERFACTOR:
+ case EAXSOURCE_ROLLOFFFACTOR:
+ case EAXSOURCE_ROOMROLLOFFFACTOR:
+ case EAXSOURCE_AIRABSORPTIONFACTOR:
case EAXSOURCE_FLAGS:
- eax_defer_source_flags(call);
+ eax3_set(call, props.source);
break;
case EAXSOURCE_SENDPARAMETERS:
- eax_defer_send(call);
+ eax4_defer_sends<Eax4SendValidator, EAXSOURCESENDPROPERTIES>(call, props.sends);
break;
case EAXSOURCE_ALLSENDPARAMETERS:
- eax_defer_send_all(call);
+ eax4_defer_sends<Eax4AllSendValidator, EAXSOURCEALLSENDPROPERTIES>(call, props.sends);
break;
case EAXSOURCE_OCCLUSIONSENDPARAMETERS:
- eax_defer_send_occlusion_all(call);
+ eax4_defer_sends<Eax4OcclusionSendValidator, EAXSOURCEOCCLUSIONSENDPROPERTIES>(call, props.sends);
break;
case EAXSOURCE_EXCLUSIONSENDPARAMETERS:
- eax_defer_send_exclusion_all(call);
+ eax4_defer_sends<Eax4ExclusionSendValidator, EAXSOURCEEXCLUSIONSENDPROPERTIES>(call, props.sends);
break;
case EAXSOURCE_ACTIVEFXSLOTID:
- eax_defer_active_fx_slots(call);
+ eax4_defer_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots);
break;
- case EAXSOURCE_MACROFXFACTOR:
- eax_defer_source_macro_fx_factor(call);
- break;
+ default:
+ eax_fail_unknown_property_id();
+ }
+}
- case EAXSOURCE_SPEAKERLEVELS:
- eax_defer_source_speaker_level_all(call);
- break;
+void ALsource::eax5_defer_all_2d(const EaxCall& call, EAX50SOURCEPROPERTIES& props)
+{
+ const auto& src_props = call.get_value<Exception, const EAXSOURCE2DPROPERTIES>();
+ Eax5SourceAll2dValidator{}(src_props);
+ props.lDirect = src_props.lDirect;
+ props.lDirectHF = src_props.lDirectHF;
+ props.lRoom = src_props.lRoom;
+ props.lRoomHF = src_props.lRoomHF;
+ props.ulFlags = src_props.ulFlags;
+}
- case EAXSOURCE_ALL2DPARAMETERS:
- eax_defer_source_2d_all(call);
- break;
+void ALsource::eax5_defer_speaker_levels(const EaxCall& call, EaxSpeakerLevels& props)
+{
+ const auto values = call.get_values<const EAXSPEAKERLEVELPROPERTIES>(eax_max_speakers);
+ std::for_each(values.cbegin(), values.cend(), Eax5SpeakerAllValidator{});
- default:
- eax_fail("Unsupported property id.");
+ for (const auto& value : values) {
+ const auto index = static_cast<size_t>(value.lSpeakerID - EAXSPEAKER_FRONT_LEFT);
+ props[index].lLevel = value.lLevel;
}
}
-const GUID& ALsource::eax_get_send_fx_slot_guid(
- int eax_version,
- EaxFxSlotIndexValue fx_slot_index)
+void ALsource::eax5_set(const EaxCall& call, Eax5Props& props)
{
- switch (eax_version)
- {
- case 4:
- switch (fx_slot_index)
- {
- case 0:
- return EAXPROPERTYID_EAX40_FXSlot0;
+ switch (call.get_property_id()) {
+ case EAXSOURCE_NONE:
+ break;
- case 1:
- return EAXPROPERTYID_EAX40_FXSlot1;
+ case EAXSOURCE_ALLPARAMETERS:
+ eax_defer<Eax5SourceAllValidator>(call, props.source);
+ break;
- case 2:
- return EAXPROPERTYID_EAX40_FXSlot2;
+ case EAXSOURCE_OBSTRUCTIONPARAMETERS:
+ case EAXSOURCE_OCCLUSIONPARAMETERS:
+ case EAXSOURCE_EXCLUSIONPARAMETERS:
+ case EAXSOURCE_DIRECT:
+ case EAXSOURCE_DIRECTHF:
+ case EAXSOURCE_ROOM:
+ case EAXSOURCE_ROOMHF:
+ case EAXSOURCE_OBSTRUCTION:
+ case EAXSOURCE_OBSTRUCTIONLFRATIO:
+ case EAXSOURCE_OCCLUSION:
+ case EAXSOURCE_OCCLUSIONLFRATIO:
+ case EAXSOURCE_OCCLUSIONROOMRATIO:
+ case EAXSOURCE_OCCLUSIONDIRECTRATIO:
+ case EAXSOURCE_EXCLUSION:
+ case EAXSOURCE_EXCLUSIONLFRATIO:
+ case EAXSOURCE_OUTSIDEVOLUMEHF:
+ case EAXSOURCE_DOPPLERFACTOR:
+ case EAXSOURCE_ROLLOFFFACTOR:
+ case EAXSOURCE_ROOMROLLOFFFACTOR:
+ case EAXSOURCE_AIRABSORPTIONFACTOR:
+ case EAXSOURCE_FLAGS:
+ eax3_set(call, props.source);
+ break;
- case 3:
- return EAXPROPERTYID_EAX40_FXSlot3;
+ case EAXSOURCE_SENDPARAMETERS:
+ eax5_defer_sends<Eax5SendValidator, EAXSOURCESENDPROPERTIES>(call, props.sends);
+ break;
- default:
- eax_fail("FX slot index out of range.");
- }
+ case EAXSOURCE_ALLSENDPARAMETERS:
+ eax5_defer_sends<Eax5AllSendValidator, EAXSOURCEALLSENDPROPERTIES>(call, props.sends);
+ break;
- case 5:
- switch (fx_slot_index)
- {
- case 0:
- return EAXPROPERTYID_EAX50_FXSlot0;
+ case EAXSOURCE_OCCLUSIONSENDPARAMETERS:
+ eax5_defer_sends<Eax5OcclusionSendValidator, EAXSOURCEOCCLUSIONSENDPROPERTIES>(call, props.sends);
+ break;
- case 1:
- return EAXPROPERTYID_EAX50_FXSlot1;
+ case EAXSOURCE_EXCLUSIONSENDPARAMETERS:
+ eax5_defer_sends<Eax5ExclusionSendValidator, EAXSOURCEEXCLUSIONSENDPROPERTIES>(call, props.sends);
+ break;
- case 2:
- return EAXPROPERTYID_EAX50_FXSlot2;
+ case EAXSOURCE_ACTIVEFXSLOTID:
+ eax5_defer_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots);
+ break;
- case 3:
- return EAXPROPERTYID_EAX50_FXSlot3;
+ case EAXSOURCE_MACROFXFACTOR:
+ eax_defer<Eax5SourceMacroFXFactorValidator>(call, props.source.flMacroFXFactor);
+ break;
- default:
- eax_fail("FX slot index out of range.");
- }
+ case EAXSOURCE_SPEAKERLEVELS:
+ eax5_defer_speaker_levels(call, props.speaker_levels);
+ break;
+
+ case EAXSOURCE_ALL2DPARAMETERS:
+ eax5_defer_all_2d(call, props.source);
+ break;
default:
- eax_fail("Unsupported EAX version.");
+ eax_fail_unknown_property_id();
}
}
-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)
+void ALsource::eax_set(const EaxCall& call)
{
- 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;
+ switch (call.get_version()) {
+ case 1: eax1_set(call, eax1_.d); break;
+ case 2: eax2_set(call, eax2_.d); break;
+ case 3: eax3_set(call, eax3_.d); break;
+ case 4: eax4_set(call, eax4_.d); break;
+ case 5: eax5_set(call, eax5_.d); break;
+ default: eax_fail_unknown_property_id();
+ }
}
-void ALsource::eax1_get(const EaxCall& call)
+void ALsource::eax1_get(const EaxCall& call, const Eax1Props& props)
{
- switch (call.get_property_id())
- {
+ switch (call.get_property_id()) {
case DSPROPERTY_EAXBUFFER_ALL:
case DSPROPERTY_EAXBUFFER_REVERBMIX:
- call.set_value<EaxSourceException>(eax1_);
+ call.set_value<Exception>(props.fMix);
break;
default:
- eax_fail("Unsupported property id.");
+ eax_fail_unknown_property_id();
}
}
-void ALsource::eax_api_get_source_all_v2(
- const EaxCall& call)
+void ALsource::eax2_get(const EaxCall& call, const Eax2Props& props)
{
- 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;
-
- call.set_value<EaxSourceException>(eax_2_all);
-}
+ switch (call.get_property_id()) {
+ case DSPROPERTY_EAX20BUFFER_NONE:
+ break;
-void ALsource::eax_api_get_source_all_v3(
- const EaxCall& call)
-{
- call.set_value<EaxSourceException>(static_cast<const EAX30SOURCEPROPERTIES&>(eax_.source));
-}
+ case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS:
+ call.set_value<Exception>(props);
+ break;
-void ALsource::eax_api_get_source_all_v5(
- const EaxCall& call)
-{
- call.set_value<EaxSourceException>(eax_.source);
-}
+ case DSPROPERTY_EAX20BUFFER_DIRECT:
+ call.set_value<Exception>(props.lDirect);
+ break;
-void ALsource::eax_api_get_source_all(
- const EaxCall& call)
-{
- switch (call.get_version())
- {
- case 2:
- eax_api_get_source_all_v2(call);
+ case DSPROPERTY_EAX20BUFFER_DIRECTHF:
+ call.set_value<Exception>(props.lDirectHF);
break;
- case 3:
- case 4:
- eax_api_get_source_all_v3(call);
+ case DSPROPERTY_EAX20BUFFER_ROOM:
+ call.set_value<Exception>(props.lRoom);
break;
- case 5:
- eax_api_get_source_all_v5(call);
+ case DSPROPERTY_EAX20BUFFER_ROOMHF:
+ call.set_value<Exception>(props.lRoomHF);
break;
- default:
- eax_fail("Unsupported EAX version.");
- }
-}
+ case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR:
+ call.set_value<Exception>(props.flRoomRolloffFactor);
+ break;
-void ALsource::eax_api_get_source_all_obstruction(
- const EaxCall& call)
-{
- auto eax_obstruction_all = EAXOBSTRUCTIONPROPERTIES{};
- eax_obstruction_all.lObstruction = eax_.source.lObstruction;
- eax_obstruction_all.flObstructionLFRatio = eax_.source.flObstructionLFRatio;
+ case DSPROPERTY_EAX20BUFFER_OBSTRUCTION:
+ call.set_value<Exception>(props.lObstruction);
+ break;
- call.set_value<EaxSourceException>(eax_obstruction_all);
-}
+ case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO:
+ call.set_value<Exception>(props.flObstructionLFRatio);
+ break;
-void ALsource::eax_api_get_source_all_occlusion(
- const EaxCall& call)
-{
- auto eax_occlusion_all = EAXOCCLUSIONPROPERTIES{};
- eax_occlusion_all.lOcclusion = eax_.source.lOcclusion;
- eax_occlusion_all.flOcclusionLFRatio = eax_.source.flOcclusionLFRatio;
- eax_occlusion_all.flOcclusionRoomRatio = eax_.source.flOcclusionRoomRatio;
- eax_occlusion_all.flOcclusionDirectRatio = eax_.source.flOcclusionDirectRatio;
+ case DSPROPERTY_EAX20BUFFER_OCCLUSION:
+ call.set_value<Exception>(props.lOcclusion);
+ break;
- call.set_value<EaxSourceException>(eax_occlusion_all);
-}
+ case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO:
+ call.set_value<Exception>(props.flOcclusionLFRatio);
+ break;
-void ALsource::eax_api_get_source_all_exclusion(
- const EaxCall& call)
-{
- auto eax_exclusion_all = EAXEXCLUSIONPROPERTIES{};
- eax_exclusion_all.lExclusion = eax_.source.lExclusion;
- eax_exclusion_all.flExclusionLFRatio = eax_.source.flExclusionLFRatio;
+ case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO:
+ call.set_value<Exception>(props.flOcclusionRoomRatio);
+ break;
- call.set_value<EaxSourceException>(eax_exclusion_all);
-}
+ case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF:
+ call.set_value<Exception>(props.lOutsideVolumeHF);
+ break;
-void ALsource::eax_api_get_source_active_fx_slot_id(
- const EaxCall& call)
-{
- switch (call.get_version())
- {
- case 4:
- {
- const auto& active_fx_slots = reinterpret_cast<const EAX40ACTIVEFXSLOTS&>(eax_.active_fx_slots);
- call.set_value<EaxSourceException>(active_fx_slots);
- }
+ case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR:
+ call.set_value<Exception>(props.flAirAbsorptionFactor);
break;
- case 5:
- {
- const auto& active_fx_slots = reinterpret_cast<const EAX50ACTIVEFXSLOTS&>(eax_.active_fx_slots);
- call.set_value<EaxSourceException>(active_fx_slots);
- }
+ case DSPROPERTY_EAX20BUFFER_FLAGS:
+ call.set_value<Exception>(props.dwFlags);
break;
default:
- eax_fail("Unsupported EAX version.");
+ eax_fail_unknown_property_id();
}
}
-void ALsource::eax_api_get_source_all_2d(
- const EaxCall& call)
+void ALsource::eax3_get_obstruction(const EaxCall& call, const Eax3Props& props)
{
- 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;
-
- call.set_value<EaxSourceException>(eax_2d_all);
+ const auto& subprops = reinterpret_cast<const EAXOBSTRUCTIONPROPERTIES&>(props.lObstruction);
+ call.set_value<Exception>(subprops);
}
-void ALsource::eax_api_get_source_speaker_level_all(
- const EaxCall& call)
+void ALsource::eax3_get_occlusion(const EaxCall& call, const Eax3Props& props)
{
- auto& all = call.get_value<EaxSourceException, EAXSPEAKERLEVELPROPERTIES>();
-
- eax_validate_source_speaker_id(all.lSpeakerID);
- const auto speaker_index = static_cast<std::size_t>(all.lSpeakerID - 1);
- all.lLevel = eax_.speaker_levels[speaker_index];
+ const auto& subprops = reinterpret_cast<const EAXOCCLUSIONPROPERTIES&>(props.lOcclusion);
+ call.set_value<Exception>(subprops);
}
-void ALsource::eax_get(
- const EaxCall& call)
+void ALsource::eax3_get_exclusion(const EaxCall& call, const Eax3Props& props)
{
- const auto version = call.get_version();
-
- if (version == 1)
- {
- eax1_get(call);
- return;
- }
-
- const auto property_id = (version == 2 ? eax2_translate_property_id(call) : call.get_property_id());
+ const auto& subprops = reinterpret_cast<const EAXEXCLUSIONPROPERTIES&>(props.lExclusion);
+ call.set_value<Exception>(subprops);
+}
- switch (property_id)
- {
+void ALsource::eax3_get(const EaxCall& call, const Eax3Props& props)
+{
+ switch (call.get_property_id()) {
case EAXSOURCE_NONE:
break;
case EAXSOURCE_ALLPARAMETERS:
- eax_api_get_source_all(call);
+ call.set_value<Exception>(props);
break;
case EAXSOURCE_OBSTRUCTIONPARAMETERS:
- eax_api_get_source_all_obstruction(call);
+ eax3_get_obstruction(call, props);
break;
case EAXSOURCE_OCCLUSIONPARAMETERS:
- eax_api_get_source_all_occlusion(call);
+ eax3_get_occlusion(call, props);
break;
case EAXSOURCE_EXCLUSIONPARAMETERS:
- eax_api_get_source_all_exclusion(call);
+ eax3_get_exclusion(call, props);
break;
case EAXSOURCE_DIRECT:
- call.set_value<EaxSourceException>(eax_.source.lDirect);
+ call.set_value<Exception>(props.lDirect);
break;
case EAXSOURCE_DIRECTHF:
- call.set_value<EaxSourceException>(eax_.source.lDirectHF);
+ call.set_value<Exception>(props.lDirectHF);
break;
case EAXSOURCE_ROOM:
- call.set_value<EaxSourceException>(eax_.source.lRoom);
+ call.set_value<Exception>(props.lRoom);
break;
case EAXSOURCE_ROOMHF:
- call.set_value<EaxSourceException>(eax_.source.lRoomHF);
+ call.set_value<Exception>(props.lRoomHF);
break;
case EAXSOURCE_OBSTRUCTION:
- call.set_value<EaxSourceException>(eax_.source.lObstruction);
+ call.set_value<Exception>(props.lObstruction);
break;
case EAXSOURCE_OBSTRUCTIONLFRATIO:
- call.set_value<EaxSourceException>(eax_.source.flObstructionLFRatio);
+ call.set_value<Exception>(props.flObstructionLFRatio);
break;
case EAXSOURCE_OCCLUSION:
- call.set_value<EaxSourceException>(eax_.source.lOcclusion);
+ call.set_value<Exception>(props.lOcclusion);
break;
case EAXSOURCE_OCCLUSIONLFRATIO:
- call.set_value<EaxSourceException>(eax_.source.flOcclusionLFRatio);
+ call.set_value<Exception>(props.flOcclusionLFRatio);
break;
case EAXSOURCE_OCCLUSIONROOMRATIO:
- call.set_value<EaxSourceException>(eax_.source.flOcclusionRoomRatio);
+ call.set_value<Exception>(props.flOcclusionRoomRatio);
break;
case EAXSOURCE_OCCLUSIONDIRECTRATIO:
- call.set_value<EaxSourceException>(eax_.source.flOcclusionDirectRatio);
+ call.set_value<Exception>(props.flOcclusionDirectRatio);
break;
case EAXSOURCE_EXCLUSION:
- call.set_value<EaxSourceException>(eax_.source.lExclusion);
+ call.set_value<Exception>(props.lExclusion);
break;
case EAXSOURCE_EXCLUSIONLFRATIO:
- call.set_value<EaxSourceException>(eax_.source.flExclusionLFRatio);
+ call.set_value<Exception>(props.flExclusionLFRatio);
break;
case EAXSOURCE_OUTSIDEVOLUMEHF:
- call.set_value<EaxSourceException>(eax_.source.lOutsideVolumeHF);
+ call.set_value<Exception>(props.lOutsideVolumeHF);
break;
case EAXSOURCE_DOPPLERFACTOR:
- call.set_value<EaxSourceException>(eax_.source.flDopplerFactor);
+ call.set_value<Exception>(props.flDopplerFactor);
break;
case EAXSOURCE_ROLLOFFFACTOR:
- call.set_value<EaxSourceException>(eax_.source.flRolloffFactor);
+ call.set_value<Exception>(props.flRolloffFactor);
break;
case EAXSOURCE_ROOMROLLOFFFACTOR:
- call.set_value<EaxSourceException>(eax_.source.flRoomRolloffFactor);
+ call.set_value<Exception>(props.flRoomRolloffFactor);
+ break;
+
+ case EAXSOURCE_AIRABSORPTIONFACTOR:
+ call.set_value<Exception>(props.flAirAbsorptionFactor);
+ break;
+
+ case EAXSOURCE_FLAGS:
+ call.set_value<Exception>(props.ulFlags);
+ break;
+
+ default:
+ eax_fail_unknown_property_id();
+ }
+}
+
+void ALsource::eax4_get(const EaxCall& call, const Eax4Props& props)
+{
+ switch (call.get_property_id()) {
+ case EAXSOURCE_NONE:
break;
+ case EAXSOURCE_ALLPARAMETERS:
+ case EAXSOURCE_OBSTRUCTIONPARAMETERS:
+ case EAXSOURCE_OCCLUSIONPARAMETERS:
+ case EAXSOURCE_EXCLUSIONPARAMETERS:
+ case EAXSOURCE_DIRECT:
+ case EAXSOURCE_DIRECTHF:
+ case EAXSOURCE_ROOM:
+ case EAXSOURCE_ROOMHF:
+ case EAXSOURCE_OBSTRUCTION:
+ case EAXSOURCE_OBSTRUCTIONLFRATIO:
+ case EAXSOURCE_OCCLUSION:
+ case EAXSOURCE_OCCLUSIONLFRATIO:
+ case EAXSOURCE_OCCLUSIONROOMRATIO:
+ case EAXSOURCE_OCCLUSIONDIRECTRATIO:
+ case EAXSOURCE_EXCLUSION:
+ case EAXSOURCE_EXCLUSIONLFRATIO:
+ case EAXSOURCE_OUTSIDEVOLUMEHF:
+ case EAXSOURCE_DOPPLERFACTOR:
+ case EAXSOURCE_ROLLOFFFACTOR:
+ case EAXSOURCE_ROOMROLLOFFFACTOR:
case EAXSOURCE_AIRABSORPTIONFACTOR:
- call.set_value<EaxSourceException>(eax_.source.flAirAbsorptionFactor);
+ case EAXSOURCE_FLAGS:
+ eax3_get(call, props.source);
break;
+ case EAXSOURCE_SENDPARAMETERS:
+ eax_get_sends<EAXSOURCESENDPROPERTIES>(call, props.sends);
+ break;
+
+ case EAXSOURCE_ALLSENDPARAMETERS:
+ eax_get_sends<EAXSOURCEALLSENDPROPERTIES>(call, props.sends);
+ break;
+
+ case EAXSOURCE_OCCLUSIONSENDPARAMETERS:
+ eax_get_sends<EAXSOURCEOCCLUSIONSENDPROPERTIES>(call, props.sends);
+ break;
+
+ case EAXSOURCE_EXCLUSIONSENDPARAMETERS:
+ eax_get_sends<EAXSOURCEEXCLUSIONSENDPROPERTIES>(call, props.sends);
+ break;
+
+ case EAXSOURCE_ACTIVEFXSLOTID:
+ call.set_value<Exception>(props.active_fx_slots);
+ break;
+
+ default:
+ eax_fail_unknown_property_id();
+ }
+}
+
+void ALsource::eax5_get_all_2d(const EaxCall& call, const EAX50SOURCEPROPERTIES& props)
+{
+ auto& subprops = call.get_value<Exception, EAXSOURCE2DPROPERTIES>();
+ subprops.lDirect = props.lDirect;
+ subprops.lDirectHF = props.lDirectHF;
+ subprops.lRoom = props.lRoom;
+ subprops.lRoomHF = props.lRoomHF;
+ subprops.ulFlags = props.ulFlags;
+}
+
+void ALsource::eax5_get_speaker_levels(const EaxCall& call, const EaxSpeakerLevels& props)
+{
+ const auto subprops = call.get_values<EAXSPEAKERLEVELPROPERTIES>(eax_max_speakers);
+ std::uninitialized_copy_n(props.cbegin(), subprops.size(), subprops.begin());
+}
+
+void ALsource::eax5_get(const EaxCall& call, const Eax5Props& props)
+{
+ switch (call.get_property_id()) {
+ case EAXSOURCE_NONE:
+ break;
+
+ case EAXSOURCE_ALLPARAMETERS:
+ case EAXSOURCE_OBSTRUCTIONPARAMETERS:
+ case EAXSOURCE_OCCLUSIONPARAMETERS:
+ case EAXSOURCE_EXCLUSIONPARAMETERS:
+ case EAXSOURCE_DIRECT:
+ case EAXSOURCE_DIRECTHF:
+ case EAXSOURCE_ROOM:
+ case EAXSOURCE_ROOMHF:
+ case EAXSOURCE_OBSTRUCTION:
+ case EAXSOURCE_OBSTRUCTIONLFRATIO:
+ case EAXSOURCE_OCCLUSION:
+ case EAXSOURCE_OCCLUSIONLFRATIO:
+ case EAXSOURCE_OCCLUSIONROOMRATIO:
+ case EAXSOURCE_OCCLUSIONDIRECTRATIO:
+ case EAXSOURCE_EXCLUSION:
+ case EAXSOURCE_EXCLUSIONLFRATIO:
+ case EAXSOURCE_OUTSIDEVOLUMEHF:
+ case EAXSOURCE_DOPPLERFACTOR:
+ case EAXSOURCE_ROLLOFFFACTOR:
+ case EAXSOURCE_ROOMROLLOFFFACTOR:
+ case EAXSOURCE_AIRABSORPTIONFACTOR:
case EAXSOURCE_FLAGS:
- call.set_value<EaxSourceException>(eax_.source.ulFlags);
+ eax3_get(call, props.source);
break;
case EAXSOURCE_SENDPARAMETERS:
- eax_api_get_send_properties<EaxSourceException, EAXSOURCESENDPROPERTIES>(call);
+ eax_get_sends<EAXSOURCESENDPROPERTIES>(call, props.sends);
break;
case EAXSOURCE_ALLSENDPARAMETERS:
- eax_api_get_send_properties<EaxSourceException, EAXSOURCEALLSENDPROPERTIES>(call);
+ eax_get_sends<EAXSOURCEALLSENDPROPERTIES>(call, props.sends);
break;
case EAXSOURCE_OCCLUSIONSENDPARAMETERS:
- eax_api_get_send_properties<EaxSourceException, EAXSOURCEOCCLUSIONSENDPROPERTIES>(call);
+ eax_get_sends<EAXSOURCEOCCLUSIONSENDPROPERTIES>(call, props.sends);
break;
case EAXSOURCE_EXCLUSIONSENDPARAMETERS:
- eax_api_get_send_properties<EaxSourceException, EAXSOURCEEXCLUSIONSENDPROPERTIES>(call);
+ eax_get_sends<EAXSOURCEEXCLUSIONSENDPROPERTIES>(call, props.sends);
break;
case EAXSOURCE_ACTIVEFXSLOTID:
- eax_api_get_source_active_fx_slot_id(call);
+ call.set_value<Exception>(props.active_fx_slots);
break;
case EAXSOURCE_MACROFXFACTOR:
- call.set_value<EaxSourceException>(eax_.source.flMacroFXFactor);
+ call.set_value<Exception>(props.source.flMacroFXFactor);
break;
case EAXSOURCE_SPEAKERLEVELS:
- eax_api_get_source_speaker_level_all(call);
+ call.set_value<Exception>(props.speaker_levels);
break;
case EAXSOURCE_ALL2DPARAMETERS:
- eax_api_get_source_all_2d(call);
+ eax5_get_all_2d(call, props.source);
break;
default:
- eax_fail("Unsupported property id.");
+ eax_fail_unknown_property_id();
+ }
+}
+
+void ALsource::eax_get(const EaxCall& call)
+{
+ switch (call.get_version()) {
+ case 1: eax1_get(call, eax1_.i); break;
+ case 2: eax2_get(call, eax2_.i); break;
+ case 3: eax3_get(call, eax3_.i); break;
+ case 4: eax4_get(call, eax4_.i); break;
+ case 5: eax5_get(call, eax5_.i); break;
+ default: eax_fail_unknown_version();
}
}
-void ALsource::eax_set_al_source_send(
- ALeffectslot *slot,
- size_t sendidx,
- const EaxAlLowPassParam &filter)
+void ALsource::eax_set_al_source_send(ALeffectslot *slot, size_t sendidx, const EaxAlLowPassParam &filter)
{
if(sendidx >= EAX_MAX_FXSLOTS)
return;
@@ -6088,12 +4851,113 @@ void ALsource::eax_set_al_source_send(
send.GainLF = 1.0f;
send.LFReference = HIGHPASSFREQREF;
- if(slot) IncrementRef(slot->ref);
+ if(slot != nullptr)
+ IncrementRef(slot->ref);
if(auto *oldslot = send.Slot)
DecrementRef(oldslot->ref);
- send.Slot = slot;
+ send.Slot = slot;
mPropsDirty = true;
}
+void ALsource::eax_commit_active_fx_slots()
+{
+ // Mark all slots as non-active.
+ eax_active_fx_slots_.fill(false);
+
+ // Mark primary FX slot as active.
+ if (eax_primary_fx_slot_id_.has_value())
+ eax_active_fx_slots_[*eax_primary_fx_slot_id_] = true;
+
+ // Mark the other FX slots as active.
+ for (const auto& slot_id : eax_.active_fx_slots.guidActiveFXSlots) {
+ if (slot_id == EAXPROPERTYID_EAX50_FXSlot0)
+ eax_active_fx_slots_[0] = true;
+ else if (slot_id == EAXPROPERTYID_EAX50_FXSlot1)
+ eax_active_fx_slots_[1] = true;
+ else if (slot_id == EAXPROPERTYID_EAX50_FXSlot2)
+ eax_active_fx_slots_[2] = true;
+ else if (slot_id == EAXPROPERTYID_EAX50_FXSlot3)
+ eax_active_fx_slots_[3] = true;
+ }
+
+ // Deactivate EFX auxiliary effect slots.
+ for (auto i = size_t{}; i < EAX_MAX_FXSLOTS; ++i) {
+ if (!eax_active_fx_slots_[i])
+ eax_set_al_source_send(nullptr, i, EaxAlLowPassParam{1.0f, 1.0f});
+ }
+}
+
+void ALsource::eax_commit_filters()
+{
+ eax_update_direct_filter();
+ eax_update_room_filters();
+}
+
+void ALsource::eax_commit(EaxCommitType commit_type)
+{
+ const auto primary_fx_slot_id = eax_al_context_->eax_get_primary_fx_slot_index();
+ const auto is_primary_fx_slot_id_changed = (eax_primary_fx_slot_id_ == primary_fx_slot_id);
+
+ const auto is_forced = (
+ eax_is_version_changed_ ||
+ is_primary_fx_slot_id_changed ||
+ commit_type == EaxCommitType::forced);
+
+ eax_is_version_changed_ = false;
+ eax_primary_fx_slot_id_ = primary_fx_slot_id;
+
+ switch (eax_version_) {
+ case 1:
+ if (!is_forced && eax1_.i == eax1_.d)
+ return;
+ eax1_.i = eax1_.d;
+ eax1_translate(eax1_.i, eax_);
+ break;
+
+ case 2:
+ if (!is_forced && eax2_.i == eax2_.d)
+ return;
+ eax2_.i = eax2_.d;
+ eax2_translate(eax2_.i, eax_);
+ break;
+
+ case 3:
+ if (!is_forced && eax3_.i == eax3_.d)
+ return;
+ eax3_.i = eax3_.d;
+ eax3_translate(eax3_.i, eax_);
+ break;
+
+ case 4:
+ if (!is_forced && eax4_.i == eax4_.d)
+ return;
+ eax4_.i = eax4_.d;
+ eax4_translate(eax4_.i, eax_);
+ break;
+
+ case 5:
+ if (!is_forced && eax5_.i == eax5_.d)
+ return;
+ eax5_.i = eax5_.d;
+ eax_ = eax5_.d;
+ break;
+
+ default:
+ eax_fail_unknown_version();
+ }
+
+ eax_set_efx_outer_gain_hf();
+ eax_set_efx_doppler_factor();
+ eax_set_efx_rolloff_factor();
+ eax_set_efx_room_rolloff_factor();
+ eax_set_efx_air_absorption_factor();
+ eax_set_efx_dry_gain_hf_auto();
+ eax_set_efx_wet_gain_auto();
+ eax_set_efx_wet_gain_hf_auto();
+
+ eax_commit_active_fx_slots();
+ eax_commit_filters();
+}
+
#endif // ALSOFT_EAX
diff --git a/al/source.h b/al/source.h
index 2d93e177..850c31aa 100644
--- a/al/source.h
+++ b/al/source.h
@@ -23,6 +23,7 @@
#ifdef ALSOFT_EAX
#include "eax/call.h"
+#include "eax/exception.h"
#include "eax/fx_slot_index.h"
#include "eax/utils.h"
#endif // ALSOFT_EAX
@@ -48,67 +49,12 @@ struct ALbufferQueueItem : public VoiceBufferItem {
#ifdef ALSOFT_EAX
-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
+class EaxSourceException : public EaxException {
+public:
+ explicit EaxSourceException(const char* message)
+ : EaxException{"EAX_SOURCE", message}
+ {}
+};
#endif // ALSOFT_EAX
struct ALsource {
@@ -214,594 +160,895 @@ struct ALsource {
#ifdef ALSOFT_EAX
public:
void eax_initialize(ALCcontext *context) noexcept;
-
-
- void eax_dispatch(const EaxCall& call)
- { call.is_get() ? eax_get(call) : eax_set(call); }
-
-
- void eax_update_filters();
-
- void eax_update(
- EaxContextSharedDirtyFlags dirty_flags);
-
- void eax_commit() { eax_apply_deferred(); }
+ void eax_dispatch(const EaxCall& call);
+ void eax_commit();
void eax_commit_and_update();
+ bool eax_is_initialized() const noexcept { return eax_al_context_ != nullptr; }
- bool eax_is_initialized() const noexcept { return eax_al_context_; }
-
-
- static ALsource* eax_lookup_source(
- ALCcontext& al_context,
- ALuint source_id) noexcept;
-
+ static ALsource* eax_lookup_source(ALCcontext& al_context, ALuint source_id) noexcept;
private:
- static constexpr auto eax_max_speakers = 9;
-
-
- using EaxActiveFxSlots = std::array<bool, EAX_MAX_FXSLOTS>;
- using EaxSpeakerLevels = std::array<long, eax_max_speakers>;
-
- struct Eax
- {
- using Sends = std::array<EAXSOURCEALLSENDPROPERTIES, EAX_MAX_FXSLOTS>;
-
- 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_{};
-
- EAXBUFFER_REVERBPROPERTIES eax1_{};
- 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);
-
-
- void eax_set_source_defaults() noexcept;
- void eax_set_active_fx_slots_defaults() noexcept;
- void eax_set_send_defaults(EAXSOURCEALLSENDPROPERTIES& eax_send) noexcept;
- void eax_set_sends_defaults() noexcept;
- void eax_set_speaker_levels_defaults() noexcept;
- void eax_set_defaults() noexcept;
-
-
- 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_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 EaxCall& 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 eax1_validate_reverb_mix(float reverb_mix);
-
- 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 EaxCall& call);
-
- void eax_defer_send_exclusion_all(
- const EaxCall& call);
-
- void eax_defer_send_occlusion_all(
- const EaxCall& call);
-
- void eax_defer_send_all(
- const EaxCall& 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);
+ using Exception = EaxSourceException;
+ enum class EaxCommitType {
+ normal,
+ forced,
+ };
- void eax_defer_source_direct(
- long lDirect);
+ static constexpr auto eax_max_speakers = 9;
- void eax_defer_source_direct_hf(
- long lDirectHF);
+ using EaxFxSlotIds = const GUID* [EAX_MAX_FXSLOTS];
- void eax_defer_source_room(
- long lRoom);
+ static constexpr const EaxFxSlotIds eax4_fx_slot_ids = {
+ &EAXPROPERTYID_EAX40_FXSlot0,
+ &EAXPROPERTYID_EAX40_FXSlot1,
+ &EAXPROPERTYID_EAX40_FXSlot2,
+ &EAXPROPERTYID_EAX40_FXSlot3,
+ };
- void eax_defer_source_room_hf(
- long lRoomHF);
+ static constexpr const EaxFxSlotIds eax5_fx_slot_ids = {
+ &EAXPROPERTYID_EAX50_FXSlot0,
+ &EAXPROPERTYID_EAX50_FXSlot1,
+ &EAXPROPERTYID_EAX50_FXSlot2,
+ &EAXPROPERTYID_EAX50_FXSlot3,
+ };
- void eax_defer_source_obstruction(
- long lObstruction);
+ using EaxActiveFxSlots = std::array<bool, EAX_MAX_FXSLOTS>;
+ using EaxSpeakerLevels = std::array<EAXSPEAKERLEVELPROPERTIES, eax_max_speakers>;
+ using EaxSends = std::array<EAXSOURCEALLSENDPROPERTIES, EAX_MAX_FXSLOTS>;
- void eax_defer_source_obstruction_lf_ratio(
- float flObstructionLFRatio);
+ using Eax1Props = EAXBUFFER_REVERBPROPERTIES;
- void eax_defer_source_occlusion(
- long lOcclusion);
+ struct Eax1State {
+ Eax1Props i; // Immediate.
+ Eax1Props d; // Deferred.
+ };
- void eax_defer_source_occlusion_lf_ratio(
- float flOcclusionLFRatio);
+ using Eax2Props = EAX20BUFFERPROPERTIES;
- void eax_defer_source_occlusion_room_ratio(
- float flOcclusionRoomRatio);
+ struct Eax2State {
+ Eax2Props i; // Immediate.
+ Eax2Props d; // Deferred.
+ };
- void eax_defer_source_occlusion_direct_ratio(
- float flOcclusionDirectRatio);
+ using Eax3Props = EAX30SOURCEPROPERTIES;
- void eax_defer_source_exclusion(
- long lExclusion);
+ struct Eax3State {
+ Eax3Props i; // Immediate.
+ Eax3Props d; // Deferred.
+ };
- void eax_defer_source_exclusion_lf_ratio(
- float flExclusionLFRatio);
+ struct Eax4Props {
+ Eax3Props source;
+ EaxSends sends;
+ EAX40ACTIVEFXSLOTS active_fx_slots;
- void eax_defer_source_outside_volume_hf(
- long lOutsideVolumeHF);
+ bool operator==(const Eax4Props& rhs) noexcept
+ {
+ return std::memcmp(this, &rhs, sizeof(Eax4Props)) == 0;
+ }
+ };
- void eax_defer_source_doppler_factor(
- float flDopplerFactor);
+ struct Eax4State {
+ Eax4Props i; // Immediate.
+ Eax4Props d; // Deferred.
+ };
- void eax_defer_source_rolloff_factor(
- float flRolloffFactor);
+ struct Eax5Props {
+ EAX50SOURCEPROPERTIES source;
+ EaxSends sends;
+ EAX50ACTIVEFXSLOTS active_fx_slots;
+ EaxSpeakerLevels speaker_levels;
- void eax_defer_source_room_rolloff_factor(
- float flRoomRolloffFactor);
+ bool operator==(const Eax5Props& rhs) noexcept
+ {
+ return std::memcmp(this, &rhs, sizeof(Eax5Props)) == 0;
+ }
+ };
- void eax_defer_source_air_absorption_factor(
- float flAirAbsorptionFactor);
+ struct Eax5State {
+ Eax5Props i; // Immediate.
+ Eax5Props d; // Deferred.
+ };
- void eax_defer_source_flags(
- unsigned long ulFlags);
+ ALCcontext* eax_al_context_{};
+ EaxFxSlotIndex eax_primary_fx_slot_id_{};
+ EaxActiveFxSlots eax_active_fx_slots_{};
+ bool eax_is_version_changed_{};
+ int eax_version_{};
+ Eax1State eax1_{};
+ Eax2State eax2_{};
+ Eax3State eax3_{};
+ Eax4State eax4_{};
+ Eax5State eax5_{};
+ Eax5Props eax_{};
+
+ // ----------------------------------------------------------------------
+ // Source validators
+
+ struct Eax1SourceReverbMixValidator {
+ void operator()(float reverb_mix) const
+ {
+ if (reverb_mix == EAX_REVERBMIX_USEDISTANCE)
+ return;
+
+ eax_validate_range<Exception>(
+ "Reverb Mix",
+ reverb_mix,
+ EAX_BUFFER_MINREVERBMIX,
+ EAX_BUFFER_MAXREVERBMIX);
+ }
+ };
- void eax_defer_source_macro_fx_factor(
- float flMacroFXFactor);
+ struct Eax2SourceDirectValidator {
+ void operator()(long lDirect) const
+ {
+ eax_validate_range<Exception>(
+ "Direct",
+ lDirect,
+ EAXSOURCE_MINDIRECT,
+ EAXSOURCE_MAXDIRECT);
+ }
+ };
- void eax_defer_source_2d_all(
- const EAXSOURCE2DPROPERTIES& all);
+ struct Eax2SourceDirectHfValidator {
+ void operator()(long lDirectHF) const
+ {
+ eax_validate_range<Exception>(
+ "Direct HF",
+ lDirectHF,
+ EAXSOURCE_MINDIRECTHF,
+ EAXSOURCE_MAXDIRECTHF);
+ }
+ };
- void eax_defer_source_obstruction_all(
- const EAXOBSTRUCTIONPROPERTIES& all);
+ struct Eax2SourceRoomValidator {
+ void operator()(long lRoom) const
+ {
+ eax_validate_range<Exception>(
+ "Room",
+ lRoom,
+ EAXSOURCE_MINROOM,
+ EAXSOURCE_MAXROOM);
+ }
+ };
- void eax_defer_source_exclusion_all(
- const EAXEXCLUSIONPROPERTIES& all);
+ struct Eax2SourceRoomHfValidator {
+ void operator()(long lRoomHF) const
+ {
+ eax_validate_range<Exception>(
+ "Room HF",
+ lRoomHF,
+ EAXSOURCE_MINROOMHF,
+ EAXSOURCE_MAXROOMHF);
+ }
+ };
- void eax_defer_source_occlusion_all(
- const EAXOCCLUSIONPROPERTIES& all);
+ struct Eax2SourceRoomRolloffFactorValidator {
+ void operator()(float flRoomRolloffFactor) const
+ {
+ eax_validate_range<Exception>(
+ "Room Rolloff Factor",
+ flRoomRolloffFactor,
+ EAXSOURCE_MINROOMROLLOFFFACTOR,
+ EAXSOURCE_MAXROOMROLLOFFFACTOR);
+ }
+ };
- void eax_defer_source_all(
- const EAX20BUFFERPROPERTIES& all);
+ struct Eax2SourceObstructionValidator {
+ void operator()(long lObstruction) const
+ {
+ eax_validate_range<Exception>(
+ "Obstruction",
+ lObstruction,
+ EAXSOURCE_MINOBSTRUCTION,
+ EAXSOURCE_MAXOBSTRUCTION);
+ }
+ };
- void eax_defer_source_all(
- const EAX30SOURCEPROPERTIES& all);
+ struct Eax2SourceObstructionLfRatioValidator {
+ void operator()(float flObstructionLFRatio) const
+ {
+ eax_validate_range<Exception>(
+ "Obstruction LF Ratio",
+ flObstructionLFRatio,
+ EAXSOURCE_MINOBSTRUCTIONLFRATIO,
+ EAXSOURCE_MAXOBSTRUCTIONLFRATIO);
+ }
+ };
- void eax_defer_source_all(
- const EAX50SOURCEPROPERTIES& all);
+ struct Eax2SourceOcclusionValidator {
+ void operator()(long lOcclusion) const
+ {
+ eax_validate_range<Exception>(
+ "Occlusion",
+ lOcclusion,
+ EAXSOURCE_MINOCCLUSION,
+ EAXSOURCE_MAXOCCLUSION);
+ }
+ };
- void eax_defer_source_speaker_level_all(
- const EAXSPEAKERLEVELPROPERTIES& all);
+ struct Eax2SourceOcclusionLfRatioValidator {
+ void operator()(float flOcclusionLFRatio) const
+ {
+ eax_validate_range<Exception>(
+ "Occlusion LF Ratio",
+ flOcclusionLFRatio,
+ EAXSOURCE_MINOCCLUSIONLFRATIO,
+ EAXSOURCE_MAXOCCLUSIONLFRATIO);
+ }
+ };
+ struct Eax2SourceOcclusionRoomRatioValidator {
+ void operator()(float flOcclusionRoomRatio) const
+ {
+ eax_validate_range<Exception>(
+ "Occlusion Room Ratio",
+ flOcclusionRoomRatio,
+ EAXSOURCE_MINOCCLUSIONROOMRATIO,
+ EAXSOURCE_MAXOCCLUSIONROOMRATIO);
+ }
+ };
- void eax_defer_source_direct(
- const EaxCall& call);
+ struct Eax2SourceOutsideVolumeHfValidator {
+ void operator()(long lOutsideVolumeHF) const
+ {
+ eax_validate_range<Exception>(
+ "Outside Volume HF",
+ lOutsideVolumeHF,
+ EAXSOURCE_MINOUTSIDEVOLUMEHF,
+ EAXSOURCE_MAXOUTSIDEVOLUMEHF);
+ }
+ };
- void eax_defer_source_direct_hf(
- const EaxCall& call);
+ struct Eax2SourceAirAbsorptionFactorValidator {
+ void operator()(float flAirAbsorptionFactor) const
+ {
+ eax_validate_range<Exception>(
+ "Air Absorption Factor",
+ flAirAbsorptionFactor,
+ EAXSOURCE_MINAIRABSORPTIONFACTOR,
+ EAXSOURCE_MAXAIRABSORPTIONFACTOR);
+ }
+ };
- void eax_defer_source_room(
- const EaxCall& call);
+ struct Eax2SourceFlagsValidator {
+ void operator()(unsigned long dwFlags) const
+ {
+ eax_validate_range<Exception>(
+ "Flags",
+ dwFlags,
+ 0UL,
+ ~EAX20SOURCEFLAGS_RESERVED);
+ }
+ };
- void eax_defer_source_room_hf(
- const EaxCall& call);
+ struct Eax3SourceOcclusionDirectRatioValidator {
+ void operator()(float flOcclusionDirectRatio) const
+ {
+ eax_validate_range<Exception>(
+ "Occlusion Direct Ratio",
+ flOcclusionDirectRatio,
+ EAXSOURCE_MINOCCLUSIONDIRECTRATIO,
+ EAXSOURCE_MAXOCCLUSIONDIRECTRATIO);
+ }
+ };
- void eax_defer_source_obstruction(
- const EaxCall& call);
+ struct Eax3SourceExclusionValidator {
+ void operator()(long lExclusion) const
+ {
+ eax_validate_range<Exception>(
+ "Exclusion",
+ lExclusion,
+ EAXSOURCE_MINEXCLUSION,
+ EAXSOURCE_MAXEXCLUSION);
+ }
+ };
- void eax_defer_source_obstruction_lf_ratio(
- const EaxCall& call);
+ struct Eax3SourceExclusionLfRatioValidator {
+ void operator()(float flExclusionLFRatio) const
+ {
+ eax_validate_range<Exception>(
+ "Exclusion LF Ratio",
+ flExclusionLFRatio,
+ EAXSOURCE_MINEXCLUSIONLFRATIO,
+ EAXSOURCE_MAXEXCLUSIONLFRATIO);
+ }
+ };
- void eax_defer_source_occlusion(
- const EaxCall& call);
+ struct Eax3SourceDopplerFactorValidator {
+ void operator()(float flDopplerFactor) const
+ {
+ eax_validate_range<Exception>(
+ "Doppler Factor",
+ flDopplerFactor,
+ EAXSOURCE_MINDOPPLERFACTOR,
+ EAXSOURCE_MAXDOPPLERFACTOR);
+ }
+ };
- void eax_defer_source_occlusion_lf_ratio(
- const EaxCall& call);
+ struct Eax3SourceRolloffFactorValidator {
+ void operator()(float flRolloffFactor) const
+ {
+ eax_validate_range<Exception>(
+ "Rolloff Factor",
+ flRolloffFactor,
+ EAXSOURCE_MINROLLOFFFACTOR,
+ EAXSOURCE_MAXROLLOFFFACTOR);
+ }
+ };
- void eax_defer_source_occlusion_room_ratio(
- const EaxCall& call);
+ struct Eax5SourceMacroFXFactorValidator {
+ void operator()(float flMacroFXFactor) const
+ {
+ eax_validate_range<Exception>(
+ "Macro FX Factor",
+ flMacroFXFactor,
+ EAXSOURCE_MINMACROFXFACTOR,
+ EAXSOURCE_MAXMACROFXFACTOR);
+ }
+ };
- void eax_defer_source_occlusion_direct_ratio(
- const EaxCall& call);
+ struct Eax5SourceFlagsValidator {
+ void operator()(unsigned long dwFlags) const
+ {
+ eax_validate_range<Exception>(
+ "Flags",
+ dwFlags,
+ 0UL,
+ ~EAX50SOURCEFLAGS_RESERVED);
+ }
+ };
- void eax_defer_source_exclusion(
- const EaxCall& call);
+ struct Eax1SourceAllValidator {
+ void operator()(const Eax1Props& props) const
+ {
+ Eax1SourceReverbMixValidator{}(props.fMix);
+ }
+ };
- void eax_defer_source_exclusion_lf_ratio(
- const EaxCall& call);
+ struct Eax2SourceAllValidator {
+ void operator()(const Eax2Props& props) const
+ {
+ Eax2SourceDirectValidator{}(props.lDirect);
+ Eax2SourceDirectHfValidator{}(props.lDirectHF);
+ Eax2SourceRoomValidator{}(props.lRoom);
+ Eax2SourceRoomHfValidator{}(props.lRoomHF);
+ Eax2SourceRoomRolloffFactorValidator{}(props.flRoomRolloffFactor);
+ Eax2SourceObstructionValidator{}(props.lObstruction);
+ Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
+ Eax2SourceOcclusionValidator{}(props.lOcclusion);
+ Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
+ Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
+ Eax2SourceOutsideVolumeHfValidator{}(props.lOutsideVolumeHF);
+ Eax2SourceAirAbsorptionFactorValidator{}(props.flAirAbsorptionFactor);
+ Eax2SourceFlagsValidator{}(props.dwFlags);
+ }
+ };
- void eax_defer_source_outside_volume_hf(
- const EaxCall& call);
+ struct Eax3SourceAllValidator {
+ void operator()(const Eax3Props& props) const
+ {
+ Eax2SourceDirectValidator{}(props.lDirect);
+ Eax2SourceDirectHfValidator{}(props.lDirectHF);
+ Eax2SourceRoomValidator{}(props.lRoom);
+ Eax2SourceRoomHfValidator{}(props.lRoomHF);
+ Eax2SourceObstructionValidator{}(props.lObstruction);
+ Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
+ Eax2SourceOcclusionValidator{}(props.lOcclusion);
+ Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
+ Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
+ Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
+ Eax3SourceExclusionValidator{}(props.lExclusion);
+ Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
+ Eax2SourceOutsideVolumeHfValidator{}(props.lOutsideVolumeHF);
+ Eax3SourceDopplerFactorValidator{}(props.flDopplerFactor);
+ Eax3SourceRolloffFactorValidator{}(props.flRolloffFactor);
+ Eax2SourceRoomRolloffFactorValidator{}(props.flRoomRolloffFactor);
+ Eax2SourceAirAbsorptionFactorValidator{}(props.flAirAbsorptionFactor);
+ Eax2SourceFlagsValidator{}(props.ulFlags);
+ }
+ };
- void eax_defer_source_doppler_factor(
- const EaxCall& call);
+ struct Eax5SourceAllValidator {
+ void operator()(const EAX50SOURCEPROPERTIES& props) const
+ {
+ Eax3SourceAllValidator{}(static_cast<const Eax3Props&>(props));
+ Eax5SourceMacroFXFactorValidator{}(props.flMacroFXFactor);
+ }
+ };
- void eax_defer_source_rolloff_factor(
- const EaxCall& call);
+ struct Eax5SourceAll2dValidator {
+ void operator()(const EAXSOURCE2DPROPERTIES& props) const
+ {
+ Eax2SourceDirectValidator{}(props.lDirect);
+ Eax2SourceDirectHfValidator{}(props.lDirectHF);
+ Eax2SourceRoomValidator{}(props.lRoom);
+ Eax2SourceRoomHfValidator{}(props.lRoomHF);
+ Eax5SourceFlagsValidator{}(props.ulFlags);
+ }
+ };
- void eax_defer_source_room_rolloff_factor(
- const EaxCall& call);
+ struct Eax4ObstructionValidator {
+ void operator()(const EAXOBSTRUCTIONPROPERTIES& props) const
+ {
+ Eax2SourceObstructionValidator{}(props.lObstruction);
+ Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio);
+ }
+ };
- void eax_defer_source_air_absorption_factor(
- const EaxCall& call);
+ struct Eax4OcclusionValidator {
+ void operator()(const EAXOCCLUSIONPROPERTIES& props) const
+ {
+ Eax2SourceOcclusionValidator{}(props.lOcclusion);
+ Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
+ Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
+ Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
+ }
+ };
- void eax_defer_source_flags(
- const EaxCall& call);
+ struct Eax4ExclusionValidator {
+ void operator()(const EAXEXCLUSIONPROPERTIES& props) const
+ {
+ Eax3SourceExclusionValidator{}(props.lExclusion);
+ Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
+ }
+ };
- void eax_defer_source_macro_fx_factor(
- const EaxCall& call);
+ // Source validators
+ // ----------------------------------------------------------------------
+ // Send validators
- void eax_defer_source_2d_all(
- const EaxCall& call);
+ struct Eax4SendReceivingFxSlotIdValidator {
+ void operator()(const GUID& guidReceivingFXSlotID) const
+ {
+ if (guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot0 &&
+ guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot1 &&
+ guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot2 &&
+ guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot3)
+ {
+ eax_fail_unknown_receiving_fx_slot_id();
+ }
+ }
+ };
- void eax_defer_source_obstruction_all(
- const EaxCall& call);
+ struct Eax5SendReceivingFxSlotIdValidator {
+ void operator()(const GUID& guidReceivingFXSlotID) const
+ {
+ if (guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot0 &&
+ guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot1 &&
+ guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot2 &&
+ guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot3)
+ {
+ eax_fail_unknown_receiving_fx_slot_id();
+ }
+ }
+ };
- void eax_defer_source_exclusion_all(
- const EaxCall& call);
+ struct Eax4SendSendValidator {
+ void operator()(long lSend) const
+ {
+ eax_validate_range<Exception>(
+ "Send",
+ lSend,
+ EAXSOURCE_MINSEND,
+ EAXSOURCE_MAXSEND);
+ }
+ };
- void eax_defer_source_occlusion_all(
- const EaxCall& call);
+ struct Eax4SendSendHfValidator {
+ void operator()(long lSendHF) const
+ {
+ eax_validate_range<Exception>(
+ "Send HF",
+ lSendHF,
+ EAXSOURCE_MINSENDHF,
+ EAXSOURCE_MAXSENDHF);
+ }
+ };
- void eax_defer_source_all(
- const EaxCall& call);
+ template<typename TIdValidator>
+ struct EaxSendValidator {
+ void operator()(const EAXSOURCESENDPROPERTIES& props) const
+ {
+ TIdValidator{}(props.guidReceivingFXSlotID);
+ Eax4SendSendValidator{}(props.lSend);
+ Eax4SendSendHfValidator{}(props.lSendHF);
+ }
+ };
- void eax_defer_source_speaker_level_all(
- const EaxCall& call);
+ struct Eax4SendValidator : EaxSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
+ struct Eax5SendValidator : EaxSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
+ template<typename TIdValidator>
+ struct EaxOcclusionSendValidator {
+ void operator()(const EAXSOURCEOCCLUSIONSENDPROPERTIES& props) const
+ {
+ TIdValidator{}(props.guidReceivingFXSlotID);
+ Eax2SourceOcclusionValidator{}(props.lOcclusion);
+ Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
+ Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
+ Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
+ }
+ };
- void eax_set_outside_volume_hf();
+ struct Eax4OcclusionSendValidator : EaxOcclusionSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
+ struct Eax5OcclusionSendValidator : EaxOcclusionSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
- void eax_set_doppler_factor();
+ template<typename TIdValidator>
+ struct EaxExclusionSendValidator {
+ void operator()(const EAXSOURCEEXCLUSIONSENDPROPERTIES& props) const
+ {
+ TIdValidator{}(props.guidReceivingFXSlotID);
+ Eax3SourceExclusionValidator{}(props.lExclusion);
+ Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
+ }
+ };
- void eax_set_rolloff_factor();
+ struct Eax4ExclusionSendValidator : EaxExclusionSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
+ struct Eax5ExclusionSendValidator : EaxExclusionSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
- void eax_set_room_rolloff_factor();
+ template<typename TIdValidator>
+ struct EaxAllSendValidator {
+ void operator()(const EAXSOURCEALLSENDPROPERTIES& props) const
+ {
+ TIdValidator{}(props.guidReceivingFXSlotID);
+ Eax4SendSendValidator{}(props.lSend);
+ Eax4SendSendHfValidator{}(props.lSendHF);
+ Eax2SourceOcclusionValidator{}(props.lOcclusion);
+ Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio);
+ Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio);
+ Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio);
+ Eax3SourceExclusionValidator{}(props.lExclusion);
+ Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio);
+ }
+ };
- void eax_set_air_absorption_factor();
+ struct Eax4AllSendValidator : EaxAllSendValidator<Eax4SendReceivingFxSlotIdValidator> {};
+ struct Eax5AllSendValidator : EaxAllSendValidator<Eax5SendReceivingFxSlotIdValidator> {};
+ // Send validators
+ // ----------------------------------------------------------------------
+ // Active FX slot ID validators
- void eax_set_direct_hf_auto_flag();
+ struct Eax4ActiveFxSlotIdValidator {
+ void operator()(const GUID& id) const
+ {
+ if (id != EAX_NULL_GUID &&
+ id != EAX_PrimaryFXSlotID &&
+ id != EAXPROPERTYID_EAX40_FXSlot0 &&
+ id != EAXPROPERTYID_EAX40_FXSlot1 &&
+ id != EAXPROPERTYID_EAX40_FXSlot2 &&
+ id != EAXPROPERTYID_EAX40_FXSlot3)
+ {
+ eax_fail_unknown_active_fx_slot_id();
+ }
+ }
+ };
- void eax_set_room_auto_flag();
+ struct Eax5ActiveFxSlotIdValidator {
+ void operator()(const GUID& id) const
+ {
+ if (id != EAX_NULL_GUID &&
+ id != EAX_PrimaryFXSlotID &&
+ id != EAXPROPERTYID_EAX50_FXSlot0 &&
+ id != EAXPROPERTYID_EAX50_FXSlot1 &&
+ id != EAXPROPERTYID_EAX50_FXSlot2 &&
+ id != EAXPROPERTYID_EAX50_FXSlot3)
+ {
+ eax_fail_unknown_active_fx_slot_id();
+ }
+ }
+ };
- void eax_set_room_hf_auto_flag();
+ // Active FX slot ID validators
+ // ----------------------------------------------------------------------
+ // Speaker level validators.
- void eax_set_flags();
+ struct Eax5SpeakerIdValidator {
+ void operator()(long lSpeakerID) const
+ {
+ switch (lSpeakerID) {
+ case EAXSPEAKER_FRONT_LEFT:
+ case EAXSPEAKER_FRONT_CENTER:
+ case EAXSPEAKER_FRONT_RIGHT:
+ case EAXSPEAKER_SIDE_RIGHT:
+ case EAXSPEAKER_REAR_RIGHT:
+ case EAXSPEAKER_REAR_CENTER:
+ case EAXSPEAKER_REAR_LEFT:
+ case EAXSPEAKER_SIDE_LEFT:
+ case EAXSPEAKER_LOW_FREQUENCY:
+ break;
+
+ default:
+ eax_fail("Unknown speaker ID.");
+ }
+ }
+ };
+ struct Eax5SpeakerLevelValidator {
+ void operator()(long lLevel) const
+ {
+ // TODO Use a range when the feature will be implemented.
+ if (lLevel != EAXSOURCE_DEFAULTSPEAKERLEVEL)
+ eax_fail("Speaker level out of range.");
+ }
+ };
- void eax_set_macro_fx_factor();
+ struct Eax5SpeakerAllValidator {
+ void operator()(const EAXSPEAKERLEVELPROPERTIES& all) const
+ {
+ Eax5SpeakerIdValidator{}(all.lSpeakerID);
+ Eax5SpeakerLevelValidator{}(all.lLevel);
+ }
+ };
- void eax_set_speaker_levels();
+ // Speaker level validators.
+ // ----------------------------------------------------------------------
- static ALuint eax2_translate_property_id(const EaxCall& call);
+ struct Eax4SendIndexGetter {
+ EaxFxSlotIndexValue operator()(const GUID& id) const
+ {
+ if (id == EAXPROPERTYID_EAX40_FXSlot0)
+ return 0;
+ if (id == EAXPROPERTYID_EAX40_FXSlot1)
+ return 1;
+ if (id == EAXPROPERTYID_EAX40_FXSlot2)
+ return 2;
+ if (id == EAXPROPERTYID_EAX40_FXSlot3)
+ return 3;
+ eax_fail_unknown_receiving_fx_slot_id();
+ }
+ };
- void eax1_set_efx();
- void eax1_set_reverb_mix(const EaxCall& call);
- void eax1_set(const EaxCall& call);
+ struct Eax5SendIndexGetter {
+ EaxFxSlotIndexValue operator()(const GUID& id) const
+ {
+ if (id == EAXPROPERTYID_EAX50_FXSlot0)
+ return 0;
+ if (id == EAXPROPERTYID_EAX50_FXSlot1)
+ return 1;
+ if (id == EAXPROPERTYID_EAX50_FXSlot2)
+ return 2;
+ if (id == EAXPROPERTYID_EAX50_FXSlot3)
+ return 3;
+ eax_fail_unknown_receiving_fx_slot_id();
+ }
+ };
- void eax_apply_deferred();
+ [[noreturn]] static void eax_fail(const char* message);
+ [[noreturn]] static void eax_fail_unknown_property_id();
+ [[noreturn]] static void eax_fail_unknown_version();
+ [[noreturn]] static void eax_fail_unknown_active_fx_slot_id();
+ [[noreturn]] static void eax_fail_unknown_receiving_fx_slot_id();
+
+ void eax_set_sends_defaults(EaxSends& sends, const EaxFxSlotIds& ids) noexcept;
+ void eax1_set_defaults(Eax1Props& props) noexcept;
+ void eax1_set_defaults() noexcept;
+ void eax2_set_defaults(Eax2Props& props) noexcept;
+ void eax2_set_defaults() noexcept;
+ void eax3_set_defaults(Eax3Props& props) noexcept;
+ void eax3_set_defaults() noexcept;
+ void eax4_set_sends_defaults(EaxSends& sends) noexcept;
+ void eax4_set_active_fx_slots_defaults(EAX40ACTIVEFXSLOTS& slots) noexcept;
+ void eax4_set_defaults() noexcept;
+ void eax5_set_source_defaults(EAX50SOURCEPROPERTIES& props) noexcept;
+ void eax5_set_sends_defaults(EaxSends& sends) noexcept;
+ void eax5_set_active_fx_slots_defaults(EAX50ACTIVEFXSLOTS& slots) noexcept;
+ void eax5_set_speaker_levels_defaults(EaxSpeakerLevels& speaker_levels) noexcept;
+ void eax5_set_defaults(Eax5Props& props) noexcept;
+ void eax5_set_defaults() noexcept;
+ void eax_set_defaults() noexcept;
- void eax_set(
- const EaxCall& call);
+ void eax1_translate(const Eax1Props& src, Eax5Props& dst) noexcept;
+ void eax2_translate(const Eax2Props& src, Eax5Props& dst) noexcept;
+ void eax3_translate(const Eax3Props& src, Eax5Props& dst) noexcept;
+ void eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept;
+ static float eax_calculate_dst_occlusion_mb(
+ long src_occlusion_mb,
+ float path_ratio,
+ float lf_ratio) noexcept;
- static const GUID& eax_get_send_fx_slot_guid(
- int eax_version,
- EaxFxSlotIndexValue fx_slot_index);
+ EaxAlLowPassParam eax_create_direct_filter_param() const noexcept;
- static void eax_copy_send(
- const EAXSOURCEALLSENDPROPERTIES& src_send,
- EAXSOURCESENDPROPERTIES& dst_send);
+ EaxAlLowPassParam eax_create_room_filter_param(
+ const ALeffectslot& fx_slot,
+ const EAXSOURCEALLSENDPROPERTIES& send) const noexcept;
- static void eax_copy_send(
- const EAXSOURCEALLSENDPROPERTIES& src_send,
- EAXSOURCEALLSENDPROPERTIES& dst_send);
+ void eax_update_direct_filter();
+ void eax_update_room_filters();
+ void eax_commit_filters();
- static void eax_copy_send(
- const EAXSOURCEALLSENDPROPERTIES& src_send,
- EAXSOURCEOCCLUSIONSENDPROPERTIES& dst_send);
+ static void eax_copy_send_for_get(
+ const EAXSOURCEALLSENDPROPERTIES& src,
+ EAXSOURCESENDPROPERTIES& dst) noexcept
+ {
+ dst = reinterpret_cast<const EAXSOURCESENDPROPERTIES&>(src);
+ }
- static void eax_copy_send(
- const EAXSOURCEALLSENDPROPERTIES& src_send,
- EAXSOURCEEXCLUSIONSENDPROPERTIES& dst_send);
+ static void eax_copy_send_for_get(
+ const EAXSOURCEALLSENDPROPERTIES& src,
+ EAXSOURCEALLSENDPROPERTIES& dst) noexcept
+ {
+ dst = src;
+ }
- template<
- typename TException,
- typename TSrcSend
- >
- void eax_api_get_send_properties(
- const EaxCall& call) const
+ static void eax_copy_send_for_get(
+ const EAXSOURCEALLSENDPROPERTIES& src,
+ EAXSOURCEOCCLUSIONSENDPROPERTIES& dst) noexcept
{
- const auto eax_version = call.get_version();
- const auto dst_sends = call.get_values<TException, TSrcSend>();
- const auto send_count = dst_sends.size();
+ dst.guidReceivingFXSlotID = src.guidReceivingFXSlotID;
+ dst.lOcclusion = src.lOcclusion;
+ dst.flOcclusionLFRatio = src.flOcclusionLFRatio;
+ dst.flOcclusionRoomRatio = src.flOcclusionRoomRatio;
+ dst.flOcclusionDirectRatio = src.flOcclusionDirectRatio;
+ }
- 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];
+ static void eax_copy_send_for_get(
+ const EAXSOURCEALLSENDPROPERTIES& src,
+ EAXSOURCEEXCLUSIONSENDPROPERTIES& dst) noexcept
+ {
+ dst.guidReceivingFXSlotID = src.guidReceivingFXSlotID;
+ dst.lExclusion = src.lExclusion;
+ dst.flExclusionLFRatio = src.flExclusionLFRatio;
+ }
- eax_copy_send(src_send, dst_send);
+ template<typename TDstSend>
+ void eax_get_sends(const EaxCall& call, const EaxSends& src_sends)
+ {
+ const auto dst_sends = call.get_values<TDstSend>(EAX_MAX_FXSLOTS);
+ const auto count = dst_sends.size();
- dst_send.guidReceivingFXSlotID = eax_get_send_fx_slot_guid(eax_version, fx_slot_index);
+ for (auto i = decltype(count){}; i < count; ++i) {
+ const auto& src_send = src_sends[i];
+ auto& dst_send = dst_sends[i];
+ eax_copy_send_for_get(src_send, dst_send);
}
}
+ void eax1_get(const EaxCall& call, const Eax1Props& props);
+ void eax2_get(const EaxCall& call, const Eax2Props& props);
+ void eax3_get_obstruction(const EaxCall& call, const Eax3Props& props);
+ void eax3_get_occlusion(const EaxCall& call, const Eax3Props& props);
+ void eax3_get_exclusion(const EaxCall& call, const Eax3Props& props);
+ void eax3_get(const EaxCall& call, const Eax3Props& props);
+ void eax4_get(const EaxCall& call, const Eax4Props& props);
+ void eax5_get_all_2d(const EaxCall& call, const EAX50SOURCEPROPERTIES& props);
+ void eax5_get_speaker_levels(const EaxCall& call, const EaxSpeakerLevels& props);
+ void eax5_get(const EaxCall& call, const Eax5Props& props);
+ void eax_get(const EaxCall& call);
+
+ static void eax_copy_send_for_set(
+ const EAXSOURCESENDPROPERTIES& src,
+ EAXSOURCEALLSENDPROPERTIES& dst) noexcept
+ {
+ dst.lSend = src.lSend;
+ dst.lSendHF = src.lSendHF;
+ }
- void eax1_get(const EaxCall& call);
-
- void eax_api_get_source_all_v2(
- const EaxCall& call);
+ static void eax_copy_send_for_set(
+ const EAXSOURCEALLSENDPROPERTIES& src,
+ EAXSOURCEALLSENDPROPERTIES& dst) noexcept
+ {
+ dst.lSend = src.lSend;
+ dst.lSendHF = src.lSendHF;
+ dst.lOcclusion = src.lOcclusion;
+ dst.flOcclusionLFRatio = src.flOcclusionLFRatio;
+ dst.flOcclusionRoomRatio = src.flOcclusionRoomRatio;
+ dst.flOcclusionDirectRatio = src.flOcclusionDirectRatio;
+ dst.lExclusion = src.lExclusion;
+ dst.flExclusionLFRatio = src.flExclusionLFRatio;
+ }
- void eax_api_get_source_all_v3(
- const EaxCall& call);
+ static void eax_copy_send_for_set(
+ const EAXSOURCEOCCLUSIONSENDPROPERTIES& src,
+ EAXSOURCEALLSENDPROPERTIES& dst) noexcept
+ {
+ dst.lOcclusion = src.lOcclusion;
+ dst.flOcclusionLFRatio = src.flOcclusionLFRatio;
+ dst.flOcclusionRoomRatio = src.flOcclusionRoomRatio;
+ dst.flOcclusionDirectRatio = src.flOcclusionDirectRatio;
+ }
- void eax_api_get_source_all_v5(
- const EaxCall& call);
+ static void eax_copy_send_for_set(
+ const EAXSOURCEEXCLUSIONSENDPROPERTIES& src,
+ EAXSOURCEALLSENDPROPERTIES& dst) noexcept
+ {
+ dst.lExclusion = src.lExclusion;
+ dst.flExclusionLFRatio = src.flExclusionLFRatio;
+ }
- void eax_api_get_source_all(
- const EaxCall& call);
+ template<typename TValidator, typename TIndexGetter, typename TSrcSend>
+ void eax_defer_sends(const EaxCall& call, EaxSends& dst_sends)
+ {
+ const auto src_sends = call.get_values<const TSrcSend>(EAX_MAX_FXSLOTS);
+ std::for_each(src_sends.cbegin(), src_sends.cend(), TValidator{});
+ const auto count = src_sends.size();
+ const auto index_getter = TIndexGetter{};
+
+ for (auto i = decltype(count){}; i < count; ++i) {
+ const auto& src_send = src_sends[i];
+ const auto dst_index = index_getter(src_send.guidReceivingFXSlotID);
+ auto& dst_send = dst_sends[dst_index];
+ eax_copy_send_for_set(src_send, dst_send);
+ }
+ }
- void eax_api_get_source_all_obstruction(
- const EaxCall& call);
+ template<typename TValidator, typename TSrcSend>
+ void eax4_defer_sends(const EaxCall& call, EaxSends& dst_sends)
+ {
+ eax_defer_sends<TValidator, Eax4SendIndexGetter, TSrcSend>(call, dst_sends);
+ }
- void eax_api_get_source_all_occlusion(
- const EaxCall& call);
+ template<typename TValidator, typename TSrcSend>
+ void eax5_defer_sends(const EaxCall& call, EaxSends& dst_sends)
+ {
+ eax_defer_sends<TValidator, Eax5SendIndexGetter, TSrcSend>(call, dst_sends);
+ }
- void eax_api_get_source_all_exclusion(
- const EaxCall& call);
+ template<typename TValidator, size_t TIdCount>
+ void eax_defer_active_fx_slot_id(const EaxCall& call, GUID (&dst_ids)[TIdCount])
+ {
+ const auto src_ids = call.get_values<const GUID>(TIdCount);
+ std::for_each(src_ids.cbegin(), src_ids.cend(), TValidator{});
+ std::uninitialized_copy(src_ids.cbegin(), src_ids.cend(), dst_ids);
+ }
- void eax_api_get_source_active_fx_slot_id(
- const EaxCall& call);
+ template<size_t TIdCount>
+ void eax4_defer_active_fx_slot_id(const EaxCall& call, GUID (&dst_ids)[TIdCount])
+ {
+ eax_defer_active_fx_slot_id<Eax4ActiveFxSlotIdValidator>(call, dst_ids);
+ }
- void eax_api_get_source_all_2d(
- const EaxCall& call);
+ template<size_t TIdCount>
+ void eax5_defer_active_fx_slot_id(const EaxCall& call, GUID (&dst_ids)[TIdCount])
+ {
+ eax_defer_active_fx_slot_id<Eax5ActiveFxSlotIdValidator>(call, dst_ids);
+ }
- void eax_api_get_source_speaker_level_all(
- const EaxCall& call);
+ template<typename TValidator, typename TProperty>
+ static void eax_defer(const EaxCall& call, TProperty& property)
+ {
+ const auto& value = call.get_value<Exception, const TProperty>();
+ TValidator{}(value);
+ property = value;
+ }
- void eax_get(
- const EaxCall& call);
+ // Defers source's sub-properties (obstruction, occlusion, exclusion).
+ template<typename TValidator, typename TSubproperty, typename TProperty>
+ void eax_defer_sub(const EaxCall& call, TProperty& property)
+ {
+ const auto& src_props = call.get_value<Exception, const TSubproperty>();
+ TValidator{}(src_props);
+ auto& dst_props = reinterpret_cast<TSubproperty&>(property);
+ dst_props = src_props;
+ }
+ void eax_set_efx_outer_gain_hf();
+ void eax_set_efx_doppler_factor();
+ void eax_set_efx_rolloff_factor();
+ void eax_set_efx_room_rolloff_factor();
+ void eax_set_efx_air_absorption_factor();
+ void eax_set_efx_dry_gain_hf_auto();
+ void eax_set_efx_wet_gain_auto();
+ void eax_set_efx_wet_gain_hf_auto();
+
+ void eax1_set(const EaxCall& call, Eax1Props& props);
+ void eax2_set(const EaxCall& call, Eax2Props& props);
+ void eax3_set(const EaxCall& call, Eax3Props& props);
+ void eax4_set(const EaxCall& call, Eax4Props& props);
+ void eax5_defer_all_2d(const EaxCall& call, EAX50SOURCEPROPERTIES& props);
+ void eax5_defer_speaker_levels(const EaxCall& call, EaxSpeakerLevels& props);
+ void eax5_set(const EaxCall& call, Eax5Props& props);
+ void eax_set(const EaxCall& call);
// `alSource3i(source, AL_AUXILIARY_SEND_FILTER, ...)`
void eax_set_al_source_send(ALeffectslot *slot, size_t sendidx,
const EaxAlLowPassParam &filter);
+
+ void eax_commit_active_fx_slots();
+ void eax_commit(EaxCommitType commit_type);
#endif // ALSOFT_EAX
};