diff options
Diffstat (limited to 'al/eax/call.cpp')
-rw-r--r-- | al/eax/call.cpp | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/al/eax/call.cpp b/al/eax/call.cpp new file mode 100644 index 00000000..689d5cf1 --- /dev/null +++ b/al/eax/call.cpp @@ -0,0 +1,219 @@ +#include "config.h" +#include "call.h" +#include "exception.h" + +namespace { + +constexpr auto deferred_flag = 0x80000000U; + +class EaxCallException : public EaxException { +public: + explicit EaxCallException(const char* message) + : EaxException{"EAX_CALL", message} + {} +}; // EaxCallException + +} // namespace + +EaxCall::EaxCall( + EaxCallType type, + const GUID& property_set_guid, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size) + : mCallType{type}, mVersion{0}, mPropertySetId{EaxCallPropertySetId::none} + , mIsDeferred{(property_id & deferred_flag) != 0} + , mPropertyId{property_id & ~deferred_flag}, mPropertySourceId{property_source_id} + , mPropertyBuffer{property_buffer}, mPropertyBufferSize{property_size} +{ + switch(mCallType) + { + case EaxCallType::get: + case EaxCallType::set: + break; + + default: + fail("Invalid type."); + } + + if (false) + { + } + else if (property_set_guid == EAXPROPERTYID_EAX40_Context) + { + mVersion = 4; + mPropertySetId = EaxCallPropertySetId::context; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_Context) + { + mVersion = 5; + mPropertySetId = EaxCallPropertySetId::context; + } + else if (property_set_guid == DSPROPSETID_EAX20_ListenerProperties) + { + mVersion = 2; + mFxSlotIndex = 0u; + mPropertySetId = EaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid == DSPROPSETID_EAX30_ListenerProperties) + { + mVersion = 3; + mFxSlotIndex = 0u; + mPropertySetId = EaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot0) + { + mVersion = 4; + mFxSlotIndex = 0u; + mPropertySetId = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot0) + { + mVersion = 5; + mFxSlotIndex = 0u; + mPropertySetId = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot1) + { + mVersion = 4; + mFxSlotIndex = 1u; + mPropertySetId = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot1) + { + mVersion = 5; + mFxSlotIndex = 1u; + mPropertySetId = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot2) + { + mVersion = 4; + mFxSlotIndex = 2u; + mPropertySetId = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot2) + { + mVersion = 5; + mFxSlotIndex = 2u; + mPropertySetId = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot3) + { + mVersion = 4; + mFxSlotIndex = 3u; + mPropertySetId = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot3) + { + mVersion = 5; + mFxSlotIndex = 3u; + mPropertySetId = EaxCallPropertySetId::fx_slot; + } + else if (property_set_guid == DSPROPSETID_EAX20_BufferProperties) + { + mVersion = 2; + mPropertySetId = EaxCallPropertySetId::source; + } + else if (property_set_guid == DSPROPSETID_EAX30_BufferProperties) + { + mVersion = 3; + mPropertySetId = EaxCallPropertySetId::source; + } + else if (property_set_guid == EAXPROPERTYID_EAX40_Source) + { + mVersion = 4; + mPropertySetId = EaxCallPropertySetId::source; + } + else if (property_set_guid == EAXPROPERTYID_EAX50_Source) + { + mVersion = 5; + mPropertySetId = EaxCallPropertySetId::source; + } + else if (property_set_guid == DSPROPSETID_EAX_ReverbProperties) + { + mVersion = 1; + mFxSlotIndex = 0u; + mPropertySetId = EaxCallPropertySetId::fx_slot_effect; + } + else if (property_set_guid == DSPROPSETID_EAXBUFFER_ReverbProperties) + { + mVersion = 1; + mPropertySetId = EaxCallPropertySetId::source; + } + else + { + fail("Unsupported property set id."); + } + + switch(mPropertyId) + { + case EAXCONTEXT_LASTERROR: + case EAXCONTEXT_SPEAKERCONFIG: + case EAXCONTEXT_EAXSESSION: + case EAXFXSLOT_NONE: + case EAXFXSLOT_ALLPARAMETERS: + case EAXFXSLOT_LOADEFFECT: + case EAXFXSLOT_VOLUME: + case EAXFXSLOT_LOCK: + case EAXFXSLOT_FLAGS: + case EAXFXSLOT_OCCLUSION: + case EAXFXSLOT_OCCLUSIONLFRATIO: + // EAX allow to set "defer" flag on immediate-only properties. + // If we don't clear our flag then "applyAllUpdates" in EAX context won't be called. + mIsDeferred = false; + break; + } + + if(!mIsDeferred) + { + if(mPropertySetId != EaxCallPropertySetId::fx_slot && mPropertyId != 0) + { + if(mPropertyBuffer == nullptr) + fail("Null property buffer."); + + if(mPropertyBufferSize == 0) + fail("Empty property."); + } + } + + if(mPropertySetId == EaxCallPropertySetId::source && mPropertySourceId == 0) + fail("Null AL source id."); + + if(mPropertySetId == EaxCallPropertySetId::fx_slot) + { + if(mPropertyId < EAXFXSLOT_NONE) + mPropertySetId = EaxCallPropertySetId::fx_slot_effect; + } +} + +[[noreturn]] void EaxCall::fail(const char* message) +{ + throw EaxCallException{message}; +} + +[[noreturn]] void EaxCall::fail_too_small() +{ + fail("Property buffer too small."); +} + +EaxCall create_eax_call( + EaxCallType type, + const GUID* property_set_id, + ALuint property_id, + ALuint property_source_id, + ALvoid* property_buffer, + ALuint property_size) +{ + if(!property_set_id) + throw EaxCallException{"Null property set ID."}; + + return EaxCall{ + type, + *property_set_id, + property_id, + property_source_id, + property_buffer, + property_size + }; +} |