2022-07-14 23:17:11 +08:00
|
|
|
#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)
|
|
|
|
: type_{type}, version_{0}, property_set_id_{EaxCallPropertySetId::none}
|
2023-02-04 15:03:54 +08:00
|
|
|
, is_deferred_{(property_id & deferred_flag) != 0}
|
2022-07-14 23:17:11 +08:00
|
|
|
, property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id}
|
|
|
|
, property_buffer_{property_buffer}, property_size_{property_size}
|
|
|
|
{
|
|
|
|
switch (type_)
|
|
|
|
{
|
|
|
|
case EaxCallType::get:
|
|
|
|
case EaxCallType::set:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
fail("Invalid type.");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else if (property_set_guid == EAXPROPERTYID_EAX40_Context)
|
|
|
|
{
|
|
|
|
version_ = 4;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::context;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == EAXPROPERTYID_EAX50_Context)
|
|
|
|
{
|
|
|
|
version_ = 5;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::context;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == DSPROPSETID_EAX20_ListenerProperties)
|
|
|
|
{
|
|
|
|
version_ = 2;
|
|
|
|
fx_slot_index_ = 0u;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::fx_slot_effect;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == DSPROPSETID_EAX30_ListenerProperties)
|
|
|
|
{
|
|
|
|
version_ = 3;
|
|
|
|
fx_slot_index_ = 0u;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::fx_slot_effect;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot0)
|
|
|
|
{
|
|
|
|
version_ = 4;
|
|
|
|
fx_slot_index_ = 0u;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::fx_slot;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot0)
|
|
|
|
{
|
|
|
|
version_ = 5;
|
|
|
|
fx_slot_index_ = 0u;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::fx_slot;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot1)
|
|
|
|
{
|
|
|
|
version_ = 4;
|
|
|
|
fx_slot_index_ = 1u;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::fx_slot;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot1)
|
|
|
|
{
|
|
|
|
version_ = 5;
|
|
|
|
fx_slot_index_ = 1u;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::fx_slot;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot2)
|
|
|
|
{
|
|
|
|
version_ = 4;
|
|
|
|
fx_slot_index_ = 2u;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::fx_slot;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot2)
|
|
|
|
{
|
|
|
|
version_ = 5;
|
|
|
|
fx_slot_index_ = 2u;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::fx_slot;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot3)
|
|
|
|
{
|
|
|
|
version_ = 4;
|
|
|
|
fx_slot_index_ = 3u;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::fx_slot;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot3)
|
|
|
|
{
|
|
|
|
version_ = 5;
|
|
|
|
fx_slot_index_ = 3u;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::fx_slot;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == DSPROPSETID_EAX20_BufferProperties)
|
|
|
|
{
|
|
|
|
version_ = 2;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::source;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == DSPROPSETID_EAX30_BufferProperties)
|
|
|
|
{
|
|
|
|
version_ = 3;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::source;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == EAXPROPERTYID_EAX40_Source)
|
|
|
|
{
|
|
|
|
version_ = 4;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::source;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == EAXPROPERTYID_EAX50_Source)
|
|
|
|
{
|
|
|
|
version_ = 5;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::source;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == DSPROPSETID_EAX_ReverbProperties)
|
|
|
|
{
|
|
|
|
version_ = 1;
|
|
|
|
fx_slot_index_ = 0u;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::fx_slot_effect;
|
|
|
|
}
|
|
|
|
else if (property_set_guid == DSPROPSETID_EAXBUFFER_ReverbProperties)
|
|
|
|
{
|
|
|
|
version_ = 1;
|
|
|
|
property_set_id_ = EaxCallPropertySetId::source;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fail("Unsupported property set id.");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (version_ < 1 || version_ > 5)
|
|
|
|
{
|
|
|
|
fail("EAX version out of range.");
|
|
|
|
}
|
|
|
|
|
2023-02-04 15:03:54 +08:00
|
|
|
switch(property_id)
|
|
|
|
{
|
|
|
|
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.
|
|
|
|
is_deferred_ = false;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!is_deferred_)
|
2022-07-14 23:17:11 +08:00
|
|
|
{
|
|
|
|
if(property_set_id_ != EaxCallPropertySetId::fx_slot && property_id_ != 0)
|
|
|
|
{
|
|
|
|
if (property_buffer == nullptr)
|
|
|
|
{
|
|
|
|
fail("Null property buffer.");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (property_size == 0)
|
|
|
|
{
|
|
|
|
fail("Empty property.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(property_set_id_ == EaxCallPropertySetId::source && property_source_id_ == 0)
|
|
|
|
{
|
|
|
|
fail("Null AL source id.");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (property_set_id_ == EaxCallPropertySetId::fx_slot)
|
|
|
|
{
|
|
|
|
if (property_id_ < EAXFXSLOT_NONE)
|
|
|
|
{
|
|
|
|
property_set_id_ = 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
|
|
|
|
};
|
|
|
|
}
|