mirror of
https://github.com/love2d/megasource.git
synced 2026-08-20 12:40:06 +02:00
Update OpenAL-soft to 1.23.1-bc7cb17.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,218 @@
|
||||
#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}, 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
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
#ifndef EAX_EAX_CALL_INCLUDED
|
||||
#define EAX_EAX_CALL_INCLUDED
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "alnumeric.h"
|
||||
#include "alspan.h"
|
||||
#include "api.h"
|
||||
#include "fx_slot_index.h"
|
||||
|
||||
enum class EaxCallType {
|
||||
none,
|
||||
get,
|
||||
set,
|
||||
}; // EaxCallType
|
||||
|
||||
enum class EaxCallPropertySetId {
|
||||
none,
|
||||
context,
|
||||
fx_slot,
|
||||
source,
|
||||
fx_slot_effect,
|
||||
}; // EaxCallPropertySetId
|
||||
|
||||
class EaxCall {
|
||||
public:
|
||||
EaxCall(
|
||||
EaxCallType type,
|
||||
const GUID& property_set_guid,
|
||||
ALuint property_id,
|
||||
ALuint property_source_id,
|
||||
ALvoid* property_buffer,
|
||||
ALuint property_size);
|
||||
|
||||
[[nodiscard]] auto is_get() const noexcept -> bool { return mCallType == EaxCallType::get; }
|
||||
[[nodiscard]] auto is_deferred() const noexcept -> bool { return mIsDeferred; }
|
||||
[[nodiscard]] auto get_version() const noexcept -> int { return mVersion; }
|
||||
[[nodiscard]] auto get_property_set_id() const noexcept -> EaxCallPropertySetId { return mPropertySetId; }
|
||||
[[nodiscard]] auto get_property_id() const noexcept -> ALuint { return mPropertyId; }
|
||||
[[nodiscard]] auto get_property_al_name() const noexcept -> ALuint { return mPropertySourceId; }
|
||||
[[nodiscard]] auto get_fx_slot_index() const noexcept -> EaxFxSlotIndex { return mFxSlotIndex; }
|
||||
|
||||
template<typename TException, typename TValue>
|
||||
[[nodiscard]] auto get_value() const -> TValue&
|
||||
{
|
||||
if(mPropertyBufferSize < sizeof(TValue))
|
||||
fail_too_small();
|
||||
|
||||
return *static_cast<TValue*>(mPropertyBuffer);
|
||||
}
|
||||
|
||||
template<typename TValue>
|
||||
[[nodiscard]] auto get_values(size_t max_count) const -> al::span<TValue>
|
||||
{
|
||||
if(max_count == 0 || mPropertyBufferSize < sizeof(TValue))
|
||||
fail_too_small();
|
||||
|
||||
const auto count = std::min(mPropertyBufferSize/sizeof(TValue), max_count);
|
||||
return {static_cast<TValue*>(mPropertyBuffer), count};
|
||||
}
|
||||
|
||||
template<typename TValue>
|
||||
[[nodiscard]] auto get_values() const -> al::span<TValue>
|
||||
{
|
||||
return get_values<TValue>(~0_uz);
|
||||
}
|
||||
|
||||
template<typename TException, typename TValue>
|
||||
auto set_value(const TValue& value) const -> void
|
||||
{
|
||||
get_value<TException, TValue>() = value;
|
||||
}
|
||||
|
||||
private:
|
||||
const EaxCallType mCallType;
|
||||
int mVersion{};
|
||||
EaxFxSlotIndex mFxSlotIndex{};
|
||||
EaxCallPropertySetId mPropertySetId{EaxCallPropertySetId::none};
|
||||
bool mIsDeferred;
|
||||
|
||||
const ALuint mPropertyId;
|
||||
const ALuint mPropertySourceId;
|
||||
ALvoid*const mPropertyBuffer;
|
||||
const ALuint mPropertyBufferSize;
|
||||
|
||||
[[noreturn]] static void fail(const char* message);
|
||||
[[noreturn]] static void fail_too_small();
|
||||
}; // EaxCall
|
||||
|
||||
EaxCall create_eax_call(
|
||||
EaxCallType type,
|
||||
const GUID* property_set_id,
|
||||
ALuint property_id,
|
||||
ALuint property_source_id,
|
||||
ALvoid* property_buffer,
|
||||
ALuint property_size);
|
||||
|
||||
#endif // !EAX_EAX_CALL_INCLUDED
|
||||
@@ -0,0 +1,457 @@
|
||||
#ifndef EAX_EFFECT_INCLUDED
|
||||
#define EAX_EFFECT_INCLUDED
|
||||
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <variant>
|
||||
|
||||
#include "alnumeric.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alext.h"
|
||||
#include "core/effects/base.h"
|
||||
#include "call.h"
|
||||
|
||||
struct EaxEffectErrorMessages {
|
||||
static constexpr auto unknown_property_id() noexcept { return "Unknown property id."; }
|
||||
static constexpr auto unknown_version() noexcept { return "Unknown version."; }
|
||||
}; // EaxEffectErrorMessages
|
||||
|
||||
using EaxEffectProps = std::variant<std::monostate,
|
||||
EAXREVERBPROPERTIES,
|
||||
EAXCHORUSPROPERTIES,
|
||||
EAXAUTOWAHPROPERTIES,
|
||||
EAXAGCCOMPRESSORPROPERTIES,
|
||||
EAXDISTORTIONPROPERTIES,
|
||||
EAXECHOPROPERTIES,
|
||||
EAXEQUALIZERPROPERTIES,
|
||||
EAXFLANGERPROPERTIES,
|
||||
EAXFREQUENCYSHIFTERPROPERTIES,
|
||||
EAXRINGMODULATORPROPERTIES,
|
||||
EAXPITCHSHIFTERPROPERTIES,
|
||||
EAXVOCALMORPHERPROPERTIES>;
|
||||
|
||||
template<typename... Ts>
|
||||
struct overloaded : Ts... { using Ts::operator()...; };
|
||||
|
||||
template<typename... Ts>
|
||||
overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
constexpr ALenum EnumFromEaxEffectType(const EaxEffectProps &props)
|
||||
{
|
||||
return std::visit(overloaded{
|
||||
[](const std::monostate&) noexcept { return AL_EFFECT_NULL; },
|
||||
[](const EAXREVERBPROPERTIES&) noexcept { return AL_EFFECT_EAXREVERB; },
|
||||
[](const EAXCHORUSPROPERTIES&) noexcept { return AL_EFFECT_CHORUS; },
|
||||
[](const EAXAUTOWAHPROPERTIES&) noexcept { return AL_EFFECT_AUTOWAH; },
|
||||
[](const EAXAGCCOMPRESSORPROPERTIES&) noexcept { return AL_EFFECT_COMPRESSOR; },
|
||||
[](const EAXDISTORTIONPROPERTIES&) noexcept { return AL_EFFECT_DISTORTION; },
|
||||
[](const EAXECHOPROPERTIES&) noexcept { return AL_EFFECT_ECHO; },
|
||||
[](const EAXEQUALIZERPROPERTIES&) noexcept { return AL_EFFECT_EQUALIZER; },
|
||||
[](const EAXFLANGERPROPERTIES&) noexcept { return AL_EFFECT_FLANGER; },
|
||||
[](const EAXFREQUENCYSHIFTERPROPERTIES&) noexcept { return AL_EFFECT_FREQUENCY_SHIFTER; },
|
||||
[](const EAXRINGMODULATORPROPERTIES&) noexcept { return AL_EFFECT_RING_MODULATOR; },
|
||||
[](const EAXPITCHSHIFTERPROPERTIES&) noexcept { return AL_EFFECT_PITCH_SHIFTER; },
|
||||
[](const EAXVOCALMORPHERPROPERTIES&) noexcept { return AL_EFFECT_VOCAL_MORPHER; }
|
||||
}, props);
|
||||
}
|
||||
|
||||
struct EaxReverbCommitter {
|
||||
struct Exception;
|
||||
|
||||
EaxReverbCommitter(EaxEffectProps &eaxprops, EffectProps &alprops)
|
||||
: mEaxProps{eaxprops}, mAlProps{alprops}
|
||||
{ }
|
||||
|
||||
EaxEffectProps &mEaxProps;
|
||||
EffectProps &mAlProps;
|
||||
|
||||
[[noreturn]] static void fail(const char* message);
|
||||
[[noreturn]] static void fail_unknown_property_id()
|
||||
{ fail(EaxEffectErrorMessages::unknown_property_id()); }
|
||||
|
||||
template<typename TValidator, typename TProperty>
|
||||
static void defer(const EaxCall& call, TProperty& property)
|
||||
{
|
||||
const auto& value = call.get_value<Exception, const TProperty>();
|
||||
TValidator{}(value);
|
||||
property = value;
|
||||
}
|
||||
|
||||
template<typename TValidator, typename TDeferrer, typename TProperties, typename TProperty>
|
||||
static void defer(const EaxCall& call, TProperties& properties, TProperty&)
|
||||
{
|
||||
const auto& value = call.get_value<Exception, const TProperty>();
|
||||
TValidator{}(value);
|
||||
TDeferrer{}(properties, value);
|
||||
}
|
||||
|
||||
template<typename TValidator, typename TProperty>
|
||||
static void defer3(const EaxCall& call, EAXREVERBPROPERTIES& properties, TProperty& property)
|
||||
{
|
||||
const auto& value = call.get_value<Exception, const TProperty>();
|
||||
TValidator{}(value);
|
||||
if (value == property)
|
||||
return;
|
||||
property = value;
|
||||
properties.ulEnvironment = EAX_ENVIRONMENT_UNDEFINED;
|
||||
}
|
||||
|
||||
|
||||
bool commit(const EAX_REVERBPROPERTIES &props);
|
||||
bool commit(const EAX20LISTENERPROPERTIES &props);
|
||||
bool commit(const EAXREVERBPROPERTIES &props);
|
||||
|
||||
static void SetDefaults(EAX_REVERBPROPERTIES &props);
|
||||
static void SetDefaults(EAX20LISTENERPROPERTIES &props);
|
||||
static void SetDefaults(EAXREVERBPROPERTIES &props);
|
||||
static void SetDefaults(EaxEffectProps &props);
|
||||
|
||||
static void Get(const EaxCall &call, const EAX_REVERBPROPERTIES &props);
|
||||
static void Get(const EaxCall &call, const EAX20LISTENERPROPERTIES &props);
|
||||
static void Get(const EaxCall &call, const EAXREVERBPROPERTIES &props);
|
||||
|
||||
static void Set(const EaxCall &call, EAX_REVERBPROPERTIES &props);
|
||||
static void Set(const EaxCall &call, EAX20LISTENERPROPERTIES &props);
|
||||
static void Set(const EaxCall &call, EAXREVERBPROPERTIES &props);
|
||||
|
||||
static void translate(const EAX_REVERBPROPERTIES& src, EAXREVERBPROPERTIES& dst) noexcept;
|
||||
static void translate(const EAX20LISTENERPROPERTIES& src, EAXREVERBPROPERTIES& dst) noexcept;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct EaxCommitter {
|
||||
struct Exception;
|
||||
|
||||
EaxCommitter(EaxEffectProps &eaxprops, EffectProps &alprops)
|
||||
: mEaxProps{eaxprops}, mAlProps{alprops}
|
||||
{ }
|
||||
|
||||
EaxEffectProps &mEaxProps;
|
||||
EffectProps &mAlProps;
|
||||
|
||||
template<typename TValidator, typename TProperty>
|
||||
static void defer(const EaxCall& call, TProperty& property)
|
||||
{
|
||||
const auto& value = call.get_value<Exception, const TProperty>();
|
||||
TValidator{}(value);
|
||||
property = value;
|
||||
}
|
||||
|
||||
[[noreturn]] static void fail(const char *message);
|
||||
[[noreturn]] static void fail_unknown_property_id()
|
||||
{ fail(EaxEffectErrorMessages::unknown_property_id()); }
|
||||
};
|
||||
|
||||
struct EaxAutowahCommitter : public EaxCommitter<EaxAutowahCommitter> {
|
||||
using EaxCommitter<EaxAutowahCommitter>::EaxCommitter;
|
||||
|
||||
bool commit(const EAXAUTOWAHPROPERTIES &props);
|
||||
|
||||
static void SetDefaults(EaxEffectProps &props);
|
||||
static void Get(const EaxCall &call, const EAXAUTOWAHPROPERTIES &props);
|
||||
static void Set(const EaxCall &call, EAXAUTOWAHPROPERTIES &props);
|
||||
};
|
||||
struct EaxChorusCommitter : public EaxCommitter<EaxChorusCommitter> {
|
||||
using EaxCommitter<EaxChorusCommitter>::EaxCommitter;
|
||||
|
||||
bool commit(const EAXCHORUSPROPERTIES &props);
|
||||
|
||||
static void SetDefaults(EaxEffectProps &props);
|
||||
static void Get(const EaxCall &call, const EAXCHORUSPROPERTIES &props);
|
||||
static void Set(const EaxCall &call, EAXCHORUSPROPERTIES &props);
|
||||
};
|
||||
struct EaxCompressorCommitter : public EaxCommitter<EaxCompressorCommitter> {
|
||||
using EaxCommitter<EaxCompressorCommitter>::EaxCommitter;
|
||||
|
||||
bool commit(const EAXAGCCOMPRESSORPROPERTIES &props);
|
||||
|
||||
static void SetDefaults(EaxEffectProps &props);
|
||||
static void Get(const EaxCall &call, const EAXAGCCOMPRESSORPROPERTIES &props);
|
||||
static void Set(const EaxCall &call, EAXAGCCOMPRESSORPROPERTIES &props);
|
||||
};
|
||||
struct EaxDistortionCommitter : public EaxCommitter<EaxDistortionCommitter> {
|
||||
using EaxCommitter<EaxDistortionCommitter>::EaxCommitter;
|
||||
|
||||
bool commit(const EAXDISTORTIONPROPERTIES &props);
|
||||
|
||||
static void SetDefaults(EaxEffectProps &props);
|
||||
static void Get(const EaxCall &call, const EAXDISTORTIONPROPERTIES &props);
|
||||
static void Set(const EaxCall &call, EAXDISTORTIONPROPERTIES &props);
|
||||
};
|
||||
struct EaxEchoCommitter : public EaxCommitter<EaxEchoCommitter> {
|
||||
using EaxCommitter<EaxEchoCommitter>::EaxCommitter;
|
||||
|
||||
bool commit(const EAXECHOPROPERTIES &props);
|
||||
|
||||
static void SetDefaults(EaxEffectProps &props);
|
||||
static void Get(const EaxCall &call, const EAXECHOPROPERTIES &props);
|
||||
static void Set(const EaxCall &call, EAXECHOPROPERTIES &props);
|
||||
};
|
||||
struct EaxEqualizerCommitter : public EaxCommitter<EaxEqualizerCommitter> {
|
||||
using EaxCommitter<EaxEqualizerCommitter>::EaxCommitter;
|
||||
|
||||
bool commit(const EAXEQUALIZERPROPERTIES &props);
|
||||
|
||||
static void SetDefaults(EaxEffectProps &props);
|
||||
static void Get(const EaxCall &call, const EAXEQUALIZERPROPERTIES &props);
|
||||
static void Set(const EaxCall &call, EAXEQUALIZERPROPERTIES &props);
|
||||
};
|
||||
struct EaxFlangerCommitter : public EaxCommitter<EaxFlangerCommitter> {
|
||||
using EaxCommitter<EaxFlangerCommitter>::EaxCommitter;
|
||||
|
||||
bool commit(const EAXFLANGERPROPERTIES &props);
|
||||
|
||||
static void SetDefaults(EaxEffectProps &props);
|
||||
static void Get(const EaxCall &call, const EAXFLANGERPROPERTIES &props);
|
||||
static void Set(const EaxCall &call, EAXFLANGERPROPERTIES &props);
|
||||
};
|
||||
struct EaxFrequencyShifterCommitter : public EaxCommitter<EaxFrequencyShifterCommitter> {
|
||||
using EaxCommitter<EaxFrequencyShifterCommitter>::EaxCommitter;
|
||||
|
||||
bool commit(const EAXFREQUENCYSHIFTERPROPERTIES &props);
|
||||
|
||||
static void SetDefaults(EaxEffectProps &props);
|
||||
static void Get(const EaxCall &call, const EAXFREQUENCYSHIFTERPROPERTIES &props);
|
||||
static void Set(const EaxCall &call, EAXFREQUENCYSHIFTERPROPERTIES &props);
|
||||
};
|
||||
struct EaxModulatorCommitter : public EaxCommitter<EaxModulatorCommitter> {
|
||||
using EaxCommitter<EaxModulatorCommitter>::EaxCommitter;
|
||||
|
||||
bool commit(const EAXRINGMODULATORPROPERTIES &props);
|
||||
|
||||
static void SetDefaults(EaxEffectProps &props);
|
||||
static void Get(const EaxCall &call, const EAXRINGMODULATORPROPERTIES &props);
|
||||
static void Set(const EaxCall &call, EAXRINGMODULATORPROPERTIES &props);
|
||||
};
|
||||
struct EaxPitchShifterCommitter : public EaxCommitter<EaxPitchShifterCommitter> {
|
||||
using EaxCommitter<EaxPitchShifterCommitter>::EaxCommitter;
|
||||
|
||||
bool commit(const EAXPITCHSHIFTERPROPERTIES &props);
|
||||
|
||||
static void SetDefaults(EaxEffectProps &props);
|
||||
static void Get(const EaxCall &call, const EAXPITCHSHIFTERPROPERTIES &props);
|
||||
static void Set(const EaxCall &call, EAXPITCHSHIFTERPROPERTIES &props);
|
||||
};
|
||||
struct EaxVocalMorpherCommitter : public EaxCommitter<EaxVocalMorpherCommitter> {
|
||||
using EaxCommitter<EaxVocalMorpherCommitter>::EaxCommitter;
|
||||
|
||||
bool commit(const EAXVOCALMORPHERPROPERTIES &props);
|
||||
|
||||
static void SetDefaults(EaxEffectProps &props);
|
||||
static void Get(const EaxCall &call, const EAXVOCALMORPHERPROPERTIES &props);
|
||||
static void Set(const EaxCall &call, EAXVOCALMORPHERPROPERTIES &props);
|
||||
};
|
||||
struct EaxNullCommitter : public EaxCommitter<EaxNullCommitter> {
|
||||
using EaxCommitter<EaxNullCommitter>::EaxCommitter;
|
||||
|
||||
bool commit(const std::monostate &props);
|
||||
|
||||
static void SetDefaults(EaxEffectProps &props);
|
||||
static void Get(const EaxCall &call, const std::monostate &props);
|
||||
static void Set(const EaxCall &call, std::monostate &props);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct CommitterFromProps { };
|
||||
|
||||
template<> struct CommitterFromProps<std::monostate> { using type = EaxNullCommitter; };
|
||||
template<> struct CommitterFromProps<EAXREVERBPROPERTIES> { using type = EaxReverbCommitter; };
|
||||
template<> struct CommitterFromProps<EAXCHORUSPROPERTIES> { using type = EaxChorusCommitter; };
|
||||
template<> struct CommitterFromProps<EAXAGCCOMPRESSORPROPERTIES> { using type = EaxCompressorCommitter; };
|
||||
template<> struct CommitterFromProps<EAXAUTOWAHPROPERTIES> { using type = EaxAutowahCommitter; };
|
||||
template<> struct CommitterFromProps<EAXDISTORTIONPROPERTIES> { using type = EaxDistortionCommitter; };
|
||||
template<> struct CommitterFromProps<EAXECHOPROPERTIES> { using type = EaxEchoCommitter; };
|
||||
template<> struct CommitterFromProps<EAXEQUALIZERPROPERTIES> { using type = EaxEqualizerCommitter; };
|
||||
template<> struct CommitterFromProps<EAXFLANGERPROPERTIES> { using type = EaxFlangerCommitter; };
|
||||
template<> struct CommitterFromProps<EAXFREQUENCYSHIFTERPROPERTIES> { using type = EaxFrequencyShifterCommitter; };
|
||||
template<> struct CommitterFromProps<EAXRINGMODULATORPROPERTIES> { using type = EaxModulatorCommitter; };
|
||||
template<> struct CommitterFromProps<EAXPITCHSHIFTERPROPERTIES> { using type = EaxPitchShifterCommitter; };
|
||||
template<> struct CommitterFromProps<EAXVOCALMORPHERPROPERTIES> { using type = EaxVocalMorpherCommitter; };
|
||||
|
||||
template<typename T>
|
||||
using CommitterFor = typename CommitterFromProps<std::remove_cv_t<std::remove_reference_t<T>>>::type;
|
||||
|
||||
|
||||
class EaxEffect {
|
||||
public:
|
||||
EaxEffect() noexcept = default;
|
||||
~EaxEffect() = default;
|
||||
|
||||
ALenum al_effect_type_{AL_EFFECT_NULL};
|
||||
EffectProps al_effect_props_{};
|
||||
|
||||
using Props1 = EAX_REVERBPROPERTIES;
|
||||
using Props2 = EAX20LISTENERPROPERTIES;
|
||||
using Props3 = EAXREVERBPROPERTIES;
|
||||
using Props4 = EaxEffectProps;
|
||||
|
||||
struct State1 {
|
||||
Props1 i; // Immediate.
|
||||
Props1 d; // Deferred.
|
||||
};
|
||||
|
||||
struct State2 {
|
||||
Props2 i; // Immediate.
|
||||
Props2 d; // Deferred.
|
||||
};
|
||||
|
||||
struct State3 {
|
||||
Props3 i; // Immediate.
|
||||
Props3 d; // Deferred.
|
||||
};
|
||||
|
||||
struct State4 {
|
||||
Props4 i; // Immediate.
|
||||
Props4 d; // Deferred.
|
||||
};
|
||||
|
||||
int version_{};
|
||||
bool changed_{};
|
||||
Props4 props_{};
|
||||
State1 state1_{};
|
||||
State2 state2_{};
|
||||
State3 state3_{};
|
||||
State4 state4_{};
|
||||
State4 state5_{};
|
||||
|
||||
|
||||
static void call_set_defaults(const ALenum altype, EaxEffectProps &props)
|
||||
{
|
||||
switch(altype)
|
||||
{
|
||||
case AL_EFFECT_EAXREVERB: return EaxReverbCommitter::SetDefaults(props);
|
||||
case AL_EFFECT_CHORUS: return EaxChorusCommitter::SetDefaults(props);
|
||||
case AL_EFFECT_AUTOWAH: return EaxAutowahCommitter::SetDefaults(props);
|
||||
case AL_EFFECT_COMPRESSOR: return EaxCompressorCommitter::SetDefaults(props);
|
||||
case AL_EFFECT_DISTORTION: return EaxDistortionCommitter::SetDefaults(props);
|
||||
case AL_EFFECT_ECHO: return EaxEchoCommitter::SetDefaults(props);
|
||||
case AL_EFFECT_EQUALIZER: return EaxEqualizerCommitter::SetDefaults(props);
|
||||
case AL_EFFECT_FLANGER: return EaxFlangerCommitter::SetDefaults(props);
|
||||
case AL_EFFECT_FREQUENCY_SHIFTER: return EaxFrequencyShifterCommitter::SetDefaults(props);
|
||||
case AL_EFFECT_RING_MODULATOR: return EaxModulatorCommitter::SetDefaults(props);
|
||||
case AL_EFFECT_PITCH_SHIFTER: return EaxPitchShifterCommitter::SetDefaults(props);
|
||||
case AL_EFFECT_VOCAL_MORPHER: return EaxVocalMorpherCommitter::SetDefaults(props);
|
||||
case AL_EFFECT_NULL: break;
|
||||
}
|
||||
return EaxNullCommitter::SetDefaults(props);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void init()
|
||||
{
|
||||
EaxReverbCommitter::SetDefaults(state1_.d);
|
||||
state1_.i = state1_.d;
|
||||
EaxReverbCommitter::SetDefaults(state2_.d);
|
||||
state2_.i = state2_.d;
|
||||
EaxReverbCommitter::SetDefaults(state3_.d);
|
||||
state3_.i = state3_.d;
|
||||
T::SetDefaults(state4_.d);
|
||||
state4_.i = state4_.d;
|
||||
T::SetDefaults(state5_.d);
|
||||
state5_.i = state5_.d;
|
||||
}
|
||||
|
||||
void set_defaults(int eax_version, ALenum altype)
|
||||
{
|
||||
switch(eax_version)
|
||||
{
|
||||
case 1: EaxReverbCommitter::SetDefaults(state1_.d); break;
|
||||
case 2: EaxReverbCommitter::SetDefaults(state2_.d); break;
|
||||
case 3: EaxReverbCommitter::SetDefaults(state3_.d); break;
|
||||
case 4: call_set_defaults(altype, state4_.d); break;
|
||||
case 5: call_set_defaults(altype, state5_.d); break;
|
||||
}
|
||||
changed_ = true;
|
||||
}
|
||||
|
||||
|
||||
static void call_set(const EaxCall &call, EaxEffectProps &props)
|
||||
{
|
||||
return std::visit([&](auto &arg)
|
||||
{ return CommitterFor<decltype(arg)>::Set(call, arg); },
|
||||
props);
|
||||
}
|
||||
|
||||
void set(const EaxCall &call)
|
||||
{
|
||||
switch(call.get_version())
|
||||
{
|
||||
case 1: EaxReverbCommitter::Set(call, state1_.d); break;
|
||||
case 2: EaxReverbCommitter::Set(call, state2_.d); break;
|
||||
case 3: EaxReverbCommitter::Set(call, state3_.d); break;
|
||||
case 4: call_set(call, state4_.d); break;
|
||||
case 5: call_set(call, state5_.d); break;
|
||||
}
|
||||
changed_ = true;
|
||||
}
|
||||
|
||||
|
||||
static void call_get(const EaxCall &call, const EaxEffectProps &props)
|
||||
{
|
||||
return std::visit([&](auto &arg)
|
||||
{ return CommitterFor<decltype(arg)>::Get(call, arg); },
|
||||
props);
|
||||
}
|
||||
|
||||
void get(const EaxCall &call) const
|
||||
{
|
||||
switch(call.get_version())
|
||||
{
|
||||
case 1: EaxReverbCommitter::Get(call, state1_.d); break;
|
||||
case 2: EaxReverbCommitter::Get(call, state2_.d); break;
|
||||
case 3: EaxReverbCommitter::Get(call, state3_.d); break;
|
||||
case 4: call_get(call, state4_.d); break;
|
||||
case 5: call_get(call, state5_.d); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool call_commit(const EaxEffectProps &props)
|
||||
{
|
||||
return std::visit([&](auto &arg)
|
||||
{ return CommitterFor<decltype(arg)>{props_, al_effect_props_}.commit(arg); },
|
||||
props);
|
||||
}
|
||||
|
||||
bool commit(int eax_version)
|
||||
{
|
||||
changed_ |= version_ != eax_version;
|
||||
if(!changed_) return false;
|
||||
|
||||
bool ret{version_ != eax_version};
|
||||
version_ = eax_version;
|
||||
changed_ = false;
|
||||
|
||||
switch(eax_version)
|
||||
{
|
||||
case 1:
|
||||
state1_.i = state1_.d;
|
||||
ret |= EaxReverbCommitter{props_, al_effect_props_}.commit(state1_.d);
|
||||
break;
|
||||
case 2:
|
||||
state2_.i = state2_.d;
|
||||
ret |= EaxReverbCommitter{props_, al_effect_props_}.commit(state2_.d);
|
||||
break;
|
||||
case 3:
|
||||
state3_.i = state3_.d;
|
||||
ret |= EaxReverbCommitter{props_, al_effect_props_}.commit(state3_.d);
|
||||
break;
|
||||
case 4:
|
||||
state4_.i = state4_.d;
|
||||
ret |= call_commit(state4_.d);
|
||||
break;
|
||||
case 5:
|
||||
state5_.i = state5_.d;
|
||||
ret |= call_commit(state5_.d);
|
||||
break;
|
||||
}
|
||||
al_effect_type_ = EnumFromEaxEffectType(props_);
|
||||
return ret;
|
||||
}
|
||||
#undef EAXCALL
|
||||
}; // EaxEffect
|
||||
|
||||
using EaxEffectUPtr = std::unique_ptr<EaxEffect>;
|
||||
|
||||
#endif // !EAX_EFFECT_INCLUDED
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "exception.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
|
||||
EaxException::EaxException(std::string_view context, std::string_view message)
|
||||
: std::runtime_error{make_message(context, message)}
|
||||
{
|
||||
}
|
||||
EaxException::~EaxException() = default;
|
||||
|
||||
|
||||
std::string EaxException::make_message(std::string_view context, std::string_view message)
|
||||
{
|
||||
auto what = std::string{};
|
||||
if(context.empty() && message.empty())
|
||||
return what;
|
||||
|
||||
what.reserve((!context.empty() ? context.size() + 3 : 0) + message.length() + 1);
|
||||
if(!context.empty())
|
||||
{
|
||||
what += "[";
|
||||
what += context;
|
||||
what += "] ";
|
||||
}
|
||||
what += message;
|
||||
|
||||
return what;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef EAX_EXCEPTION_INCLUDED
|
||||
#define EAX_EXCEPTION_INCLUDED
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
|
||||
class EaxException : public std::runtime_error {
|
||||
static std::string make_message(std::string_view context, std::string_view message);
|
||||
|
||||
public:
|
||||
EaxException(std::string_view context, std::string_view message);
|
||||
~EaxException() override;
|
||||
}; // EaxException
|
||||
|
||||
|
||||
#endif // !EAX_EXCEPTION_INCLUDED
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "fx_slot_index.h"
|
||||
|
||||
#include "exception.h"
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
||||
class EaxFxSlotIndexException :
|
||||
public EaxException
|
||||
{
|
||||
public:
|
||||
explicit EaxFxSlotIndexException(
|
||||
const char* message)
|
||||
:
|
||||
EaxException{"EAX_FX_SLOT_INDEX", message}
|
||||
{
|
||||
}
|
||||
}; // EaxFxSlotIndexException
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void EaxFxSlotIndex::set(EaxFxSlotIndexValue index)
|
||||
{
|
||||
if(index >= EaxFxSlotIndexValue{EAX_MAX_FXSLOTS})
|
||||
fail("Index out of range.");
|
||||
|
||||
emplace(index);
|
||||
}
|
||||
|
||||
void EaxFxSlotIndex::set(const GUID &guid)
|
||||
{
|
||||
if (false)
|
||||
{
|
||||
}
|
||||
else if (guid == EAX_NULL_GUID)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
else if (guid == EAXPROPERTYID_EAX40_FXSlot0 || guid == EAXPROPERTYID_EAX50_FXSlot0)
|
||||
{
|
||||
emplace(0u);
|
||||
}
|
||||
else if (guid == EAXPROPERTYID_EAX40_FXSlot1 || guid == EAXPROPERTYID_EAX50_FXSlot1)
|
||||
{
|
||||
emplace(1u);
|
||||
}
|
||||
else if (guid == EAXPROPERTYID_EAX40_FXSlot2 || guid == EAXPROPERTYID_EAX50_FXSlot2)
|
||||
{
|
||||
emplace(2u);
|
||||
}
|
||||
else if (guid == EAXPROPERTYID_EAX40_FXSlot3 || guid == EAXPROPERTYID_EAX50_FXSlot3)
|
||||
{
|
||||
emplace(3u);
|
||||
}
|
||||
else
|
||||
{
|
||||
fail("Unsupported GUID.");
|
||||
}
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void EaxFxSlotIndex::fail(const char* message)
|
||||
{
|
||||
throw EaxFxSlotIndexException{message};
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef EAX_FX_SLOT_INDEX_INCLUDED
|
||||
#define EAX_FX_SLOT_INDEX_INCLUDED
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <optional>
|
||||
|
||||
#include "api.h"
|
||||
|
||||
|
||||
using EaxFxSlotIndexValue = std::size_t;
|
||||
|
||||
class EaxFxSlotIndex : public std::optional<EaxFxSlotIndexValue> {
|
||||
public:
|
||||
using std::optional<EaxFxSlotIndexValue>::optional;
|
||||
|
||||
EaxFxSlotIndex& operator=(const EaxFxSlotIndexValue &value) { set(value); return *this; }
|
||||
EaxFxSlotIndex& operator=(const GUID &guid) { set(guid); return *this; }
|
||||
|
||||
void set(EaxFxSlotIndexValue index);
|
||||
void set(const GUID& guid);
|
||||
|
||||
private:
|
||||
[[noreturn]]
|
||||
static void fail(const char *message);
|
||||
}; // EaxFxSlotIndex
|
||||
|
||||
inline bool operator==(const EaxFxSlotIndex& lhs, const EaxFxSlotIndex& rhs) noexcept
|
||||
{
|
||||
if(lhs.has_value() != rhs.has_value())
|
||||
return false;
|
||||
if(lhs.has_value())
|
||||
return *lhs == *rhs;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool operator!=(const EaxFxSlotIndex& lhs, const EaxFxSlotIndex& rhs) noexcept
|
||||
{ return !(lhs == rhs); }
|
||||
|
||||
#endif // !EAX_FX_SLOT_INDEX_INCLUDED
|
||||
@@ -0,0 +1,75 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "fx_slots.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "api.h"
|
||||
#include "exception.h"
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
||||
class EaxFxSlotsException :
|
||||
public EaxException
|
||||
{
|
||||
public:
|
||||
explicit EaxFxSlotsException(
|
||||
const char* message)
|
||||
:
|
||||
EaxException{"EAX_FX_SLOTS", message}
|
||||
{
|
||||
}
|
||||
}; // EaxFxSlotsException
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void EaxFxSlots::initialize(ALCcontext& al_context)
|
||||
{
|
||||
initialize_fx_slots(al_context);
|
||||
}
|
||||
|
||||
void EaxFxSlots::uninitialize() noexcept
|
||||
{
|
||||
for (auto& fx_slot : fx_slots_)
|
||||
{
|
||||
fx_slot = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const ALeffectslot& EaxFxSlots::get(EaxFxSlotIndex index) const
|
||||
{
|
||||
if(!index.has_value())
|
||||
fail("Empty index.");
|
||||
return *fx_slots_[index.value()];
|
||||
}
|
||||
|
||||
ALeffectslot& EaxFxSlots::get(EaxFxSlotIndex index)
|
||||
{
|
||||
if(!index.has_value())
|
||||
fail("Empty index.");
|
||||
return *fx_slots_[index.value()];
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void EaxFxSlots::fail(
|
||||
const char* message)
|
||||
{
|
||||
throw EaxFxSlotsException{message};
|
||||
}
|
||||
|
||||
void EaxFxSlots::initialize_fx_slots(ALCcontext& al_context)
|
||||
{
|
||||
auto fx_slot_index = EaxFxSlotIndexValue{};
|
||||
|
||||
for (auto& fx_slot : fx_slots_)
|
||||
{
|
||||
fx_slot = eax_create_al_effect_slot(al_context);
|
||||
fx_slot->eax_initialize(al_context, fx_slot_index);
|
||||
fx_slot_index += 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef EAX_FX_SLOTS_INCLUDED
|
||||
#define EAX_FX_SLOTS_INCLUDED
|
||||
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "al/auxeffectslot.h"
|
||||
|
||||
#include "api.h"
|
||||
#include "call.h"
|
||||
#include "fx_slot_index.h"
|
||||
|
||||
|
||||
class EaxFxSlots
|
||||
{
|
||||
public:
|
||||
void initialize(ALCcontext& al_context);
|
||||
|
||||
void uninitialize() noexcept;
|
||||
|
||||
void commit()
|
||||
{
|
||||
for(auto& fx_slot : fx_slots_)
|
||||
fx_slot->eax_commit();
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] auto get(EaxFxSlotIndex index) const -> const ALeffectslot&;
|
||||
|
||||
[[nodiscard]] auto get(EaxFxSlotIndex index) -> ALeffectslot&;
|
||||
|
||||
private:
|
||||
using Items = std::array<EaxAlEffectSlotUPtr, EAX_MAX_FXSLOTS>;
|
||||
|
||||
|
||||
Items fx_slots_{};
|
||||
|
||||
|
||||
[[noreturn]]
|
||||
static void fail(const char* message);
|
||||
|
||||
void initialize_fx_slots(ALCcontext& al_context);
|
||||
}; // EaxFxSlots
|
||||
|
||||
|
||||
#endif // !EAX_FX_SLOTS_INCLUDED
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef EAX_GLOBALS_INCLUDED
|
||||
#define EAX_GLOBALS_INCLUDED
|
||||
|
||||
inline bool eax_g_is_enabled{true};
|
||||
|
||||
#endif /* EAX_GLOBALS_INCLUDED */
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <exception>
|
||||
|
||||
#include "alstring.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
|
||||
void eax_log_exception(std::string_view message) noexcept
|
||||
{
|
||||
const auto exception_ptr = std::current_exception();
|
||||
assert(exception_ptr);
|
||||
|
||||
try {
|
||||
std::rethrow_exception(exception_ptr);
|
||||
}
|
||||
catch(const std::exception& ex) {
|
||||
ERR("%.*s %s\n", al::sizei(message), message.data(), ex.what());
|
||||
}
|
||||
catch(...) {
|
||||
ERR("%.*s %s\n", al::sizei(message), message.data(), "Generic exception.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
#ifndef EAX_UTILS_INCLUDED
|
||||
#define EAX_UTILS_INCLUDED
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
#include "opthelpers.h"
|
||||
|
||||
using EaxDirtyFlags = unsigned int;
|
||||
|
||||
struct EaxAlLowPassParam {
|
||||
float gain;
|
||||
float gain_hf;
|
||||
};
|
||||
|
||||
void eax_log_exception(std::string_view message) noexcept;
|
||||
|
||||
template<typename TException, typename TValue>
|
||||
void eax_validate_range(std::string_view value_name, const TValue& value, const TValue& min_value,
|
||||
const TValue& max_value)
|
||||
{
|
||||
if(value >= min_value && value <= max_value) LIKELY
|
||||
return;
|
||||
|
||||
const auto message =
|
||||
std::string{value_name} +
|
||||
" out of range (value: " +
|
||||
std::to_string(value) + "; min: " +
|
||||
std::to_string(min_value) + "; max: " +
|
||||
std::to_string(max_value) + ").";
|
||||
|
||||
throw TException{message.c_str()};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
struct EaxIsBitFieldStruct {
|
||||
private:
|
||||
using yes = std::true_type;
|
||||
using no = std::false_type;
|
||||
|
||||
template<typename U>
|
||||
static auto test(int) -> decltype(std::declval<typename U::EaxIsBitFieldStruct>(), yes{});
|
||||
|
||||
template<typename>
|
||||
static no test(...);
|
||||
|
||||
public:
|
||||
static constexpr auto value = std::is_same<decltype(test<T>(0)), yes>::value;
|
||||
};
|
||||
|
||||
template<typename T, typename TValue>
|
||||
inline bool eax_bit_fields_are_equal(const T& lhs, const T& rhs) noexcept
|
||||
{
|
||||
static_assert(sizeof(T) == sizeof(TValue), "Invalid type size.");
|
||||
return reinterpret_cast<const TValue&>(lhs) == reinterpret_cast<const TValue&>(rhs);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<
|
||||
typename T,
|
||||
std::enable_if_t<detail::EaxIsBitFieldStruct<T>::value, int> = 0
|
||||
>
|
||||
inline bool operator==(const T& lhs, const T& rhs) noexcept
|
||||
{
|
||||
using Value = std::conditional_t<
|
||||
sizeof(T) == 1,
|
||||
std::uint8_t,
|
||||
std::conditional_t<
|
||||
sizeof(T) == 2,
|
||||
std::uint16_t,
|
||||
std::conditional_t<
|
||||
sizeof(T) == 4,
|
||||
std::uint32_t,
|
||||
void>>>;
|
||||
|
||||
static_assert(!std::is_same<Value, void>::value, "Unsupported type.");
|
||||
return detail::eax_bit_fields_are_equal<T, Value>(lhs, rhs);
|
||||
}
|
||||
|
||||
template<
|
||||
typename T,
|
||||
std::enable_if_t<detail::EaxIsBitFieldStruct<T>::value, int> = 0
|
||||
>
|
||||
inline bool operator!=(const T& lhs, const T& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
#endif // !EAX_UTILS_INCLUDED
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef EAX_X_RAM_INCLUDED
|
||||
#define EAX_X_RAM_INCLUDED
|
||||
|
||||
|
||||
#include "AL/al.h"
|
||||
|
||||
|
||||
constexpr auto eax_x_ram_min_size = ALsizei{};
|
||||
constexpr auto eax_x_ram_max_size = ALsizei{64 * 1'024 * 1'024};
|
||||
|
||||
|
||||
constexpr auto AL_EAX_RAM_SIZE = ALenum{0x202201};
|
||||
constexpr auto AL_EAX_RAM_FREE = ALenum{0x202202};
|
||||
|
||||
constexpr auto AL_STORAGE_AUTOMATIC = ALenum{0x202203};
|
||||
constexpr auto AL_STORAGE_HARDWARE = ALenum{0x202204};
|
||||
constexpr auto AL_STORAGE_ACCESSIBLE = ALenum{0x202205};
|
||||
|
||||
|
||||
constexpr auto AL_EAX_RAM_SIZE_NAME = "AL_EAX_RAM_SIZE";
|
||||
constexpr auto AL_EAX_RAM_FREE_NAME = "AL_EAX_RAM_FREE";
|
||||
|
||||
constexpr auto AL_STORAGE_AUTOMATIC_NAME = "AL_STORAGE_AUTOMATIC";
|
||||
constexpr auto AL_STORAGE_HARDWARE_NAME = "AL_STORAGE_HARDWARE";
|
||||
constexpr auto AL_STORAGE_ACCESSIBLE_NAME = "AL_STORAGE_ACCESSIBLE";
|
||||
|
||||
/* NOLINTBEGIN(readability-inconsistent-declaration-parameter-name)
|
||||
* These functions are defined using macros to forward them in a generic way to
|
||||
* implementation functions, which gives the parameters generic names.
|
||||
*/
|
||||
ALboolean AL_APIENTRY EAXSetBufferMode(ALsizei n, const ALuint *buffers, ALint value) noexcept;
|
||||
ALenum AL_APIENTRY EAXGetBufferMode(ALuint buffer, ALint *pReserved) noexcept;
|
||||
/* NOLINTEND(readability-inconsistent-declaration-parameter-name) */
|
||||
|
||||
#endif // !EAX_X_RAM_INCLUDED
|
||||
Reference in New Issue
Block a user