update openal

This commit is contained in:
AzaezelX 2024-06-30 14:35:57 -05:00
parent 62f3b93ff9
commit 6721a6b021
287 changed files with 33851 additions and 27325 deletions

View file

@ -10,34 +10,39 @@
//
#include <array>
#include <cfloat>
#include <cstdint>
#include <cstring>
#include <array>
#include <tuple>
#ifdef _WIN32
#include <guiddef.h>
#endif
#include "AL/al.h"
#ifndef GUID_DEFINED
#define GUID_DEFINED
typedef struct _GUID {
#ifndef _WIN32
using GUID = struct _GUID { /* NOLINT(*-reserved-identifier) */
std::uint32_t Data1;
std::uint16_t Data2;
std::uint16_t Data3;
std::uint8_t Data4[8];
} GUID;
std::array<std::uint8_t,8> Data4;
};
#ifndef _SYS_GUID_OPERATOR_EQ_
#define _SYS_GUID_OPERATOR_EQ_
inline bool operator==(const GUID& lhs, const GUID& rhs) noexcept
{ return std::memcmp(&lhs, &rhs, sizeof(GUID)) == 0; }
inline bool operator!=(const GUID& lhs, const GUID& rhs) noexcept
{ return !(lhs == rhs); }
#endif // _SYS_GUID_OPERATOR_EQ_
#endif // GUID_DEFINED
#endif // _WIN32
#define DECL_EQOP(T, ...) \
[[nodiscard]] auto get_members() const noexcept { return std::forward_as_tuple(__VA_ARGS__); } \
[[nodiscard]] friend bool operator==(const T &lhs, const T &rhs) noexcept \
{ return lhs.get_members() == rhs.get_members(); } \
[[nodiscard]] friend bool operator!=(const T &lhs, const T &rhs) noexcept \
{ return !(lhs == rhs); }
extern const GUID DSPROPSETID_EAX_ReverbProperties;
@ -276,11 +281,15 @@ struct EAXVECTOR {
float x;
float y;
float z;
[[nodiscard]]
auto get_members() const noexcept { return std::forward_as_tuple(x, y, z); }
}; // EAXVECTOR
[[nodiscard]]
inline bool operator==(const EAXVECTOR& lhs, const EAXVECTOR& rhs) noexcept
{ return std::memcmp(&lhs, &rhs, sizeof(EAXVECTOR)) == 0; }
{ return lhs.get_members() == rhs.get_members(); }
[[nodiscard]]
inline bool operator!=(const EAXVECTOR& lhs, const EAXVECTOR& rhs) noexcept
{ return !(lhs == rhs); }
@ -361,6 +370,7 @@ constexpr auto EAXCONTEXT_MINMACROFXFACTOR = 0.0F;
constexpr auto EAXCONTEXT_MAXMACROFXFACTOR = 1.0F;
constexpr auto EAXCONTEXT_DEFAULTMACROFXFACTOR = 0.0F;
constexpr auto EAXCONTEXT_DEFAULTLASTERROR = EAX_OK;
extern const GUID EAXPROPERTYID_EAX40_FXSlot0;
extern const GUID EAXPROPERTYID_EAX50_FXSlot0;
@ -613,7 +623,7 @@ struct EAX30SOURCEPROPERTIES {
float flOcclusionLFRatio; // occlusion low-frequency level re. main control
float flOcclusionRoomRatio; // relative occlusion control for room effect
float flOcclusionDirectRatio; // relative occlusion control for direct path
long lExclusion; // main exlusion control (attenuation at high frequencies)
long lExclusion; // main exclusion control (attenuation at high frequencies)
float flExclusionLFRatio; // exclusion low-frequency level re. main control
long lOutsideVolumeHF; // outside sound cone level at high frequencies
float flDopplerFactor; // like DS3D flDopplerFactor but per source
@ -653,11 +663,11 @@ struct EAXSPEAKERLEVELPROPERTIES {
}; // EAXSPEAKERLEVELPROPERTIES
struct EAX40ACTIVEFXSLOTS {
GUID guidActiveFXSlots[EAX40_MAX_ACTIVE_FXSLOTS];
std::array<GUID,EAX40_MAX_ACTIVE_FXSLOTS> guidActiveFXSlots;
}; // EAX40ACTIVEFXSLOTS
struct EAX50ACTIVEFXSLOTS {
GUID guidActiveFXSlots[EAX50_MAX_ACTIVE_FXSLOTS];
std::array<GUID,EAX50_MAX_ACTIVE_FXSLOTS> guidActiveFXSlots;
}; // EAX50ACTIVEFXSLOTS
// Use this structure for EAXSOURCE_OBSTRUCTIONPARAMETERS property.
@ -836,6 +846,11 @@ struct EAXREVERBPROPERTIES {
float flLFReference; // reference low frequency
float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect
unsigned long ulFlags; // modifies the behavior of properties
DECL_EQOP(EAXREVERBPROPERTIES, ulEnvironment, flEnvironmentSize, flEnvironmentDiffusion, lRoom,
lRoomHF, lRoomLF, flDecayTime, flDecayHFRatio, flDecayLFRatio, lReflections,
flReflectionsDelay, vReflectionsPan, lReverb, flReverbDelay, vReverbPan, flEchoTime,
flEchoDepth, flModulationTime, flModulationDepth, flAirAbsorptionHF, flHFReference,
flLFReference, flRoomRolloffFactor, ulFlags)
}; // EAXREVERBPROPERTIES
@ -965,6 +980,7 @@ enum EAXAGCCOMPRESSOR_PROPERTY : unsigned int {
struct EAXAGCCOMPRESSORPROPERTIES {
unsigned long ulOnOff; // Switch Compressor on or off
DECL_EQOP(EAXAGCCOMPRESSORPROPERTIES, ulOnOff)
}; // EAXAGCCOMPRESSORPROPERTIES
@ -991,6 +1007,7 @@ struct EAXAUTOWAHPROPERTIES {
float flReleaseTime; // Release time (seconds)
long lResonance; // Resonance (mB)
long lPeakLevel; // Peak level (mB)
DECL_EQOP(EAXAUTOWAHPROPERTIES, flAttackTime, flReleaseTime, lResonance, lPeakLevel)
}; // EAXAUTOWAHPROPERTIES
@ -1038,6 +1055,7 @@ struct EAXCHORUSPROPERTIES {
float flDepth; // Depth (0 to 1)
float flFeedback; // Feedback (-1 to 1)
float flDelay; // Delay (seconds)
DECL_EQOP(EAXCHORUSPROPERTIES, ulWaveform, lPhase, flRate, flDepth, flFeedback, flDelay)
}; // EAXCHORUSPROPERTIES
@ -1086,6 +1104,7 @@ struct EAXDISTORTIONPROPERTIES {
float flLowPassCutOff; // Controls the cut-off of the filter pre-distortion (Hz)
float flEQCenter; // Controls the center frequency of the EQ post-distortion (Hz)
float flEQBandwidth; // Controls the bandwidth of the EQ post-distortion (Hz)
DECL_EQOP(EAXDISTORTIONPROPERTIES, flEdge, lGain, flLowPassCutOff, flEQCenter, flEQBandwidth)
}; // EAXDISTORTIONPROPERTIES
@ -1130,6 +1149,7 @@ struct EAXECHOPROPERTIES {
float flDamping; // Controls a low-pass filter that dampens the echoes (0 to 1)
float flFeedback; // Controls the duration of echo repetition (0 to 1)
float flSpread; // Controls the left-right spread of the echoes
DECL_EQOP(EAXECHOPROPERTIES, flDelay, flLRDelay, flDamping, flFeedback, flSpread)
}; // EAXECHOPROPERTIES
@ -1184,6 +1204,8 @@ struct EAXEQUALIZERPROPERTIES {
float flMid2Width; // (octaves)
long lHighGain; // (mB)
float flHighCutOff; // (Hz)
DECL_EQOP(EAXEQUALIZERPROPERTIES, lLowGain, flLowCutOff, lMid1Gain, flMid1Center, flMid1Width,
lMid2Gain, flMid2Center, flMid2Width, lHighGain, flHighCutOff)
}; // EAXEQUALIZERPROPERTIES
@ -1255,6 +1277,7 @@ struct EAXFLANGERPROPERTIES {
float flDepth; // Depth (0 to 1)
float flFeedback; // Feedback (0 to 1)
float flDelay; // Delay (seconds)
DECL_EQOP(EAXFLANGERPROPERTIES, ulWaveform, lPhase, flRate, flDepth, flFeedback, flDelay)
}; // EAXFLANGERPROPERTIES
@ -1305,6 +1328,7 @@ struct EAXFREQUENCYSHIFTERPROPERTIES {
float flFrequency; // (Hz)
unsigned long ulLeftDirection; // see enum above
unsigned long ulRightDirection; // see enum above
DECL_EQOP(EAXFREQUENCYSHIFTERPROPERTIES, flFrequency, ulLeftDirection, ulRightDirection)
}; // EAXFREQUENCYSHIFTERPROPERTIES
@ -1383,6 +1407,8 @@ struct EAXVOCALMORPHERPROPERTIES {
long lPhonemeBCoarseTuning; // (semitones)
unsigned long ulWaveform; // Waveform selector - see enum above
float flRate; // (Hz)
DECL_EQOP(EAXVOCALMORPHERPROPERTIES, ulPhonemeA, lPhonemeACoarseTuning, ulPhonemeB,
lPhonemeBCoarseTuning, ulWaveform, flRate)
}; // EAXVOCALMORPHERPROPERTIES
@ -1425,6 +1451,7 @@ enum EAXPITCHSHIFTER_PROPERTY : unsigned int {
struct EAXPITCHSHIFTERPROPERTIES {
long lCoarseTune; // Amount of pitch shift (semitones)
long lFineTune; // Amount of pitch shift (cents)
DECL_EQOP(EAXPITCHSHIFTERPROPERTIES, lCoarseTune, lFineTune)
}; // EAXPITCHSHIFTERPROPERTIES
@ -1460,6 +1487,7 @@ struct EAXRINGMODULATORPROPERTIES {
float flFrequency; // Frequency of modulation (Hz)
float flHighPassCutOff; // Cut-off frequency of high-pass filter (Hz)
unsigned long ulWaveform; // Waveform selector - see enum above
DECL_EQOP(EAXRINGMODULATORPROPERTIES, flFrequency, flHighPassCutOff, ulWaveform)
}; // EAXRINGMODULATORPROPERTIES
@ -1490,4 +1518,5 @@ using LPEAXGET = ALenum(AL_APIENTRY*)(
ALvoid* property_buffer,
ALuint property_size);
#undef DECL_EQOP
#endif // !EAX_API_INCLUDED

View file

@ -22,8 +22,7 @@ EaxCall::EaxCall(
ALuint property_source_id,
ALvoid* property_buffer,
ALuint property_size)
: mCallType{type}, mVersion{0}, mPropertySetId{EaxCallPropertySetId::none}
, mIsDeferred{(property_id & deferred_flag) != 0}
: mCallType{type}, mIsDeferred{(property_id & deferred_flag) != 0}
, mPropertyId{property_id & ~deferred_flag}, mPropertySourceId{property_source_id}
, mPropertyBuffer{property_buffer}, mPropertyBufferSize{property_size}
{

View file

@ -31,16 +31,16 @@ public:
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; }
[[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>
TValue& get_value() const
[[nodiscard]] auto get_value() const -> TValue&
{
if(mPropertyBufferSize < sizeof(TValue))
fail_too_small();
@ -49,32 +49,32 @@ public:
}
template<typename TValue>
al::span<TValue> get_values(size_t max_count) const
[[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 = minz(mPropertyBufferSize / sizeof(TValue), max_count);
return al::as_span(static_cast<TValue*>(mPropertyBuffer), count);
const auto count = std::min(mPropertyBufferSize/sizeof(TValue), max_count);
return {static_cast<TValue*>(mPropertyBuffer), count};
}
template<typename TValue>
al::span<TValue> get_values() const
[[nodiscard]] auto get_values() const -> al::span<TValue>
{
return get_values<TValue>(~size_t{});
return get_values<TValue>(~0_uz);
}
template<typename TException, typename TValue>
void set_value(const TValue& value) const
auto set_value(const TValue& value) const -> void
{
get_value<TException, TValue>() = value;
}
private:
const EaxCallType mCallType;
int mVersion;
EaxFxSlotIndex mFxSlotIndex;
EaxCallPropertySetId mPropertySetId;
int mVersion{};
EaxFxSlotIndex mFxSlotIndex{};
EaxCallPropertySetId mPropertySetId{EaxCallPropertySetId::none};
bool mIsDeferred;
const ALuint mPropertyId;

View file

@ -4,60 +4,56 @@
#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
{
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;
};
};
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)
{
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;
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 {
@ -105,7 +101,6 @@ struct EaxReverbCommitter {
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);
@ -115,16 +110,13 @@ struct EaxReverbCommitter {
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;
static void translate(const EAX_REVERBPROPERTIES& src, EAXREVERBPROPERTIES& dst) noexcept;
static void translate(const EAX20LISTENERPROPERTIES& src, EAXREVERBPROPERTIES& dst) noexcept;
};
template<typename T>
@ -149,51 +141,137 @@ struct EaxCommitter {
[[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;
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:
@ -238,51 +316,39 @@ public:
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)
static 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);
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()
{
call_set_defaults<EaxReverbCommitter>(state1_.d);
EaxReverbCommitter::SetDefaults(state1_.d);
state1_.i = state1_.d;
call_set_defaults<EaxReverbCommitter>(state2_.d);
EaxReverbCommitter::SetDefaults(state2_.d);
state2_.i = state2_.d;
call_set_defaults<EaxReverbCommitter>(state3_.d);
EaxReverbCommitter::SetDefaults(state3_.d);
state3_.i = state3_.d;
call_set_defaults<T>(state4_.d);
T::SetDefaults(state4_.d);
state4_.i = state4_.d;
call_set_defaults<T>(state5_.d);
T::SetDefaults(state5_.d);
state5_.i = state5_.d;
}
@ -290,9 +356,9 @@ public:
{
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 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;
}
@ -300,47 +366,20 @@ public:
}
#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); }
{
return std::visit([&](auto &arg)
{ return CommitterFor<decltype(arg)>::Set(call, arg); },
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 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;
}
@ -348,32 +387,32 @@ public:
}
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); }
{
return std::visit([&](auto &arg)
{ return CommitterFor<decltype(arg)>::Get(call, arg); },
props);
}
void get(const EaxCall &call)
void get(const EaxCall &call) const
{
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 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;
}
}
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); }
{
return std::visit([&](auto &arg)
{ return CommitterFor<decltype(arg)>{props_, al_effect_props_}.commit(arg); },
props);
}
bool commit(int eax_version)
{
@ -388,15 +427,15 @@ public:
{
case 1:
state1_.i = state1_.d;
ret |= call_commit<EaxReverbCommitter>(state1_.d);
ret |= EaxReverbCommitter{props_, al_effect_props_}.commit(state1_.d);
break;
case 2:
state2_.i = state2_.d;
ret |= call_commit<EaxReverbCommitter>(state2_.d);
ret |= EaxReverbCommitter{props_, al_effect_props_}.commit(state2_.d);
break;
case 3:
state3_.i = state3_.d;
ret |= call_commit<EaxReverbCommitter>(state3_.d);
ret |= EaxReverbCommitter{props_, al_effect_props_}.commit(state3_.d);
break;
case 4:
state4_.i = state4_.d;

View file

@ -6,54 +6,27 @@
#include <string>
EaxException::EaxException(const char *context, const char *message)
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(const char *context, const char *message)
std::string EaxException::make_message(std::string_view context, std::string_view 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(context.empty() && message.empty())
return what;
if (has_contex)
what.reserve((!context.empty() ? context.size() + 3 : 0) + message.length() + 1);
if(!context.empty())
{
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);
what += "[";
what += context;
what += "] ";
}
what += message;
return what;
}

View file

@ -1,18 +1,23 @@
#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(const char *context, const char *message);
static std::string make_message(std::string_view context, std::string_view message);
public:
EaxException(const char *context, const char *message);
EaxException() = delete;
EaxException(const EaxException&) = default;
EaxException(EaxException&&) = default;
EaxException(std::string_view context, std::string_view message);
~EaxException() override;
}; // EaxException
auto operator=(const EaxException&) -> EaxException& = default;
auto operator=(EaxException&&) -> EaxException& = default;
};
#endif // !EAX_EXCEPTION_INCLUDED
#endif /* EAX_EXCEPTION_INCLUDED */

View file

@ -3,17 +3,16 @@
#include <cstddef>
#include <optional>
#include "aloptional.h"
#include "api.h"
using EaxFxSlotIndexValue = std::size_t;
class EaxFxSlotIndex : public al::optional<EaxFxSlotIndexValue>
{
class EaxFxSlotIndex : public std::optional<EaxFxSlotIndexValue> {
public:
using al::optional<EaxFxSlotIndexValue>::optional;
using std::optional<EaxFxSlotIndexValue>::optional;
EaxFxSlotIndex& operator=(const EaxFxSlotIndexValue &value) { set(value); return *this; }
EaxFxSlotIndex& operator=(const GUID &guid) { set(guid); return *this; }

View file

@ -6,13 +6,10 @@
#include "al/auxeffectslot.h"
#include "api.h"
#include "call.h"
#include "fx_slot_index.h"
class EaxFxSlots
{
class EaxFxSlots {
public:
void initialize(ALCcontext& al_context);
@ -25,11 +22,9 @@ public:
}
const ALeffectslot& get(
EaxFxSlotIndex index) const;
[[nodiscard]] auto get(EaxFxSlotIndex index) const -> const ALeffectslot&;
ALeffectslot& get(
EaxFxSlotIndex index);
[[nodiscard]] auto get(EaxFxSlotIndex index) -> ALeffectslot&;
private:
using Items = std::array<EaxAlEffectSlotUPtr, EAX_MAX_FXSLOTS>;
@ -39,8 +34,7 @@ private:
[[noreturn]]
static void fail(
const char* message);
static void fail(const char* message);
void initialize_fx_slots(ALCcontext& al_context);
}; // EaxFxSlots

View file

@ -1,21 +0,0 @@
#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";

View file

@ -1,22 +1,6 @@
#ifndef EAX_GLOBALS_INCLUDED
#define EAX_GLOBALS_INCLUDED
inline bool eax_g_is_enabled{true};
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
#endif /* EAX_GLOBALS_INCLUDED */

View file

@ -5,10 +5,11 @@
#include <cassert>
#include <exception>
#include "alstring.h"
#include "core/logging.h"
void eax_log_exception(const char *message) noexcept
void eax_log_exception(std::string_view message) noexcept
{
const auto exception_ptr = std::current_exception();
assert(exception_ptr);
@ -17,10 +18,9 @@ void eax_log_exception(const char *message) noexcept
std::rethrow_exception(exception_ptr);
}
catch(const std::exception& ex) {
const auto ex_message = ex.what();
ERR("%s %s\n", message ? message : "", ex_message);
ERR("%.*s %s\n", al::sizei(message), message.data(), ex.what());
}
catch(...) {
ERR("%s %s\n", message ? message : "", "Generic exception.");
ERR("%.*s %s\n", al::sizei(message), message.data(), "Generic exception.");
}
}

View file

@ -4,8 +4,11 @@
#include <algorithm>
#include <cstdint>
#include <string>
#include <string_view>
#include <type_traits>
#include "opthelpers.h"
using EaxDirtyFlags = unsigned int;
struct EaxAlLowPassParam {
@ -13,16 +16,13 @@ struct EaxAlLowPassParam {
float gain_hf;
};
void eax_log_exception(const char *message) noexcept;
void eax_log_exception(std::string_view message) noexcept;
template<typename TException, typename TValue>
void eax_validate_range(
const char* value_name,
const TValue& value,
const TValue& min_value,
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)
if(value >= min_value && value <= max_value) LIKELY
return;
const auto message =

View file

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