aboutsummaryrefslogtreecommitdiffstats
path: root/al/source.cpp
diff options
context:
space:
mode:
authorBoris I. Bendovsky <[email protected]>2022-01-30 14:47:32 +0200
committerGitHub <[email protected]>2022-01-30 04:47:32 -0800
commit19ed994dc30ed84ea7cbbb5152577669fc25caf6 (patch)
treef68933bf8f778806618bd6c0b1bf9ced1b0ccf08 /al/source.cpp
parent619249371a40f03cf988d1f5750d643df797c485 (diff)
Add EAX extensions (EAX 2.0-5.0, X-RAM) (#632)
* Add EAX extensions (EAX 2.0-5.0, X-RAM) * Comment out C++17 leftovers * Remove everything related to patching * Update alsoftrc.sample * Rewrite integration * Fix GCC compilation under Linux * Always reset EAX effect properties when loading it into FX slot
Diffstat (limited to 'al/source.cpp')
-rw-r--r--al/source.cpp2488
1 files changed, 2488 insertions, 0 deletions
diff --git a/al/source.cpp b/al/source.cpp
index f7b07338..3f7fa540 100644
--- a/al/source.cpp
+++ b/al/source.cpp
@@ -72,6 +72,10 @@
#include "ringbuffer.h"
#include "threads.h"
+#if ALSOFT_EAX
+#include "eax_exception.h"
+#include "eax_globals.h"
+#endif // ALSOFT_EAX
namespace {
@@ -2414,16 +2418,52 @@ START_API_FUNC
{
ALsource *source{AllocSource(context.get())};
sources[0] = source->id;
+
+#if ALSOFT_EAX
+ if (context->has_eax())
+ {
+ std::unique_lock<std::mutex> prop_lock{context->mPropLock};
+ context->eax_initialize_source(*source);
+ }
+#endif // ALSOFT_EAX
}
else
{
+#if ALSOFT_EAX
+ auto eax_sources = al::vector<ALsource*>{};
+
+ if (context->has_eax())
+ {
+ eax_sources.reserve(static_cast<ALuint>(n));
+ }
+#endif // ALSOFT_EAX
+
al::vector<ALuint> ids;
ids.reserve(static_cast<ALuint>(n));
do {
ALsource *source{AllocSource(context.get())};
ids.emplace_back(source->id);
+
+#if ALSOFT_EAX
+ if (context->has_eax())
+ {
+ eax_sources.emplace_back(source);
+ }
+#endif // ALSOFT_EAX
} while(--n);
std::copy(ids.cbegin(), ids.cend(), sources);
+
+#if ALSOFT_EAX
+ if (context->has_eax())
+ {
+ std::unique_lock<std::mutex> prop_lock{context->mPropLock};
+
+ for (auto& eax_source : eax_sources)
+ {
+ context->eax_initialize_source(*eax_source);
+ }
+ }
+#endif // ALSOFT_EAX
}
}
END_API_FUNC
@@ -3555,6 +3595,10 @@ ALsource::ALsource()
ALsource::~ALsource()
{
+#if ALSOFT_EAX
+ eax_uninitialize();
+#endif // ALSOFT_EAX
+
for(auto &item : mQueue)
{
if(ALbuffer *buffer{item.mBuffer})
@@ -3597,3 +3641,2447 @@ SourceSubList::~SourceSubList()
al_free(Sources);
Sources = nullptr;
}
+
+
+#if ALSOFT_EAX
+class EaxSourceException :
+ public EaxException
+{
+public:
+ explicit EaxSourceException(
+ const char* message)
+ :
+ EaxException{"EAX_SOURCE", message}
+ {
+ }
+}; // EaxSourceException
+
+
+class EaxSourceActiveFxSlotsException :
+ public EaxException
+{
+public:
+ explicit EaxSourceActiveFxSlotsException(
+ const char* message)
+ :
+ EaxException{"EAX_SOURCE_ACTIVE_FX_SLOTS", message}
+ {
+ }
+}; // EaxSourceActiveFxSlotsException
+
+
+class EaxSourceSendException :
+ public EaxException
+{
+public:
+ explicit EaxSourceSendException(
+ const char* message)
+ :
+ EaxException{"EAX_SOURCE_SEND", message}
+ {
+ }
+}; // EaxSourceSendException
+
+
+void ALsource::eax_initialize(
+ const EaxSourceInitParam& param) noexcept
+{
+ eax_validate_init_param(param);
+ eax_copy_init_param(param);
+ eax_set_defaults();
+ eax_initialize_fx_slots();
+
+ eax_d_ = eax_;
+}
+
+void ALsource::eax_uninitialize()
+{
+ if (!eax_al_context_)
+ {
+ return;
+ }
+
+ if (eax_al_context_->has_eax())
+ {
+ for (auto i = 0; i < EAX_MAX_FXSLOTS; ++i)
+ {
+ eax_al_source_3i(
+ AL_AUXILIARY_SEND_FILTER,
+ AL_EFFECTSLOT_NULL,
+ static_cast<ALint>(i),
+ AL_FILTER_NULL
+ );
+ }
+ }
+
+ eax_al_context_ = nullptr;
+}
+
+void ALsource::eax_dispatch(
+ const EaxEaxCall& eax_call)
+{
+ if (eax_call.is_get())
+ {
+ eax_get(eax_call);
+ }
+ else
+ {
+ eax_set(eax_call);
+ }
+}
+
+void ALsource::eax_update_filters()
+{
+ eax_update_filters_internal();
+}
+
+void ALsource::eax_update(
+ EaxContextSharedDirtyFlags dirty_flags)
+{
+ if (dirty_flags.primary_fx_slot_id)
+ {
+ if (eax_uses_primary_id_)
+ {
+ eax_update_primary_fx_slot_id();
+ }
+ }
+
+ if (dirty_flags.air_absorption_hf)
+ {
+ eax_set_air_absorption_factor();
+ }
+}
+
+ALsource* ALsource::eax_lookup_source(
+ ALCcontext& al_context,
+ ALuint source_id) noexcept
+{
+ return LookupSource(&al_context, source_id);
+}
+
+[[noreturn]]
+void ALsource::eax_fail(
+ const char* message)
+{
+ throw EaxSourceException{message};
+}
+
+void ALsource::eax_validate_init_param(
+ const EaxSourceInitParam& param)
+{
+ if (!param.al_context)
+ {
+ eax_fail("Null context.");
+ }
+
+ if (!param.al_filter)
+ {
+ eax_fail("Null filter.");
+ }
+}
+
+void ALsource::eax_copy_init_param(
+ const EaxSourceInitParam& param)
+{
+ eax_al_context_ = param.al_context;
+ eax_al_filter_ = param.al_filter;
+}
+
+void ALsource::eax_set_source_defaults()
+{
+ eax_.source.lDirect = EAXSOURCE_DEFAULTDIRECT;
+ eax_.source.lDirectHF = EAXSOURCE_DEFAULTDIRECTHF;
+ eax_.source.lRoom = EAXSOURCE_DEFAULTROOM;
+ eax_.source.lRoomHF = EAXSOURCE_DEFAULTROOMHF;
+ eax_.source.lObstruction = EAXSOURCE_DEFAULTOBSTRUCTION;
+ eax_.source.flObstructionLFRatio = EAXSOURCE_DEFAULTOBSTRUCTIONLFRATIO;
+ eax_.source.lOcclusion = EAXSOURCE_DEFAULTOCCLUSION;
+ eax_.source.flOcclusionLFRatio = EAXSOURCE_DEFAULTOCCLUSIONLFRATIO;
+ eax_.source.flOcclusionRoomRatio = EAXSOURCE_DEFAULTOCCLUSIONROOMRATIO;
+ eax_.source.flOcclusionDirectRatio = EAXSOURCE_DEFAULTOCCLUSIONDIRECTRATIO;
+ eax_.source.lExclusion = EAXSOURCE_DEFAULTEXCLUSION;
+ eax_.source.flExclusionLFRatio = EAXSOURCE_DEFAULTEXCLUSIONLFRATIO;
+ eax_.source.lOutsideVolumeHF = EAXSOURCE_DEFAULTOUTSIDEVOLUMEHF;
+ eax_.source.flDopplerFactor = EAXSOURCE_DEFAULTDOPPLERFACTOR;
+ eax_.source.flRolloffFactor = EAXSOURCE_DEFAULTROLLOFFFACTOR;
+ eax_.source.flRoomRolloffFactor = EAXSOURCE_DEFAULTROOMROLLOFFFACTOR;
+ eax_.source.flAirAbsorptionFactor = EAXSOURCE_DEFAULTAIRABSORPTIONFACTOR;
+ eax_.source.ulFlags = EAXSOURCE_DEFAULTFLAGS;
+}
+
+void ALsource::eax_set_active_fx_slots_defaults()
+{
+ eax_.active_fx_slots = EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID;
+}
+
+void ALsource::eax_set_send_defaults(
+ EAXSOURCEALLSENDPROPERTIES& eax_send)
+{
+ eax_send.guidReceivingFXSlotID = EAX_NULL_GUID;
+ eax_send.lSend = EAXSOURCE_DEFAULTSEND;
+ eax_send.lSendHF = EAXSOURCE_DEFAULTSENDHF;
+ eax_send.lOcclusion = EAXSOURCE_DEFAULTOCCLUSION;
+ eax_send.flOcclusionLFRatio = EAXSOURCE_DEFAULTOCCLUSIONLFRATIO;
+ eax_send.flOcclusionRoomRatio = EAXSOURCE_DEFAULTOCCLUSIONROOMRATIO;
+ eax_send.flOcclusionDirectRatio = EAXSOURCE_DEFAULTOCCLUSIONDIRECTRATIO;
+ eax_send.lExclusion = EAXSOURCE_DEFAULTEXCLUSION;
+ eax_send.flExclusionLFRatio = EAXSOURCE_DEFAULTEXCLUSIONLFRATIO;
+}
+
+void ALsource::eax_set_sends_defaults()
+{
+ for (auto& eax_send : eax_.sends)
+ {
+ eax_set_send_defaults(eax_send);
+ }
+}
+
+void ALsource::eax_set_speaker_levels_defaults()
+{
+ std::fill(eax_.speaker_levels.begin(), eax_.speaker_levels.end(), EAXSOURCE_DEFAULTSPEAKERLEVEL);
+}
+
+void ALsource::eax_set_defaults()
+{
+ eax_set_source_defaults();
+ eax_set_active_fx_slots_defaults();
+ eax_set_sends_defaults();
+ eax_set_speaker_levels_defaults();
+}
+
+float ALsource::eax_calculate_dst_occlusion_mb(
+ long src_occlusion_mb,
+ float path_ratio,
+ float lf_ratio) noexcept
+{
+ const auto ratio_1 = path_ratio + lf_ratio - 1.0F;
+ const auto ratio_2 = path_ratio * lf_ratio;
+ const auto ratio = (ratio_2 > ratio_1) ? ratio_2 : ratio_1;
+ const auto dst_occlustion_mb = static_cast<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;
+ }
+ }
+
+ const auto max_gain = eax_al_context_->eax_get_max_filter_gain();
+
+ const auto al_low_pass_param = EaxAlLowPassParam
+ {
+ clamp(level_mb_to_gain(gain_mb), 0.0F, max_gain),
+ clamp(level_mb_to_gain(gain_hf_mb), 0.0F, max_gain)
+ };
+
+ return al_low_pass_param;
+}
+
+EaxAlLowPassParam ALsource::eax_create_room_filter_param(
+ const ALeffectslot& fx_slot,
+ const EAXSOURCEALLSENDPROPERTIES& send) const noexcept
+{
+ const auto& fx_slot_eax = fx_slot.eax_get_eax_fx_slot();
+
+ const auto gain_mb =
+ static_cast<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 max_gain = eax_al_context_->eax_get_max_filter_gain();
+
+ const auto al_low_pass_param = EaxAlLowPassParam
+ {
+ clamp(level_mb_to_gain(gain_mb), 0.0F, max_gain),
+ clamp(level_mb_to_gain(gain_hf_mb), 0.0F, max_gain)
+ };
+
+ return al_low_pass_param;
+}
+
+void ALsource::eax_set_al_filter_parameters(
+ const EaxAlLowPassParam& al_low_pass_param) const noexcept
+{
+ eax_al_filter_->eax_set_low_pass_params(*eax_al_context_, al_low_pass_param);
+}
+
+void ALsource::eax_set_fx_slots()
+{
+ eax_uses_primary_id_ = false;
+ eax_has_active_fx_slots_ = false;
+
+ for (auto i = 0; i < EAX_MAX_FXSLOTS; ++i)
+ {
+ const auto& eax_active_fx_slot_id = eax_.active_fx_slots.guidActiveFXSlots[i];
+
+ auto fx_slot_index = EaxFxSlotIndex{};
+
+ if (eax_active_fx_slot_id == EAX_PrimaryFXSlotID)
+ {
+ eax_uses_primary_id_ = true;
+ fx_slot_index = eax_al_context_->eax_get_primary_fx_slot_index();
+ }
+ else
+ {
+ fx_slot_index = eax_active_fx_slot_id;
+ }
+
+ if (fx_slot_index.has_value())
+ {
+ eax_has_active_fx_slots_ = true;
+ eax_active_fx_slots_[fx_slot_index] = true;
+ }
+ }
+
+ for (auto i = 0; i < EAX_MAX_FXSLOTS; ++i)
+ {
+ if (!eax_active_fx_slots_[static_cast<std::size_t>(i)])
+ {
+ eax_al_source_3i(
+ AL_AUXILIARY_SEND_FILTER,
+ AL_EFFECTSLOT_NULL,
+ i,
+ AL_FILTER_NULL);
+ }
+ }
+}
+
+void ALsource::eax_initialize_fx_slots()
+{
+ eax_set_fx_slots();
+ eax_update_filters_internal();
+}
+
+void ALsource::eax_update_direct_filter_internal()
+{
+ const auto& direct_param = eax_create_direct_filter_param();
+ eax_set_al_filter_parameters(direct_param);
+
+ eax_al_source_i(
+ AL_DIRECT_FILTER,
+ static_cast<ALint>(eax_al_filter_->id));
+}
+
+void ALsource::eax_update_room_filters_internal()
+{
+ if (!eax_has_active_fx_slots_)
+ {
+ return;
+ }
+
+ for (auto i = 0; i < EAX_MAX_FXSLOTS; ++i)
+ {
+ if (eax_active_fx_slots_[static_cast<std::size_t>(i)])
+ {
+ const auto& fx_slot = eax_al_context_->eax_get_fx_slot(static_cast<std::size_t>(i));
+ const auto& send = eax_.sends[static_cast<std::size_t>(i)];
+ const auto& room_param = eax_create_room_filter_param(fx_slot, send);
+
+ eax_set_al_filter_parameters(room_param);
+
+ eax_al_source_3i(
+ AL_AUXILIARY_SEND_FILTER,
+ static_cast<ALint>(fx_slot.id),
+ i,
+ static_cast<ALint>(eax_al_filter_->id)
+ );
+ }
+ }
+}
+
+void ALsource::eax_update_filters_internal()
+{
+ eax_update_direct_filter_internal();
+ eax_update_room_filters_internal();
+}
+
+void ALsource::eax_update_primary_fx_slot_id()
+{
+ const auto& previous_primary_fx_slot_index = eax_al_context_->eax_get_previous_primary_fx_slot_index();
+ const auto& primary_fx_slot_index = eax_al_context_->eax_get_primary_fx_slot_index();
+
+ if (previous_primary_fx_slot_index == primary_fx_slot_index)
+ {
+ return;
+ }
+
+ if (previous_primary_fx_slot_index.has_value())
+ {
+ const auto fx_slot_index = previous_primary_fx_slot_index.get();
+ eax_active_fx_slots_[fx_slot_index] = false;
+
+ eax_al_source_3i(
+ AL_AUXILIARY_SEND_FILTER,
+ AL_EFFECTSLOT_NULL,
+ static_cast<ALint>(fx_slot_index),
+ static_cast<ALint>(AL_FILTER_NULL));
+ }
+
+ if (primary_fx_slot_index.has_value())
+ {
+ const auto fx_slot_index = primary_fx_slot_index.get();
+ eax_active_fx_slots_[fx_slot_index] = true;
+
+ const auto& fx_slot = eax_al_context_->eax_get_fx_slot(fx_slot_index);
+ const auto& send = eax_.sends[fx_slot_index];
+ const auto& room_param = eax_create_room_filter_param(fx_slot, send);
+
+ eax_set_al_filter_parameters(room_param);
+
+ eax_al_source_3i(
+ AL_AUXILIARY_SEND_FILTER,
+ static_cast<ALint>(fx_slot.id),
+ static_cast<ALint>(fx_slot_index),
+ static_cast<ALint>(eax_al_filter_->id));
+ }
+
+ eax_has_active_fx_slots_ = std::any_of(
+ eax_active_fx_slots_.cbegin(),
+ eax_active_fx_slots_.cend(),
+ [](const auto& item)
+ {
+ return item;
+ }
+ );
+}
+
+void ALsource::eax_defer_active_fx_slots(
+ const EaxEaxCall& eax_call)
+{
+ const auto active_fx_slots_span =
+ eax_call.get_values<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);
+}
+
+
+const char* ALsource::eax_get_exclusion_name() noexcept
+{
+ return "Exclusion";
+}
+
+const char* ALsource::eax_get_exclusion_lf_ratio_name() noexcept
+{
+ return "Exclusion LF Ratio";
+}
+
+const char* ALsource::eax_get_occlusion_name() noexcept
+{
+ return "Occlusion";
+}
+
+const char* ALsource::eax_get_occlusion_lf_ratio_name() noexcept
+{
+ return "Occlusion LF Ratio";
+}
+
+const char* ALsource::eax_get_occlusion_direct_ratio_name() noexcept
+{
+ return "Occlusion Direct Ratio";
+}
+
+const char* ALsource::eax_get_occlusion_room_ratio_name() noexcept
+{
+ return "Occlusion Room Ratio";
+}
+
+
+void ALsource::eax_validate_send_receiving_fx_slot_guid(
+ const GUID& guidReceivingFXSlotID)
+{
+ if (guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot0 &&
+ guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot0 &&
+ guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot1 &&
+ guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot1 &&
+ guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot2 &&
+ guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot2 &&
+ guidReceivingFXSlotID != EAXPROPERTYID_EAX40_FXSlot3 &&
+ guidReceivingFXSlotID != EAXPROPERTYID_EAX50_FXSlot3)
+ {
+ throw EaxSourceSendException{"Unsupported receiving FX slot GUID."};
+ }
+}
+
+void ALsource::eax_validate_send_send(
+ long lSend)
+{
+ eax_validate_range<EaxSourceSendException>(
+ "Send",
+ lSend,
+ EAXSOURCE_MINSEND,
+ EAXSOURCE_MAXSEND);
+}
+
+void ALsource::eax_validate_send_send_hf(
+ long lSendHF)
+{
+ eax_validate_range<EaxSourceSendException>(
+ "Send HF",
+ lSendHF,
+ EAXSOURCE_MINSENDHF,
+ EAXSOURCE_MAXSENDHF);
+}
+
+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)
+{
+ eax_validate_send_receiving_fx_slot_guid(all.guidReceivingFXSlotID);
+ eax_validate_send_occlusion(all.lOcclusion);
+ eax_validate_send_occlusion_lf_ratio(all.flOcclusionLFRatio);
+ eax_validate_send_occlusion_room_ratio(all.flOcclusionRoomRatio);
+ eax_validate_send_occlusion_direct_ratio(all.flOcclusionDirectRatio);
+}
+
+void ALsource::eax_validate_send_all(
+ const EAXSOURCEALLSENDPROPERTIES& all)
+{
+ eax_validate_send_receiving_fx_slot_guid(all.guidReceivingFXSlotID);
+ eax_validate_send_send(all.lSend);
+ eax_validate_send_send_hf(all.lSendHF);
+ eax_validate_send_occlusion(all.lOcclusion);
+ eax_validate_send_occlusion_lf_ratio(all.flOcclusionLFRatio);
+ eax_validate_send_occlusion_room_ratio(all.flOcclusionRoomRatio);
+ eax_validate_send_occlusion_direct_ratio(all.flOcclusionDirectRatio);
+ eax_validate_send_exclusion(all.lExclusion);
+ eax_validate_send_exclusion_lf_ratio(all.flExclusionLFRatio);
+}
+
+EaxFxSlotIndexValue ALsource::eax_get_send_index(
+ const GUID& send_guid)
+{
+ if (false)
+ {
+ }
+ else if (send_guid == EAXPROPERTYID_EAX40_FXSlot0 || send_guid == EAXPROPERTYID_EAX50_FXSlot0)
+ {
+ return 0;
+ }
+ else if (send_guid == EAXPROPERTYID_EAX40_FXSlot1 || send_guid == EAXPROPERTYID_EAX50_FXSlot1)
+ {
+ return 1;
+ }
+ else if (send_guid == EAXPROPERTYID_EAX40_FXSlot2 || send_guid == EAXPROPERTYID_EAX50_FXSlot2)
+ {
+ return 2;
+ }
+ else if (send_guid == EAXPROPERTYID_EAX40_FXSlot3 || send_guid == EAXPROPERTYID_EAX50_FXSlot3)
+ {
+ return 3;
+ }
+ else
+ {
+ throw EaxSourceSendException{"Unsupported receiving FX slot GUID."};
+ }
+}
+
+void ALsource::eax_defer_send_send(
+ long lSend,
+ EaxFxSlotIndexValue index)
+{
+ eax_d_.sends[index].lSend = lSend;
+
+ eax_sends_dirty_flags_.sends[index].lSend =
+ (eax_.sends[index].lSend != eax_d_.sends[index].lSend);
+}
+
+void ALsource::eax_defer_send_send_hf(
+ long lSendHF,
+ EaxFxSlotIndexValue index)
+{
+ eax_d_.sends[index].lSendHF = lSendHF;
+
+ eax_sends_dirty_flags_.sends[index].lSendHF =
+ (eax_.sends[index].lSendHF != eax_d_.sends[index].lSendHF);
+}
+
+void ALsource::eax_defer_send_occlusion(
+ long lOcclusion,
+ EaxFxSlotIndexValue index)
+{
+ eax_d_.sends[index].lOcclusion = lOcclusion;
+
+ eax_sends_dirty_flags_.sends[index].lOcclusion =
+ (eax_.sends[index].lOcclusion != eax_d_.sends[index].lOcclusion);
+}
+
+void ALsource::eax_defer_send_occlusion_lf_ratio(
+ float flOcclusionLFRatio,
+ EaxFxSlotIndexValue index)
+{
+ eax_d_.sends[index].flOcclusionLFRatio = flOcclusionLFRatio;
+
+ eax_sends_dirty_flags_.sends[index].flOcclusionLFRatio =
+ (eax_.sends[index].flOcclusionLFRatio != eax_d_.sends[index].flOcclusionLFRatio);
+}
+
+void ALsource::eax_defer_send_occlusion_room_ratio(
+ float flOcclusionRoomRatio,
+ EaxFxSlotIndexValue index)
+{
+ eax_d_.sends[index].flOcclusionRoomRatio = flOcclusionRoomRatio;
+
+ eax_sends_dirty_flags_.sends[index].flOcclusionRoomRatio =
+ (eax_.sends[index].flOcclusionRoomRatio != eax_d_.sends[index].flOcclusionRoomRatio);
+}
+
+void ALsource::eax_defer_send_occlusion_direct_ratio(
+ float flOcclusionDirectRatio,
+ EaxFxSlotIndexValue index)
+{
+ eax_d_.sends[index].flOcclusionDirectRatio = flOcclusionDirectRatio;
+
+ eax_sends_dirty_flags_.sends[index].flOcclusionDirectRatio =
+ (eax_.sends[index].flOcclusionDirectRatio != eax_d_.sends[index].flOcclusionDirectRatio);
+}
+
+void ALsource::eax_defer_send_exclusion(
+ long lExclusion,
+ EaxFxSlotIndexValue index)
+{
+ eax_d_.sends[index].lExclusion = lExclusion;
+
+ eax_sends_dirty_flags_.sends[index].lExclusion =
+ (eax_.sends[index].lExclusion != eax_d_.sends[index].lExclusion);
+}
+
+void ALsource::eax_defer_send_exclusion_lf_ratio(
+ float flExclusionLFRatio,
+ EaxFxSlotIndexValue index)
+{
+ eax_d_.sends[index].flExclusionLFRatio = flExclusionLFRatio;
+
+ eax_sends_dirty_flags_.sends[index].flExclusionLFRatio =
+ (eax_.sends[index].flExclusionLFRatio != eax_d_.sends[index].flExclusionLFRatio);
+}
+
+void ALsource::eax_defer_send(
+ const EAXSOURCESENDPROPERTIES& all,
+ EaxFxSlotIndexValue index)
+{
+ eax_defer_send_send(all.lSend, index);
+ eax_defer_send_send_hf(all.lSendHF, index);
+}
+
+void ALsource::eax_defer_send_exclusion_all(
+ const EAXSOURCEEXCLUSIONSENDPROPERTIES& all,
+ EaxFxSlotIndexValue index)
+{
+ eax_defer_send_exclusion(all.lExclusion, index);
+ eax_defer_send_exclusion_lf_ratio(all.flExclusionLFRatio, index);
+}
+
+void ALsource::eax_defer_send_occlusion_all(
+ const EAXSOURCEOCCLUSIONSENDPROPERTIES& all,
+ EaxFxSlotIndexValue index)
+{
+ eax_defer_send_occlusion(all.lOcclusion, index);
+ eax_defer_send_occlusion_lf_ratio(all.flOcclusionLFRatio, index);
+ eax_defer_send_occlusion_room_ratio(all.flOcclusionRoomRatio, index);
+ eax_defer_send_occlusion_direct_ratio(all.flOcclusionDirectRatio, index);
+}
+
+void ALsource::eax_defer_send_all(
+ const EAXSOURCEALLSENDPROPERTIES& all,
+ EaxFxSlotIndexValue index)
+{
+ eax_defer_send_send(all.lSend, index);
+ eax_defer_send_send_hf(all.lSendHF, index);
+ eax_defer_send_occlusion(all.lOcclusion, index);
+ eax_defer_send_occlusion_lf_ratio(all.flOcclusionLFRatio, index);
+ eax_defer_send_occlusion_room_ratio(all.flOcclusionRoomRatio, index);
+ eax_defer_send_occlusion_direct_ratio(all.flOcclusionDirectRatio, index);
+ eax_defer_send_exclusion(all.lExclusion, index);
+ eax_defer_send_exclusion_lf_ratio(all.flExclusionLFRatio, index);
+}
+
+void ALsource::eax_defer_send(
+ const EaxEaxCall& eax_call)
+{
+ const auto eax_all_span =
+ eax_call.get_values<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);
+ }
+
+ for (auto i = std::size_t{}; i < count; ++i)
+ {
+ const auto& all = eax_all_span[i];
+ const auto send_index = eax_get_send_index(all.guidReceivingFXSlotID);
+ eax_defer_send(all, send_index);
+ }
+}
+
+void ALsource::eax_defer_send_exclusion_all(
+ const EaxEaxCall& eax_call)
+{
+ const auto eax_all_span =
+ eax_call.get_values<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);
+ }
+}
+
+void ALsource::eax_defer_send_occlusion_all(
+ const EaxEaxCall& eax_call)
+{
+ const auto eax_all_span =
+ eax_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."};
+ }
+
+ for (auto i = std::size_t{}; i < count; ++i)
+ {
+ const auto& all = eax_all_span[i];
+ eax_validate_send_occlusion_all(all);
+ }
+
+ for (auto i = std::size_t{}; i < count; ++i)
+ {
+ const auto& all = eax_all_span[i];
+ const auto send_index = eax_get_send_index(all.guidReceivingFXSlotID);
+ eax_defer_send_occlusion_all(all, send_index);
+ }
+}
+
+void ALsource::eax_defer_send_all(
+ const EaxEaxCall& eax_call)
+{
+ const auto eax_all_span =
+ eax_call.get_values<EaxSourceException, const EAXSOURCEALLSENDPROPERTIES>();
+
+ const auto count = eax_all_span.size();
+
+ if (count <= 0 || count > EAX_MAX_FXSLOTS)
+ {
+ throw EaxSourceSendException{"Send all count out of range."};
+ }
+
+ for (auto i = std::size_t{}; i < count; ++i)
+ {
+ const auto& all = eax_all_span[i];
+ eax_validate_send_all(all);
+ }
+
+ for (auto i = std::size_t{}; i < count; ++i)
+ {
+ const auto& all = eax_all_span[i];
+ const auto send_index = eax_get_send_index(all.guidReceivingFXSlotID);
+ eax_defer_send_all(all, send_index);
+ }
+}
+
+
+void ALsource::eax_validate_source_direct(
+ long direct)
+{
+ eax_validate_range<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);
+}
+
+void ALsource::eax_defer_source_all(
+ const EAX30SOURCEPROPERTIES& all)
+{
+ eax_defer_source_direct(all.lDirect);
+ eax_defer_source_direct_hf(all.lDirectHF);
+ eax_defer_source_room(all.lRoom);
+ eax_defer_source_room_hf(all.lRoomHF);
+ eax_defer_source_obstruction(all.lObstruction);
+ eax_defer_source_obstruction_lf_ratio(all.flObstructionLFRatio);
+ eax_defer_source_occlusion(all.lOcclusion);
+ eax_defer_source_occlusion_lf_ratio(all.flOcclusionLFRatio);
+ eax_defer_source_occlusion_room_ratio(all.flOcclusionRoomRatio);
+ eax_defer_source_occlusion_direct_ratio(all.flOcclusionDirectRatio);
+ eax_defer_source_exclusion(all.lExclusion);
+ eax_defer_source_exclusion_lf_ratio(all.flExclusionLFRatio);
+ eax_defer_source_outside_volume_hf(all.lOutsideVolumeHF);
+ eax_defer_source_doppler_factor(all.flDopplerFactor);
+ eax_defer_source_rolloff_factor(all.flRolloffFactor);
+ eax_defer_source_room_rolloff_factor(all.flRoomRolloffFactor);
+ eax_defer_source_air_absorption_factor(all.flAirAbsorptionFactor);
+ eax_defer_source_flags(all.ulFlags);
+}
+
+void ALsource::eax_defer_source_all(
+ const EAX50SOURCEPROPERTIES& all)
+{
+ eax_defer_source_all(static_cast<const EAX30SOURCEPROPERTIES&>(all));
+ eax_defer_source_macro_fx_factor(all.flMacroFXFactor);
+}
+
+void ALsource::eax_defer_source_speaker_level_all(
+ const EAXSPEAKERLEVELPROPERTIES& all)
+{
+ const auto speaker_index = static_cast<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];
+
+ if (speaker_level != speaker_level_d)
+ {
+ eax_source_dirty_misc_flags_.speaker_levels = true;
+ }
+}
+
+void ALsource::eax_defer_source_direct(
+ const EaxEaxCall& eax_call)
+{
+ const auto direct =
+ eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::lDirect)>();
+
+ eax_validate_source_direct(direct);
+ eax_defer_source_direct(direct);
+}
+
+void ALsource::eax_defer_source_direct_hf(
+ const EaxEaxCall& eax_call)
+{
+ const auto direct_hf =
+ eax_call.get_value<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 EaxEaxCall& eax_call)
+{
+ const auto room =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto room_hf =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto obstruction =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto obstruction_lf_ratio =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto occlusion =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto occlusion_lf_ratio =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto occlusion_room_ratio =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto occlusion_direct_ratio =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto exclusion =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto exclusion_lf_ratio =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto outside_volume_hf =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto doppler_factor =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto rolloff_factor =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto room_rolloff_factor =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto air_absorption_factor =
+ eax_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 EaxEaxCall& eax_call)
+{
+ const auto flags =
+ eax_call.get_value<EaxSourceException, const decltype(EAX30SOURCEPROPERTIES::ulFlags)>();
+
+ eax_validate_source_flags(flags, eax_call.get_version());
+ eax_defer_source_flags(flags);
+}
+
+void ALsource::eax_defer_source_macro_fx_factor(
+ const EaxEaxCall& eax_call)
+{
+ const auto macro_fx_factor =
+ eax_call.get_value<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 EaxEaxCall& eax_call)
+{
+ const auto all = eax_call.get_value<EaxSourceException, const EAXSOURCE2DPROPERTIES>();
+
+ eax_validate_source_2d_all(all, eax_call.get_version());
+ eax_defer_source_2d_all(all);
+}
+
+void ALsource::eax_defer_source_obstruction_all(
+ const EaxEaxCall& eax_call)
+{
+ const auto all = eax_call.get_value<EaxSourceException, const EAXOBSTRUCTIONPROPERTIES>();
+
+ eax_validate_source_obstruction_all(all);
+ eax_defer_source_obstruction_all(all);
+}
+
+void ALsource::eax_defer_source_exclusion_all(
+ const EaxEaxCall& eax_call)
+{
+ const auto all = eax_call.get_value<EaxSourceException, const EAXEXCLUSIONPROPERTIES>();
+
+ eax_validate_source_exclusion_all(all);
+ eax_defer_source_exclusion_all(all);
+}
+
+void ALsource::eax_defer_source_occlusion_all(
+ const EaxEaxCall& eax_call)
+{
+ const auto all = eax_call.get_value<EaxSourceException, const EAXOCCLUSIONPROPERTIES>();
+
+ eax_validate_source_occlusion_all(all);
+ eax_defer_source_occlusion_all(all);
+}
+
+void ALsource::eax_defer_source_all(
+ const EaxEaxCall& eax_call)
+{
+ const auto eax_version = eax_call.get_version();
+
+ if (eax_version == 2)
+ {
+ const auto all = eax_call.get_value<EaxSourceException, const EAX20BUFFERPROPERTIES>();
+
+ eax_validate_source_all(all, eax_version);
+ eax_defer_source_all(all);
+ }
+ else if (eax_version < 5)
+ {
+ const auto all = eax_call.get_value<EaxSourceException, const EAX30SOURCEPROPERTIES>();
+
+ eax_validate_source_all(all, eax_version);
+ eax_defer_source_all(all);
+ }
+ else
+ {
+ const auto all = eax_call.get_value<EaxSourceException, const EAX50SOURCEPROPERTIES>();
+
+ eax_validate_source_all(all, eax_version);
+ eax_defer_source_all(all);
+ }
+}
+
+void ALsource::eax_defer_source_speaker_level_all(
+ const EaxEaxCall& eax_call)
+{
+ const auto speaker_level_properties = eax_call.get_value<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()
+{
+ const auto efx_gain_hf = clamp(
+ level_mb_to_gain(static_cast<float>(eax_.source.lOutsideVolumeHF)),
+ AL_MIN_CONE_OUTER_GAINHF,
+ AL_MAX_CONE_OUTER_GAINHF
+ );
+
+ eax_al_source_f(
+ AL_CONE_OUTER_GAINHF,
+ efx_gain_hf
+ );
+}
+
+void ALsource::eax_set_doppler_factor()
+{
+ eax_al_source_f(
+ AL_DOPPLER_FACTOR,
+ eax_.source.flDopplerFactor
+ );
+}
+
+void ALsource::eax_set_rolloff_factor()
+{
+ eax_al_source_f(
+ AL_ROLLOFF_FACTOR,
+ eax_.source.flRolloffFactor
+ );
+}
+
+void ALsource::eax_set_room_rolloff_factor()
+{
+ eax_al_source_f(
+ AL_ROOM_ROLLOFF_FACTOR,
+ eax_.source.flRoomRolloffFactor
+ );
+}
+
+void ALsource::eax_set_air_absorption_factor()
+{
+ const auto air_absorption_factor =
+ eax_al_context_->eax_get_air_absorption_factor() * eax_.source.flAirAbsorptionFactor;
+
+ eax_al_source_f(
+ AL_AIR_ABSORPTION_FACTOR,
+ air_absorption_factor
+ );
+}
+
+void ALsource::eax_set_direct_hf_auto_flag()
+{
+ const auto is_enable = (eax_.source.ulFlags & EAXSOURCEFLAGS_DIRECTHFAUTO) != 0;
+ const auto al_value = static_cast<ALint>(is_enable ? AL_TRUE : AL_FALSE);
+
+ eax_al_source_i(
+ AL_DIRECT_FILTER_GAINHF_AUTO,
+ al_value
+ );
+}
+
+void ALsource::eax_set_room_auto_flag()
+{
+ const auto is_enable = (eax_.source.ulFlags & EAXSOURCEFLAGS_ROOMAUTO) != 0;
+ const auto al_value = static_cast<ALint>(is_enable ? AL_TRUE : AL_FALSE);
+
+ eax_al_source_i(
+ AL_AUXILIARY_SEND_FILTER_GAIN_AUTO,
+ al_value
+ );
+}
+
+void ALsource::eax_set_room_hf_auto_flag()
+{
+ const auto is_enable = (eax_.source.ulFlags & EAXSOURCEFLAGS_ROOMHFAUTO) != 0;
+ const auto al_value = static_cast<ALint>(is_enable ? AL_TRUE : AL_FALSE);
+
+ eax_al_source_i(
+ AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO,
+ al_value
+ );
+}
+
+void ALsource::eax_set_flags()
+{
+ eax_set_direct_hf_auto_flag();
+ eax_set_room_auto_flag();
+ eax_set_room_hf_auto_flag();
+ eax_set_speaker_levels();
+}
+
+void ALsource::eax_set_macro_fx_factor()
+{
+ // TODO
+}
+
+void ALsource::eax_set_speaker_levels()
+{
+ // TODO
+}
+
+void ALsource::eax_apply_deferred()
+{
+ if (!eax_are_active_fx_slots_dirty_ &&
+ eax_sends_dirty_flags_ == EaxSourceSendsDirtyFlags{} &&
+ eax_source_dirty_filter_flags_ == EaxSourceSourceFilterDirtyFlags{} &&
+ eax_source_dirty_misc_flags_ == EaxSourceSourceMiscDirtyFlags{})
+ {
+ return;
+ }
+
+ eax_ = eax_d_;
+
+ if (eax_are_active_fx_slots_dirty_)
+ {
+ eax_are_active_fx_slots_dirty_ = false;
+ eax_set_fx_slots();
+ eax_update_filters_internal();
+ }
+ else if (eax_has_active_fx_slots_)
+ {
+ if (eax_source_dirty_filter_flags_ != EaxSourceSourceFilterDirtyFlags{})
+ {
+ eax_update_filters_internal();
+ }
+ else if (eax_sends_dirty_flags_ != EaxSourceSendsDirtyFlags{})
+ {
+ for (auto i = std::size_t{}; i < EAX_MAX_FXSLOTS; ++i)
+ {
+ if (eax_active_fx_slots_[i])
+ {
+ if (eax_sends_dirty_flags_.sends[i] != EaxSourceSendDirtyFlags{})
+ {
+ eax_update_filters_internal();
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (eax_source_dirty_misc_flags_ != EaxSourceSourceMiscDirtyFlags{})
+ {
+ if (eax_source_dirty_misc_flags_.lOutsideVolumeHF)
+ {
+ eax_set_outside_volume_hf();
+ }
+
+ if (eax_source_dirty_misc_flags_.flDopplerFactor)
+ {
+ eax_set_doppler_factor();
+ }
+
+ if (eax_source_dirty_misc_flags_.flRolloffFactor)
+ {
+ eax_set_rolloff_factor();
+ }
+
+ if (eax_source_dirty_misc_flags_.flRoomRolloffFactor)
+ {
+ eax_set_room_rolloff_factor();
+ }
+
+ if (eax_source_dirty_misc_flags_.flAirAbsorptionFactor)
+ {
+ eax_set_air_absorption_factor();
+ }
+
+ if (eax_source_dirty_misc_flags_.ulFlags)
+ {
+ eax_set_flags();
+ }
+
+ if (eax_source_dirty_misc_flags_.flMacroFXFactor)
+ {
+ eax_set_macro_fx_factor();
+ }
+
+ eax_source_dirty_misc_flags_ = EaxSourceSourceMiscDirtyFlags{};
+ }
+
+ eax_sends_dirty_flags_ = EaxSourceSendsDirtyFlags{};
+ eax_source_dirty_filter_flags_ = EaxSourceSourceFilterDirtyFlags{};
+}
+
+void ALsource::eax_set(
+ const EaxEaxCall& eax_call)
+{
+ switch (eax_call.get_property_id())
+ {
+ case EAXSOURCE_NONE:
+ break;
+
+ case EAXSOURCE_ALLPARAMETERS:
+ eax_defer_source_all(eax_call);
+ break;
+
+ case EAXSOURCE_OBSTRUCTIONPARAMETERS:
+ eax_defer_source_obstruction_all(eax_call);
+ break;
+
+ case EAXSOURCE_OCCLUSIONPARAMETERS:
+ eax_defer_source_occlusion_all(eax_call);
+ break;
+
+ case EAXSOURCE_EXCLUSIONPARAMETERS:
+ eax_defer_source_exclusion_all(eax_call);
+ break;
+
+ case EAXSOURCE_DIRECT:
+ eax_defer_source_direct(eax_call);
+ break;
+
+ case EAXSOURCE_DIRECTHF:
+ eax_defer_source_direct_hf(eax_call);
+ break;
+
+ case EAXSOURCE_ROOM:
+ eax_defer_source_room(eax_call);
+ break;
+
+ case EAXSOURCE_ROOMHF:
+ eax_defer_source_room_hf(eax_call);
+ break;
+
+ case EAXSOURCE_OBSTRUCTION:
+ eax_defer_source_obstruction(eax_call);
+ break;
+
+ case EAXSOURCE_OBSTRUCTIONLFRATIO:
+ eax_defer_source_obstruction_lf_ratio(eax_call);
+ break;
+
+ case EAXSOURCE_OCCLUSION:
+ eax_defer_source_occlusion(eax_call);
+ break;
+
+ case EAXSOURCE_OCCLUSIONLFRATIO:
+ eax_defer_source_occlusion_lf_ratio(eax_call);
+ break;
+
+ case EAXSOURCE_OCCLUSIONROOMRATIO:
+ eax_defer_source_occlusion_room_ratio(eax_call);
+ break;
+
+ case EAXSOURCE_OCCLUSIONDIRECTRATIO:
+ eax_defer_source_occlusion_direct_ratio(eax_call);
+ break;
+
+ case EAXSOURCE_EXCLUSION:
+ eax_defer_source_exclusion(eax_call);
+ break;
+
+ case EAXSOURCE_EXCLUSIONLFRATIO:
+ eax_defer_source_exclusion_lf_ratio(eax_call);
+ break;
+
+ case EAXSOURCE_OUTSIDEVOLUMEHF:
+ eax_defer_source_outside_volume_hf(eax_call);
+ break;
+
+ case EAXSOURCE_DOPPLERFACTOR:
+ eax_defer_source_doppler_factor(eax_call);
+ break;
+
+ case EAXSOURCE_ROLLOFFFACTOR:
+ eax_defer_source_rolloff_factor(eax_call);
+ break;
+
+ case EAXSOURCE_ROOMROLLOFFFACTOR:
+ eax_defer_source_room_rolloff_factor(eax_call);
+ break;
+
+ case EAXSOURCE_AIRABSORPTIONFACTOR:
+ eax_defer_source_air_absorption_factor(eax_call);
+ break;
+
+ case EAXSOURCE_FLAGS:
+ eax_defer_source_flags(eax_call);
+ break;
+
+ case EAXSOURCE_SENDPARAMETERS:
+ eax_defer_send(eax_call);
+ break;
+
+ case EAXSOURCE_ALLSENDPARAMETERS:
+ eax_defer_send_all(eax_call);
+ break;
+
+ case EAXSOURCE_OCCLUSIONSENDPARAMETERS:
+ eax_defer_send_occlusion_all(eax_call);
+ break;
+
+ case EAXSOURCE_EXCLUSIONSENDPARAMETERS:
+ eax_defer_send_exclusion_all(eax_call);
+ break;
+
+ case EAXSOURCE_ACTIVEFXSLOTID:
+ eax_defer_active_fx_slots(eax_call);
+ break;
+
+ case EAXSOURCE_MACROFXFACTOR:
+ eax_defer_source_macro_fx_factor(eax_call);
+ break;
+
+ case EAXSOURCE_SPEAKERLEVELS:
+ eax_defer_source_speaker_level_all(eax_call);
+ break;
+
+ case EAXSOURCE_ALL2DPARAMETERS:
+ eax_defer_source_2d_all(eax_call);
+ break;
+
+ default:
+ eax_fail("Unsupported property id.");
+ }
+
+ if (!eax_call.is_deferred())
+ {
+ eax_apply_deferred();
+ }
+}
+
+const GUID& ALsource::eax_get_send_fx_slot_guid(
+ int eax_version,
+ EaxFxSlotIndexValue fx_slot_index)
+{
+ switch (eax_version)
+ {
+ case 4:
+ switch (fx_slot_index)
+ {
+ case 0:
+ return EAXPROPERTYID_EAX40_FXSlot0;
+
+ case 1:
+ return EAXPROPERTYID_EAX40_FXSlot1;
+
+ case 2:
+ return EAXPROPERTYID_EAX40_FXSlot2;
+
+ case 3:
+ return EAXPROPERTYID_EAX40_FXSlot3;
+
+ default:
+ eax_fail("FX slot index out of range.");
+ }
+
+ case 5:
+ switch (fx_slot_index)
+ {
+ case 0:
+ return EAXPROPERTYID_EAX50_FXSlot0;
+
+ case 1:
+ return EAXPROPERTYID_EAX50_FXSlot1;
+
+ case 2:
+ return EAXPROPERTYID_EAX50_FXSlot2;
+
+ case 3:
+ return EAXPROPERTYID_EAX50_FXSlot3;
+
+ default:
+ eax_fail("FX slot index out of range.");
+ }
+
+ default:
+ eax_fail("Unsupported EAX version.");
+ }
+}
+
+void ALsource::eax_copy_send(
+ const EAXSOURCEALLSENDPROPERTIES& src_send,
+ EAXSOURCESENDPROPERTIES& dst_send)
+{
+ dst_send.lSend = src_send.lSend;
+ dst_send.lSendHF = src_send.lSendHF;
+}
+
+void ALsource::eax_copy_send(
+ const EAXSOURCEALLSENDPROPERTIES& src_send,
+ EAXSOURCEALLSENDPROPERTIES& dst_send)
+{
+ dst_send = src_send;
+}
+
+void ALsource::eax_copy_send(
+ const EAXSOURCEALLSENDPROPERTIES& src_send,
+ EAXSOURCEOCCLUSIONSENDPROPERTIES& dst_send)
+{
+ dst_send.lOcclusion = src_send.lOcclusion;
+ dst_send.flOcclusionLFRatio = src_send.flOcclusionLFRatio;
+ dst_send.flOcclusionRoomRatio = src_send.flOcclusionRoomRatio;
+ dst_send.flOcclusionDirectRatio = src_send.flOcclusionDirectRatio;
+}
+
+void ALsource::eax_copy_send(
+ const EAXSOURCEALLSENDPROPERTIES& src_send,
+ EAXSOURCEEXCLUSIONSENDPROPERTIES& dst_send)
+{
+ dst_send.lExclusion = src_send.lExclusion;
+ dst_send.flExclusionLFRatio = src_send.flExclusionLFRatio;
+}
+
+void ALsource::eax_api_get_source_all_v2(
+ const EaxEaxCall& eax_call)
+{
+ auto eax_2_all = EAX20BUFFERPROPERTIES{};
+ eax_2_all.lDirect = eax_.source.lDirect;
+ eax_2_all.lDirectHF = eax_.source.lDirectHF;
+ eax_2_all.lRoom = eax_.source.lRoom;
+ eax_2_all.lRoomHF = eax_.source.lRoomHF;
+ eax_2_all.flRoomRolloffFactor = eax_.source.flRoomRolloffFactor;
+ eax_2_all.lObstruction = eax_.source.lObstruction;
+ eax_2_all.flObstructionLFRatio = eax_.source.flObstructionLFRatio;
+ eax_2_all.lOcclusion = eax_.source.lOcclusion;
+ eax_2_all.flOcclusionLFRatio = eax_.source.flOcclusionLFRatio;
+ eax_2_all.flOcclusionRoomRatio = eax_.source.flOcclusionRoomRatio;
+ eax_2_all.lOutsideVolumeHF = eax_.source.lOutsideVolumeHF;
+ eax_2_all.flAirAbsorptionFactor = eax_.source.flAirAbsorptionFactor;
+ eax_2_all.dwFlags = eax_.source.ulFlags;
+
+ eax_call.set_value<EaxSourceException>(eax_2_all);
+}
+
+void ALsource::eax_api_get_source_all_v3(
+ const EaxEaxCall& eax_call)
+{
+ eax_call.set_value<EaxSourceException>(static_cast<const EAX30SOURCEPROPERTIES&>(eax_.source));
+}
+
+void ALsource::eax_api_get_source_all_v5(
+ const EaxEaxCall& eax_call)
+{
+ eax_call.set_value<EaxSourceException>(eax_.source);
+}
+
+void ALsource::eax_api_get_source_all(
+ const EaxEaxCall& eax_call)
+{
+ switch (eax_call.get_version())
+ {
+ case 2:
+ eax_api_get_source_all_v2(eax_call);
+ break;
+
+ case 3:
+ case 4:
+ eax_api_get_source_all_v3(eax_call);
+ break;
+
+ case 5:
+ eax_api_get_source_all_v5(eax_call);
+ break;
+
+ default:
+ eax_fail("Unsupported EAX version.");
+ }
+}
+
+void ALsource::eax_api_get_source_all_obstruction(
+ const EaxEaxCall& eax_call)
+{
+ static_assert(
+ offsetof(EAXOBSTRUCTIONPROPERTIES, flObstructionLFRatio) - offsetof(EAXOBSTRUCTIONPROPERTIES, lObstruction) ==
+ offsetof(EAX30SOURCEPROPERTIES, flObstructionLFRatio) - offsetof(EAX30SOURCEPROPERTIES, lObstruction),
+ "Type size."
+ );
+
+ const auto eax_obstruction_all = *reinterpret_cast<const EAXOBSTRUCTIONPROPERTIES*>(&eax_.source.lObstruction);
+
+ eax_call.set_value<EaxSourceException>(eax_obstruction_all);
+}
+
+void ALsource::eax_api_get_source_all_occlusion(
+ const EaxEaxCall& eax_call)
+{
+ static_assert(
+ offsetof(EAXOCCLUSIONPROPERTIES, flOcclusionLFRatio) - offsetof(EAXOCCLUSIONPROPERTIES, lOcclusion) ==
+ offsetof(EAX30SOURCEPROPERTIES, flOcclusionLFRatio) - offsetof(EAX30SOURCEPROPERTIES, lOcclusion) &&
+
+ offsetof(EAXOCCLUSIONPROPERTIES, flOcclusionRoomRatio) - offsetof(EAXOCCLUSIONPROPERTIES, lOcclusion) ==
+ offsetof(EAX30SOURCEPROPERTIES, flOcclusionRoomRatio) - offsetof(EAX30SOURCEPROPERTIES, lOcclusion) &&
+
+ offsetof(EAXOCCLUSIONPROPERTIES, flOcclusionDirectRatio) - offsetof(EAXOCCLUSIONPROPERTIES, lOcclusion) ==
+ offsetof(EAX30SOURCEPROPERTIES, flOcclusionDirectRatio) - offsetof(EAX30SOURCEPROPERTIES, lOcclusion),
+
+ "Type size."
+ );
+
+ const auto eax_occlusion_all = *reinterpret_cast<const EAXOCCLUSIONPROPERTIES*>(&eax_.source.lOcclusion);
+
+ eax_call.set_value<EaxSourceException>(eax_occlusion_all);
+}
+
+void ALsource::eax_api_get_source_all_exclusion(
+ const EaxEaxCall& eax_call)
+{
+ static_assert(
+ offsetof(EAXEXCLUSIONPROPERTIES, flExclusionLFRatio) - offsetof(EAXEXCLUSIONPROPERTIES, lExclusion) ==
+ offsetof(EAX30SOURCEPROPERTIES, flExclusionLFRatio) - offsetof(EAX30SOURCEPROPERTIES, lExclusion),
+
+ "Type size."
+ );
+
+ const auto eax_exclusion_all = *reinterpret_cast<const EAXEXCLUSIONPROPERTIES*>(&eax_.source.lExclusion);
+
+ eax_call.set_value<EaxSourceException>(eax_exclusion_all);
+}
+
+void ALsource::eax_api_get_source_active_fx_slot_id(
+ const EaxEaxCall& eax_call)
+{
+ switch (eax_call.get_version())
+ {
+ case 4:
+ {
+ const auto& active_fx_slots = reinterpret_cast<const EAX40ACTIVEFXSLOTS&>(eax_.active_fx_slots);
+ eax_call.set_value<EaxSourceException>(active_fx_slots);
+ }
+ break;
+
+ case 5:
+ {
+ const auto& active_fx_slots = reinterpret_cast<const EAX50ACTIVEFXSLOTS&>(eax_.active_fx_slots);
+ eax_call.set_value<EaxSourceException>(active_fx_slots);
+ }
+ break;
+
+ default:
+ eax_fail("Unsupported EAX version.");
+ }
+}
+
+void ALsource::eax_api_get_source_all_2d(
+ const EaxEaxCall& eax_call)
+{
+ auto eax_2d_all = EAXSOURCE2DPROPERTIES{};
+ eax_2d_all.lDirect = eax_.source.lDirect;
+ eax_2d_all.lDirectHF = eax_.source.lDirectHF;
+ eax_2d_all.lRoom = eax_.source.lRoom;
+ eax_2d_all.lRoomHF = eax_.source.lRoomHF;
+ eax_2d_all.ulFlags = eax_.source.ulFlags;
+
+ eax_call.set_value<EaxSourceException>(eax_2d_all);
+}
+
+void ALsource::eax_api_get_source_speaker_level_all(
+ const EaxEaxCall& eax_call)
+{
+ auto& all = eax_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];
+}
+
+void ALsource::eax_get(
+ const EaxEaxCall& eax_call)
+{
+ switch (eax_call.get_property_id())
+ {
+ case EAXSOURCE_NONE:
+ break;
+
+ case EAXSOURCE_ALLPARAMETERS:
+ eax_api_get_source_all(eax_call);
+ break;
+
+ case EAXSOURCE_OBSTRUCTIONPARAMETERS:
+ eax_api_get_source_all_obstruction(eax_call);
+ break;
+
+ case EAXSOURCE_OCCLUSIONPARAMETERS:
+ eax_api_get_source_all_occlusion(eax_call);
+ break;
+
+ case EAXSOURCE_EXCLUSIONPARAMETERS:
+ eax_api_get_source_all_exclusion(eax_call);
+ break;
+
+ case EAXSOURCE_DIRECT:
+ eax_call.set_value<EaxSourceException>(eax_.source.lDirect);
+ break;
+
+ case EAXSOURCE_DIRECTHF:
+ eax_call.set_value<EaxSourceException>(eax_.source.lDirectHF);
+ break;
+
+ case EAXSOURCE_ROOM:
+ eax_call.set_value<EaxSourceException>(eax_.source.lRoom);
+ break;
+
+ case EAXSOURCE_ROOMHF:
+ eax_call.set_value<EaxSourceException>(eax_.source.lRoomHF);
+ break;
+
+ case EAXSOURCE_OBSTRUCTION:
+ eax_call.set_value<EaxSourceException>(eax_.source.lObstruction);
+ break;
+
+ case EAXSOURCE_OBSTRUCTIONLFRATIO:
+ eax_call.set_value<EaxSourceException>(eax_.source.flObstructionLFRatio);
+ break;
+
+ case EAXSOURCE_OCCLUSION:
+ eax_call.set_value<EaxSourceException>(eax_.source.lOcclusion);
+ break;
+
+ case EAXSOURCE_OCCLUSIONLFRATIO:
+ eax_call.set_value<EaxSourceException>(eax_.source.flOcclusionLFRatio);
+ break;
+
+ case EAXSOURCE_OCCLUSIONROOMRATIO:
+ eax_call.set_value<EaxSourceException>(eax_.source.flOcclusionRoomRatio);
+ break;
+
+ case EAXSOURCE_OCCLUSIONDIRECTRATIO:
+ eax_call.set_value<EaxSourceException>(eax_.source.flOcclusionDirectRatio);
+ break;
+
+ case EAXSOURCE_EXCLUSION:
+ eax_call.set_value<EaxSourceException>(eax_.source.lExclusion);
+ break;
+
+ case EAXSOURCE_EXCLUSIONLFRATIO:
+ eax_call.set_value<EaxSourceException>(eax_.source.flExclusionLFRatio);
+ break;
+
+ case EAXSOURCE_OUTSIDEVOLUMEHF:
+ eax_call.set_value<EaxSourceException>(eax_.source.lOutsideVolumeHF);
+ break;
+
+ case EAXSOURCE_DOPPLERFACTOR:
+ eax_call.set_value<EaxSourceException>(eax_.source.flDopplerFactor);
+ break;
+
+ case EAXSOURCE_ROLLOFFFACTOR:
+ eax_call.set_value<EaxSourceException>(eax_.source.flRolloffFactor);
+ break;
+
+ case EAXSOURCE_ROOMROLLOFFFACTOR:
+ eax_call.set_value<EaxSourceException>(eax_.source.flRoomRolloffFactor);
+ break;
+
+ case EAXSOURCE_AIRABSORPTIONFACTOR:
+ eax_call.set_value<EaxSourceException>(eax_.source.flAirAbsorptionFactor);
+ break;
+
+ case EAXSOURCE_FLAGS:
+ eax_call.set_value<EaxSourceException>(eax_.source.ulFlags);
+ break;
+
+ case EAXSOURCE_SENDPARAMETERS:
+ eax_api_get_send_properties<EaxSourceException, EAXSOURCESENDPROPERTIES>(eax_call);
+ break;
+
+ case EAXSOURCE_ALLSENDPARAMETERS:
+ eax_api_get_send_properties<EaxSourceException, EAXSOURCEALLSENDPROPERTIES>(eax_call);
+ break;
+
+ case EAXSOURCE_OCCLUSIONSENDPARAMETERS:
+ eax_api_get_send_properties<EaxSourceException, EAXSOURCEOCCLUSIONSENDPROPERTIES>(eax_call);
+ break;
+
+ case EAXSOURCE_EXCLUSIONSENDPARAMETERS:
+ eax_api_get_send_properties<EaxSourceException, EAXSOURCEEXCLUSIONSENDPROPERTIES>(eax_call);
+ break;
+
+ case EAXSOURCE_ACTIVEFXSLOTID:
+ eax_api_get_source_active_fx_slot_id(eax_call);
+ break;
+
+ case EAXSOURCE_MACROFXFACTOR:
+ eax_call.set_value<EaxSourceException>(eax_.source.flMacroFXFactor);
+ break;
+
+ case EAXSOURCE_SPEAKERLEVELS:
+ eax_api_get_source_speaker_level_all(eax_call);
+ break;
+
+ case EAXSOURCE_ALL2DPARAMETERS:
+ eax_api_get_source_all_2d(eax_call);
+ break;
+
+ default:
+ eax_fail("Unsupported property id.");
+ }
+}
+
+void ALsource::eax_al_source_i(
+ ALenum param,
+ ALint value)
+{
+ SetSourceiv(this, eax_al_context_, static_cast<SourceProp>(param), {&value, 1});
+}
+
+void ALsource::eax_al_source_f(
+ ALenum param,
+ ALfloat value)
+{
+ SetSourcefv(this, eax_al_context_, static_cast<SourceProp>(param), {&value, 1});
+}
+
+void ALsource::eax_al_source_3i(
+ ALenum param,
+ ALint value1,
+ ALint value2,
+ ALint value3)
+{
+ const ALint values[3] = {value1, value2, value3};
+ SetSourceiv(this, eax_al_context_, static_cast<SourceProp>(param), values);
+}
+
+
+#endif // ALSOFT_EAX