diff options
Diffstat (limited to 'al/source.h')
-rw-r--r-- | al/source.h | 1333 |
1 files changed, 790 insertions, 543 deletions
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 }; |