First Commit

This commit is contained in:
2025-02-06 22:24:29 +08:00
parent ed7df4c81e
commit 7539e6a53c
18116 changed files with 6181499 additions and 0 deletions

1621
externals/openal-soft/al/eax/api.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

1493
externals/openal-soft/al/eax/api.h vendored Normal file

File diff suppressed because it is too large Load Diff

219
externals/openal-soft/al/eax/call.cpp vendored Normal file
View File

@@ -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
};
}

97
externals/openal-soft/al/eax/call.h vendored Normal file
View File

@@ -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);
bool is_get() const noexcept { return mCallType == EaxCallType::get; }
bool is_deferred() const noexcept { return mIsDeferred; }
int get_version() const noexcept { return mVersion; }
EaxCallPropertySetId get_property_set_id() const noexcept { return mPropertySetId; }
ALuint get_property_id() const noexcept { return mPropertyId; }
ALuint get_property_al_name() const noexcept { return mPropertySourceId; }
EaxFxSlotIndex get_fx_slot_index() const noexcept { return mFxSlotIndex; }
template<typename TException, typename TValue>
TValue& get_value() const
{
if(mPropertyBufferSize < sizeof(TValue))
fail_too_small();
return *static_cast<TValue*>(mPropertyBuffer);
}
template<typename TValue>
al::span<TValue> get_values(size_t max_count) const
{
if(max_count == 0 || mPropertyBufferSize < sizeof(TValue))
fail_too_small();
const auto count = minz(mPropertyBufferSize / sizeof(TValue), max_count);
return al::as_span(static_cast<TValue*>(mPropertyBuffer), count);
}
template<typename TValue>
al::span<TValue> get_values() const
{
return get_values<TValue>(~size_t{});
}
template<typename TException, typename TValue>
void set_value(const TValue& value) const
{
get_value<TException, TValue>() = value;
}
private:
const EaxCallType mCallType;
int mVersion;
EaxFxSlotIndex mFxSlotIndex;
EaxCallPropertySetId mPropertySetId;
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

418
externals/openal-soft/al/eax/effect.h vendored Normal file
View File

@@ -0,0 +1,418 @@
#ifndef EAX_EFFECT_INCLUDED
#define EAX_EFFECT_INCLUDED
#include <cassert>
#include <memory>
#include "alnumeric.h"
#include "AL/al.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
/* TODO: Use std::variant (C++17). */
enum class EaxEffectType {
None, Reverb, Chorus, Autowah, Compressor, Distortion, Echo, Equalizer, Flanger,
FrequencyShifter, Modulator, PitchShifter, VocalMorpher
};
struct EaxEffectProps {
EaxEffectType mType;
union {
EAXREVERBPROPERTIES mReverb;
EAXCHORUSPROPERTIES mChorus;
EAXAUTOWAHPROPERTIES mAutowah;
EAXAGCCOMPRESSORPROPERTIES mCompressor;
EAXDISTORTIONPROPERTIES mDistortion;
EAXECHOPROPERTIES mEcho;
EAXEQUALIZERPROPERTIES mEqualizer;
EAXFLANGERPROPERTIES mFlanger;
EAXFREQUENCYSHIFTERPROPERTIES mFrequencyShifter;
EAXRINGMODULATORPROPERTIES mModulator;
EAXPITCHSHIFTERPROPERTIES mPitchShifter;
EAXVOCALMORPHERPROPERTIES mVocalMorpher;
};
};
constexpr ALenum EnumFromEaxEffectType(const EaxEffectProps &props)
{
switch(props.mType)
{
case EaxEffectType::None: break;
case EaxEffectType::Reverb: return AL_EFFECT_EAXREVERB;
case EaxEffectType::Chorus: return AL_EFFECT_CHORUS;
case EaxEffectType::Autowah: return AL_EFFECT_AUTOWAH;
case EaxEffectType::Compressor: return AL_EFFECT_COMPRESSOR;
case EaxEffectType::Distortion: return AL_EFFECT_DISTORTION;
case EaxEffectType::Echo: return AL_EFFECT_ECHO;
case EaxEffectType::Equalizer: return AL_EFFECT_EQUALIZER;
case EaxEffectType::Flanger: return AL_EFFECT_FLANGER;
case EaxEffectType::FrequencyShifter: return AL_EFFECT_FREQUENCY_SHIFTER;
case EaxEffectType::Modulator: return AL_EFFECT_RING_MODULATOR;
case EaxEffectType::PitchShifter: return AL_EFFECT_PITCH_SHIFTER;
case EaxEffectType::VocalMorpher: return AL_EFFECT_VOCAL_MORPHER;
}
return AL_EFFECT_NULL;
}
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);
bool commit(const EaxEffectProps &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 Get(const EaxCall &call, const EaxEffectProps &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 Set(const EaxCall &call, EaxEffectProps &props);
static void translate(const EAX_REVERBPROPERTIES& src, EaxEffectProps& dst) noexcept;
static void translate(const EAX20LISTENERPROPERTIES& src, EaxEffectProps& dst) noexcept;
static void translate(const EAXREVERBPROPERTIES& src, EaxEffectProps& 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()); }
bool commit(const EaxEffectProps &props);
static void SetDefaults(EaxEffectProps &props);
static void Get(const EaxCall &call, const EaxEffectProps &props);
static void Set(const EaxCall &call, EaxEffectProps &props);
};
struct EaxAutowahCommitter : public EaxCommitter<EaxAutowahCommitter> {
using EaxCommitter<EaxAutowahCommitter>::EaxCommitter;
};
struct EaxChorusCommitter : public EaxCommitter<EaxChorusCommitter> {
using EaxCommitter<EaxChorusCommitter>::EaxCommitter;
};
struct EaxCompressorCommitter : public EaxCommitter<EaxCompressorCommitter> {
using EaxCommitter<EaxCompressorCommitter>::EaxCommitter;
};
struct EaxDistortionCommitter : public EaxCommitter<EaxDistortionCommitter> {
using EaxCommitter<EaxDistortionCommitter>::EaxCommitter;
};
struct EaxEchoCommitter : public EaxCommitter<EaxEchoCommitter> {
using EaxCommitter<EaxEchoCommitter>::EaxCommitter;
};
struct EaxEqualizerCommitter : public EaxCommitter<EaxEqualizerCommitter> {
using EaxCommitter<EaxEqualizerCommitter>::EaxCommitter;
};
struct EaxFlangerCommitter : public EaxCommitter<EaxFlangerCommitter> {
using EaxCommitter<EaxFlangerCommitter>::EaxCommitter;
};
struct EaxFrequencyShifterCommitter : public EaxCommitter<EaxFrequencyShifterCommitter> {
using EaxCommitter<EaxFrequencyShifterCommitter>::EaxCommitter;
};
struct EaxModulatorCommitter : public EaxCommitter<EaxModulatorCommitter> {
using EaxCommitter<EaxModulatorCommitter>::EaxCommitter;
};
struct EaxPitchShifterCommitter : public EaxCommitter<EaxPitchShifterCommitter> {
using EaxCommitter<EaxPitchShifterCommitter>::EaxCommitter;
};
struct EaxVocalMorpherCommitter : public EaxCommitter<EaxVocalMorpherCommitter> {
using EaxCommitter<EaxVocalMorpherCommitter>::EaxCommitter;
};
struct EaxNullCommitter : public EaxCommitter<EaxNullCommitter> {
using EaxCommitter<EaxNullCommitter>::EaxCommitter;
};
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_{};
template<typename T, typename ...Args>
void call_set_defaults(Args&& ...args)
{ return T::SetDefaults(std::forward<Args>(args)...); }
void call_set_defaults(const ALenum altype, EaxEffectProps &props)
{
if(altype == AL_EFFECT_EAXREVERB)
return call_set_defaults<EaxReverbCommitter>(props);
if(altype == AL_EFFECT_CHORUS)
return call_set_defaults<EaxChorusCommitter>(props);
if(altype == AL_EFFECT_AUTOWAH)
return call_set_defaults<EaxAutowahCommitter>(props);
if(altype == AL_EFFECT_COMPRESSOR)
return call_set_defaults<EaxCompressorCommitter>(props);
if(altype == AL_EFFECT_DISTORTION)
return call_set_defaults<EaxDistortionCommitter>(props);
if(altype == AL_EFFECT_ECHO)
return call_set_defaults<EaxEchoCommitter>(props);
if(altype == AL_EFFECT_EQUALIZER)
return call_set_defaults<EaxEqualizerCommitter>(props);
if(altype == AL_EFFECT_FLANGER)
return call_set_defaults<EaxFlangerCommitter>(props);
if(altype == AL_EFFECT_FREQUENCY_SHIFTER)
return call_set_defaults<EaxFrequencyShifterCommitter>(props);
if(altype == AL_EFFECT_RING_MODULATOR)
return call_set_defaults<EaxModulatorCommitter>(props);
if(altype == AL_EFFECT_PITCH_SHIFTER)
return call_set_defaults<EaxPitchShifterCommitter>(props);
if(altype == AL_EFFECT_VOCAL_MORPHER)
return call_set_defaults<EaxVocalMorpherCommitter>(props);
return call_set_defaults<EaxNullCommitter>(props);
}
template<typename T>
void init()
{
call_set_defaults<EaxReverbCommitter>(state1_.d);
state1_.i = state1_.d;
call_set_defaults<EaxReverbCommitter>(state2_.d);
state2_.i = state2_.d;
call_set_defaults<EaxReverbCommitter>(state3_.d);
state3_.i = state3_.d;
call_set_defaults<T>(state4_.d);
state4_.i = state4_.d;
call_set_defaults<T>(state5_.d);
state5_.i = state5_.d;
}
void set_defaults(int eax_version, ALenum altype)
{
switch(eax_version)
{
case 1: call_set_defaults<EaxReverbCommitter>(state1_.d); break;
case 2: call_set_defaults<EaxReverbCommitter>(state2_.d); break;
case 3: call_set_defaults<EaxReverbCommitter>(state3_.d); break;
case 4: call_set_defaults(altype, state4_.d); break;
case 5: call_set_defaults(altype, state5_.d); break;
}
changed_ = true;
}
#define EAXCALL(T, Callable, ...) \
if(T == EaxEffectType::Reverb) \
return Callable<EaxReverbCommitter>(__VA_ARGS__); \
if(T == EaxEffectType::Chorus) \
return Callable<EaxChorusCommitter>(__VA_ARGS__); \
if(T == EaxEffectType::Autowah) \
return Callable<EaxAutowahCommitter>(__VA_ARGS__); \
if(T == EaxEffectType::Compressor) \
return Callable<EaxCompressorCommitter>(__VA_ARGS__); \
if(T == EaxEffectType::Distortion) \
return Callable<EaxDistortionCommitter>(__VA_ARGS__); \
if(T == EaxEffectType::Echo) \
return Callable<EaxEchoCommitter>(__VA_ARGS__); \
if(T == EaxEffectType::Equalizer) \
return Callable<EaxEqualizerCommitter>(__VA_ARGS__); \
if(T == EaxEffectType::Flanger) \
return Callable<EaxFlangerCommitter>(__VA_ARGS__); \
if(T == EaxEffectType::FrequencyShifter) \
return Callable<EaxFrequencyShifterCommitter>(__VA_ARGS__); \
if(T == EaxEffectType::Modulator) \
return Callable<EaxModulatorCommitter>(__VA_ARGS__); \
if(T == EaxEffectType::PitchShifter) \
return Callable<EaxPitchShifterCommitter>(__VA_ARGS__); \
if(T == EaxEffectType::VocalMorpher) \
return Callable<EaxVocalMorpherCommitter>(__VA_ARGS__); \
return Callable<EaxNullCommitter>(__VA_ARGS__)
template<typename T, typename ...Args>
static void call_set(Args&& ...args)
{ return T::Set(std::forward<Args>(args)...); }
static void call_set(const EaxCall &call, EaxEffectProps &props)
{ EAXCALL(props.mType, call_set, call, props); }
void set(const EaxCall &call)
{
switch(call.get_version())
{
case 1: call_set<EaxReverbCommitter>(call, state1_.d); break;
case 2: call_set<EaxReverbCommitter>(call, state2_.d); break;
case 3: call_set<EaxReverbCommitter>(call, state3_.d); break;
case 4: call_set(call, state4_.d); break;
case 5: call_set(call, state5_.d); break;
}
changed_ = true;
}
template<typename T, typename ...Args>
static void call_get(Args&& ...args)
{ return T::Get(std::forward<Args>(args)...); }
static void call_get(const EaxCall &call, const EaxEffectProps &props)
{ EAXCALL(props.mType, call_get, call, props); }
void get(const EaxCall &call)
{
switch(call.get_version())
{
case 1: call_get<EaxReverbCommitter>(call, state1_.d); break;
case 2: call_get<EaxReverbCommitter>(call, state2_.d); break;
case 3: call_get<EaxReverbCommitter>(call, state3_.d); break;
case 4: call_get(call, state4_.d); break;
case 5: call_get(call, state5_.d); break;
}
}
template<typename T, typename ...Args>
bool call_commit(Args&& ...args)
{ return T{props_, al_effect_props_}.commit(std::forward<Args>(args)...); }
bool call_commit(const EaxEffectProps &props)
{ EAXCALL(props.mType, call_commit, 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 |= call_commit<EaxReverbCommitter>(state1_.d);
break;
case 2:
state2_.i = state2_.d;
ret |= call_commit<EaxReverbCommitter>(state2_.d);
break;
case 3:
state3_.i = state3_.d;
ret |= call_commit<EaxReverbCommitter>(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

View File

@@ -0,0 +1,59 @@
#include "config.h"
#include "exception.h"
#include <cassert>
#include <string>
EaxException::EaxException(const char *context, const char *message)
: std::runtime_error{make_message(context, message)}
{
}
EaxException::~EaxException() = default;
std::string EaxException::make_message(const char *context, const char *message)
{
const auto context_size = (context ? std::string::traits_type::length(context) : 0);
const auto has_contex = (context_size > 0);
const auto message_size = (message ? std::string::traits_type::length(message) : 0);
const auto has_message = (message_size > 0);
if (!has_contex && !has_message)
{
return std::string{};
}
static constexpr char left_prefix[] = "[";
const auto left_prefix_size = std::string::traits_type::length(left_prefix);
static constexpr char right_prefix[] = "] ";
const auto right_prefix_size = std::string::traits_type::length(right_prefix);
const auto what_size =
(
has_contex ?
left_prefix_size + context_size + right_prefix_size :
0) +
message_size +
1;
auto what = std::string{};
what.reserve(what_size);
if (has_contex)
{
what.append(left_prefix, left_prefix_size);
what.append(context, context_size);
what.append(right_prefix, right_prefix_size);
}
if (has_message)
{
what.append(message, message_size);
}
return what;
}

View File

@@ -0,0 +1,18 @@
#ifndef EAX_EXCEPTION_INCLUDED
#define EAX_EXCEPTION_INCLUDED
#include <stdexcept>
#include <string>
class EaxException : public std::runtime_error {
static std::string make_message(const char *context, const char *message);
public:
EaxException(const char *context, const char *message);
~EaxException() override;
}; // EaxException
#endif // !EAX_EXCEPTION_INCLUDED

View File

@@ -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};
}

View File

@@ -0,0 +1,41 @@
#ifndef EAX_FX_SLOT_INDEX_INCLUDED
#define EAX_FX_SLOT_INDEX_INCLUDED
#include <cstddef>
#include "aloptional.h"
#include "api.h"
using EaxFxSlotIndexValue = std::size_t;
class EaxFxSlotIndex : public al::optional<EaxFxSlotIndexValue>
{
public:
using al::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

View File

@@ -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;
}
}

49
externals/openal-soft/al/eax/fx_slots.h vendored Normal file
View File

@@ -0,0 +1,49 @@
#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();
}
const ALeffectslot& get(
EaxFxSlotIndex index) const;
ALeffectslot& get(
EaxFxSlotIndex index);
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

View File

@@ -0,0 +1,21 @@
#include "config.h"
#include "globals.h"
bool eax_g_is_enabled = true;
const char eax1_ext_name[] = "EAX";
const char eax2_ext_name[] = "EAX2.0";
const char eax3_ext_name[] = "EAX3.0";
const char eax4_ext_name[] = "EAX4.0";
const char eax5_ext_name[] = "EAX5.0";
const char eax_x_ram_ext_name[] = "EAX-RAM";
const char eax_eax_set_func_name[] = "EAXSet";
const char eax_eax_get_func_name[] = "EAXGet";
const char eax_eax_set_buffer_mode_func_name[] = "EAXSetBufferMode";
const char eax_eax_get_buffer_mode_func_name[] = "EAXGetBufferMode";

22
externals/openal-soft/al/eax/globals.h vendored Normal file
View File

@@ -0,0 +1,22 @@
#ifndef EAX_GLOBALS_INCLUDED
#define EAX_GLOBALS_INCLUDED
extern bool eax_g_is_enabled;
extern const char eax1_ext_name[];
extern const char eax2_ext_name[];
extern const char eax3_ext_name[];
extern const char eax4_ext_name[];
extern const char eax5_ext_name[];
extern const char eax_x_ram_ext_name[];
extern const char eax_eax_set_func_name[];
extern const char eax_eax_get_func_name[];
extern const char eax_eax_set_buffer_mode_func_name[];
extern const char eax_eax_get_buffer_mode_func_name[];
#endif // !EAX_GLOBALS_INCLUDED

26
externals/openal-soft/al/eax/utils.cpp vendored Normal file
View File

@@ -0,0 +1,26 @@
#include "config.h"
#include "utils.h"
#include <cassert>
#include <exception>
#include "core/logging.h"
void eax_log_exception(const char *message) noexcept
{
const auto exception_ptr = std::current_exception();
assert(exception_ptr);
try {
std::rethrow_exception(exception_ptr);
}
catch(const std::exception& ex) {
const auto ex_message = ex.what();
ERR("%s %s\n", message ? message : "", ex_message);
}
catch(...) {
ERR("%s %s\n", message ? message : "", "Generic exception.");
}
}

95
externals/openal-soft/al/eax/utils.h vendored Normal file
View File

@@ -0,0 +1,95 @@
#ifndef EAX_UTILS_INCLUDED
#define EAX_UTILS_INCLUDED
#include <algorithm>
#include <cstdint>
#include <string>
#include <type_traits>
using EaxDirtyFlags = unsigned int;
struct EaxAlLowPassParam {
float gain;
float gain_hf;
};
void eax_log_exception(const char *message) noexcept;
template<typename TException, typename TValue>
void eax_validate_range(
const char* value_name,
const TValue& value,
const TValue& min_value,
const TValue& max_value)
{
if (value >= min_value && value <= max_value)
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

38
externals/openal-soft/al/eax/x_ram.h vendored Normal file
View File

@@ -0,0 +1,38 @@
#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";
ALboolean AL_APIENTRY EAXSetBufferMode(
ALsizei n,
const ALuint* buffers,
ALint value);
ALenum AL_APIENTRY EAXGetBufferMode(
ALuint buffer,
ALint* pReserved);
#endif // !EAX_X_RAM_INCLUDED