mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-15 16:44:36 +00:00
Initial commit
added libraries: opus flac libsndfile updated: libvorbis libogg openal - Everything works as expected for now. Bare in mind libsndfile needed the check for whether or not it could find the xiph libraries removed in order for this to work.
This commit is contained in:
parent
05a083ca6f
commit
a745fc3757
1954 changed files with 431332 additions and 21037 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -18,16 +18,25 @@
|
|||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include <memory>
|
||||
|
||||
#include "eax_eax_call.h"
|
||||
#include "eax_effect.h"
|
||||
#include "eax_fx_slot_index.h"
|
||||
#include "eax/call.h"
|
||||
#include "eax/effect.h"
|
||||
#include "eax/exception.h"
|
||||
#include "eax/fx_slot_index.h"
|
||||
#include "eax/utils.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
struct ALbuffer;
|
||||
struct ALeffect;
|
||||
struct WetBuffer;
|
||||
|
||||
#ifdef ALSOFT_EAX
|
||||
class EaxFxSlotException : public EaxException {
|
||||
public:
|
||||
explicit EaxFxSlotException(const char* message)
|
||||
: EaxException{"EAX_FX_SLOT", message}
|
||||
{}
|
||||
};
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
enum class SlotState : ALenum {
|
||||
Initial = AL_INITIAL,
|
||||
|
|
@ -54,12 +63,12 @@ struct ALeffectslot {
|
|||
|
||||
RefCount ref{0u};
|
||||
|
||||
EffectSlot mSlot;
|
||||
EffectSlot *mSlot{nullptr};
|
||||
|
||||
/* Self ID */
|
||||
ALuint id{};
|
||||
|
||||
ALeffectslot();
|
||||
ALeffectslot(ALCcontext *context);
|
||||
ALeffectslot(const ALeffectslot&) = delete;
|
||||
ALeffectslot& operator=(const ALeffectslot&) = delete;
|
||||
~ALeffectslot();
|
||||
|
|
@ -73,205 +82,287 @@ struct ALeffectslot {
|
|||
|
||||
#ifdef ALSOFT_EAX
|
||||
public:
|
||||
void eax_initialize(
|
||||
ALCcontext& al_context,
|
||||
EaxFxSlotIndexValue index);
|
||||
void eax_initialize(ALCcontext& al_context, EaxFxSlotIndexValue index);
|
||||
|
||||
const EAX50FXSLOTPROPERTIES& eax_get_eax_fx_slot() const noexcept;
|
||||
EaxFxSlotIndexValue eax_get_index() const noexcept { return eax_fx_slot_index_; }
|
||||
const EAX50FXSLOTPROPERTIES& eax_get_eax_fx_slot() const noexcept
|
||||
{ return eax_; }
|
||||
|
||||
// Returns `true` if all sources should be updated, or `false` otherwise.
|
||||
bool eax_dispatch(const EaxCall& call)
|
||||
{ return call.is_get() ? eax_get(call) : eax_set(call); }
|
||||
|
||||
// [[nodiscard]]
|
||||
bool eax_dispatch(const EaxEaxCall& eax_call)
|
||||
{ return eax_call.is_get() ? eax_get(eax_call) : eax_set(eax_call); }
|
||||
|
||||
|
||||
void eax_unlock_legacy() noexcept;
|
||||
|
||||
void eax_commit() { eax_apply_deferred(); }
|
||||
void eax_commit();
|
||||
|
||||
private:
|
||||
static constexpr auto eax_load_effect_dirty_bit = EaxDirtyFlags{1} << 0;
|
||||
static constexpr auto eax_volume_dirty_bit = EaxDirtyFlags{1} << 1;
|
||||
static constexpr auto eax_lock_dirty_bit = EaxDirtyFlags{1} << 2;
|
||||
static constexpr auto eax_flags_dirty_bit = EaxDirtyFlags{1} << 3;
|
||||
static constexpr auto eax_occlusion_dirty_bit = EaxDirtyFlags{1} << 4;
|
||||
static constexpr auto eax_occlusion_lf_ratio_dirty_bit = EaxDirtyFlags{1} << 5;
|
||||
|
||||
using Exception = EaxFxSlotException;
|
||||
|
||||
using Eax4Props = EAX40FXSLOTPROPERTIES;
|
||||
|
||||
struct Eax4State {
|
||||
Eax4Props i; // Immediate.
|
||||
};
|
||||
|
||||
using Eax5Props = EAX50FXSLOTPROPERTIES;
|
||||
|
||||
struct Eax5State {
|
||||
Eax5Props i; // Immediate.
|
||||
};
|
||||
|
||||
struct EaxRangeValidator {
|
||||
template<typename TValue>
|
||||
void operator()(
|
||||
const char* name,
|
||||
const TValue& value,
|
||||
const TValue& min_value,
|
||||
const TValue& max_value) const
|
||||
{
|
||||
eax_validate_range<Exception>(name, value, min_value, max_value);
|
||||
}
|
||||
};
|
||||
|
||||
struct Eax4GuidLoadEffectValidator {
|
||||
void operator()(const GUID& guidLoadEffect) const
|
||||
{
|
||||
if (guidLoadEffect != EAX_NULL_GUID &&
|
||||
guidLoadEffect != EAX_REVERB_EFFECT &&
|
||||
guidLoadEffect != EAX_AGCCOMPRESSOR_EFFECT &&
|
||||
guidLoadEffect != EAX_AUTOWAH_EFFECT &&
|
||||
guidLoadEffect != EAX_CHORUS_EFFECT &&
|
||||
guidLoadEffect != EAX_DISTORTION_EFFECT &&
|
||||
guidLoadEffect != EAX_ECHO_EFFECT &&
|
||||
guidLoadEffect != EAX_EQUALIZER_EFFECT &&
|
||||
guidLoadEffect != EAX_FLANGER_EFFECT &&
|
||||
guidLoadEffect != EAX_FREQUENCYSHIFTER_EFFECT &&
|
||||
guidLoadEffect != EAX_VOCALMORPHER_EFFECT &&
|
||||
guidLoadEffect != EAX_PITCHSHIFTER_EFFECT &&
|
||||
guidLoadEffect != EAX_RINGMODULATOR_EFFECT)
|
||||
{
|
||||
eax_fail_unknown_effect_id();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Eax4VolumeValidator {
|
||||
void operator()(long lVolume) const
|
||||
{
|
||||
EaxRangeValidator{}(
|
||||
"Volume",
|
||||
lVolume,
|
||||
EAXFXSLOT_MINVOLUME,
|
||||
EAXFXSLOT_MAXVOLUME);
|
||||
}
|
||||
};
|
||||
|
||||
struct Eax4LockValidator {
|
||||
void operator()(long lLock) const
|
||||
{
|
||||
EaxRangeValidator{}(
|
||||
"Lock",
|
||||
lLock,
|
||||
EAXFXSLOT_MINLOCK,
|
||||
EAXFXSLOT_MAXLOCK);
|
||||
}
|
||||
};
|
||||
|
||||
struct Eax4FlagsValidator {
|
||||
void operator()(unsigned long ulFlags) const
|
||||
{
|
||||
EaxRangeValidator{}(
|
||||
"Flags",
|
||||
ulFlags,
|
||||
0UL,
|
||||
~EAX40FXSLOTFLAGS_RESERVED);
|
||||
}
|
||||
};
|
||||
|
||||
struct Eax4AllValidator {
|
||||
void operator()(const EAX40FXSLOTPROPERTIES& all) const
|
||||
{
|
||||
Eax4GuidLoadEffectValidator{}(all.guidLoadEffect);
|
||||
Eax4VolumeValidator{}(all.lVolume);
|
||||
Eax4LockValidator{}(all.lLock);
|
||||
Eax4FlagsValidator{}(all.ulFlags);
|
||||
}
|
||||
};
|
||||
|
||||
struct Eax5OcclusionValidator {
|
||||
void operator()(long lOcclusion) const
|
||||
{
|
||||
EaxRangeValidator{}(
|
||||
"Occlusion",
|
||||
lOcclusion,
|
||||
EAXFXSLOT_MINOCCLUSION,
|
||||
EAXFXSLOT_MAXOCCLUSION);
|
||||
}
|
||||
};
|
||||
|
||||
struct Eax5OcclusionLfRatioValidator {
|
||||
void operator()(float flOcclusionLFRatio) const
|
||||
{
|
||||
EaxRangeValidator{}(
|
||||
"Occlusion LF Ratio",
|
||||
flOcclusionLFRatio,
|
||||
EAXFXSLOT_MINOCCLUSIONLFRATIO,
|
||||
EAXFXSLOT_MAXOCCLUSIONLFRATIO);
|
||||
}
|
||||
};
|
||||
|
||||
struct Eax5FlagsValidator {
|
||||
void operator()(unsigned long ulFlags) const
|
||||
{
|
||||
EaxRangeValidator{}(
|
||||
"Flags",
|
||||
ulFlags,
|
||||
0UL,
|
||||
~EAX50FXSLOTFLAGS_RESERVED);
|
||||
}
|
||||
};
|
||||
|
||||
struct Eax5AllValidator {
|
||||
void operator()(const EAX50FXSLOTPROPERTIES& all) const
|
||||
{
|
||||
Eax4AllValidator{}(static_cast<const EAX40FXSLOTPROPERTIES&>(all));
|
||||
Eax5OcclusionValidator{}(all.lOcclusion);
|
||||
Eax5OcclusionLfRatioValidator{}(all.flOcclusionLFRatio);
|
||||
}
|
||||
};
|
||||
|
||||
ALCcontext* eax_al_context_{};
|
||||
|
||||
EaxFxSlotIndexValue eax_fx_slot_index_{};
|
||||
|
||||
EAX50FXSLOTPROPERTIES eax_eax_fx_slot_{};
|
||||
|
||||
int eax_version_{}; // Current EAX version.
|
||||
EaxDirtyFlags eax_df_{}; // Dirty flags for the current EAX version.
|
||||
EaxEffectUPtr eax_effect_{};
|
||||
bool eax_is_locked_{};
|
||||
Eax5State eax123_{}; // EAX1/EAX2/EAX3 state.
|
||||
Eax4State eax4_{}; // EAX4 state.
|
||||
Eax5State eax5_{}; // EAX5 state.
|
||||
Eax5Props eax_{}; // Current EAX state.
|
||||
|
||||
[[noreturn]] static void eax_fail(const char* message);
|
||||
[[noreturn]] static void eax_fail_unknown_effect_id();
|
||||
[[noreturn]] static void eax_fail_unknown_property_id();
|
||||
[[noreturn]] static void eax_fail_unknown_version();
|
||||
|
||||
[[noreturn]]
|
||||
static void eax_fail(
|
||||
const char* message);
|
||||
// Gets a new value from EAX call,
|
||||
// validates it,
|
||||
// sets a dirty flag only if the new value differs form the old one,
|
||||
// and assigns the new value.
|
||||
template<typename TValidator, EaxDirtyFlags TDirtyBit, typename TProperties>
|
||||
static void eax_fx_slot_set(const EaxCall& call, TProperties& dst, EaxDirtyFlags& dirty_flags)
|
||||
{
|
||||
const auto& src = call.get_value<Exception, const TProperties>();
|
||||
TValidator{}(src);
|
||||
dirty_flags |= (dst != src ? TDirtyBit : EaxDirtyFlags{});
|
||||
dst = src;
|
||||
}
|
||||
|
||||
// Gets a new value from EAX call,
|
||||
// validates it,
|
||||
// sets a dirty flag without comparing the values,
|
||||
// and assigns the new value.
|
||||
template<typename TValidator, EaxDirtyFlags TDirtyBit, typename TProperties>
|
||||
static void eax_fx_slot_set_dirty(const EaxCall& call, TProperties& dst,
|
||||
EaxDirtyFlags& dirty_flags)
|
||||
{
|
||||
const auto& src = call.get_value<Exception, const TProperties>();
|
||||
TValidator{}(src);
|
||||
dirty_flags |= TDirtyBit;
|
||||
dst = src;
|
||||
}
|
||||
|
||||
GUID eax_get_eax_default_effect_guid() const noexcept;
|
||||
constexpr bool eax4_fx_slot_is_legacy() const noexcept
|
||||
{ return eax_fx_slot_index_ < 2; }
|
||||
|
||||
void eax4_fx_slot_ensure_unlocked() const;
|
||||
|
||||
static ALenum eax_get_efx_effect_type(const GUID& guid);
|
||||
const GUID& eax_get_eax_default_effect_guid() const noexcept;
|
||||
long eax_get_eax_default_lock() const noexcept;
|
||||
|
||||
void eax_set_eax_fx_slot_defaults();
|
||||
void eax4_fx_slot_set_defaults(Eax4Props& props) noexcept;
|
||||
void eax5_fx_slot_set_defaults(Eax5Props& props) noexcept;
|
||||
void eax4_fx_slot_set_current_defaults(const Eax4Props& props) noexcept;
|
||||
void eax5_fx_slot_set_current_defaults(const Eax5Props& props) noexcept;
|
||||
void eax_fx_slot_set_current_defaults();
|
||||
void eax_fx_slot_set_defaults();
|
||||
|
||||
void eax_initialize_eax();
|
||||
void eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props) const;
|
||||
void eax5_fx_slot_get(const EaxCall& call, const Eax5Props& props) const;
|
||||
void eax_fx_slot_get(const EaxCall& call) const;
|
||||
// Returns `true` if all sources should be updated, or `false` otherwise.
|
||||
bool eax_get(const EaxCall& call);
|
||||
|
||||
void eax_initialize_lock();
|
||||
void eax_fx_slot_load_effect(int version, ALenum altype);
|
||||
void eax_fx_slot_set_volume();
|
||||
void eax_fx_slot_set_environment_flag();
|
||||
void eax_fx_slot_set_flags();
|
||||
|
||||
void eax4_fx_slot_set_all(const EaxCall& call);
|
||||
void eax5_fx_slot_set_all(const EaxCall& call);
|
||||
|
||||
void eax_initialize_effects();
|
||||
bool eax_fx_slot_should_update_sources() const noexcept;
|
||||
|
||||
// Returns `true` if all sources should be updated, or `false` otherwise.
|
||||
bool eax4_fx_slot_set(const EaxCall& call);
|
||||
// Returns `true` if all sources should be updated, or `false` otherwise.
|
||||
bool eax5_fx_slot_set(const EaxCall& call);
|
||||
// Returns `true` if all sources should be updated, or `false` otherwise.
|
||||
bool eax_fx_slot_set(const EaxCall& call);
|
||||
// Returns `true` if all sources should be updated, or `false` otherwise.
|
||||
bool eax_set(const EaxCall& call);
|
||||
|
||||
void eax_get_fx_slot_all(
|
||||
const EaxEaxCall& eax_call) const;
|
||||
template<
|
||||
EaxDirtyFlags TDirtyBit,
|
||||
typename TMemberResult,
|
||||
typename TProps,
|
||||
typename TState>
|
||||
void eax_fx_slot_commit_property(TState& state, EaxDirtyFlags& dst_df,
|
||||
TMemberResult TProps::*member) noexcept
|
||||
{
|
||||
auto& src_i = state.i;
|
||||
auto& dst_i = eax_;
|
||||
|
||||
void eax_get_fx_slot(
|
||||
const EaxEaxCall& eax_call) const;
|
||||
|
||||
// [[nodiscard]]
|
||||
bool eax_get(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
|
||||
void eax_set_fx_slot_effect(
|
||||
ALenum effect_type);
|
||||
|
||||
void eax_set_fx_slot_effect();
|
||||
|
||||
|
||||
void eax_set_efx_effect_slot_gain();
|
||||
|
||||
void eax_set_fx_slot_volume();
|
||||
|
||||
|
||||
void eax_set_effect_slot_send_auto();
|
||||
|
||||
void eax_set_fx_slot_flags();
|
||||
|
||||
|
||||
void eax_ensure_is_unlocked() const;
|
||||
|
||||
|
||||
void eax_validate_fx_slot_effect(
|
||||
const GUID& eax_effect_id);
|
||||
|
||||
void eax_validate_fx_slot_volume(
|
||||
long eax_volume);
|
||||
|
||||
void eax_validate_fx_slot_lock(
|
||||
long eax_lock);
|
||||
|
||||
void eax_validate_fx_slot_flags(
|
||||
unsigned long eax_flags,
|
||||
int eax_version);
|
||||
|
||||
void eax_validate_fx_slot_occlusion(
|
||||
long eax_occlusion);
|
||||
|
||||
void eax_validate_fx_slot_occlusion_lf_ratio(
|
||||
float eax_occlusion_lf_ratio);
|
||||
|
||||
void eax_validate_fx_slot_all(
|
||||
const EAX40FXSLOTPROPERTIES& fx_slot,
|
||||
int eax_version);
|
||||
|
||||
void eax_validate_fx_slot_all(
|
||||
const EAX50FXSLOTPROPERTIES& fx_slot,
|
||||
int eax_version);
|
||||
|
||||
|
||||
void eax_set_fx_slot_effect(
|
||||
const GUID& eax_effect_id);
|
||||
|
||||
void eax_set_fx_slot_volume(
|
||||
long eax_volume);
|
||||
|
||||
void eax_set_fx_slot_lock(
|
||||
long eax_lock);
|
||||
|
||||
void eax_set_fx_slot_flags(
|
||||
unsigned long eax_flags);
|
||||
|
||||
// [[nodiscard]]
|
||||
bool eax_set_fx_slot_occlusion(
|
||||
long eax_occlusion);
|
||||
|
||||
// [[nodiscard]]
|
||||
bool eax_set_fx_slot_occlusion_lf_ratio(
|
||||
float eax_occlusion_lf_ratio);
|
||||
|
||||
void eax_set_fx_slot_all(
|
||||
const EAX40FXSLOTPROPERTIES& eax_fx_slot);
|
||||
|
||||
// [[nodiscard]]
|
||||
bool eax_set_fx_slot_all(
|
||||
const EAX50FXSLOTPROPERTIES& eax_fx_slot);
|
||||
|
||||
|
||||
void eax_set_fx_slot_effect(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_set_fx_slot_volume(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_set_fx_slot_lock(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_set_fx_slot_flags(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
// [[nodiscard]]
|
||||
bool eax_set_fx_slot_occlusion(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
// [[nodiscard]]
|
||||
bool eax_set_fx_slot_occlusion_lf_ratio(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
// [[nodiscard]]
|
||||
bool eax_set_fx_slot_all(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
bool eax_set_fx_slot(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void eax_apply_deferred();
|
||||
|
||||
// [[nodiscard]]
|
||||
bool eax_set(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
|
||||
void eax_dispatch_effect(
|
||||
const EaxEaxCall& eax_call);
|
||||
if((eax_df_ & TDirtyBit) != EaxDirtyFlags{})
|
||||
{
|
||||
dst_df |= TDirtyBit;
|
||||
dst_i.*member = src_i.*member;
|
||||
}
|
||||
}
|
||||
|
||||
void eax4_fx_slot_commit(EaxDirtyFlags& dst_df);
|
||||
void eax5_fx_slot_commit(Eax5State& state, EaxDirtyFlags& dst_df);
|
||||
|
||||
// `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)`
|
||||
void eax_set_effect_slot_effect(EaxEffect &effect);
|
||||
void eax_set_efx_slot_effect(EaxEffect &effect);
|
||||
|
||||
// `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, value)`
|
||||
void eax_set_effect_slot_send_auto(bool is_send_auto);
|
||||
void eax_set_efx_slot_send_auto(bool is_send_auto);
|
||||
|
||||
// `alAuxiliaryEffectSlotf(effect_slot, AL_EFFECTSLOT_GAIN, gain)`
|
||||
void eax_set_effect_slot_gain(ALfloat gain);
|
||||
void eax_set_efx_slot_gain(ALfloat gain);
|
||||
|
||||
public:
|
||||
class EaxDeleter {
|
||||
public:
|
||||
void operator()(ALeffectslot *effect_slot);
|
||||
}; // EaxAlEffectSlotDeleter
|
||||
};
|
||||
#endif // ALSOFT_EAX
|
||||
};
|
||||
|
||||
void UpdateAllEffectSlotProps(ALCcontext *context);
|
||||
|
||||
#ifdef ALSOFT_EAX
|
||||
|
||||
using EaxAlEffectSlotUPtr = std::unique_ptr<ALeffectslot, ALeffectslot::EaxDeleter>;
|
||||
|
||||
|
||||
EaxAlEffectSlotUPtr eax_create_al_effect_slot(
|
||||
ALCcontext& context);
|
||||
|
||||
void eax_delete_al_effect_slot(
|
||||
ALCcontext& context,
|
||||
ALeffectslot& effect_slot);
|
||||
EaxAlEffectSlotUPtr eax_create_al_effect_slot(ALCcontext& context);
|
||||
void eax_delete_al_effect_slot(ALCcontext& context, ALeffectslot& effect_slot);
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -13,45 +13,22 @@
|
|||
#include "vector.h"
|
||||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include "eax_x_ram.h"
|
||||
#include "eax/x_ram.h"
|
||||
|
||||
enum class EaxStorage : uint8_t {
|
||||
Automatic,
|
||||
Accessible,
|
||||
Hardware
|
||||
};
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
/* User formats */
|
||||
enum UserFmtType : unsigned char {
|
||||
UserFmtUByte = FmtUByte,
|
||||
UserFmtShort = FmtShort,
|
||||
UserFmtFloat = FmtFloat,
|
||||
UserFmtMulaw = FmtMulaw,
|
||||
UserFmtAlaw = FmtAlaw,
|
||||
UserFmtDouble = FmtDouble,
|
||||
|
||||
UserFmtIMA4 = 128,
|
||||
UserFmtMSADPCM,
|
||||
};
|
||||
enum UserFmtChannels : unsigned char {
|
||||
UserFmtMono = FmtMono,
|
||||
UserFmtStereo = FmtStereo,
|
||||
UserFmtRear = FmtRear,
|
||||
UserFmtQuad = FmtQuad,
|
||||
UserFmtX51 = FmtX51,
|
||||
UserFmtX61 = FmtX61,
|
||||
UserFmtX71 = FmtX71,
|
||||
UserFmtBFormat2D = FmtBFormat2D,
|
||||
UserFmtBFormat3D = FmtBFormat3D,
|
||||
UserFmtUHJ2 = FmtUHJ2,
|
||||
UserFmtUHJ3 = FmtUHJ3,
|
||||
UserFmtUHJ4 = FmtUHJ4,
|
||||
};
|
||||
|
||||
|
||||
struct ALbuffer : public BufferStorage {
|
||||
ALbitfieldSOFT Access{0u};
|
||||
|
||||
al::vector<al::byte,16> mData;
|
||||
al::vector<al::byte,16> mDataStorage;
|
||||
|
||||
UserFmtType OriginalType{UserFmtShort};
|
||||
ALuint OriginalSize{0};
|
||||
ALuint OriginalAlign{0};
|
||||
|
||||
ALuint UnpackAlign{0};
|
||||
ALuint PackAlign{0};
|
||||
|
|
@ -73,7 +50,7 @@ struct ALbuffer : public BufferStorage {
|
|||
DISABLE_ALLOC()
|
||||
|
||||
#ifdef ALSOFT_EAX
|
||||
ALenum eax_x_ram_mode{AL_STORAGE_AUTOMATIC};
|
||||
EaxStorage eax_x_ram_mode{EaxStorage::Automatic};
|
||||
bool eax_x_ram_is_hardware{};
|
||||
#endif // ALSOFT_EAX
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include "al/eax_api.h"
|
||||
#include "api.h"
|
||||
|
||||
|
||||
const GUID DSPROPSETID_EAX_ReverbProperties =
|
||||
|
|
@ -269,74 +269,15 @@ const GUID EAX_RINGMODULATOR_EFFECT =
|
|||
};
|
||||
|
||||
|
||||
bool operator==(
|
||||
const EAX40CONTEXTPROPERTIES& lhs,
|
||||
const EAX40CONTEXTPROPERTIES& rhs) noexcept
|
||||
{
|
||||
return
|
||||
lhs.guidPrimaryFXSlotID == rhs.guidPrimaryFXSlotID &&
|
||||
lhs.flDistanceFactor == rhs.flDistanceFactor &&
|
||||
lhs.flAirAbsorptionHF == rhs.flAirAbsorptionHF &&
|
||||
lhs.flHFReference == rhs.flHFReference;
|
||||
}
|
||||
const GUID EAX40CONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX40_FXSlot0;
|
||||
const GUID EAX50CONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX50_FXSlot0;
|
||||
|
||||
bool operator==(
|
||||
const EAX50CONTEXTPROPERTIES& lhs,
|
||||
const EAX50CONTEXTPROPERTIES& rhs) noexcept
|
||||
{
|
||||
return
|
||||
static_cast<const EAX40CONTEXTPROPERTIES&>(lhs) == static_cast<const EAX40CONTEXTPROPERTIES&>(rhs) &&
|
||||
lhs.flMacroFXFactor == rhs.flMacroFXFactor;
|
||||
}
|
||||
|
||||
|
||||
const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX40_FXSlot0;
|
||||
|
||||
bool operator==(
|
||||
const EAX40FXSLOTPROPERTIES& lhs,
|
||||
const EAX40FXSLOTPROPERTIES& rhs) noexcept
|
||||
{
|
||||
return
|
||||
lhs.guidLoadEffect == rhs.guidLoadEffect &&
|
||||
lhs.lVolume == rhs.lVolume &&
|
||||
lhs.lLock == rhs.lLock &&
|
||||
lhs.ulFlags == rhs.ulFlags;
|
||||
}
|
||||
|
||||
bool operator==(
|
||||
const EAX50FXSLOTPROPERTIES& lhs,
|
||||
const EAX50FXSLOTPROPERTIES& rhs) noexcept
|
||||
{
|
||||
return
|
||||
static_cast<const EAX40FXSLOTPROPERTIES&>(lhs) == static_cast<const EAX40FXSLOTPROPERTIES&>(rhs) &&
|
||||
lhs.lOcclusion == rhs.lOcclusion &&
|
||||
lhs.flOcclusionLFRatio == rhs.flOcclusionLFRatio;
|
||||
}
|
||||
|
||||
const EAX50ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS
|
||||
const EAX40ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID = EAX40ACTIVEFXSLOTS
|
||||
{{
|
||||
EAX_NULL_GUID,
|
||||
EAXPROPERTYID_EAX40_FXSlot0,
|
||||
}};
|
||||
|
||||
bool operator==(
|
||||
const EAX50ACTIVEFXSLOTS& lhs,
|
||||
const EAX50ACTIVEFXSLOTS& rhs) noexcept
|
||||
{
|
||||
return std::equal(
|
||||
std::cbegin(lhs.guidActiveFXSlots),
|
||||
std::cend(lhs.guidActiveFXSlots),
|
||||
std::begin(rhs.guidActiveFXSlots));
|
||||
}
|
||||
|
||||
bool operator!=(
|
||||
const EAX50ACTIVEFXSLOTS& lhs,
|
||||
const EAX50ACTIVEFXSLOTS& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
|
||||
const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOTS
|
||||
{{
|
||||
EAX_NULL_GUID,
|
||||
|
|
@ -354,44 +295,569 @@ const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID = EAX50ACTIVEFXSLOT
|
|||
EAX_NULL_GUID,
|
||||
}};
|
||||
|
||||
bool operator==(
|
||||
const EAXREVERBPROPERTIES& lhs,
|
||||
const EAXREVERBPROPERTIES& rhs) noexcept
|
||||
{
|
||||
return
|
||||
lhs.ulEnvironment == rhs.ulEnvironment &&
|
||||
lhs.flEnvironmentSize == rhs.flEnvironmentSize &&
|
||||
lhs.flEnvironmentDiffusion == rhs.flEnvironmentDiffusion &&
|
||||
lhs.lRoom == rhs.lRoom &&
|
||||
lhs.lRoomHF == rhs.lRoomHF &&
|
||||
lhs.lRoomLF == rhs.lRoomLF &&
|
||||
lhs.flDecayTime == rhs.flDecayTime &&
|
||||
lhs.flDecayHFRatio == rhs.flDecayHFRatio &&
|
||||
lhs.flDecayLFRatio == rhs.flDecayLFRatio &&
|
||||
lhs.lReflections == rhs.lReflections &&
|
||||
lhs.flReflectionsDelay == rhs.flReflectionsDelay &&
|
||||
lhs.vReflectionsPan == rhs.vReflectionsPan &&
|
||||
lhs.lReverb == rhs.lReverb &&
|
||||
lhs.flReverbDelay == rhs.flReverbDelay &&
|
||||
lhs.vReverbPan == rhs.vReverbPan &&
|
||||
lhs.flEchoTime == rhs.flEchoTime &&
|
||||
lhs.flEchoDepth == rhs.flEchoDepth &&
|
||||
lhs.flModulationTime == rhs.flModulationTime &&
|
||||
lhs.flModulationDepth == rhs.flModulationDepth &&
|
||||
lhs.flAirAbsorptionHF == rhs.flAirAbsorptionHF &&
|
||||
lhs.flHFReference == rhs.flHFReference &&
|
||||
lhs.flLFReference == rhs.flLFReference &&
|
||||
lhs.flRoomRolloffFactor == rhs.flRoomRolloffFactor &&
|
||||
lhs.ulFlags == rhs.ulFlags;
|
||||
}
|
||||
|
||||
bool operator!=(
|
||||
const EAXREVERBPROPERTIES& lhs,
|
||||
const EAXREVERBPROPERTIES& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
// EAX1 =====================================================================
|
||||
|
||||
namespace {
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_GENERIC = {EAX_ENVIRONMENT_GENERIC, 0.5F, 1.493F, 0.5F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PADDEDCELL = {EAX_ENVIRONMENT_PADDEDCELL, 0.25F, 0.1F, 0.0F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ROOM = {EAX_ENVIRONMENT_ROOM, 0.417F, 0.4F, 0.666F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_BATHROOM = {EAX_ENVIRONMENT_BATHROOM, 0.653F, 1.499F, 0.166F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_LIVINGROOM = {EAX_ENVIRONMENT_LIVINGROOM, 0.208F, 0.478F, 0.0F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONEROOM = {EAX_ENVIRONMENT_STONEROOM, 0.5F, 2.309F, 0.888F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_AUDITORIUM = {EAX_ENVIRONMENT_AUDITORIUM, 0.403F, 4.279F, 0.5F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CONCERTHALL = {EAX_ENVIRONMENT_CONCERTHALL, 0.5F, 3.961F, 0.5F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CAVE = {EAX_ENVIRONMENT_CAVE, 0.5F, 2.886F, 1.304F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ARENA = {EAX_ENVIRONMENT_ARENA, 0.361F, 7.284F, 0.332F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HANGAR = {EAX_ENVIRONMENT_HANGAR, 0.5F, 10.0F, 0.3F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CARPETTEDHALLWAY = {EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153F, 0.259F, 2.0F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HALLWAY = {EAX_ENVIRONMENT_HALLWAY, 0.361F, 1.493F, 0.0F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONECORRIDOR = {EAX_ENVIRONMENT_STONECORRIDOR, 0.444F, 2.697F, 0.638F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ALLEY = {EAX_ENVIRONMENT_ALLEY, 0.25F, 1.752F, 0.776F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_FOREST = {EAX_ENVIRONMENT_FOREST, 0.111F, 3.145F, 0.472F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CITY = {EAX_ENVIRONMENT_CITY, 0.111F, 2.767F, 0.224F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_MOUNTAINS = {EAX_ENVIRONMENT_MOUNTAINS, 0.194F, 7.841F, 0.472F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_QUARRY = {EAX_ENVIRONMENT_QUARRY, 1.0F, 1.499F, 0.5F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PLAIN = {EAX_ENVIRONMENT_PLAIN, 0.097F, 2.767F, 0.224F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PARKINGLOT = {EAX_ENVIRONMENT_PARKINGLOT, 0.208F, 1.652F, 1.5F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_SEWERPIPE = {EAX_ENVIRONMENT_SEWERPIPE, 0.652F, 2.886F, 0.25F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_UNDERWATER = {EAX_ENVIRONMENT_UNDERWATER, 1.0F, 1.499F, 0.0F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DRUGGED = {EAX_ENVIRONMENT_DRUGGED, 0.875F, 8.392F, 1.388F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DIZZY = {EAX_ENVIRONMENT_DIZZY, 0.139F, 17.234F, 0.666F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PSYCHOTIC = {EAX_ENVIRONMENT_PSYCHOTIC, 0.486F, 7.563F, 0.806F};
|
||||
} // namespace
|
||||
|
||||
const Eax1ReverbPresets EAX1REVERB_PRESETS{{
|
||||
EAX1REVERB_PRESET_GENERIC,
|
||||
EAX1REVERB_PRESET_PADDEDCELL,
|
||||
EAX1REVERB_PRESET_ROOM,
|
||||
EAX1REVERB_PRESET_BATHROOM,
|
||||
EAX1REVERB_PRESET_LIVINGROOM,
|
||||
EAX1REVERB_PRESET_STONEROOM,
|
||||
EAX1REVERB_PRESET_AUDITORIUM,
|
||||
EAX1REVERB_PRESET_CONCERTHALL,
|
||||
EAX1REVERB_PRESET_CAVE,
|
||||
EAX1REVERB_PRESET_ARENA,
|
||||
EAX1REVERB_PRESET_HANGAR,
|
||||
EAX1REVERB_PRESET_CARPETTEDHALLWAY,
|
||||
EAX1REVERB_PRESET_HALLWAY,
|
||||
EAX1REVERB_PRESET_STONECORRIDOR,
|
||||
EAX1REVERB_PRESET_ALLEY,
|
||||
EAX1REVERB_PRESET_FOREST,
|
||||
EAX1REVERB_PRESET_CITY,
|
||||
EAX1REVERB_PRESET_MOUNTAINS,
|
||||
EAX1REVERB_PRESET_QUARRY,
|
||||
EAX1REVERB_PRESET_PLAIN,
|
||||
EAX1REVERB_PRESET_PARKINGLOT,
|
||||
EAX1REVERB_PRESET_SEWERPIPE,
|
||||
EAX1REVERB_PRESET_UNDERWATER,
|
||||
EAX1REVERB_PRESET_DRUGGED,
|
||||
EAX1REVERB_PRESET_DIZZY,
|
||||
EAX1REVERB_PRESET_PSYCHOTIC,
|
||||
}};
|
||||
|
||||
// EAX2 =====================================================================
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_GENERIC{
|
||||
EAX2LISTENER_DEFAULTROOM,
|
||||
EAX2LISTENER_DEFAULTROOMHF,
|
||||
EAX2LISTENER_DEFAULTROOMROLLOFFFACTOR,
|
||||
EAX2LISTENER_DEFAULTDECAYTIME,
|
||||
EAX2LISTENER_DEFAULTDECAYHFRATIO,
|
||||
EAX2LISTENER_DEFAULTREFLECTIONS,
|
||||
EAX2LISTENER_DEFAULTREFLECTIONSDELAY,
|
||||
EAX2LISTENER_DEFAULTREVERB,
|
||||
EAX2LISTENER_DEFAULTREVERBDELAY,
|
||||
EAX2LISTENER_DEFAULTENVIRONMENT,
|
||||
EAX2LISTENER_DEFAULTENVIRONMENTSIZE,
|
||||
EAX2LISTENER_DEFAULTENVIRONMENTDIFFUSION,
|
||||
EAX2LISTENER_DEFAULTAIRABSORPTIONHF,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_PADDEDCELL{
|
||||
-1'000L,
|
||||
-6'000L,
|
||||
0.0F,
|
||||
0.17F,
|
||||
0.1F,
|
||||
-1'204L,
|
||||
0.001F,
|
||||
207L,
|
||||
0.002F,
|
||||
EAX2_ENVIRONMENT_PADDEDCELL,
|
||||
1.4F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_ROOM{
|
||||
-1'000L,
|
||||
-454L,
|
||||
0.0F,
|
||||
0.4F,
|
||||
0.83F,
|
||||
-1'646L,
|
||||
0.002F,
|
||||
53L,
|
||||
0.003F,
|
||||
EAX2_ENVIRONMENT_ROOM,
|
||||
1.9F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_BATHROOM{
|
||||
-1'000L,
|
||||
-1'200L,
|
||||
0.0F,
|
||||
1.49F,
|
||||
0.54F,
|
||||
-370L,
|
||||
0.007F,
|
||||
1'030L,
|
||||
0.011F,
|
||||
EAX2_ENVIRONMENT_BATHROOM,
|
||||
1.4F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_LIVINGROOM{
|
||||
-1'000L,
|
||||
-6'000L,
|
||||
0.0F,
|
||||
0.5F,
|
||||
0.1F,
|
||||
-1'376L,
|
||||
0.003F,
|
||||
-1'104L,
|
||||
0.004F,
|
||||
EAX2_ENVIRONMENT_LIVINGROOM,
|
||||
2.5F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_STONEROOM{
|
||||
-1'000L,
|
||||
-300L,
|
||||
0.0F,
|
||||
2.31F,
|
||||
0.64F,
|
||||
-711L,
|
||||
0.012F,
|
||||
83L,
|
||||
0.017F,
|
||||
EAX2_ENVIRONMENT_STONEROOM,
|
||||
11.6F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_AUDITORIUM{
|
||||
-1'000L,
|
||||
-476L,
|
||||
0.0F,
|
||||
4.32F,
|
||||
0.59F,
|
||||
-789L,
|
||||
0.02F,
|
||||
-289L,
|
||||
0.03F,
|
||||
EAX2_ENVIRONMENT_AUDITORIUM,
|
||||
21.6F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_CONCERTHALL{
|
||||
-1'000L,
|
||||
-500L,
|
||||
0.0F,
|
||||
3.92F,
|
||||
0.7F,
|
||||
-1'230L,
|
||||
0.02F,
|
||||
-2L,
|
||||
0.029F,
|
||||
EAX2_ENVIRONMENT_CONCERTHALL,
|
||||
19.6F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_CAVE{
|
||||
-1'000L,
|
||||
0L,
|
||||
0.0F,
|
||||
2.91F,
|
||||
1.3F,
|
||||
-602L,
|
||||
0.015F,
|
||||
-302L,
|
||||
0.022F,
|
||||
EAX2_ENVIRONMENT_CAVE,
|
||||
14.6F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENERFLAGS_DECAYTIMESCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSSCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBDELAYSCALE,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_ARENA{
|
||||
-1'000L,
|
||||
-698L,
|
||||
0.0F,
|
||||
7.24F,
|
||||
0.33F,
|
||||
-1'166L,
|
||||
0.02F,
|
||||
16L,
|
||||
0.03F,
|
||||
EAX2_ENVIRONMENT_ARENA,
|
||||
36.2F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_HANGAR{
|
||||
-1'000L,
|
||||
-1'000L,
|
||||
0.0F,
|
||||
10.05F,
|
||||
0.23F,
|
||||
-602L,
|
||||
0.02F,
|
||||
198L,
|
||||
0.03F,
|
||||
EAX2_ENVIRONMENT_HANGAR,
|
||||
50.3F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_CARPETTEDHALLWAY{
|
||||
-1'000L,
|
||||
-4'000L,
|
||||
0.0F,
|
||||
0.3F,
|
||||
0.1F,
|
||||
-1'831L,
|
||||
0.002F,
|
||||
-1'630L,
|
||||
0.03F,
|
||||
EAX2_ENVIRONMENT_CARPETEDHALLWAY,
|
||||
1.9F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_HALLWAY{
|
||||
-1'000L,
|
||||
-300L,
|
||||
0.0F,
|
||||
1.49F,
|
||||
0.59F,
|
||||
-1'219L,
|
||||
0.007F,
|
||||
441L,
|
||||
0.011F,
|
||||
EAX2_ENVIRONMENT_HALLWAY,
|
||||
1.8F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_STONECORRIDOR{
|
||||
-1'000L,
|
||||
-237L,
|
||||
0.0F,
|
||||
2.7F,
|
||||
0.79F,
|
||||
-1'214L,
|
||||
0.013F,
|
||||
395L,
|
||||
0.02F,
|
||||
EAX2_ENVIRONMENT_STONECORRIDOR,
|
||||
13.5F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_ALLEY{
|
||||
-1'000L,
|
||||
-270L,
|
||||
0.0F,
|
||||
1.49F,
|
||||
0.86F,
|
||||
-1'204L,
|
||||
0.007F,
|
||||
-4L,
|
||||
0.011F,
|
||||
EAX2_ENVIRONMENT_ALLEY,
|
||||
7.5F,
|
||||
0.3F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_FOREST{
|
||||
-1'000L,
|
||||
-3'300L,
|
||||
0.0F,
|
||||
1.49F,
|
||||
0.54F,
|
||||
-2'560L,
|
||||
0.162F,
|
||||
-229L,
|
||||
0.088F,
|
||||
EAX2_ENVIRONMENT_FOREST,
|
||||
38.0F,
|
||||
0.3F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_CITY{
|
||||
-1'000L,
|
||||
-800L,
|
||||
0.0F,
|
||||
1.49F,
|
||||
0.67F,
|
||||
-2'273L,
|
||||
0.007F,
|
||||
-1'691L,
|
||||
0.011F,
|
||||
EAX2_ENVIRONMENT_CITY,
|
||||
7.5F,
|
||||
0.5F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_MOUNTAINS{
|
||||
-1'000L,
|
||||
-2'500L,
|
||||
0.0F,
|
||||
1.49F,
|
||||
0.21F,
|
||||
-2'780L,
|
||||
0.3F,
|
||||
-1'434L,
|
||||
0.1F,
|
||||
EAX2_ENVIRONMENT_MOUNTAINS,
|
||||
100.0F,
|
||||
0.27F,
|
||||
-5.0F,
|
||||
EAX2LISTENERFLAGS_DECAYTIMESCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSSCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBDELAYSCALE,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_QUARRY{
|
||||
-1'000L,
|
||||
-1'000L,
|
||||
0.0F,
|
||||
1.49F,
|
||||
0.83F,
|
||||
-10'000L,
|
||||
0.061F,
|
||||
500L,
|
||||
0.025F,
|
||||
EAX2_ENVIRONMENT_QUARRY,
|
||||
17.5F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_PLAIN{
|
||||
-1'000L,
|
||||
-2'000L,
|
||||
0.0F,
|
||||
1.49F,
|
||||
0.5F,
|
||||
-2'466L,
|
||||
0.179F,
|
||||
-1'926L,
|
||||
0.1F,
|
||||
EAX2_ENVIRONMENT_PLAIN,
|
||||
42.5F,
|
||||
0.21F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_PARKINGLOT{
|
||||
-1'000L,
|
||||
0L,
|
||||
0.0F,
|
||||
1.65F,
|
||||
1.5F,
|
||||
-1'363L,
|
||||
0.008F,
|
||||
-1'153L,
|
||||
0.012F,
|
||||
EAX2_ENVIRONMENT_PARKINGLOT,
|
||||
8.3F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENERFLAGS_DECAYTIMESCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSSCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBDELAYSCALE,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_SEWERPIPE{
|
||||
-1'000L,
|
||||
-1'000L,
|
||||
0.0F,
|
||||
2.81F,
|
||||
0.14F,
|
||||
429L,
|
||||
0.014F,
|
||||
1'023L,
|
||||
0.021F,
|
||||
EAX2_ENVIRONMENT_SEWERPIPE,
|
||||
1.7F,
|
||||
0.8F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_UNDERWATER{
|
||||
-1'000L,
|
||||
-4'000L,
|
||||
0.0F,
|
||||
1.49F,
|
||||
0.1F,
|
||||
-449L,
|
||||
0.007F,
|
||||
1'700L,
|
||||
0.011F,
|
||||
EAX2_ENVIRONMENT_UNDERWATER,
|
||||
1.8F,
|
||||
1.0F,
|
||||
-5.0F,
|
||||
EAX2LISTENER_DEFAULTFLAGS,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_DRUGGED{
|
||||
-1'000L,
|
||||
0L,
|
||||
0.0F,
|
||||
8.39F,
|
||||
1.39F,
|
||||
-115L,
|
||||
0.002F,
|
||||
985L,
|
||||
0.03F,
|
||||
EAX2_ENVIRONMENT_DRUGGED,
|
||||
1.9F,
|
||||
0.5F,
|
||||
-5.0F,
|
||||
EAX2LISTENERFLAGS_DECAYTIMESCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSSCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBDELAYSCALE,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_DIZZY{
|
||||
-1'000L,
|
||||
-400L,
|
||||
0.0F,
|
||||
17.23F,
|
||||
0.56F,
|
||||
-1'713L,
|
||||
0.02F,
|
||||
-613L,
|
||||
0.03F,
|
||||
EAX2_ENVIRONMENT_DIZZY,
|
||||
1.8F,
|
||||
0.6F,
|
||||
-5.0F,
|
||||
EAX2LISTENERFLAGS_DECAYTIMESCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSSCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBDELAYSCALE,
|
||||
};
|
||||
|
||||
constexpr EAX20LISTENERPROPERTIES EAX2REVERB_PRESET_PSYCHOTIC{
|
||||
-1'000L,
|
||||
-151L,
|
||||
0.0F,
|
||||
7.56F,
|
||||
0.91F,
|
||||
-626L,
|
||||
0.02F,
|
||||
774L,
|
||||
0.03F,
|
||||
EAX2_ENVIRONMENT_PSYCHOTIC,
|
||||
1.0F,
|
||||
0.5F,
|
||||
-5.0F,
|
||||
EAX2LISTENERFLAGS_DECAYTIMESCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSSCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBDELAYSCALE,
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
const Eax2ReverbPresets EAX2REVERB_PRESETS{
|
||||
EAX2REVERB_PRESET_GENERIC,
|
||||
EAX2REVERB_PRESET_PADDEDCELL,
|
||||
EAX2REVERB_PRESET_ROOM,
|
||||
EAX2REVERB_PRESET_BATHROOM,
|
||||
EAX2REVERB_PRESET_LIVINGROOM,
|
||||
EAX2REVERB_PRESET_STONEROOM,
|
||||
EAX2REVERB_PRESET_AUDITORIUM,
|
||||
EAX2REVERB_PRESET_CONCERTHALL,
|
||||
EAX2REVERB_PRESET_CAVE,
|
||||
EAX2REVERB_PRESET_ARENA,
|
||||
EAX2REVERB_PRESET_HANGAR,
|
||||
EAX2REVERB_PRESET_CARPETTEDHALLWAY,
|
||||
EAX2REVERB_PRESET_HALLWAY,
|
||||
EAX2REVERB_PRESET_STONECORRIDOR,
|
||||
EAX2REVERB_PRESET_ALLEY,
|
||||
EAX2REVERB_PRESET_FOREST,
|
||||
EAX2REVERB_PRESET_CITY,
|
||||
EAX2REVERB_PRESET_MOUNTAINS,
|
||||
EAX2REVERB_PRESET_QUARRY,
|
||||
EAX2REVERB_PRESET_PLAIN,
|
||||
EAX2REVERB_PRESET_PARKINGLOT,
|
||||
EAX2REVERB_PRESET_SEWERPIPE,
|
||||
EAX2REVERB_PRESET_UNDERWATER,
|
||||
EAX2REVERB_PRESET_DRUGGED,
|
||||
EAX2REVERB_PRESET_DIZZY,
|
||||
EAX2REVERB_PRESET_PSYCHOTIC,
|
||||
};
|
||||
|
||||
// EAX3+ ====================================================================
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
@ -1153,61 +1619,3 @@ const EaxReverbPresets EAXREVERB_PRESETS{{
|
|||
EAXREVERB_PRESET_DIZZY,
|
||||
EAXREVERB_PRESET_PSYCHOTIC,
|
||||
}};
|
||||
|
||||
namespace {
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_GENERIC = {EAX_ENVIRONMENT_GENERIC, 0.5F, 1.493F, 0.5F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PADDEDCELL = {EAX_ENVIRONMENT_PADDEDCELL, 0.25F, 0.1F, 0.0F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ROOM = {EAX_ENVIRONMENT_ROOM, 0.417F, 0.4F, 0.666F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_BATHROOM = {EAX_ENVIRONMENT_BATHROOM, 0.653F, 1.499F, 0.166F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_LIVINGROOM = {EAX_ENVIRONMENT_LIVINGROOM, 0.208F, 0.478F, 0.0F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONEROOM = {EAX_ENVIRONMENT_STONEROOM, 0.5F, 2.309F, 0.888F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_AUDITORIUM = {EAX_ENVIRONMENT_AUDITORIUM, 0.403F, 4.279F, 0.5F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CONCERTHALL = {EAX_ENVIRONMENT_CONCERTHALL, 0.5F, 3.961F, 0.5F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CAVE = {EAX_ENVIRONMENT_CAVE, 0.5F, 2.886F, 1.304F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ARENA = {EAX_ENVIRONMENT_ARENA, 0.361F, 7.284F, 0.332F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HANGAR = {EAX_ENVIRONMENT_HANGAR, 0.5F, 10.0F, 0.3F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CARPETTEDHALLWAY = {EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153F, 0.259F, 2.0F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_HALLWAY = {EAX_ENVIRONMENT_HALLWAY, 0.361F, 1.493F, 0.0F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_STONECORRIDOR = {EAX_ENVIRONMENT_STONECORRIDOR, 0.444F, 2.697F, 0.638F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_ALLEY = {EAX_ENVIRONMENT_ALLEY, 0.25F, 1.752F, 0.776F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_FOREST = {EAX_ENVIRONMENT_FOREST, 0.111F, 3.145F, 0.472F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_CITY = {EAX_ENVIRONMENT_CITY, 0.111F, 2.767F, 0.224F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_MOUNTAINS = {EAX_ENVIRONMENT_MOUNTAINS, 0.194F, 7.841F, 0.472F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_QUARRY = {EAX_ENVIRONMENT_QUARRY, 1.0F, 1.499F, 0.5F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PLAIN = {EAX_ENVIRONMENT_PLAIN, 0.097F, 2.767F, 0.224F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PARKINGLOT = {EAX_ENVIRONMENT_PARKINGLOT, 0.208F, 1.652F, 1.5F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_SEWERPIPE = {EAX_ENVIRONMENT_SEWERPIPE, 0.652F, 2.886F, 0.25F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_UNDERWATER = {EAX_ENVIRONMENT_UNDERWATER, 1.0F, 1.499F, 0.0F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DRUGGED = {EAX_ENVIRONMENT_DRUGGED, 0.875F, 8.392F, 1.388F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_DIZZY = {EAX_ENVIRONMENT_DIZZY, 0.139F, 17.234F, 0.666F};
|
||||
constexpr EAX_REVERBPROPERTIES EAX1REVERB_PRESET_PSYCHOTIC = {EAX_ENVIRONMENT_PSYCHOTIC, 0.486F, 7.563F, 0.806F};
|
||||
} // namespace
|
||||
|
||||
const Eax1ReverbPresets EAX1REVERB_PRESETS{{
|
||||
EAX1REVERB_PRESET_GENERIC,
|
||||
EAX1REVERB_PRESET_PADDEDCELL,
|
||||
EAX1REVERB_PRESET_ROOM,
|
||||
EAX1REVERB_PRESET_BATHROOM,
|
||||
EAX1REVERB_PRESET_LIVINGROOM,
|
||||
EAX1REVERB_PRESET_STONEROOM,
|
||||
EAX1REVERB_PRESET_AUDITORIUM,
|
||||
EAX1REVERB_PRESET_CONCERTHALL,
|
||||
EAX1REVERB_PRESET_CAVE,
|
||||
EAX1REVERB_PRESET_ARENA,
|
||||
EAX1REVERB_PRESET_HANGAR,
|
||||
EAX1REVERB_PRESET_CARPETTEDHALLWAY,
|
||||
EAX1REVERB_PRESET_HALLWAY,
|
||||
EAX1REVERB_PRESET_STONECORRIDOR,
|
||||
EAX1REVERB_PRESET_ALLEY,
|
||||
EAX1REVERB_PRESET_FOREST,
|
||||
EAX1REVERB_PRESET_CITY,
|
||||
EAX1REVERB_PRESET_MOUNTAINS,
|
||||
EAX1REVERB_PRESET_QUARRY,
|
||||
EAX1REVERB_PRESET_PLAIN,
|
||||
EAX1REVERB_PRESET_PARKINGLOT,
|
||||
EAX1REVERB_PRESET_SEWERPIPE,
|
||||
EAX1REVERB_PRESET_UNDERWATER,
|
||||
EAX1REVERB_PRESET_DRUGGED,
|
||||
EAX1REVERB_PRESET_DIZZY,
|
||||
EAX1REVERB_PRESET_PSYCHOTIC,
|
||||
}};
|
||||
|
|
@ -21,30 +21,27 @@
|
|||
|
||||
#ifndef GUID_DEFINED
|
||||
#define GUID_DEFINED
|
||||
typedef struct _GUID
|
||||
{
|
||||
typedef struct _GUID {
|
||||
std::uint32_t Data1;
|
||||
std::uint16_t Data2;
|
||||
std::uint16_t Data3;
|
||||
std::uint8_t Data4[8];
|
||||
} GUID;
|
||||
|
||||
#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;
|
||||
}
|
||||
{ return std::memcmp(&lhs, &rhs, sizeof(GUID)) == 0; }
|
||||
|
||||
inline bool operator!=(const GUID& lhs, const GUID& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
{ return !(lhs == rhs); }
|
||||
#endif // _SYS_GUID_OPERATOR_EQ_
|
||||
#endif // GUID_DEFINED
|
||||
|
||||
|
||||
extern const GUID DSPROPSETID_EAX_ReverbProperties;
|
||||
|
||||
enum DSPROPERTY_EAX_REVERBPROPERTY : unsigned int
|
||||
{
|
||||
enum DSPROPERTY_EAX_REVERBPROPERTY : unsigned int {
|
||||
DSPROPERTY_EAX_ALL,
|
||||
DSPROPERTY_EAX_ENVIRONMENT,
|
||||
DSPROPERTY_EAX_VOLUME,
|
||||
|
|
@ -52,37 +49,25 @@ enum DSPROPERTY_EAX_REVERBPROPERTY : unsigned int
|
|||
DSPROPERTY_EAX_DAMPING,
|
||||
}; // DSPROPERTY_EAX_REVERBPROPERTY
|
||||
|
||||
struct EAX_REVERBPROPERTIES
|
||||
{
|
||||
struct EAX_REVERBPROPERTIES {
|
||||
unsigned long environment;
|
||||
float fVolume;
|
||||
float fDecayTime_sec;
|
||||
float fDamping;
|
||||
}; // EAX_REVERBPROPERTIES
|
||||
|
||||
inline bool operator==(const EAX_REVERBPROPERTIES& lhs, const EAX_REVERBPROPERTIES& rhs) noexcept
|
||||
{
|
||||
return std::memcmp(&lhs, &rhs, sizeof(EAX_REVERBPROPERTIES)) == 0;
|
||||
}
|
||||
|
||||
extern const GUID DSPROPSETID_EAXBUFFER_ReverbProperties;
|
||||
|
||||
enum DSPROPERTY_EAXBUFFER_REVERBPROPERTY : unsigned int
|
||||
{
|
||||
enum DSPROPERTY_EAXBUFFER_REVERBPROPERTY : unsigned int {
|
||||
DSPROPERTY_EAXBUFFER_ALL,
|
||||
DSPROPERTY_EAXBUFFER_REVERBMIX,
|
||||
}; // DSPROPERTY_EAXBUFFER_REVERBPROPERTY
|
||||
|
||||
struct EAXBUFFER_REVERBPROPERTIES
|
||||
{
|
||||
struct EAXBUFFER_REVERBPROPERTIES {
|
||||
float fMix;
|
||||
};
|
||||
|
||||
inline bool operator==(const EAXBUFFER_REVERBPROPERTIES& lhs, const EAXBUFFER_REVERBPROPERTIES& rhs) noexcept
|
||||
{
|
||||
return lhs.fMix == rhs.fMix;
|
||||
}
|
||||
|
||||
constexpr auto EAX_BUFFER_MINREVERBMIX = 0.0F;
|
||||
constexpr auto EAX_BUFFER_MAXREVERBMIX = 1.0F;
|
||||
constexpr auto EAX_REVERBMIX_USEDISTANCE = -1.0F;
|
||||
|
|
@ -90,9 +75,7 @@ constexpr auto EAX_REVERBMIX_USEDISTANCE = -1.0F;
|
|||
|
||||
extern const GUID DSPROPSETID_EAX20_ListenerProperties;
|
||||
|
||||
enum DSPROPERTY_EAX20_LISTENERPROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum DSPROPERTY_EAX20_LISTENERPROPERTY : unsigned int {
|
||||
DSPROPERTY_EAX20LISTENER_NONE,
|
||||
DSPROPERTY_EAX20LISTENER_ALLPARAMETERS,
|
||||
DSPROPERTY_EAX20LISTENER_ROOM,
|
||||
|
|
@ -111,8 +94,7 @@ enum DSPROPERTY_EAX20_LISTENERPROPERTY :
|
|||
DSPROPERTY_EAX20LISTENER_FLAGS
|
||||
}; // DSPROPERTY_EAX20_LISTENERPROPERTY
|
||||
|
||||
struct EAX20LISTENERPROPERTIES
|
||||
{
|
||||
struct EAX20LISTENERPROPERTIES {
|
||||
long lRoom; // room effect level at low frequencies
|
||||
long lRoomHF; // room effect high-frequency level re. low frequency level
|
||||
float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect
|
||||
|
|
@ -129,13 +111,109 @@ struct EAX20LISTENERPROPERTIES
|
|||
unsigned long dwFlags; // modifies the behavior of properties
|
||||
}; // EAX20LISTENERPROPERTIES
|
||||
|
||||
enum : unsigned long {
|
||||
EAX2_ENVIRONMENT_GENERIC,
|
||||
EAX2_ENVIRONMENT_PADDEDCELL,
|
||||
EAX2_ENVIRONMENT_ROOM,
|
||||
EAX2_ENVIRONMENT_BATHROOM,
|
||||
EAX2_ENVIRONMENT_LIVINGROOM,
|
||||
EAX2_ENVIRONMENT_STONEROOM,
|
||||
EAX2_ENVIRONMENT_AUDITORIUM,
|
||||
EAX2_ENVIRONMENT_CONCERTHALL,
|
||||
EAX2_ENVIRONMENT_CAVE,
|
||||
EAX2_ENVIRONMENT_ARENA,
|
||||
EAX2_ENVIRONMENT_HANGAR,
|
||||
EAX2_ENVIRONMENT_CARPETEDHALLWAY,
|
||||
EAX2_ENVIRONMENT_HALLWAY,
|
||||
EAX2_ENVIRONMENT_STONECORRIDOR,
|
||||
EAX2_ENVIRONMENT_ALLEY,
|
||||
EAX2_ENVIRONMENT_FOREST,
|
||||
EAX2_ENVIRONMENT_CITY,
|
||||
EAX2_ENVIRONMENT_MOUNTAINS,
|
||||
EAX2_ENVIRONMENT_QUARRY,
|
||||
EAX2_ENVIRONMENT_PLAIN,
|
||||
EAX2_ENVIRONMENT_PARKINGLOT,
|
||||
EAX2_ENVIRONMENT_SEWERPIPE,
|
||||
EAX2_ENVIRONMENT_UNDERWATER,
|
||||
EAX2_ENVIRONMENT_DRUGGED,
|
||||
EAX2_ENVIRONMENT_DIZZY,
|
||||
EAX2_ENVIRONMENT_PSYCHOTIC,
|
||||
|
||||
EAX2_ENVIRONMENT_COUNT,
|
||||
};
|
||||
|
||||
constexpr auto EAX2LISTENERFLAGS_DECAYTIMESCALE = 0x00000001UL;
|
||||
constexpr auto EAX2LISTENERFLAGS_REFLECTIONSSCALE = 0x00000002UL;
|
||||
constexpr auto EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE = 0x00000004UL;
|
||||
constexpr auto EAX2LISTENERFLAGS_REVERBSCALE = 0x00000008UL;
|
||||
constexpr auto EAX2LISTENERFLAGS_REVERBDELAYSCALE = 0x00000010UL;
|
||||
constexpr auto EAX2LISTENERFLAGS_DECAYHFLIMIT = 0x00000020UL;
|
||||
constexpr auto EAX2LISTENERFLAGS_RESERVED = 0xFFFFFFC0UL;
|
||||
|
||||
constexpr auto EAX2LISTENER_MINROOM = -10'000L;
|
||||
constexpr auto EAX2LISTENER_MAXROOM = 0L;
|
||||
constexpr auto EAX2LISTENER_DEFAULTROOM = -1'000L;
|
||||
|
||||
constexpr auto EAX2LISTENER_MINROOMHF = -10'000L;
|
||||
constexpr auto EAX2LISTENER_MAXROOMHF = 0L;
|
||||
constexpr auto EAX2LISTENER_DEFAULTROOMHF = -100L;
|
||||
|
||||
constexpr auto EAX2LISTENER_MINROOMROLLOFFFACTOR = 0.0F;
|
||||
constexpr auto EAX2LISTENER_MAXROOMROLLOFFFACTOR = 10.0F;
|
||||
constexpr auto EAX2LISTENER_DEFAULTROOMROLLOFFFACTOR = 0.0F;
|
||||
|
||||
constexpr auto EAX2LISTENER_MINDECAYTIME = 0.1F;
|
||||
constexpr auto EAX2LISTENER_MAXDECAYTIME = 20.0F;
|
||||
constexpr auto EAX2LISTENER_DEFAULTDECAYTIME = 1.49F;
|
||||
|
||||
constexpr auto EAX2LISTENER_MINDECAYHFRATIO = 0.1F;
|
||||
constexpr auto EAX2LISTENER_MAXDECAYHFRATIO = 2.0F;
|
||||
constexpr auto EAX2LISTENER_DEFAULTDECAYHFRATIO = 0.83F;
|
||||
|
||||
constexpr auto EAX2LISTENER_MINREFLECTIONS = -10'000L;
|
||||
constexpr auto EAX2LISTENER_MAXREFLECTIONS = 1'000L;
|
||||
constexpr auto EAX2LISTENER_DEFAULTREFLECTIONS = -2'602L;
|
||||
|
||||
constexpr auto EAX2LISTENER_MINREFLECTIONSDELAY = 0.0F;
|
||||
constexpr auto EAX2LISTENER_MAXREFLECTIONSDELAY = 0.3F;
|
||||
constexpr auto EAX2LISTENER_DEFAULTREFLECTIONSDELAY = 0.007F;
|
||||
|
||||
constexpr auto EAX2LISTENER_MINREVERB = -10'000L;
|
||||
constexpr auto EAX2LISTENER_MAXREVERB = 2'000L;
|
||||
constexpr auto EAX2LISTENER_DEFAULTREVERB = 200L;
|
||||
|
||||
constexpr auto EAX2LISTENER_MINREVERBDELAY = 0.0F;
|
||||
constexpr auto EAX2LISTENER_MAXREVERBDELAY = 0.1F;
|
||||
constexpr auto EAX2LISTENER_DEFAULTREVERBDELAY = 0.011F;
|
||||
|
||||
constexpr auto EAX2LISTENER_MINENVIRONMENT = 0UL;
|
||||
constexpr auto EAX2LISTENER_MAXENVIRONMENT = EAX2_ENVIRONMENT_COUNT - 1;
|
||||
constexpr auto EAX2LISTENER_DEFAULTENVIRONMENT = EAX2_ENVIRONMENT_GENERIC;
|
||||
|
||||
constexpr auto EAX2LISTENER_MINENVIRONMENTSIZE = 1.0F;
|
||||
constexpr auto EAX2LISTENER_MAXENVIRONMENTSIZE = 100.0F;
|
||||
constexpr auto EAX2LISTENER_DEFAULTENVIRONMENTSIZE = 7.5F;
|
||||
|
||||
constexpr auto EAX2LISTENER_MINENVIRONMENTDIFFUSION = 0.0F;
|
||||
constexpr auto EAX2LISTENER_MAXENVIRONMENTDIFFUSION = 1.0F;
|
||||
constexpr auto EAX2LISTENER_DEFAULTENVIRONMENTDIFFUSION = 1.0F;
|
||||
|
||||
constexpr auto EAX2LISTENER_MINAIRABSORPTIONHF = -100.0F;
|
||||
constexpr auto EAX2LISTENER_MAXAIRABSORPTIONHF = 0.0F;
|
||||
constexpr auto EAX2LISTENER_DEFAULTAIRABSORPTIONHF = -5.0F;
|
||||
|
||||
constexpr auto EAX2LISTENER_DEFAULTFLAGS =
|
||||
EAX2LISTENERFLAGS_DECAYTIMESCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSSCALE |
|
||||
EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBSCALE |
|
||||
EAX2LISTENERFLAGS_REVERBDELAYSCALE |
|
||||
EAX2LISTENERFLAGS_DECAYHFLIMIT;
|
||||
|
||||
|
||||
extern const GUID DSPROPSETID_EAX20_BufferProperties;
|
||||
|
||||
|
||||
enum DSPROPERTY_EAX20_BUFFERPROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum DSPROPERTY_EAX20_BUFFERPROPERTY : unsigned int {
|
||||
DSPROPERTY_EAX20BUFFER_NONE,
|
||||
DSPROPERTY_EAX20BUFFER_ALLPARAMETERS,
|
||||
DSPROPERTY_EAX20BUFFER_DIRECT,
|
||||
|
|
@ -153,9 +231,7 @@ enum DSPROPERTY_EAX20_BUFFERPROPERTY :
|
|||
DSPROPERTY_EAX20BUFFER_FLAGS
|
||||
}; // DSPROPERTY_EAX20_BUFFERPROPERTY
|
||||
|
||||
|
||||
struct EAX20BUFFERPROPERTIES
|
||||
{
|
||||
struct EAX20BUFFERPROPERTIES {
|
||||
long lDirect; // direct path level
|
||||
long lDirectHF; // direct path level at high frequencies
|
||||
long lRoom; // room effect level
|
||||
|
|
@ -171,7 +247,6 @@ struct EAX20BUFFERPROPERTIES
|
|||
unsigned long dwFlags; // modifies the behavior of properties
|
||||
}; // EAX20BUFFERPROPERTIES
|
||||
|
||||
|
||||
extern const GUID DSPROPSETID_EAX30_ListenerProperties;
|
||||
|
||||
extern const GUID DSPROPSETID_EAX30_BufferProperties;
|
||||
|
|
@ -197,8 +272,7 @@ extern const GUID EAX_NULL_GUID;
|
|||
extern const GUID EAX_PrimaryFXSlotID;
|
||||
|
||||
|
||||
struct EAXVECTOR
|
||||
{
|
||||
struct EAXVECTOR {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
|
|
@ -216,24 +290,19 @@ extern const GUID EAXPROPERTYID_EAX40_Context;
|
|||
extern const GUID EAXPROPERTYID_EAX50_Context;
|
||||
|
||||
// EAX50
|
||||
enum :
|
||||
unsigned long
|
||||
{
|
||||
HEADPHONES = 0,
|
||||
SPEAKERS_2,
|
||||
SPEAKERS_4,
|
||||
SPEAKERS_5, // 5.1 speakers
|
||||
SPEAKERS_6, // 6.1 speakers
|
||||
SPEAKERS_7, // 7.1 speakers
|
||||
};
|
||||
constexpr auto HEADPHONES = 0UL;
|
||||
constexpr auto SPEAKERS_2 = 1UL;
|
||||
constexpr auto SPEAKERS_4 = 2UL;
|
||||
constexpr auto SPEAKERS_5 = 3UL; // 5.1 speakers
|
||||
constexpr auto SPEAKERS_6 = 4UL; // 6.1 speakers
|
||||
constexpr auto SPEAKERS_7 = 5UL; // 7.1 speakers
|
||||
|
||||
constexpr auto EAXCONTEXT_MINSPEAKERCONFIG = HEADPHONES;
|
||||
constexpr auto EAXCONTEXT_MAXSPEAKERCONFIG = SPEAKERS_7;
|
||||
|
||||
// EAX50
|
||||
enum :
|
||||
unsigned long
|
||||
{
|
||||
EAX_40 = 5, // EAX 4.0
|
||||
EAX_50 = 6, // EAX 5.0
|
||||
};
|
||||
constexpr auto EAX_40 = 5UL; // EAX 4.0
|
||||
constexpr auto EAX_50 = 6UL; // EAX 5.0
|
||||
|
||||
constexpr auto EAXCONTEXT_MINEAXSESSION = EAX_40;
|
||||
constexpr auto EAXCONTEXT_MAXEAXSESSION = EAX_50;
|
||||
|
|
@ -244,15 +313,12 @@ constexpr auto EAXCONTEXT_MAXMAXACTIVESENDS = 4UL;
|
|||
constexpr auto EAXCONTEXT_DEFAULTMAXACTIVESENDS = 2UL;
|
||||
|
||||
// EAX50
|
||||
struct EAXSESSIONPROPERTIES
|
||||
{
|
||||
struct EAXSESSIONPROPERTIES {
|
||||
unsigned long ulEAXVersion;
|
||||
unsigned long ulMaxActiveSends;
|
||||
}; // EAXSESSIONPROPERTIES
|
||||
|
||||
enum EAXCONTEXT_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXCONTEXT_PROPERTY : unsigned int {
|
||||
EAXCONTEXT_NONE = 0,
|
||||
EAXCONTEXT_ALLPARAMETERS,
|
||||
EAXCONTEXT_PRIMARYFXSLOTID,
|
||||
|
|
@ -267,28 +333,16 @@ enum EAXCONTEXT_PROPERTY :
|
|||
EAXCONTEXT_MACROFXFACTOR,
|
||||
}; // EAXCONTEXT_PROPERTY
|
||||
|
||||
struct EAX40CONTEXTPROPERTIES
|
||||
{
|
||||
struct EAX40CONTEXTPROPERTIES {
|
||||
GUID guidPrimaryFXSlotID;
|
||||
float flDistanceFactor;
|
||||
float flAirAbsorptionHF;
|
||||
float flHFReference;
|
||||
}; // EAX40CONTEXTPROPERTIES
|
||||
|
||||
struct EAX50CONTEXTPROPERTIES :
|
||||
public EAX40CONTEXTPROPERTIES
|
||||
{
|
||||
struct EAX50CONTEXTPROPERTIES : public EAX40CONTEXTPROPERTIES {
|
||||
float flMacroFXFactor;
|
||||
}; // EAX40CONTEXTPROPERTIES
|
||||
|
||||
|
||||
bool operator==(
|
||||
const EAX40CONTEXTPROPERTIES& lhs,
|
||||
const EAX40CONTEXTPROPERTIES& rhs) noexcept;
|
||||
|
||||
bool operator==(
|
||||
const EAX50CONTEXTPROPERTIES& lhs,
|
||||
const EAX50CONTEXTPROPERTIES& rhs) noexcept;
|
||||
}; // EAX50CONTEXTPROPERTIES
|
||||
|
||||
|
||||
constexpr auto EAXCONTEXT_MINDISTANCEFACTOR = FLT_MIN;
|
||||
|
|
@ -309,26 +363,18 @@ constexpr auto EAXCONTEXT_DEFAULTMACROFXFACTOR = 0.0F;
|
|||
|
||||
|
||||
extern const GUID EAXPROPERTYID_EAX40_FXSlot0;
|
||||
|
||||
extern const GUID EAXPROPERTYID_EAX50_FXSlot0;
|
||||
|
||||
extern const GUID EAXPROPERTYID_EAX40_FXSlot1;
|
||||
|
||||
extern const GUID EAXPROPERTYID_EAX50_FXSlot1;
|
||||
|
||||
extern const GUID EAXPROPERTYID_EAX40_FXSlot2;
|
||||
|
||||
extern const GUID EAXPROPERTYID_EAX50_FXSlot2;
|
||||
|
||||
extern const GUID EAXPROPERTYID_EAX40_FXSlot3;
|
||||
|
||||
extern const GUID EAXPROPERTYID_EAX50_FXSlot3;
|
||||
|
||||
extern const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID;
|
||||
extern const GUID EAX40CONTEXT_DEFAULTPRIMARYFXSLOTID;
|
||||
extern const GUID EAX50CONTEXT_DEFAULTPRIMARYFXSLOTID;
|
||||
|
||||
enum EAXFXSLOT_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXFXSLOT_PROPERTY : unsigned int {
|
||||
EAXFXSLOT_PARAMETER = 0,
|
||||
|
||||
EAXFXSLOT_NONE = 0x10000,
|
||||
|
|
@ -358,9 +404,7 @@ constexpr auto EAXFXSLOT_DEFAULTVOLUME = 0L;
|
|||
constexpr auto EAXFXSLOT_MINLOCK = 0L;
|
||||
constexpr auto EAXFXSLOT_MAXLOCK = 1L;
|
||||
|
||||
enum :
|
||||
long
|
||||
{
|
||||
enum : long {
|
||||
EAXFXSLOT_UNLOCKED = 0,
|
||||
EAXFXSLOT_LOCKED = 1
|
||||
};
|
||||
|
|
@ -379,39 +423,24 @@ constexpr auto EAX50FXSLOT_DEFAULTFLAGS =
|
|||
EAXFXSLOTFLAGS_ENVIRONMENT |
|
||||
EAXFXSLOTFLAGS_UPMIX; // ignored for reverb;
|
||||
|
||||
struct EAX40FXSLOTPROPERTIES
|
||||
{
|
||||
struct EAX40FXSLOTPROPERTIES {
|
||||
GUID guidLoadEffect;
|
||||
long lVolume;
|
||||
long lLock;
|
||||
unsigned long ulFlags;
|
||||
}; // EAX40FXSLOTPROPERTIES
|
||||
|
||||
struct EAX50FXSLOTPROPERTIES :
|
||||
public EAX40FXSLOTPROPERTIES
|
||||
{
|
||||
struct EAX50FXSLOTPROPERTIES : public EAX40FXSLOTPROPERTIES {
|
||||
long lOcclusion;
|
||||
float flOcclusionLFRatio;
|
||||
}; // EAX50FXSLOTPROPERTIES
|
||||
|
||||
bool operator==(
|
||||
const EAX40FXSLOTPROPERTIES& lhs,
|
||||
const EAX40FXSLOTPROPERTIES& rhs) noexcept;
|
||||
|
||||
bool operator==(
|
||||
const EAX50FXSLOTPROPERTIES& lhs,
|
||||
const EAX50FXSLOTPROPERTIES& rhs) noexcept;
|
||||
|
||||
extern const GUID EAXPROPERTYID_EAX40_Source;
|
||||
|
||||
extern const GUID EAXPROPERTYID_EAX50_Source;
|
||||
|
||||
// Source object properties
|
||||
enum EAXSOURCE_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXSOURCE_PROPERTY : unsigned int {
|
||||
// EAX30
|
||||
|
||||
EAXSOURCE_NONE,
|
||||
EAXSOURCE_ALLPARAMETERS,
|
||||
EAXSOURCE_OBSTRUCTIONPARAMETERS,
|
||||
|
|
@ -437,7 +466,6 @@ enum EAXSOURCE_PROPERTY :
|
|||
EAXSOURCE_FLAGS,
|
||||
|
||||
// EAX40
|
||||
|
||||
EAXSOURCE_SENDPARAMETERS,
|
||||
EAXSOURCE_ALLSENDPARAMETERS,
|
||||
EAXSOURCE_OCCLUSIONSENDPARAMETERS,
|
||||
|
|
@ -445,7 +473,6 @@ enum EAXSOURCE_PROPERTY :
|
|||
EAXSOURCE_ACTIVEFXSLOTID,
|
||||
|
||||
// EAX50
|
||||
|
||||
EAXSOURCE_MACROFXFACTOR,
|
||||
EAXSOURCE_SPEAKERLEVELS,
|
||||
EAXSOURCE_ALL2DPARAMETERS,
|
||||
|
|
@ -457,9 +484,7 @@ constexpr auto EAXSOURCEFLAGS_ROOMAUTO = 0x00000002UL; // relates to EAXSOURCE_R
|
|||
constexpr auto EAXSOURCEFLAGS_ROOMHFAUTO = 0x00000004UL; // relates to EAXSOURCE_ROOMHF
|
||||
// EAX50
|
||||
constexpr auto EAXSOURCEFLAGS_3DELEVATIONFILTER = 0x00000008UL;
|
||||
// EAX50
|
||||
constexpr auto EAXSOURCEFLAGS_UPMIX = 0x00000010UL;
|
||||
// EAX50
|
||||
constexpr auto EAXSOURCEFLAGS_APPLYSPEAKERLEVELS = 0x00000020UL;
|
||||
|
||||
constexpr auto EAX20SOURCEFLAGS_RESERVED = 0xFFFFFFF8UL; // reserved future use
|
||||
|
|
@ -548,8 +573,6 @@ constexpr auto EAXSOURCE_MINMACROFXFACTOR = 0.0F;
|
|||
constexpr auto EAXSOURCE_MAXMACROFXFACTOR = 1.0F;
|
||||
constexpr auto EAXSOURCE_DEFAULTMACROFXFACTOR = 1.0F;
|
||||
|
||||
// EAX50
|
||||
|
||||
constexpr auto EAXSOURCE_MINSPEAKERLEVEL = -10'000L;
|
||||
constexpr auto EAXSOURCE_MAXSPEAKERLEVEL = 0L;
|
||||
constexpr auto EAXSOURCE_DEFAULTSPEAKERLEVEL = -10'000L;
|
||||
|
|
@ -559,9 +582,7 @@ constexpr auto EAXSOURCE_DEFAULTFLAGS =
|
|||
EAXSOURCEFLAGS_ROOMAUTO |
|
||||
EAXSOURCEFLAGS_ROOMHFAUTO;
|
||||
|
||||
enum :
|
||||
long
|
||||
{
|
||||
enum : long {
|
||||
EAXSPEAKER_FRONT_LEFT = 1,
|
||||
EAXSPEAKER_FRONT_CENTER = 2,
|
||||
EAXSPEAKER_FRONT_RIGHT = 3,
|
||||
|
|
@ -581,8 +602,7 @@ constexpr auto EAX50SOURCE_DEFAULTFLAGS =
|
|||
EAXSOURCEFLAGS_ROOMHFAUTO |
|
||||
EAXSOURCEFLAGS_UPMIX;
|
||||
|
||||
struct EAX30SOURCEPROPERTIES
|
||||
{
|
||||
struct EAX30SOURCEPROPERTIES {
|
||||
long lDirect; // direct path level (at low and mid frequencies)
|
||||
long lDirectHF; // relative direct path level at high frequencies
|
||||
long lRoom; // room effect level (at low and mid frequencies)
|
||||
|
|
@ -603,14 +623,11 @@ struct EAX30SOURCEPROPERTIES
|
|||
unsigned long ulFlags; // modifies the behavior of properties
|
||||
}; // EAX30SOURCEPROPERTIES
|
||||
|
||||
struct EAX50SOURCEPROPERTIES :
|
||||
public EAX30SOURCEPROPERTIES
|
||||
{
|
||||
struct EAX50SOURCEPROPERTIES : public EAX30SOURCEPROPERTIES {
|
||||
float flMacroFXFactor;
|
||||
}; // EAX50SOURCEPROPERTIES
|
||||
|
||||
struct EAXSOURCEALLSENDPROPERTIES
|
||||
{
|
||||
struct EAXSOURCEALLSENDPROPERTIES {
|
||||
GUID guidReceivingFXSlotID;
|
||||
long lSend; // send level (at low and mid frequencies)
|
||||
long lSendHF; // relative send level at high frequencies
|
||||
|
|
@ -622,8 +639,7 @@ struct EAXSOURCEALLSENDPROPERTIES
|
|||
float flExclusionLFRatio;
|
||||
}; // EAXSOURCEALLSENDPROPERTIES
|
||||
|
||||
struct EAXSOURCE2DPROPERTIES
|
||||
{
|
||||
struct EAXSOURCE2DPROPERTIES {
|
||||
long lDirect; // direct path level (at low and mid frequencies)
|
||||
long lDirectHF; // relative direct path level at high frequencies
|
||||
long lRoom; // room effect level (at low and mid frequencies)
|
||||
|
|
@ -631,40 +647,27 @@ struct EAXSOURCE2DPROPERTIES
|
|||
unsigned long ulFlags; // modifies the behavior of properties
|
||||
}; // EAXSOURCE2DPROPERTIES
|
||||
|
||||
struct EAXSPEAKERLEVELPROPERTIES
|
||||
{
|
||||
struct EAXSPEAKERLEVELPROPERTIES {
|
||||
long lSpeakerID;
|
||||
long lLevel;
|
||||
}; // EAXSPEAKERLEVELPROPERTIES
|
||||
|
||||
struct EAX40ACTIVEFXSLOTS
|
||||
{
|
||||
struct EAX40ACTIVEFXSLOTS {
|
||||
GUID guidActiveFXSlots[EAX40_MAX_ACTIVE_FXSLOTS];
|
||||
}; // EAX40ACTIVEFXSLOTS
|
||||
|
||||
struct EAX50ACTIVEFXSLOTS
|
||||
{
|
||||
struct EAX50ACTIVEFXSLOTS {
|
||||
GUID guidActiveFXSlots[EAX50_MAX_ACTIVE_FXSLOTS];
|
||||
}; // EAX50ACTIVEFXSLOTS
|
||||
|
||||
bool operator==(
|
||||
const EAX50ACTIVEFXSLOTS& lhs,
|
||||
const EAX50ACTIVEFXSLOTS& rhs) noexcept;
|
||||
|
||||
bool operator!=(
|
||||
const EAX50ACTIVEFXSLOTS& lhs,
|
||||
const EAX50ACTIVEFXSLOTS& rhs) noexcept;
|
||||
|
||||
// Use this structure for EAXSOURCE_OBSTRUCTIONPARAMETERS property.
|
||||
struct EAXOBSTRUCTIONPROPERTIES
|
||||
{
|
||||
struct EAXOBSTRUCTIONPROPERTIES {
|
||||
long lObstruction;
|
||||
float flObstructionLFRatio;
|
||||
}; // EAXOBSTRUCTIONPROPERTIES
|
||||
|
||||
// Use this structure for EAXSOURCE_OCCLUSIONPARAMETERS property.
|
||||
struct EAXOCCLUSIONPROPERTIES
|
||||
{
|
||||
struct EAXOCCLUSIONPROPERTIES {
|
||||
long lOcclusion;
|
||||
float flOcclusionLFRatio;
|
||||
float flOcclusionRoomRatio;
|
||||
|
|
@ -672,23 +675,20 @@ struct EAXOCCLUSIONPROPERTIES
|
|||
}; // EAXOCCLUSIONPROPERTIES
|
||||
|
||||
// Use this structure for EAXSOURCE_EXCLUSIONPARAMETERS property.
|
||||
struct EAXEXCLUSIONPROPERTIES
|
||||
{
|
||||
struct EAXEXCLUSIONPROPERTIES {
|
||||
long lExclusion;
|
||||
float flExclusionLFRatio;
|
||||
}; // EAXEXCLUSIONPROPERTIES
|
||||
|
||||
// Use this structure for EAXSOURCE_SENDPARAMETERS properties.
|
||||
struct EAXSOURCESENDPROPERTIES
|
||||
{
|
||||
struct EAXSOURCESENDPROPERTIES {
|
||||
GUID guidReceivingFXSlotID;
|
||||
long lSend;
|
||||
long lSendHF;
|
||||
}; // EAXSOURCESENDPROPERTIES
|
||||
|
||||
// Use this structure for EAXSOURCE_OCCLUSIONSENDPARAMETERS
|
||||
struct EAXSOURCEOCCLUSIONSENDPROPERTIES
|
||||
{
|
||||
struct EAXSOURCEOCCLUSIONSENDPROPERTIES {
|
||||
GUID guidReceivingFXSlotID;
|
||||
long lOcclusion;
|
||||
float flOcclusionLFRatio;
|
||||
|
|
@ -697,14 +697,13 @@ struct EAXSOURCEOCCLUSIONSENDPROPERTIES
|
|||
}; // EAXSOURCEOCCLUSIONSENDPROPERTIES
|
||||
|
||||
// Use this structure for EAXSOURCE_EXCLUSIONSENDPARAMETERS
|
||||
struct EAXSOURCEEXCLUSIONSENDPROPERTIES
|
||||
{
|
||||
struct EAXSOURCEEXCLUSIONSENDPROPERTIES {
|
||||
GUID guidReceivingFXSlotID;
|
||||
long lExclusion;
|
||||
float flExclusionLFRatio;
|
||||
}; // EAXSOURCEEXCLUSIONSENDPROPERTIES
|
||||
|
||||
extern const EAX50ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID;
|
||||
extern const EAX40ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID;
|
||||
|
||||
extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID;
|
||||
|
||||
|
|
@ -716,9 +715,7 @@ extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID;
|
|||
extern const GUID EAX_REVERB_EFFECT;
|
||||
|
||||
// Reverb effect properties
|
||||
enum EAXREVERB_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXREVERB_PROPERTY : unsigned int {
|
||||
EAXREVERB_NONE,
|
||||
EAXREVERB_ALLPARAMETERS,
|
||||
EAXREVERB_ENVIRONMENT,
|
||||
|
|
@ -748,9 +745,7 @@ enum EAXREVERB_PROPERTY :
|
|||
}; // EAXREVERB_PROPERTY
|
||||
|
||||
// used by EAXREVERB_ENVIRONMENT
|
||||
enum :
|
||||
unsigned long
|
||||
{
|
||||
enum : unsigned long {
|
||||
EAX_ENVIRONMENT_GENERIC,
|
||||
EAX_ENVIRONMENT_PADDEDCELL,
|
||||
EAX_ENVIRONMENT_ROOM,
|
||||
|
|
@ -816,8 +811,7 @@ constexpr auto EAXREVERBFLAGS_DECAYHFLIMIT = 0x00000020UL;
|
|||
constexpr auto EAXREVERBFLAGS_RESERVED = 0xFFFFFF00UL; // reserved future use
|
||||
|
||||
|
||||
struct EAXREVERBPROPERTIES
|
||||
{
|
||||
struct EAXREVERBPROPERTIES {
|
||||
unsigned long ulEnvironment; // sets all reverb properties
|
||||
float flEnvironmentSize; // environment size in meters
|
||||
float flEnvironmentDiffusion; // environment diffusion
|
||||
|
|
@ -844,14 +838,6 @@ struct EAXREVERBPROPERTIES
|
|||
unsigned long ulFlags; // modifies the behavior of properties
|
||||
}; // EAXREVERBPROPERTIES
|
||||
|
||||
bool operator==(
|
||||
const EAXREVERBPROPERTIES& lhs,
|
||||
const EAXREVERBPROPERTIES& rhs) noexcept;
|
||||
|
||||
bool operator!=(
|
||||
const EAXREVERBPROPERTIES& lhs,
|
||||
const EAXREVERBPROPERTIES& rhs) noexcept;
|
||||
|
||||
|
||||
constexpr auto EAXREVERB_MINENVIRONMENT = static_cast<unsigned long>(EAX_ENVIRONMENT_GENERIC);
|
||||
constexpr auto EAX1REVERB_MAXENVIRONMENT = static_cast<unsigned long>(EAX_ENVIRONMENT_PSYCHOTIC);
|
||||
|
|
@ -957,28 +943,27 @@ constexpr auto EAXREVERB_DEFAULTFLAGS =
|
|||
EAXREVERBFLAGS_DECAYHFLIMIT;
|
||||
|
||||
|
||||
using EaxReverbPresets = std::array<EAXREVERBPROPERTIES, EAX1_ENVIRONMENT_COUNT>;
|
||||
extern const EaxReverbPresets EAXREVERB_PRESETS;
|
||||
|
||||
|
||||
using Eax1ReverbPresets = std::array<EAX_REVERBPROPERTIES, EAX1_ENVIRONMENT_COUNT>;
|
||||
extern const Eax1ReverbPresets EAX1REVERB_PRESETS;
|
||||
|
||||
using Eax2ReverbPresets = std::array<EAX20LISTENERPROPERTIES, EAX2_ENVIRONMENT_COUNT>;
|
||||
extern const Eax2ReverbPresets EAX2REVERB_PRESETS;
|
||||
|
||||
using EaxReverbPresets = std::array<EAXREVERBPROPERTIES, EAX1_ENVIRONMENT_COUNT>;
|
||||
extern const EaxReverbPresets EAXREVERB_PRESETS;
|
||||
|
||||
|
||||
// AGC Compressor Effect
|
||||
|
||||
extern const GUID EAX_AGCCOMPRESSOR_EFFECT;
|
||||
|
||||
enum EAXAGCCOMPRESSOR_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXAGCCOMPRESSOR_PROPERTY : unsigned int {
|
||||
EAXAGCCOMPRESSOR_NONE,
|
||||
EAXAGCCOMPRESSOR_ALLPARAMETERS,
|
||||
EAXAGCCOMPRESSOR_ONOFF,
|
||||
}; // EAXAGCCOMPRESSOR_PROPERTY
|
||||
|
||||
struct EAXAGCCOMPRESSORPROPERTIES
|
||||
{
|
||||
struct EAXAGCCOMPRESSORPROPERTIES {
|
||||
unsigned long ulOnOff; // Switch Compressor on or off
|
||||
}; // EAXAGCCOMPRESSORPROPERTIES
|
||||
|
||||
|
|
@ -992,9 +977,7 @@ constexpr auto EAXAGCCOMPRESSOR_DEFAULTONOFF = EAXAGCCOMPRESSOR_MAXONOFF;
|
|||
|
||||
extern const GUID EAX_AUTOWAH_EFFECT;
|
||||
|
||||
enum EAXAUTOWAH_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXAUTOWAH_PROPERTY : unsigned int {
|
||||
EAXAUTOWAH_NONE,
|
||||
EAXAUTOWAH_ALLPARAMETERS,
|
||||
EAXAUTOWAH_ATTACKTIME,
|
||||
|
|
@ -1003,8 +986,7 @@ enum EAXAUTOWAH_PROPERTY :
|
|||
EAXAUTOWAH_PEAKLEVEL,
|
||||
}; // EAXAUTOWAH_PROPERTY
|
||||
|
||||
struct EAXAUTOWAHPROPERTIES
|
||||
{
|
||||
struct EAXAUTOWAHPROPERTIES {
|
||||
float flAttackTime; // Attack time (seconds)
|
||||
float flReleaseTime; // Release time (seconds)
|
||||
long lResonance; // Resonance (mB)
|
||||
|
|
@ -1033,10 +1015,7 @@ constexpr auto EAXAUTOWAH_DEFAULTPEAKLEVEL = 2100L;
|
|||
|
||||
extern const GUID EAX_CHORUS_EFFECT;
|
||||
|
||||
|
||||
enum EAXCHORUS_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXCHORUS_PROPERTY : unsigned int {
|
||||
EAXCHORUS_NONE,
|
||||
EAXCHORUS_ALLPARAMETERS,
|
||||
EAXCHORUS_WAVEFORM,
|
||||
|
|
@ -1047,15 +1026,12 @@ enum EAXCHORUS_PROPERTY :
|
|||
EAXCHORUS_DELAY,
|
||||
}; // EAXCHORUS_PROPERTY
|
||||
|
||||
enum :
|
||||
unsigned long
|
||||
{
|
||||
enum : unsigned long {
|
||||
EAX_CHORUS_SINUSOID,
|
||||
EAX_CHORUS_TRIANGLE,
|
||||
};
|
||||
|
||||
struct EAXCHORUSPROPERTIES
|
||||
{
|
||||
struct EAXCHORUSPROPERTIES {
|
||||
unsigned long ulWaveform; // Waveform selector - see enum above
|
||||
long lPhase; // Phase (Degrees)
|
||||
float flRate; // Rate (Hz)
|
||||
|
|
@ -1094,9 +1070,7 @@ constexpr auto EAXCHORUS_DEFAULTDELAY = 0.016F;
|
|||
|
||||
extern const GUID EAX_DISTORTION_EFFECT;
|
||||
|
||||
enum EAXDISTORTION_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXDISTORTION_PROPERTY : unsigned int {
|
||||
EAXDISTORTION_NONE,
|
||||
EAXDISTORTION_ALLPARAMETERS,
|
||||
EAXDISTORTION_EDGE,
|
||||
|
|
@ -1106,9 +1080,7 @@ enum EAXDISTORTION_PROPERTY :
|
|||
EAXDISTORTION_EQBANDWIDTH,
|
||||
}; // EAXDISTORTION_PROPERTY
|
||||
|
||||
|
||||
struct EAXDISTORTIONPROPERTIES
|
||||
{
|
||||
struct EAXDISTORTIONPROPERTIES {
|
||||
float flEdge; // Controls the shape of the distortion (0 to 1)
|
||||
long lGain; // Controls the post distortion gain (mB)
|
||||
float flLowPassCutOff; // Controls the cut-off of the filter pre-distortion (Hz)
|
||||
|
|
@ -1142,10 +1114,7 @@ constexpr auto EAXDISTORTION_DEFAULTEQBANDWIDTH = 3600.0F;
|
|||
|
||||
extern const GUID EAX_ECHO_EFFECT;
|
||||
|
||||
|
||||
enum EAXECHO_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXECHO_PROPERTY : unsigned int {
|
||||
EAXECHO_NONE,
|
||||
EAXECHO_ALLPARAMETERS,
|
||||
EAXECHO_DELAY,
|
||||
|
|
@ -1155,9 +1124,7 @@ enum EAXECHO_PROPERTY :
|
|||
EAXECHO_SPREAD,
|
||||
}; // EAXECHO_PROPERTY
|
||||
|
||||
|
||||
struct EAXECHOPROPERTIES
|
||||
{
|
||||
struct EAXECHOPROPERTIES {
|
||||
float flDelay; // Controls the initial delay time (seconds)
|
||||
float flLRDelay; // Controls the delay time between the first and second taps (seconds)
|
||||
float flDamping; // Controls a low-pass filter that dampens the echoes (0 to 1)
|
||||
|
|
@ -1191,10 +1158,7 @@ constexpr auto EAXECHO_DEFAULTSPREAD = -1.0F;
|
|||
|
||||
extern const GUID EAX_EQUALIZER_EFFECT;
|
||||
|
||||
|
||||
enum EAXEQUALIZER_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXEQUALIZER_PROPERTY : unsigned int {
|
||||
EAXEQUALIZER_NONE,
|
||||
EAXEQUALIZER_ALLPARAMETERS,
|
||||
EAXEQUALIZER_LOWGAIN,
|
||||
|
|
@ -1209,9 +1173,7 @@ enum EAXEQUALIZER_PROPERTY :
|
|||
EAXEQUALIZER_HIGHCUTOFF,
|
||||
}; // EAXEQUALIZER_PROPERTY
|
||||
|
||||
|
||||
struct EAXEQUALIZERPROPERTIES
|
||||
{
|
||||
struct EAXEQUALIZERPROPERTIES {
|
||||
long lLowGain; // (mB)
|
||||
float flLowCutOff; // (Hz)
|
||||
long lMid1Gain; // (mB)
|
||||
|
|
@ -1270,9 +1232,7 @@ constexpr auto EAXEQUALIZER_DEFAULTHIGHCUTOFF = 6000.0F;
|
|||
|
||||
extern const GUID EAX_FLANGER_EFFECT;
|
||||
|
||||
enum EAXFLANGER_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXFLANGER_PROPERTY : unsigned int {
|
||||
EAXFLANGER_NONE,
|
||||
EAXFLANGER_ALLPARAMETERS,
|
||||
EAXFLANGER_WAVEFORM,
|
||||
|
|
@ -1283,15 +1243,12 @@ enum EAXFLANGER_PROPERTY :
|
|||
EAXFLANGER_DELAY,
|
||||
}; // EAXFLANGER_PROPERTY
|
||||
|
||||
enum :
|
||||
unsigned long
|
||||
{
|
||||
enum : unsigned long {
|
||||
EAX_FLANGER_SINUSOID,
|
||||
EAX_FLANGER_TRIANGLE,
|
||||
};
|
||||
|
||||
struct EAXFLANGERPROPERTIES
|
||||
{
|
||||
struct EAXFLANGERPROPERTIES {
|
||||
unsigned long ulWaveform; // Waveform selector - see enum above
|
||||
long lPhase; // Phase (Degrees)
|
||||
float flRate; // Rate (Hz)
|
||||
|
|
@ -1330,9 +1287,7 @@ constexpr auto EAXFLANGER_DEFAULTDELAY = 0.002F;
|
|||
|
||||
extern const GUID EAX_FREQUENCYSHIFTER_EFFECT;
|
||||
|
||||
enum EAXFREQUENCYSHIFTER_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXFREQUENCYSHIFTER_PROPERTY : unsigned int {
|
||||
EAXFREQUENCYSHIFTER_NONE,
|
||||
EAXFREQUENCYSHIFTER_ALLPARAMETERS,
|
||||
EAXFREQUENCYSHIFTER_FREQUENCY,
|
||||
|
|
@ -1340,16 +1295,13 @@ enum EAXFREQUENCYSHIFTER_PROPERTY :
|
|||
EAXFREQUENCYSHIFTER_RIGHTDIRECTION,
|
||||
}; // EAXFREQUENCYSHIFTER_PROPERTY
|
||||
|
||||
enum :
|
||||
unsigned long
|
||||
{
|
||||
enum : unsigned long {
|
||||
EAX_FREQUENCYSHIFTER_DOWN,
|
||||
EAX_FREQUENCYSHIFTER_UP,
|
||||
EAX_FREQUENCYSHIFTER_OFF
|
||||
};
|
||||
|
||||
struct EAXFREQUENCYSHIFTERPROPERTIES
|
||||
{
|
||||
struct EAXFREQUENCYSHIFTERPROPERTIES {
|
||||
float flFrequency; // (Hz)
|
||||
unsigned long ulLeftDirection; // see enum above
|
||||
unsigned long ulRightDirection; // see enum above
|
||||
|
|
@ -1373,9 +1325,7 @@ constexpr auto EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION = EAXFREQUENCYSHIFTER_M
|
|||
|
||||
extern const GUID EAX_VOCALMORPHER_EFFECT;
|
||||
|
||||
enum EAXVOCALMORPHER_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXVOCALMORPHER_PROPERTY : unsigned int {
|
||||
EAXVOCALMORPHER_NONE,
|
||||
EAXVOCALMORPHER_ALLPARAMETERS,
|
||||
EAXVOCALMORPHER_PHONEMEA,
|
||||
|
|
@ -1386,9 +1336,7 @@ enum EAXVOCALMORPHER_PROPERTY :
|
|||
EAXVOCALMORPHER_RATE,
|
||||
}; // EAXVOCALMORPHER_PROPERTY
|
||||
|
||||
enum :
|
||||
unsigned long
|
||||
{
|
||||
enum : unsigned long {
|
||||
A,
|
||||
E,
|
||||
I,
|
||||
|
|
@ -1421,17 +1369,14 @@ enum :
|
|||
Z,
|
||||
};
|
||||
|
||||
enum :
|
||||
unsigned long
|
||||
{
|
||||
enum : unsigned long {
|
||||
EAX_VOCALMORPHER_SINUSOID,
|
||||
EAX_VOCALMORPHER_TRIANGLE,
|
||||
EAX_VOCALMORPHER_SAWTOOTH
|
||||
};
|
||||
|
||||
// Use this structure for EAXVOCALMORPHER_ALLPARAMETERS
|
||||
struct EAXVOCALMORPHERPROPERTIES
|
||||
{
|
||||
struct EAXVOCALMORPHERPROPERTIES {
|
||||
unsigned long ulPhonemeA; // see enum above
|
||||
long lPhonemeACoarseTuning; // (semitones)
|
||||
unsigned long ulPhonemeB; // see enum above
|
||||
|
|
@ -1470,17 +1415,14 @@ constexpr auto EAXVOCALMORPHER_DEFAULTRATE = 1.41F;
|
|||
|
||||
extern const GUID EAX_PITCHSHIFTER_EFFECT;
|
||||
|
||||
enum EAXPITCHSHIFTER_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXPITCHSHIFTER_PROPERTY : unsigned int {
|
||||
EAXPITCHSHIFTER_NONE,
|
||||
EAXPITCHSHIFTER_ALLPARAMETERS,
|
||||
EAXPITCHSHIFTER_COARSETUNE,
|
||||
EAXPITCHSHIFTER_FINETUNE,
|
||||
}; // EAXPITCHSHIFTER_PROPERTY
|
||||
|
||||
struct EAXPITCHSHIFTERPROPERTIES
|
||||
{
|
||||
struct EAXPITCHSHIFTERPROPERTIES {
|
||||
long lCoarseTune; // Amount of pitch shift (semitones)
|
||||
long lFineTune; // Amount of pitch shift (cents)
|
||||
}; // EAXPITCHSHIFTERPROPERTIES
|
||||
|
|
@ -1499,9 +1441,7 @@ constexpr auto EAXPITCHSHIFTER_DEFAULTFINETUNE = 0L;
|
|||
|
||||
extern const GUID EAX_RINGMODULATOR_EFFECT;
|
||||
|
||||
enum EAXRINGMODULATOR_PROPERTY :
|
||||
unsigned int
|
||||
{
|
||||
enum EAXRINGMODULATOR_PROPERTY : unsigned int {
|
||||
EAXRINGMODULATOR_NONE,
|
||||
EAXRINGMODULATOR_ALLPARAMETERS,
|
||||
EAXRINGMODULATOR_FREQUENCY,
|
||||
|
|
@ -1509,17 +1449,14 @@ enum EAXRINGMODULATOR_PROPERTY :
|
|||
EAXRINGMODULATOR_WAVEFORM,
|
||||
}; // EAXRINGMODULATOR_PROPERTY
|
||||
|
||||
enum :
|
||||
unsigned long
|
||||
{
|
||||
enum : unsigned long {
|
||||
EAX_RINGMODULATOR_SINUSOID,
|
||||
EAX_RINGMODULATOR_SAWTOOTH,
|
||||
EAX_RINGMODULATOR_SQUARE,
|
||||
};
|
||||
|
||||
// Use this structure for EAXRINGMODULATOR_ALLPARAMETERS
|
||||
struct EAXRINGMODULATORPROPERTIES
|
||||
{
|
||||
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
|
||||
|
|
@ -1553,5 +1490,4 @@ using LPEAXGET = ALenum(AL_APIENTRY*)(
|
|||
ALvoid* property_buffer,
|
||||
ALuint property_size);
|
||||
|
||||
|
||||
#endif // !EAX_API_INCLUDED
|
||||
219
Engine/lib/openal-soft/al/eax/call.cpp
Normal file
219
Engine/lib/openal-soft/al/eax/call.cpp
Normal 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
Engine/lib/openal-soft/al/eax/call.h
Normal file
97
Engine/lib/openal-soft/al/eax/call.h
Normal 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
Engine/lib/openal-soft/al/eax/effect.h
Normal file
418
Engine/lib/openal-soft/al/eax/effect.h
Normal 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
|
||||
|
|
@ -1,23 +1,19 @@
|
|||
#include "config.h"
|
||||
|
||||
#include "eax_exception.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(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)
|
||||
|
||||
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);
|
||||
18
Engine/lib/openal-soft/al/eax/exception.h
Normal file
18
Engine/lib/openal-soft/al/eax/exception.h
Normal 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
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#include "config.h"
|
||||
|
||||
#include "eax_fx_slot_index.h"
|
||||
#include "fx_slot_index.h"
|
||||
|
||||
#include "eax_exception.h"
|
||||
#include "exception.h"
|
||||
|
||||
|
||||
namespace
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
#include <cstddef>
|
||||
|
||||
#include "aloptional.h"
|
||||
#include "eax_api.h"
|
||||
#include "api.h"
|
||||
|
||||
|
||||
using EaxFxSlotIndexValue = std::size_t;
|
||||
|
|
@ -1,12 +1,11 @@
|
|||
#include "config.h"
|
||||
|
||||
#include "eax_fx_slots.h"
|
||||
#include "fx_slots.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "eax_exception.h"
|
||||
|
||||
#include "eax_api.h"
|
||||
#include "api.h"
|
||||
#include "exception.h"
|
||||
|
||||
|
||||
namespace
|
||||
|
|
@ -29,8 +28,7 @@ public:
|
|||
} // namespace
|
||||
|
||||
|
||||
void EaxFxSlots::initialize(
|
||||
ALCcontext& al_context)
|
||||
void EaxFxSlots::initialize(ALCcontext& al_context)
|
||||
{
|
||||
initialize_fx_slots(al_context);
|
||||
}
|
||||
|
|
@ -57,12 +55,6 @@ ALeffectslot& EaxFxSlots::get(EaxFxSlotIndex index)
|
|||
return *fx_slots_[index.value()];
|
||||
}
|
||||
|
||||
void EaxFxSlots::unlock_legacy() noexcept
|
||||
{
|
||||
fx_slots_[0]->eax_unlock_legacy();
|
||||
fx_slots_[1]->eax_unlock_legacy();
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void EaxFxSlots::fail(
|
||||
const char* message)
|
||||
|
|
@ -70,8 +62,7 @@ void EaxFxSlots::fail(
|
|||
throw EaxFxSlotsException{message};
|
||||
}
|
||||
|
||||
void EaxFxSlots::initialize_fx_slots(
|
||||
ALCcontext& al_context)
|
||||
void EaxFxSlots::initialize_fx_slots(ALCcontext& al_context)
|
||||
{
|
||||
auto fx_slot_index = EaxFxSlotIndexValue{};
|
||||
|
||||
|
|
@ -6,16 +6,15 @@
|
|||
|
||||
#include "al/auxeffectslot.h"
|
||||
|
||||
#include "eax_api.h"
|
||||
|
||||
#include "eax_fx_slot_index.h"
|
||||
#include "api.h"
|
||||
#include "call.h"
|
||||
#include "fx_slot_index.h"
|
||||
|
||||
|
||||
class EaxFxSlots
|
||||
{
|
||||
public:
|
||||
void initialize(
|
||||
ALCcontext& al_context);
|
||||
void initialize(ALCcontext& al_context);
|
||||
|
||||
void uninitialize() noexcept;
|
||||
|
||||
|
|
@ -32,9 +31,6 @@ public:
|
|||
ALeffectslot& get(
|
||||
EaxFxSlotIndex index);
|
||||
|
||||
void unlock_legacy() noexcept;
|
||||
|
||||
|
||||
private:
|
||||
using Items = std::array<EaxAlEffectSlotUPtr, EAX_MAX_FXSLOTS>;
|
||||
|
||||
|
|
@ -46,8 +42,7 @@ private:
|
|||
static void fail(
|
||||
const char* message);
|
||||
|
||||
void initialize_fx_slots(
|
||||
ALCcontext& al_context);
|
||||
void initialize_fx_slots(ALCcontext& al_context);
|
||||
}; // EaxFxSlots
|
||||
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "config.h"
|
||||
|
||||
#include "eax_globals.h"
|
||||
#include "globals.h"
|
||||
|
||||
|
||||
bool eax_g_is_enabled = true;
|
||||
26
Engine/lib/openal-soft/al/eax/utils.cpp
Normal file
26
Engine/lib/openal-soft/al/eax/utils.cpp
Normal 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.");
|
||||
}
|
||||
}
|
||||
|
|
@ -6,22 +6,16 @@
|
|||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
using EaxDirtyFlags = unsigned int;
|
||||
|
||||
struct EaxAlLowPassParam
|
||||
{
|
||||
struct EaxAlLowPassParam {
|
||||
float gain;
|
||||
float gain_hf;
|
||||
}; // EaxAlLowPassParam
|
||||
};
|
||||
|
||||
void eax_log_exception(const char *message) noexcept;
|
||||
|
||||
void eax_log_exception(
|
||||
const char* message = nullptr) noexcept;
|
||||
|
||||
|
||||
template<
|
||||
typename TException,
|
||||
typename TValue
|
||||
>
|
||||
template<typename TException, typename TValue>
|
||||
void eax_validate_range(
|
||||
const char* value_name,
|
||||
const TValue& value,
|
||||
|
|
@ -29,9 +23,7 @@ void eax_validate_range(
|
|||
const TValue& max_value)
|
||||
{
|
||||
if (value >= min_value && value <= max_value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto message =
|
||||
std::string{value_name} +
|
||||
|
|
@ -43,60 +35,38 @@ void eax_validate_range(
|
|||
throw TException{message.c_str()};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
|
||||
template<
|
||||
typename T
|
||||
>
|
||||
struct EaxIsBitFieldStruct
|
||||
{
|
||||
template<typename T>
|
||||
struct EaxIsBitFieldStruct {
|
||||
private:
|
||||
using yes = std::true_type;
|
||||
using no = std::false_type;
|
||||
|
||||
template<
|
||||
typename U
|
||||
>
|
||||
template<typename U>
|
||||
static auto test(int) -> decltype(std::declval<typename U::EaxIsBitFieldStruct>(), yes{});
|
||||
|
||||
template<
|
||||
typename
|
||||
>
|
||||
template<typename>
|
||||
static no test(...);
|
||||
|
||||
|
||||
public:
|
||||
static constexpr auto value = std::is_same<decltype(test<T>(0)), yes>::value;
|
||||
}; // EaxIsBitFieldStruct
|
||||
};
|
||||
|
||||
|
||||
template<
|
||||
typename T,
|
||||
typename TValue
|
||||
>
|
||||
inline bool eax_bit_fields_are_equal(
|
||||
const T& lhs,
|
||||
const T& rhs) noexcept
|
||||
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
|
||||
inline bool operator==(const T& lhs, const T& rhs) noexcept
|
||||
{
|
||||
using Value = std::conditional_t<
|
||||
sizeof(T) == 1,
|
||||
|
|
@ -107,13 +77,9 @@ inline bool operator==(
|
|||
std::conditional_t<
|
||||
sizeof(T) == 4,
|
||||
std::uint32_t,
|
||||
void
|
||||
>
|
||||
>
|
||||
>;
|
||||
void>>>;
|
||||
|
||||
static_assert(!std::is_same<Value, void>::value, "Unsupported type.");
|
||||
|
||||
return detail::eax_bit_fields_are_equal<T, Value>(lhs, rhs);
|
||||
}
|
||||
|
||||
|
|
@ -121,12 +87,9 @@ template<
|
|||
typename T,
|
||||
std::enable_if_t<detail::EaxIsBitFieldStruct<T>::value, int> = 0
|
||||
>
|
||||
inline bool operator!=(
|
||||
const T& lhs,
|
||||
const T& rhs) noexcept
|
||||
inline bool operator!=(const T& lhs, const T& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
|
||||
#endif // !EAX_UTILS_INCLUDED
|
||||
|
|
@ -1,324 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
#include "al/eax_eax_call.h"
|
||||
|
||||
#include "al/eax_exception.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto deferred_flag = 0x80000000U;
|
||||
|
||||
class EaxEaxCallException :
|
||||
public EaxException
|
||||
{
|
||||
public:
|
||||
explicit EaxEaxCallException(
|
||||
const char* message)
|
||||
:
|
||||
EaxException{"EAX_EAX_CALL", message}
|
||||
{
|
||||
}
|
||||
}; // EaxEaxCallException
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
EaxEaxCall::EaxEaxCall(
|
||||
bool is_get,
|
||||
const GUID& property_set_guid,
|
||||
ALuint property_id,
|
||||
ALuint property_source_id,
|
||||
ALvoid* property_buffer,
|
||||
ALuint property_size)
|
||||
: is_get_{is_get}, version_{0}, property_set_id_{EaxEaxCallPropertySetId::none}
|
||||
, property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id}
|
||||
, property_buffer_{property_buffer}, property_size_{property_size}
|
||||
{
|
||||
if (false)
|
||||
{
|
||||
}
|
||||
else if (property_set_guid == EAXPROPERTYID_EAX40_Context)
|
||||
{
|
||||
version_ = 4;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::context;
|
||||
}
|
||||
else if (property_set_guid == EAXPROPERTYID_EAX50_Context)
|
||||
{
|
||||
version_ = 5;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::context;
|
||||
}
|
||||
else if (property_set_guid == DSPROPSETID_EAX20_ListenerProperties)
|
||||
{
|
||||
version_ = 2;
|
||||
fx_slot_index_ = 0u;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect;
|
||||
property_id_ = convert_eax_v2_0_listener_property_id(property_id_);
|
||||
}
|
||||
else if (property_set_guid == DSPROPSETID_EAX30_ListenerProperties)
|
||||
{
|
||||
version_ = 3;
|
||||
fx_slot_index_ = 0u;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect;
|
||||
}
|
||||
else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot0)
|
||||
{
|
||||
version_ = 4;
|
||||
fx_slot_index_ = 0u;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::fx_slot;
|
||||
}
|
||||
else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot0)
|
||||
{
|
||||
version_ = 5;
|
||||
fx_slot_index_ = 0u;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::fx_slot;
|
||||
}
|
||||
else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot1)
|
||||
{
|
||||
version_ = 4;
|
||||
fx_slot_index_ = 1u;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::fx_slot;
|
||||
}
|
||||
else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot1)
|
||||
{
|
||||
version_ = 5;
|
||||
fx_slot_index_ = 1u;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::fx_slot;
|
||||
}
|
||||
else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot2)
|
||||
{
|
||||
version_ = 4;
|
||||
fx_slot_index_ = 2u;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::fx_slot;
|
||||
}
|
||||
else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot2)
|
||||
{
|
||||
version_ = 5;
|
||||
fx_slot_index_ = 2u;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::fx_slot;
|
||||
}
|
||||
else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot3)
|
||||
{
|
||||
version_ = 4;
|
||||
fx_slot_index_ = 3u;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::fx_slot;
|
||||
}
|
||||
else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot3)
|
||||
{
|
||||
version_ = 5;
|
||||
fx_slot_index_ = 3u;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::fx_slot;
|
||||
}
|
||||
else if (property_set_guid == DSPROPSETID_EAX20_BufferProperties)
|
||||
{
|
||||
version_ = 2;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::source;
|
||||
property_id_ = convert_eax_v2_0_buffer_property_id(property_id_);
|
||||
}
|
||||
else if (property_set_guid == DSPROPSETID_EAX30_BufferProperties)
|
||||
{
|
||||
version_ = 3;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::source;
|
||||
}
|
||||
else if (property_set_guid == EAXPROPERTYID_EAX40_Source)
|
||||
{
|
||||
version_ = 4;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::source;
|
||||
}
|
||||
else if (property_set_guid == EAXPROPERTYID_EAX50_Source)
|
||||
{
|
||||
version_ = 5;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::source;
|
||||
}
|
||||
else if (property_set_guid == DSPROPSETID_EAX_ReverbProperties)
|
||||
{
|
||||
version_ = 1;
|
||||
fx_slot_index_ = 0u;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect;
|
||||
}
|
||||
else if (property_set_guid == DSPROPSETID_EAXBUFFER_ReverbProperties)
|
||||
{
|
||||
version_ = 1;
|
||||
property_set_id_ = EaxEaxCallPropertySetId::source;
|
||||
}
|
||||
else
|
||||
{
|
||||
fail("Unsupported property set id.");
|
||||
}
|
||||
|
||||
if (version_ < 1 || version_ > 5)
|
||||
{
|
||||
fail("EAX version out of range.");
|
||||
}
|
||||
|
||||
if(!(property_id&deferred_flag))
|
||||
{
|
||||
if(property_set_id_ != EaxEaxCallPropertySetId::fx_slot && property_id_ != 0)
|
||||
{
|
||||
if (!property_buffer)
|
||||
{
|
||||
fail("Null property buffer.");
|
||||
}
|
||||
|
||||
if (property_size == 0)
|
||||
{
|
||||
fail("Empty property.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(property_set_id_ == EaxEaxCallPropertySetId::source && property_source_id_ == 0)
|
||||
{
|
||||
fail("Null AL source id.");
|
||||
}
|
||||
|
||||
if (property_set_id_ == EaxEaxCallPropertySetId::fx_slot)
|
||||
{
|
||||
if (property_id_ < EAXFXSLOT_NONE)
|
||||
{
|
||||
property_set_id_ = EaxEaxCallPropertySetId::fx_slot_effect;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void EaxEaxCall::fail(
|
||||
const char* message)
|
||||
{
|
||||
throw EaxEaxCallException{message};
|
||||
}
|
||||
|
||||
ALuint EaxEaxCall::convert_eax_v2_0_listener_property_id(
|
||||
ALuint property_id)
|
||||
{
|
||||
switch (property_id)
|
||||
{
|
||||
case DSPROPERTY_EAX20LISTENER_NONE:
|
||||
return EAXREVERB_NONE;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS:
|
||||
return EAXREVERB_ALLPARAMETERS;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_ROOM:
|
||||
return EAXREVERB_ROOM;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_ROOMHF:
|
||||
return EAXREVERB_ROOMHF;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR:
|
||||
return EAXREVERB_ROOMROLLOFFFACTOR;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_DECAYTIME:
|
||||
return EAXREVERB_DECAYTIME;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO:
|
||||
return EAXREVERB_DECAYHFRATIO;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_REFLECTIONS:
|
||||
return EAXREVERB_REFLECTIONS;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY:
|
||||
return EAXREVERB_REFLECTIONSDELAY;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_REVERB:
|
||||
return EAXREVERB_REVERB;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_REVERBDELAY:
|
||||
return EAXREVERB_REVERBDELAY;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_ENVIRONMENT:
|
||||
return EAXREVERB_ENVIRONMENT;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE:
|
||||
return EAXREVERB_ENVIRONMENTSIZE;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION:
|
||||
return EAXREVERB_ENVIRONMENTDIFFUSION;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF:
|
||||
return EAXREVERB_AIRABSORPTIONHF;
|
||||
|
||||
case DSPROPERTY_EAX20LISTENER_FLAGS:
|
||||
return EAXREVERB_FLAGS;
|
||||
|
||||
default:
|
||||
fail("Unsupported EAX 2.0 listener property id.");
|
||||
}
|
||||
}
|
||||
|
||||
ALuint EaxEaxCall::convert_eax_v2_0_buffer_property_id(
|
||||
ALuint property_id)
|
||||
{
|
||||
switch (property_id)
|
||||
{
|
||||
case DSPROPERTY_EAX20BUFFER_NONE:
|
||||
return EAXSOURCE_NONE;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS:
|
||||
return EAXSOURCE_ALLPARAMETERS;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_DIRECT:
|
||||
return EAXSOURCE_DIRECT;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_DIRECTHF:
|
||||
return EAXSOURCE_DIRECTHF;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_ROOM:
|
||||
return EAXSOURCE_ROOM;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_ROOMHF:
|
||||
return EAXSOURCE_ROOMHF;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR:
|
||||
return EAXSOURCE_ROOMROLLOFFFACTOR;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_OBSTRUCTION:
|
||||
return EAXSOURCE_OBSTRUCTION;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO:
|
||||
return EAXSOURCE_OBSTRUCTIONLFRATIO;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_OCCLUSION:
|
||||
return EAXSOURCE_OCCLUSION;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO:
|
||||
return EAXSOURCE_OCCLUSIONLFRATIO;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO:
|
||||
return EAXSOURCE_OCCLUSIONROOMRATIO;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF:
|
||||
return EAXSOURCE_OUTSIDEVOLUMEHF;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR:
|
||||
return EAXSOURCE_AIRABSORPTIONFACTOR;
|
||||
|
||||
case DSPROPERTY_EAX20BUFFER_FLAGS:
|
||||
return EAXSOURCE_FLAGS;
|
||||
|
||||
default:
|
||||
fail("Unsupported EAX 2.0 buffer property id.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EaxEaxCall create_eax_call(
|
||||
bool is_get,
|
||||
const GUID* property_set_id,
|
||||
ALuint property_id,
|
||||
ALuint property_source_id,
|
||||
ALvoid* property_buffer,
|
||||
ALuint property_size)
|
||||
{
|
||||
if(!property_set_id)
|
||||
throw EaxEaxCallException{"Null property set ID."};
|
||||
|
||||
return EaxEaxCall{
|
||||
is_get,
|
||||
*property_set_id,
|
||||
property_id,
|
||||
property_source_id,
|
||||
property_buffer,
|
||||
property_size
|
||||
};
|
||||
}
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
#ifndef EAX_EAX_CALL_INCLUDED
|
||||
#define EAX_EAX_CALL_INCLUDED
|
||||
|
||||
|
||||
#include "AL/al.h"
|
||||
|
||||
#include "alspan.h"
|
||||
|
||||
#include "eax_api.h"
|
||||
#include "eax_fx_slot_index.h"
|
||||
|
||||
|
||||
enum class EaxEaxCallPropertySetId
|
||||
{
|
||||
none,
|
||||
|
||||
context,
|
||||
fx_slot,
|
||||
source,
|
||||
fx_slot_effect,
|
||||
}; // EaxEaxCallPropertySetId
|
||||
|
||||
|
||||
class EaxEaxCall
|
||||
{
|
||||
public:
|
||||
EaxEaxCall(
|
||||
bool is_get,
|
||||
const GUID& property_set_guid,
|
||||
ALuint property_id,
|
||||
ALuint property_source_id,
|
||||
ALvoid* property_buffer,
|
||||
ALuint property_size);
|
||||
|
||||
bool is_get() const noexcept { return is_get_; }
|
||||
int get_version() const noexcept { return version_; }
|
||||
EaxEaxCallPropertySetId get_property_set_id() const noexcept { return property_set_id_; }
|
||||
ALuint get_property_id() const noexcept { return property_id_; }
|
||||
ALuint get_property_al_name() const noexcept { return property_source_id_; }
|
||||
EaxFxSlotIndex get_fx_slot_index() const noexcept { return fx_slot_index_; }
|
||||
|
||||
template<
|
||||
typename TException,
|
||||
typename TValue
|
||||
>
|
||||
TValue& get_value() const
|
||||
{
|
||||
if (property_size_ < static_cast<ALuint>(sizeof(TValue)))
|
||||
{
|
||||
throw TException{"Property buffer too small."};
|
||||
}
|
||||
|
||||
return *static_cast<TValue*>(property_buffer_);
|
||||
}
|
||||
|
||||
template<
|
||||
typename TException,
|
||||
typename TValue
|
||||
>
|
||||
al::span<TValue> get_values() const
|
||||
{
|
||||
if (property_size_ < static_cast<ALuint>(sizeof(TValue)))
|
||||
{
|
||||
throw TException{"Property buffer too small."};
|
||||
}
|
||||
|
||||
const auto count = property_size_ / sizeof(TValue);
|
||||
|
||||
return al::span<TValue>{static_cast<TValue*>(property_buffer_), count};
|
||||
}
|
||||
|
||||
template<
|
||||
typename TException,
|
||||
typename TValue
|
||||
>
|
||||
void set_value(
|
||||
const TValue& value) const
|
||||
{
|
||||
get_value<TException, TValue>() = value;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
const bool is_get_;
|
||||
int version_;
|
||||
EaxFxSlotIndex fx_slot_index_;
|
||||
EaxEaxCallPropertySetId property_set_id_;
|
||||
|
||||
ALuint property_id_;
|
||||
const ALuint property_source_id_;
|
||||
ALvoid*const property_buffer_;
|
||||
const ALuint property_size_;
|
||||
|
||||
|
||||
[[noreturn]]
|
||||
static void fail(
|
||||
const char* message);
|
||||
|
||||
|
||||
static ALuint convert_eax_v2_0_listener_property_id(
|
||||
ALuint property_id);
|
||||
|
||||
static ALuint convert_eax_v2_0_buffer_property_id(
|
||||
ALuint property_id);
|
||||
}; // EaxEaxCall
|
||||
|
||||
|
||||
EaxEaxCall create_eax_call(
|
||||
bool is_get,
|
||||
const GUID* property_set_id,
|
||||
ALuint property_id,
|
||||
ALuint property_source_id,
|
||||
ALvoid* property_buffer,
|
||||
ALuint property_size);
|
||||
|
||||
|
||||
#endif // !EAX_EAX_CALL_INCLUDED
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
#include "eax_effect.h"
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
#ifndef EAX_EFFECT_INCLUDED
|
||||
#define EAX_EFFECT_INCLUDED
|
||||
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "core/effects/base.h"
|
||||
#include "eax_eax_call.h"
|
||||
|
||||
class EaxEffect
|
||||
{
|
||||
public:
|
||||
EaxEffect(ALenum type) : al_effect_type_{type} { }
|
||||
virtual ~EaxEffect() = default;
|
||||
|
||||
const ALenum al_effect_type_;
|
||||
EffectProps al_effect_props_{};
|
||||
|
||||
virtual void dispatch(const EaxEaxCall& eax_call) = 0;
|
||||
|
||||
// Returns "true" if any immediated property was changed.
|
||||
// [[nodiscard]]
|
||||
virtual bool apply_deferred() = 0;
|
||||
}; // EaxEffect
|
||||
|
||||
|
||||
using EaxEffectUPtr = std::unique_ptr<EaxEffect>;
|
||||
|
||||
EaxEffectUPtr eax_create_eax_null_effect();
|
||||
EaxEffectUPtr eax_create_eax_chorus_effect();
|
||||
EaxEffectUPtr eax_create_eax_distortion_effect();
|
||||
EaxEffectUPtr eax_create_eax_echo_effect();
|
||||
EaxEffectUPtr eax_create_eax_flanger_effect();
|
||||
EaxEffectUPtr eax_create_eax_frequency_shifter_effect();
|
||||
EaxEffectUPtr eax_create_eax_vocal_morpher_effect();
|
||||
EaxEffectUPtr eax_create_eax_pitch_shifter_effect();
|
||||
EaxEffectUPtr eax_create_eax_ring_modulator_effect();
|
||||
EaxEffectUPtr eax_create_eax_auto_wah_effect();
|
||||
EaxEffectUPtr eax_create_eax_compressor_effect();
|
||||
EaxEffectUPtr eax_create_eax_equalizer_effect();
|
||||
EaxEffectUPtr eax_create_eax_reverb_effect();
|
||||
|
||||
#endif // !EAX_EFFECT_INCLUDED
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
#ifndef EAX_EXCEPTION_INCLUDED
|
||||
#define EAX_EXCEPTION_INCLUDED
|
||||
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
|
||||
class EaxException :
|
||||
public std::runtime_error
|
||||
{
|
||||
public:
|
||||
EaxException(
|
||||
const char* context,
|
||||
const char* message);
|
||||
|
||||
|
||||
private:
|
||||
static std::string make_message(
|
||||
const char* context,
|
||||
const char* message);
|
||||
}; // EaxException
|
||||
|
||||
|
||||
#endif // !EAX_EXCEPTION_INCLUDED
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
#include "eax_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);
|
||||
|
||||
if (message)
|
||||
{
|
||||
ERR("%s\n", message);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::rethrow_exception(exception_ptr);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
const auto ex_message = ex.what();
|
||||
ERR("%s\n", ex_message);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ERR("%s\n", "Generic exception.");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#include "config.h"
|
||||
|
||||
#include "eax_x_ram.h"
|
||||
|
|
@ -54,7 +54,7 @@
|
|||
#ifdef ALSOFT_EAX
|
||||
#include <cassert>
|
||||
|
||||
#include "eax_exception.h"
|
||||
#include "eax/exception.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
const EffectList gEffectList[16]{
|
||||
|
|
@ -86,6 +86,7 @@ effect_exception::effect_exception(ALenum code, const char *msg, ...) : mErrorCo
|
|||
setMessage(msg, args);
|
||||
va_end(args);
|
||||
}
|
||||
effect_exception::~effect_exception() = default;
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
@ -139,7 +140,7 @@ const EffectPropsItem *getEffectPropsItemByType(ALenum type)
|
|||
auto iter = std::find_if(std::begin(EffectPropsList), std::end(EffectPropsList),
|
||||
[type](const EffectPropsItem &item) noexcept -> bool
|
||||
{ return item.Type == type; });
|
||||
return (iter != std::end(EffectPropsList)) ? std::addressof(*iter) : nullptr;
|
||||
return (iter != std::end(EffectPropsList)) ? al::to_address(iter) : nullptr;
|
||||
}
|
||||
|
||||
void InitEffectParams(ALeffect *effect, ALenum type)
|
||||
|
|
@ -166,14 +167,14 @@ bool EnsureEffects(ALCdevice *device, size_t needed)
|
|||
|
||||
while(needed > count)
|
||||
{
|
||||
if UNLIKELY(device->EffectList.size() >= 1<<25)
|
||||
if(device->EffectList.size() >= 1<<25) UNLIKELY
|
||||
return false;
|
||||
|
||||
device->EffectList.emplace_back();
|
||||
auto sublist = device->EffectList.end() - 1;
|
||||
sublist->FreeMask = ~0_u64;
|
||||
sublist->Effects = static_cast<ALeffect*>(al_calloc(alignof(ALeffect), sizeof(ALeffect)*64));
|
||||
if UNLIKELY(!sublist->Effects)
|
||||
if(!sublist->Effects) UNLIKELY
|
||||
{
|
||||
device->EffectList.pop_back();
|
||||
return false;
|
||||
|
|
@ -219,10 +220,10 @@ inline ALeffect *LookupEffect(ALCdevice *device, ALuint id)
|
|||
const size_t lidx{(id-1) >> 6};
|
||||
const ALuint slidx{(id-1) & 0x3f};
|
||||
|
||||
if UNLIKELY(lidx >= device->EffectList.size())
|
||||
if(lidx >= device->EffectList.size()) UNLIKELY
|
||||
return nullptr;
|
||||
EffectSubList &sublist = device->EffectList[lidx];
|
||||
if UNLIKELY(sublist.FreeMask & (1_u64 << slidx))
|
||||
if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY
|
||||
return nullptr;
|
||||
return sublist.Effects + slidx;
|
||||
}
|
||||
|
|
@ -233,11 +234,11 @@ AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if UNLIKELY(n < 0)
|
||||
if(n < 0) UNLIKELY
|
||||
context->setError(AL_INVALID_VALUE, "Generating %d effects", n);
|
||||
if UNLIKELY(n <= 0) return;
|
||||
if(n <= 0) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->EffectLock};
|
||||
|
|
@ -247,7 +248,7 @@ START_API_FUNC
|
|||
return;
|
||||
}
|
||||
|
||||
if LIKELY(n == 1)
|
||||
if(n == 1) LIKELY
|
||||
{
|
||||
/* Special handling for the easy and normal case. */
|
||||
ALeffect *effect{AllocEffect(device)};
|
||||
|
|
@ -273,11 +274,11 @@ AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if UNLIKELY(n < 0)
|
||||
if(n < 0) UNLIKELY
|
||||
context->setError(AL_INVALID_VALUE, "Deleting %d effects", n);
|
||||
if UNLIKELY(n <= 0) return;
|
||||
if(n <= 0) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->EffectLock};
|
||||
|
|
@ -288,7 +289,7 @@ START_API_FUNC
|
|||
|
||||
const ALuint *effects_end = effects + n;
|
||||
auto inveffect = std::find_if_not(effects, effects_end, validate_effect);
|
||||
if UNLIKELY(inveffect != effects_end)
|
||||
if(inveffect != effects_end) UNLIKELY
|
||||
{
|
||||
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", *inveffect);
|
||||
return;
|
||||
|
|
@ -308,7 +309,7 @@ AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if LIKELY(context)
|
||||
if(context) LIKELY
|
||||
{
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->EffectLock};
|
||||
|
|
@ -323,13 +324,13 @@ AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->EffectLock};
|
||||
|
||||
ALeffect *aleffect{LookupEffect(device, effect)};
|
||||
if UNLIKELY(!aleffect)
|
||||
if(!aleffect) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
|
||||
else if(param == AL_EFFECT_TYPE)
|
||||
{
|
||||
|
|
@ -373,13 +374,13 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->EffectLock};
|
||||
|
||||
ALeffect *aleffect{LookupEffect(device, effect)};
|
||||
if UNLIKELY(!aleffect)
|
||||
if(!aleffect) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
|
||||
else try
|
||||
{
|
||||
|
|
@ -396,13 +397,13 @@ AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat value)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->EffectLock};
|
||||
|
||||
ALeffect *aleffect{LookupEffect(device, effect)};
|
||||
if UNLIKELY(!aleffect)
|
||||
if(!aleffect) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
|
||||
else try
|
||||
{
|
||||
|
|
@ -419,13 +420,13 @@ AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *v
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->EffectLock};
|
||||
|
||||
ALeffect *aleffect{LookupEffect(device, effect)};
|
||||
if UNLIKELY(!aleffect)
|
||||
if(!aleffect) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
|
||||
else try
|
||||
{
|
||||
|
|
@ -442,13 +443,13 @@ AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->EffectLock};
|
||||
|
||||
const ALeffect *aleffect{LookupEffect(device, effect)};
|
||||
if UNLIKELY(!aleffect)
|
||||
if(!aleffect) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
|
||||
else if(param == AL_EFFECT_TYPE)
|
||||
*value = aleffect->type;
|
||||
|
|
@ -474,13 +475,13 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->EffectLock};
|
||||
|
||||
const ALeffect *aleffect{LookupEffect(device, effect)};
|
||||
if UNLIKELY(!aleffect)
|
||||
if(!aleffect) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
|
||||
else try
|
||||
{
|
||||
|
|
@ -497,13 +498,13 @@ AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *value
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->EffectLock};
|
||||
|
||||
const ALeffect *aleffect{LookupEffect(device, effect)};
|
||||
if UNLIKELY(!aleffect)
|
||||
if(!aleffect) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
|
||||
else try
|
||||
{
|
||||
|
|
@ -520,13 +521,13 @@ AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *valu
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->EffectLock};
|
||||
|
||||
const ALeffect *aleffect{LookupEffect(device, effect)};
|
||||
if UNLIKELY(!aleffect)
|
||||
if(!aleffect) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
|
||||
else try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,9 +13,8 @@
|
|||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include "alnumeric.h"
|
||||
|
||||
#include "al/eax_exception.h"
|
||||
#include "al/eax_utils.h"
|
||||
#include "al/eax/exception.h"
|
||||
#include "al/eax/utils.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
|
||||
|
|
@ -119,430 +118,135 @@ const EffectProps AutowahEffectProps{genDefaultProps()};
|
|||
#ifdef ALSOFT_EAX
|
||||
namespace {
|
||||
|
||||
using EaxAutoWahEffectDirtyFlagsValue = std::uint_least8_t;
|
||||
using AutowahCommitter = EaxCommitter<EaxAutowahCommitter>;
|
||||
|
||||
struct EaxAutoWahEffectDirtyFlags
|
||||
{
|
||||
using EaxIsBitFieldStruct = bool;
|
||||
|
||||
EaxAutoWahEffectDirtyFlagsValue flAttackTime : 1;
|
||||
EaxAutoWahEffectDirtyFlagsValue flReleaseTime : 1;
|
||||
EaxAutoWahEffectDirtyFlagsValue lResonance : 1;
|
||||
EaxAutoWahEffectDirtyFlagsValue lPeakLevel : 1;
|
||||
}; // EaxAutoWahEffectDirtyFlags
|
||||
|
||||
|
||||
class EaxAutoWahEffect final :
|
||||
public EaxEffect
|
||||
{
|
||||
public:
|
||||
EaxAutoWahEffect();
|
||||
|
||||
|
||||
void dispatch(const EaxEaxCall& eax_call) override;
|
||||
|
||||
// [[nodiscard]]
|
||||
bool apply_deferred() override;
|
||||
|
||||
private:
|
||||
EAXAUTOWAHPROPERTIES eax_{};
|
||||
EAXAUTOWAHPROPERTIES eax_d_{};
|
||||
EaxAutoWahEffectDirtyFlags eax_dirty_flags_{};
|
||||
|
||||
|
||||
void set_eax_defaults();
|
||||
|
||||
|
||||
void set_efx_attack_time();
|
||||
|
||||
void set_efx_release_time();
|
||||
|
||||
void set_efx_resonance();
|
||||
|
||||
void set_efx_peak_gain();
|
||||
|
||||
void set_efx_defaults();
|
||||
|
||||
|
||||
void get(const EaxEaxCall& eax_call);
|
||||
|
||||
|
||||
void validate_attack_time(
|
||||
float flAttackTime);
|
||||
|
||||
void validate_release_time(
|
||||
float flReleaseTime);
|
||||
|
||||
void validate_resonance(
|
||||
long lResonance);
|
||||
|
||||
void validate_peak_level(
|
||||
long lPeakLevel);
|
||||
|
||||
void validate_all(
|
||||
const EAXAUTOWAHPROPERTIES& eax_all);
|
||||
|
||||
|
||||
void defer_attack_time(
|
||||
float flAttackTime);
|
||||
|
||||
void defer_release_time(
|
||||
float flReleaseTime);
|
||||
|
||||
void defer_resonance(
|
||||
long lResonance);
|
||||
|
||||
void defer_peak_level(
|
||||
long lPeakLevel);
|
||||
|
||||
void defer_all(
|
||||
const EAXAUTOWAHPROPERTIES& eax_all);
|
||||
|
||||
|
||||
void defer_attack_time(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void defer_release_time(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void defer_resonance(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void defer_peak_level(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void defer_all(
|
||||
const EaxEaxCall& eax_call);
|
||||
|
||||
void set(const EaxEaxCall& eax_call);
|
||||
}; // EaxAutoWahEffect
|
||||
|
||||
|
||||
class EaxAutoWahEffectException :
|
||||
public EaxException
|
||||
{
|
||||
public:
|
||||
explicit EaxAutoWahEffectException(
|
||||
const char* message)
|
||||
:
|
||||
EaxException{"EAX_AUTO_WAH_EFFECT", message}
|
||||
struct AttackTimeValidator {
|
||||
void operator()(float flAttackTime) const
|
||||
{
|
||||
eax_validate_range<AutowahCommitter::Exception>(
|
||||
"Attack Time",
|
||||
flAttackTime,
|
||||
EAXAUTOWAH_MINATTACKTIME,
|
||||
EAXAUTOWAH_MAXATTACKTIME);
|
||||
}
|
||||
}; // EaxAutoWahEffectException
|
||||
}; // AttackTimeValidator
|
||||
|
||||
|
||||
EaxAutoWahEffect::EaxAutoWahEffect()
|
||||
: EaxEffect{AL_EFFECT_AUTOWAH}
|
||||
{
|
||||
set_eax_defaults();
|
||||
set_efx_defaults();
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::dispatch(const EaxEaxCall& eax_call)
|
||||
{
|
||||
eax_call.is_get() ? get(eax_call) : set(eax_call);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::set_eax_defaults()
|
||||
{
|
||||
eax_.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME;
|
||||
eax_.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME;
|
||||
eax_.lResonance = EAXAUTOWAH_DEFAULTRESONANCE;
|
||||
eax_.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL;
|
||||
|
||||
eax_d_ = eax_;
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::set_efx_attack_time()
|
||||
{
|
||||
const auto attack_time = clamp(
|
||||
eax_.flAttackTime,
|
||||
AL_AUTOWAH_MIN_ATTACK_TIME,
|
||||
AL_AUTOWAH_MAX_ATTACK_TIME);
|
||||
|
||||
al_effect_props_.Autowah.AttackTime = attack_time;
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::set_efx_release_time()
|
||||
{
|
||||
const auto release_time = clamp(
|
||||
eax_.flReleaseTime,
|
||||
AL_AUTOWAH_MIN_RELEASE_TIME,
|
||||
AL_AUTOWAH_MAX_RELEASE_TIME);
|
||||
|
||||
al_effect_props_.Autowah.ReleaseTime = release_time;
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::set_efx_resonance()
|
||||
{
|
||||
const auto resonance = clamp(
|
||||
level_mb_to_gain(static_cast<float>(eax_.lResonance)),
|
||||
AL_AUTOWAH_MIN_RESONANCE,
|
||||
AL_AUTOWAH_MAX_RESONANCE);
|
||||
|
||||
al_effect_props_.Autowah.Resonance = resonance;
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::set_efx_peak_gain()
|
||||
{
|
||||
const auto peak_gain = clamp(
|
||||
level_mb_to_gain(static_cast<float>(eax_.lPeakLevel)),
|
||||
AL_AUTOWAH_MIN_PEAK_GAIN,
|
||||
AL_AUTOWAH_MAX_PEAK_GAIN);
|
||||
|
||||
al_effect_props_.Autowah.PeakGain = peak_gain;
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::set_efx_defaults()
|
||||
{
|
||||
set_efx_attack_time();
|
||||
set_efx_release_time();
|
||||
set_efx_resonance();
|
||||
set_efx_peak_gain();
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::get(const EaxEaxCall& eax_call)
|
||||
{
|
||||
switch (eax_call.get_property_id())
|
||||
struct ReleaseTimeValidator {
|
||||
void operator()(float flReleaseTime) const
|
||||
{
|
||||
case EAXAUTOWAH_NONE:
|
||||
break;
|
||||
|
||||
case EAXAUTOWAH_ALLPARAMETERS:
|
||||
eax_call.set_value<EaxAutoWahEffectException>(eax_);
|
||||
break;
|
||||
|
||||
case EAXAUTOWAH_ATTACKTIME:
|
||||
eax_call.set_value<EaxAutoWahEffectException>(eax_.flAttackTime);
|
||||
break;
|
||||
|
||||
case EAXAUTOWAH_RELEASETIME:
|
||||
eax_call.set_value<EaxAutoWahEffectException>(eax_.flReleaseTime);
|
||||
break;
|
||||
|
||||
case EAXAUTOWAH_RESONANCE:
|
||||
eax_call.set_value<EaxAutoWahEffectException>(eax_.lResonance);
|
||||
break;
|
||||
|
||||
case EAXAUTOWAH_PEAKLEVEL:
|
||||
eax_call.set_value<EaxAutoWahEffectException>(eax_.lPeakLevel);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxAutoWahEffectException{"Unsupported property id."};
|
||||
eax_validate_range<AutowahCommitter::Exception>(
|
||||
"Release Time",
|
||||
flReleaseTime,
|
||||
EAXAUTOWAH_MINRELEASETIME,
|
||||
EAXAUTOWAH_MAXRELEASETIME);
|
||||
}
|
||||
}
|
||||
}; // ReleaseTimeValidator
|
||||
|
||||
void EaxAutoWahEffect::validate_attack_time(
|
||||
float flAttackTime)
|
||||
{
|
||||
eax_validate_range<EaxAutoWahEffectException>(
|
||||
"Attack Time",
|
||||
flAttackTime,
|
||||
EAXAUTOWAH_MINATTACKTIME,
|
||||
EAXAUTOWAH_MAXATTACKTIME);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::validate_release_time(
|
||||
float flReleaseTime)
|
||||
{
|
||||
eax_validate_range<EaxAutoWahEffectException>(
|
||||
"Release Time",
|
||||
flReleaseTime,
|
||||
EAXAUTOWAH_MINRELEASETIME,
|
||||
EAXAUTOWAH_MAXRELEASETIME);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::validate_resonance(
|
||||
long lResonance)
|
||||
{
|
||||
eax_validate_range<EaxAutoWahEffectException>(
|
||||
"Resonance",
|
||||
lResonance,
|
||||
EAXAUTOWAH_MINRESONANCE,
|
||||
EAXAUTOWAH_MAXRESONANCE);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::validate_peak_level(
|
||||
long lPeakLevel)
|
||||
{
|
||||
eax_validate_range<EaxAutoWahEffectException>(
|
||||
"Peak Level",
|
||||
lPeakLevel,
|
||||
EAXAUTOWAH_MINPEAKLEVEL,
|
||||
EAXAUTOWAH_MAXPEAKLEVEL);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::validate_all(
|
||||
const EAXAUTOWAHPROPERTIES& eax_all)
|
||||
{
|
||||
validate_attack_time(eax_all.flAttackTime);
|
||||
validate_release_time(eax_all.flReleaseTime);
|
||||
validate_resonance(eax_all.lResonance);
|
||||
validate_peak_level(eax_all.lPeakLevel);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::defer_attack_time(
|
||||
float flAttackTime)
|
||||
{
|
||||
eax_d_.flAttackTime = flAttackTime;
|
||||
eax_dirty_flags_.flAttackTime = (eax_.flAttackTime != eax_d_.flAttackTime);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::defer_release_time(
|
||||
float flReleaseTime)
|
||||
{
|
||||
eax_d_.flReleaseTime = flReleaseTime;
|
||||
eax_dirty_flags_.flReleaseTime = (eax_.flReleaseTime != eax_d_.flReleaseTime);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::defer_resonance(
|
||||
long lResonance)
|
||||
{
|
||||
eax_d_.lResonance = lResonance;
|
||||
eax_dirty_flags_.lResonance = (eax_.lResonance != eax_d_.lResonance);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::defer_peak_level(
|
||||
long lPeakLevel)
|
||||
{
|
||||
eax_d_.lPeakLevel = lPeakLevel;
|
||||
eax_dirty_flags_.lPeakLevel = (eax_.lPeakLevel != eax_d_.lPeakLevel);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::defer_all(
|
||||
const EAXAUTOWAHPROPERTIES& eax_all)
|
||||
{
|
||||
validate_all(eax_all);
|
||||
|
||||
defer_attack_time(eax_all.flAttackTime);
|
||||
defer_release_time(eax_all.flReleaseTime);
|
||||
defer_resonance(eax_all.lResonance);
|
||||
defer_peak_level(eax_all.lPeakLevel);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::defer_attack_time(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& attack_time =
|
||||
eax_call.get_value<EaxAutoWahEffectException, const decltype(EAXAUTOWAHPROPERTIES::flAttackTime)>();
|
||||
|
||||
validate_attack_time(attack_time);
|
||||
defer_attack_time(attack_time);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::defer_release_time(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& release_time =
|
||||
eax_call.get_value<EaxAutoWahEffectException, const decltype(EAXAUTOWAHPROPERTIES::flReleaseTime)>();
|
||||
|
||||
validate_release_time(release_time);
|
||||
defer_release_time(release_time);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::defer_resonance(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& resonance =
|
||||
eax_call.get_value<EaxAutoWahEffectException, const decltype(EAXAUTOWAHPROPERTIES::lResonance)>();
|
||||
|
||||
validate_resonance(resonance);
|
||||
defer_resonance(resonance);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::defer_peak_level(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& peak_level =
|
||||
eax_call.get_value<EaxAutoWahEffectException, const decltype(EAXAUTOWAHPROPERTIES::lPeakLevel)>();
|
||||
|
||||
validate_peak_level(peak_level);
|
||||
defer_peak_level(peak_level);
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::defer_all(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& all =
|
||||
eax_call.get_value<EaxAutoWahEffectException, const EAXAUTOWAHPROPERTIES>();
|
||||
|
||||
validate_all(all);
|
||||
defer_all(all);
|
||||
}
|
||||
|
||||
// [[nodiscard]]
|
||||
bool EaxAutoWahEffect::apply_deferred()
|
||||
{
|
||||
if (eax_dirty_flags_ == EaxAutoWahEffectDirtyFlags{})
|
||||
struct ResonanceValidator {
|
||||
void operator()(long lResonance) const
|
||||
{
|
||||
eax_validate_range<AutowahCommitter::Exception>(
|
||||
"Resonance",
|
||||
lResonance,
|
||||
EAXAUTOWAH_MINRESONANCE,
|
||||
EAXAUTOWAH_MAXRESONANCE);
|
||||
}
|
||||
}; // ResonanceValidator
|
||||
|
||||
struct PeakLevelValidator {
|
||||
void operator()(long lPeakLevel) const
|
||||
{
|
||||
eax_validate_range<AutowahCommitter::Exception>(
|
||||
"Peak Level",
|
||||
lPeakLevel,
|
||||
EAXAUTOWAH_MINPEAKLEVEL,
|
||||
EAXAUTOWAH_MAXPEAKLEVEL);
|
||||
}
|
||||
}; // PeakLevelValidator
|
||||
|
||||
struct AllValidator {
|
||||
void operator()(const EAXAUTOWAHPROPERTIES& all) const
|
||||
{
|
||||
AttackTimeValidator{}(all.flAttackTime);
|
||||
ReleaseTimeValidator{}(all.flReleaseTime);
|
||||
ResonanceValidator{}(all.lResonance);
|
||||
PeakLevelValidator{}(all.lPeakLevel);
|
||||
}
|
||||
}; // AllValidator
|
||||
|
||||
} // namespace
|
||||
|
||||
template<>
|
||||
struct AutowahCommitter::Exception : public EaxException
|
||||
{
|
||||
explicit Exception(const char *message) : EaxException{"EAX_AUTOWAH_EFFECT", message}
|
||||
{ }
|
||||
};
|
||||
|
||||
template<>
|
||||
[[noreturn]] void AutowahCommitter::fail(const char *message)
|
||||
{
|
||||
throw Exception{message};
|
||||
}
|
||||
|
||||
template<>
|
||||
bool AutowahCommitter::commit(const EaxEffectProps &props)
|
||||
{
|
||||
if(props.mType == mEaxProps.mType
|
||||
&& mEaxProps.mAutowah.flAttackTime == props.mAutowah.flAttackTime
|
||||
&& mEaxProps.mAutowah.flReleaseTime == props.mAutowah.flReleaseTime
|
||||
&& mEaxProps.mAutowah.lResonance == props.mAutowah.lResonance
|
||||
&& mEaxProps.mAutowah.lPeakLevel == props.mAutowah.lPeakLevel)
|
||||
return false;
|
||||
}
|
||||
|
||||
eax_ = eax_d_;
|
||||
mEaxProps = props;
|
||||
|
||||
if (eax_dirty_flags_.flAttackTime)
|
||||
{
|
||||
set_efx_attack_time();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flReleaseTime)
|
||||
{
|
||||
set_efx_release_time();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.lResonance)
|
||||
{
|
||||
set_efx_resonance();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.lPeakLevel)
|
||||
{
|
||||
set_efx_peak_gain();
|
||||
}
|
||||
|
||||
eax_dirty_flags_ = EaxAutoWahEffectDirtyFlags{};
|
||||
mAlProps.Autowah.AttackTime = props.mAutowah.flAttackTime;
|
||||
mAlProps.Autowah.ReleaseTime = props.mAutowah.flReleaseTime;
|
||||
mAlProps.Autowah.Resonance = level_mb_to_gain(static_cast<float>(props.mAutowah.lResonance));
|
||||
mAlProps.Autowah.PeakGain = level_mb_to_gain(static_cast<float>(props.mAutowah.lPeakLevel));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EaxAutoWahEffect::set(const EaxEaxCall& eax_call)
|
||||
template<>
|
||||
void AutowahCommitter::SetDefaults(EaxEffectProps &props)
|
||||
{
|
||||
switch (eax_call.get_property_id())
|
||||
props.mType = EaxEffectType::Autowah;
|
||||
props.mAutowah.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME;
|
||||
props.mAutowah.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME;
|
||||
props.mAutowah.lResonance = EAXAUTOWAH_DEFAULTRESONANCE;
|
||||
props.mAutowah.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL;
|
||||
}
|
||||
|
||||
template<>
|
||||
void AutowahCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
|
||||
{
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXAUTOWAH_NONE:
|
||||
break;
|
||||
|
||||
case EAXAUTOWAH_ALLPARAMETERS:
|
||||
defer_all(eax_call);
|
||||
break;
|
||||
|
||||
case EAXAUTOWAH_ATTACKTIME:
|
||||
defer_attack_time(eax_call);
|
||||
break;
|
||||
|
||||
case EAXAUTOWAH_RELEASETIME:
|
||||
defer_release_time(eax_call);
|
||||
break;
|
||||
|
||||
case EAXAUTOWAH_RESONANCE:
|
||||
defer_resonance(eax_call);
|
||||
break;
|
||||
|
||||
case EAXAUTOWAH_PEAKLEVEL:
|
||||
defer_peak_level(eax_call);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxAutoWahEffectException{"Unsupported property id."};
|
||||
case EAXAUTOWAH_NONE: break;
|
||||
case EAXAUTOWAH_ALLPARAMETERS: call.set_value<Exception>(props.mAutowah); break;
|
||||
case EAXAUTOWAH_ATTACKTIME: call.set_value<Exception>(props.mAutowah.flAttackTime); break;
|
||||
case EAXAUTOWAH_RELEASETIME: call.set_value<Exception>(props.mAutowah.flReleaseTime); break;
|
||||
case EAXAUTOWAH_RESONANCE: call.set_value<Exception>(props.mAutowah.lResonance); break;
|
||||
case EAXAUTOWAH_PEAKLEVEL: call.set_value<Exception>(props.mAutowah.lPeakLevel); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EaxEffectUPtr eax_create_eax_auto_wah_effect()
|
||||
template<>
|
||||
void AutowahCommitter::Set(const EaxCall &call, EaxEffectProps &props)
|
||||
{
|
||||
return std::make_unique<::EaxAutoWahEffect>();
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXAUTOWAH_NONE: break;
|
||||
case EAXAUTOWAH_ALLPARAMETERS: defer<AllValidator>(call, props.mAutowah); break;
|
||||
case EAXAUTOWAH_ATTACKTIME: defer<AttackTimeValidator>(call, props.mAutowah.flAttackTime); break;
|
||||
case EAXAUTOWAH_RELEASETIME: defer<ReleaseTimeValidator>(call, props.mAutowah.flReleaseTime); break;
|
||||
case EAXAUTOWAH_RESONANCE: defer<ResonanceValidator>(call, props.mAutowah.lResonance); break;
|
||||
case EAXAUTOWAH_PEAKLEVEL: defer<PeakLevelValidator>(call, props.mAutowah.lPeakLevel); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ALSOFT_EAX
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -9,9 +9,8 @@
|
|||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include "alnumeric.h"
|
||||
|
||||
#include "al/eax_exception.h"
|
||||
#include "al/eax_utils.h"
|
||||
#include "al/eax/exception.h"
|
||||
#include "al/eax/utils.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
|
||||
|
|
@ -81,216 +80,83 @@ const EffectProps CompressorEffectProps{genDefaultProps()};
|
|||
#ifdef ALSOFT_EAX
|
||||
namespace {
|
||||
|
||||
using EaxCompressorEffectDirtyFlagsValue = std::uint_least8_t;
|
||||
using CompressorCommitter = EaxCommitter<EaxCompressorCommitter>;
|
||||
|
||||
struct EaxCompressorEffectDirtyFlags
|
||||
{
|
||||
using EaxIsBitFieldStruct = bool;
|
||||
|
||||
EaxCompressorEffectDirtyFlagsValue ulOnOff : 1;
|
||||
}; // EaxCompressorEffectDirtyFlags
|
||||
|
||||
|
||||
class EaxCompressorEffect final :
|
||||
public EaxEffect
|
||||
{
|
||||
public:
|
||||
EaxCompressorEffect();
|
||||
|
||||
|
||||
void dispatch(const EaxEaxCall& eax_call) override;
|
||||
|
||||
// [[nodiscard]]
|
||||
bool apply_deferred() override;
|
||||
|
||||
private:
|
||||
EAXAGCCOMPRESSORPROPERTIES eax_{};
|
||||
EAXAGCCOMPRESSORPROPERTIES eax_d_{};
|
||||
EaxCompressorEffectDirtyFlags eax_dirty_flags_{};
|
||||
|
||||
|
||||
void set_eax_defaults();
|
||||
|
||||
void set_efx_on_off();
|
||||
void set_efx_defaults();
|
||||
|
||||
void get(const EaxEaxCall& eax_call);
|
||||
|
||||
void validate_on_off(unsigned long ulOnOff);
|
||||
void validate_all(const EAXAGCCOMPRESSORPROPERTIES& eax_all);
|
||||
|
||||
void defer_on_off(unsigned long ulOnOff);
|
||||
void defer_all(const EAXAGCCOMPRESSORPROPERTIES& eax_all);
|
||||
|
||||
void defer_on_off(const EaxEaxCall& eax_call);
|
||||
void defer_all(const EaxEaxCall& eax_call);
|
||||
|
||||
void set(const EaxEaxCall& eax_call);
|
||||
}; // EaxCompressorEffect
|
||||
|
||||
|
||||
class EaxCompressorEffectException :
|
||||
public EaxException
|
||||
{
|
||||
public:
|
||||
explicit EaxCompressorEffectException(
|
||||
const char* message)
|
||||
:
|
||||
EaxException{"EAX_COMPRESSOR_EFFECT", message}
|
||||
struct OnOffValidator {
|
||||
void operator()(unsigned long ulOnOff) const
|
||||
{
|
||||
eax_validate_range<CompressorCommitter::Exception>(
|
||||
"On-Off",
|
||||
ulOnOff,
|
||||
EAXAGCCOMPRESSOR_MINONOFF,
|
||||
EAXAGCCOMPRESSOR_MAXONOFF);
|
||||
}
|
||||
}; // EaxCompressorEffectException
|
||||
}; // OnOffValidator
|
||||
|
||||
|
||||
EaxCompressorEffect::EaxCompressorEffect()
|
||||
: EaxEffect{AL_EFFECT_COMPRESSOR}
|
||||
{
|
||||
set_eax_defaults();
|
||||
set_efx_defaults();
|
||||
}
|
||||
|
||||
// [[nodiscard]]
|
||||
void EaxCompressorEffect::dispatch(const EaxEaxCall& eax_call)
|
||||
{
|
||||
eax_call.is_get() ? get(eax_call) : set(eax_call);
|
||||
}
|
||||
|
||||
void EaxCompressorEffect::set_eax_defaults()
|
||||
{
|
||||
eax_.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF;
|
||||
|
||||
eax_d_ = eax_;
|
||||
}
|
||||
|
||||
void EaxCompressorEffect::set_efx_on_off()
|
||||
{
|
||||
const auto on_off = clamp(
|
||||
static_cast<ALint>(eax_.ulOnOff),
|
||||
AL_COMPRESSOR_MIN_ONOFF,
|
||||
AL_COMPRESSOR_MAX_ONOFF);
|
||||
|
||||
al_effect_props_.Compressor.OnOff = (on_off != AL_FALSE);
|
||||
}
|
||||
|
||||
void EaxCompressorEffect::set_efx_defaults()
|
||||
{
|
||||
set_efx_on_off();
|
||||
}
|
||||
|
||||
void EaxCompressorEffect::get(const EaxEaxCall& eax_call)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
struct AllValidator {
|
||||
void operator()(const EAXAGCCOMPRESSORPROPERTIES& all) const
|
||||
{
|
||||
case EAXAGCCOMPRESSOR_NONE:
|
||||
break;
|
||||
|
||||
case EAXAGCCOMPRESSOR_ALLPARAMETERS:
|
||||
eax_call.set_value<EaxCompressorEffectException>(eax_);
|
||||
break;
|
||||
|
||||
case EAXAGCCOMPRESSOR_ONOFF:
|
||||
eax_call.set_value<EaxCompressorEffectException>(eax_.ulOnOff);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxCompressorEffectException{"Unsupported property id."};
|
||||
OnOffValidator{}(all.ulOnOff);
|
||||
}
|
||||
}
|
||||
|
||||
void EaxCompressorEffect::validate_on_off(
|
||||
unsigned long ulOnOff)
|
||||
{
|
||||
eax_validate_range<EaxCompressorEffectException>(
|
||||
"On-Off",
|
||||
ulOnOff,
|
||||
EAXAGCCOMPRESSOR_MINONOFF,
|
||||
EAXAGCCOMPRESSOR_MAXONOFF);
|
||||
}
|
||||
|
||||
void EaxCompressorEffect::validate_all(
|
||||
const EAXAGCCOMPRESSORPROPERTIES& eax_all)
|
||||
{
|
||||
validate_on_off(eax_all.ulOnOff);
|
||||
}
|
||||
|
||||
void EaxCompressorEffect::defer_on_off(
|
||||
unsigned long ulOnOff)
|
||||
{
|
||||
eax_d_.ulOnOff = ulOnOff;
|
||||
eax_dirty_flags_.ulOnOff = (eax_.ulOnOff != eax_d_.ulOnOff);
|
||||
}
|
||||
|
||||
void EaxCompressorEffect::defer_all(
|
||||
const EAXAGCCOMPRESSORPROPERTIES& eax_all)
|
||||
{
|
||||
defer_on_off(eax_all.ulOnOff);
|
||||
}
|
||||
|
||||
void EaxCompressorEffect::defer_on_off(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& on_off =
|
||||
eax_call.get_value<EaxCompressorEffectException, const decltype(EAXAGCCOMPRESSORPROPERTIES::ulOnOff)>();
|
||||
|
||||
validate_on_off(on_off);
|
||||
defer_on_off(on_off);
|
||||
}
|
||||
|
||||
void EaxCompressorEffect::defer_all(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& all =
|
||||
eax_call.get_value<EaxCompressorEffectException, const EAXAGCCOMPRESSORPROPERTIES>();
|
||||
|
||||
validate_all(all);
|
||||
defer_all(all);
|
||||
}
|
||||
|
||||
// [[nodiscard]]
|
||||
bool EaxCompressorEffect::apply_deferred()
|
||||
{
|
||||
if (eax_dirty_flags_ == EaxCompressorEffectDirtyFlags{})
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
eax_ = eax_d_;
|
||||
|
||||
if (eax_dirty_flags_.ulOnOff)
|
||||
{
|
||||
set_efx_on_off();
|
||||
}
|
||||
|
||||
eax_dirty_flags_ = EaxCompressorEffectDirtyFlags{};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EaxCompressorEffect::set(const EaxEaxCall& eax_call)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
{
|
||||
case EAXAGCCOMPRESSOR_NONE:
|
||||
break;
|
||||
|
||||
case EAXAGCCOMPRESSOR_ALLPARAMETERS:
|
||||
defer_all(eax_call);
|
||||
break;
|
||||
|
||||
case EAXAGCCOMPRESSOR_ONOFF:
|
||||
defer_on_off(eax_call);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxCompressorEffectException{"Unsupported property id."};
|
||||
}
|
||||
}
|
||||
}; // AllValidator
|
||||
|
||||
} // namespace
|
||||
|
||||
EaxEffectUPtr eax_create_eax_compressor_effect()
|
||||
template<>
|
||||
struct CompressorCommitter::Exception : public EaxException
|
||||
{
|
||||
return std::make_unique<EaxCompressorEffect>();
|
||||
explicit Exception(const char *message) : EaxException{"EAX_CHORUS_EFFECT", message}
|
||||
{ }
|
||||
};
|
||||
|
||||
template<>
|
||||
[[noreturn]] void CompressorCommitter::fail(const char *message)
|
||||
{
|
||||
throw Exception{message};
|
||||
}
|
||||
|
||||
template<>
|
||||
bool CompressorCommitter::commit(const EaxEffectProps &props)
|
||||
{
|
||||
if(props.mType == mEaxProps.mType
|
||||
&& props.mCompressor.ulOnOff == mEaxProps.mCompressor.ulOnOff)
|
||||
return false;
|
||||
|
||||
mEaxProps = props;
|
||||
|
||||
mAlProps.Compressor.OnOff = (props.mCompressor.ulOnOff != 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void CompressorCommitter::SetDefaults(EaxEffectProps &props)
|
||||
{
|
||||
props.mType = EaxEffectType::Compressor;
|
||||
props.mCompressor.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF;
|
||||
}
|
||||
|
||||
template<>
|
||||
void CompressorCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
|
||||
{
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXAGCCOMPRESSOR_NONE: break;
|
||||
case EAXAGCCOMPRESSOR_ALLPARAMETERS: call.set_value<Exception>(props.mCompressor); break;
|
||||
case EAXAGCCOMPRESSOR_ONOFF: call.set_value<Exception>(props.mCompressor.ulOnOff); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void CompressorCommitter::Set(const EaxCall &call, EaxEffectProps &props)
|
||||
{
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXAGCCOMPRESSOR_NONE: break;
|
||||
case EAXAGCCOMPRESSOR_ALLPARAMETERS: defer<AllValidator>(call, props.mCompressor); break;
|
||||
case EAXAGCCOMPRESSOR_ONOFF: defer<OnOffValidator>(call, props.mCompressor.ulOnOff); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ALSOFT_EAX
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@
|
|||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include "alnumeric.h"
|
||||
|
||||
#include "al/eax_exception.h"
|
||||
#include "al/eax_utils.h"
|
||||
#include "al/eax/exception.h"
|
||||
#include "al/eax/utils.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
|
||||
|
|
@ -123,449 +122,150 @@ const EffectProps DistortionEffectProps{genDefaultProps()};
|
|||
#ifdef ALSOFT_EAX
|
||||
namespace {
|
||||
|
||||
using EaxDistortionEffectDirtyFlagsValue = std::uint_least8_t;
|
||||
using DistortionCommitter = EaxCommitter<EaxDistortionCommitter>;
|
||||
|
||||
struct EaxDistortionEffectDirtyFlags
|
||||
{
|
||||
using EaxIsBitFieldStruct = bool;
|
||||
|
||||
EaxDistortionEffectDirtyFlagsValue flEdge : 1;
|
||||
EaxDistortionEffectDirtyFlagsValue lGain : 1;
|
||||
EaxDistortionEffectDirtyFlagsValue flLowPassCutOff : 1;
|
||||
EaxDistortionEffectDirtyFlagsValue flEQCenter : 1;
|
||||
EaxDistortionEffectDirtyFlagsValue flEQBandwidth : 1;
|
||||
}; // EaxDistortionEffectDirtyFlags
|
||||
|
||||
|
||||
class EaxDistortionEffect final :
|
||||
public EaxEffect
|
||||
{
|
||||
public:
|
||||
EaxDistortionEffect();
|
||||
|
||||
void dispatch(const EaxEaxCall& eax_call) override;
|
||||
|
||||
// [[nodiscard]]
|
||||
bool apply_deferred() override;
|
||||
|
||||
private:
|
||||
EAXDISTORTIONPROPERTIES eax_{};
|
||||
EAXDISTORTIONPROPERTIES eax_d_{};
|
||||
EaxDistortionEffectDirtyFlags eax_dirty_flags_{};
|
||||
|
||||
void set_eax_defaults();
|
||||
|
||||
void set_efx_edge();
|
||||
void set_efx_gain();
|
||||
void set_efx_lowpass_cutoff();
|
||||
void set_efx_eq_center();
|
||||
void set_efx_eq_bandwidth();
|
||||
void set_efx_defaults();
|
||||
|
||||
void get(const EaxEaxCall& eax_call);
|
||||
|
||||
void validate_edge(float flEdge);
|
||||
void validate_gain(long lGain);
|
||||
void validate_lowpass_cutoff(float flLowPassCutOff);
|
||||
void validate_eq_center(float flEQCenter);
|
||||
void validate_eq_bandwidth(float flEQBandwidth);
|
||||
void validate_all(const EAXDISTORTIONPROPERTIES& eax_all);
|
||||
|
||||
void defer_edge(float flEdge);
|
||||
void defer_gain(long lGain);
|
||||
void defer_low_pass_cutoff(float flLowPassCutOff);
|
||||
void defer_eq_center(float flEQCenter);
|
||||
void defer_eq_bandwidth(float flEQBandwidth);
|
||||
void defer_all(const EAXDISTORTIONPROPERTIES& eax_all);
|
||||
|
||||
void defer_edge(const EaxEaxCall& eax_call);
|
||||
void defer_gain(const EaxEaxCall& eax_call);
|
||||
void defer_low_pass_cutoff(const EaxEaxCall& eax_call);
|
||||
void defer_eq_center(const EaxEaxCall& eax_call);
|
||||
void defer_eq_bandwidth(const EaxEaxCall& eax_call);
|
||||
void defer_all(const EaxEaxCall& eax_call);
|
||||
|
||||
void set(const EaxEaxCall& eax_call);
|
||||
}; // EaxDistortionEffect
|
||||
|
||||
|
||||
class EaxDistortionEffectException :
|
||||
public EaxException
|
||||
{
|
||||
public:
|
||||
explicit EaxDistortionEffectException(
|
||||
const char* message)
|
||||
:
|
||||
EaxException{"EAX_DISTORTION_EFFECT", message}
|
||||
struct EdgeValidator {
|
||||
void operator()(float flEdge) const
|
||||
{
|
||||
eax_validate_range<DistortionCommitter::Exception>(
|
||||
"Edge",
|
||||
flEdge,
|
||||
EAXDISTORTION_MINEDGE,
|
||||
EAXDISTORTION_MAXEDGE);
|
||||
}
|
||||
}; // EaxDistortionEffectException
|
||||
}; // EdgeValidator
|
||||
|
||||
|
||||
EaxDistortionEffect::EaxDistortionEffect()
|
||||
: EaxEffect{AL_EFFECT_DISTORTION}
|
||||
{
|
||||
set_eax_defaults();
|
||||
set_efx_defaults();
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::dispatch(const EaxEaxCall& eax_call)
|
||||
{
|
||||
eax_call.is_get() ? get(eax_call) : set(eax_call);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::set_eax_defaults()
|
||||
{
|
||||
eax_.flEdge = EAXDISTORTION_DEFAULTEDGE;
|
||||
eax_.lGain = EAXDISTORTION_DEFAULTGAIN;
|
||||
eax_.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF;
|
||||
eax_.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER;
|
||||
eax_.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH;
|
||||
|
||||
eax_d_ = eax_;
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::set_efx_edge()
|
||||
{
|
||||
const auto edge = clamp(
|
||||
eax_.flEdge,
|
||||
AL_DISTORTION_MIN_EDGE,
|
||||
AL_DISTORTION_MAX_EDGE);
|
||||
|
||||
al_effect_props_.Distortion.Edge = edge;
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::set_efx_gain()
|
||||
{
|
||||
const auto gain = clamp(
|
||||
level_mb_to_gain(static_cast<float>(eax_.lGain)),
|
||||
AL_DISTORTION_MIN_GAIN,
|
||||
AL_DISTORTION_MAX_GAIN);
|
||||
|
||||
al_effect_props_.Distortion.Gain = gain;
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::set_efx_lowpass_cutoff()
|
||||
{
|
||||
const auto lowpass_cutoff = clamp(
|
||||
eax_.flLowPassCutOff,
|
||||
AL_DISTORTION_MIN_LOWPASS_CUTOFF,
|
||||
AL_DISTORTION_MAX_LOWPASS_CUTOFF);
|
||||
|
||||
al_effect_props_.Distortion.LowpassCutoff = lowpass_cutoff;
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::set_efx_eq_center()
|
||||
{
|
||||
const auto eq_center = clamp(
|
||||
eax_.flEQCenter,
|
||||
AL_DISTORTION_MIN_EQCENTER,
|
||||
AL_DISTORTION_MAX_EQCENTER);
|
||||
|
||||
al_effect_props_.Distortion.EQCenter = eq_center;
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::set_efx_eq_bandwidth()
|
||||
{
|
||||
const auto eq_bandwidth = clamp(
|
||||
eax_.flEdge,
|
||||
AL_DISTORTION_MIN_EQBANDWIDTH,
|
||||
AL_DISTORTION_MAX_EQBANDWIDTH);
|
||||
|
||||
al_effect_props_.Distortion.EQBandwidth = eq_bandwidth;
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::set_efx_defaults()
|
||||
{
|
||||
set_efx_edge();
|
||||
set_efx_gain();
|
||||
set_efx_lowpass_cutoff();
|
||||
set_efx_eq_center();
|
||||
set_efx_eq_bandwidth();
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::get(const EaxEaxCall& eax_call)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
struct GainValidator {
|
||||
void operator()(long lGain) const
|
||||
{
|
||||
case EAXDISTORTION_NONE:
|
||||
break;
|
||||
|
||||
case EAXDISTORTION_ALLPARAMETERS:
|
||||
eax_call.set_value<EaxDistortionEffectException>(eax_);
|
||||
break;
|
||||
|
||||
case EAXDISTORTION_EDGE:
|
||||
eax_call.set_value<EaxDistortionEffectException>(eax_.flEdge);
|
||||
break;
|
||||
|
||||
case EAXDISTORTION_GAIN:
|
||||
eax_call.set_value<EaxDistortionEffectException>(eax_.lGain);
|
||||
break;
|
||||
|
||||
case EAXDISTORTION_LOWPASSCUTOFF:
|
||||
eax_call.set_value<EaxDistortionEffectException>(eax_.flLowPassCutOff);
|
||||
break;
|
||||
|
||||
case EAXDISTORTION_EQCENTER:
|
||||
eax_call.set_value<EaxDistortionEffectException>(eax_.flEQCenter);
|
||||
break;
|
||||
|
||||
case EAXDISTORTION_EQBANDWIDTH:
|
||||
eax_call.set_value<EaxDistortionEffectException>(eax_.flEQBandwidth);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxDistortionEffectException{"Unsupported property id."};
|
||||
eax_validate_range<DistortionCommitter::Exception>(
|
||||
"Gain",
|
||||
lGain,
|
||||
EAXDISTORTION_MINGAIN,
|
||||
EAXDISTORTION_MAXGAIN);
|
||||
}
|
||||
}
|
||||
}; // GainValidator
|
||||
|
||||
void EaxDistortionEffect::validate_edge(
|
||||
float flEdge)
|
||||
{
|
||||
eax_validate_range<EaxDistortionEffectException>(
|
||||
"Edge",
|
||||
flEdge,
|
||||
EAXDISTORTION_MINEDGE,
|
||||
EAXDISTORTION_MAXEDGE);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::validate_gain(
|
||||
long lGain)
|
||||
{
|
||||
eax_validate_range<EaxDistortionEffectException>(
|
||||
"Gain",
|
||||
lGain,
|
||||
EAXDISTORTION_MINGAIN,
|
||||
EAXDISTORTION_MAXGAIN);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::validate_lowpass_cutoff(
|
||||
float flLowPassCutOff)
|
||||
{
|
||||
eax_validate_range<EaxDistortionEffectException>(
|
||||
"Low-pass Cut-off",
|
||||
flLowPassCutOff,
|
||||
EAXDISTORTION_MINLOWPASSCUTOFF,
|
||||
EAXDISTORTION_MAXLOWPASSCUTOFF);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::validate_eq_center(
|
||||
float flEQCenter)
|
||||
{
|
||||
eax_validate_range<EaxDistortionEffectException>(
|
||||
"EQ Center",
|
||||
flEQCenter,
|
||||
EAXDISTORTION_MINEQCENTER,
|
||||
EAXDISTORTION_MAXEQCENTER);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::validate_eq_bandwidth(
|
||||
float flEQBandwidth)
|
||||
{
|
||||
eax_validate_range<EaxDistortionEffectException>(
|
||||
"EQ Bandwidth",
|
||||
flEQBandwidth,
|
||||
EAXDISTORTION_MINEQBANDWIDTH,
|
||||
EAXDISTORTION_MAXEQBANDWIDTH);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::validate_all(
|
||||
const EAXDISTORTIONPROPERTIES& eax_all)
|
||||
{
|
||||
validate_edge(eax_all.flEdge);
|
||||
validate_gain(eax_all.lGain);
|
||||
validate_lowpass_cutoff(eax_all.flLowPassCutOff);
|
||||
validate_eq_center(eax_all.flEQCenter);
|
||||
validate_eq_bandwidth(eax_all.flEQBandwidth);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::defer_edge(
|
||||
float flEdge)
|
||||
{
|
||||
eax_d_.flEdge = flEdge;
|
||||
eax_dirty_flags_.flEdge = (eax_.flEdge != eax_d_.flEdge);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::defer_gain(
|
||||
long lGain)
|
||||
{
|
||||
eax_d_.lGain = lGain;
|
||||
eax_dirty_flags_.lGain = (eax_.lGain != eax_d_.lGain);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::defer_low_pass_cutoff(
|
||||
float flLowPassCutOff)
|
||||
{
|
||||
eax_d_.flLowPassCutOff = flLowPassCutOff;
|
||||
eax_dirty_flags_.flLowPassCutOff = (eax_.flLowPassCutOff != eax_d_.flLowPassCutOff);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::defer_eq_center(
|
||||
float flEQCenter)
|
||||
{
|
||||
eax_d_.flEQCenter = flEQCenter;
|
||||
eax_dirty_flags_.flEQCenter = (eax_.flEQCenter != eax_d_.flEQCenter);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::defer_eq_bandwidth(
|
||||
float flEQBandwidth)
|
||||
{
|
||||
eax_d_.flEQBandwidth = flEQBandwidth;
|
||||
eax_dirty_flags_.flEQBandwidth = (eax_.flEQBandwidth != eax_d_.flEQBandwidth);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::defer_all(
|
||||
const EAXDISTORTIONPROPERTIES& eax_all)
|
||||
{
|
||||
defer_edge(eax_all.flEdge);
|
||||
defer_gain(eax_all.lGain);
|
||||
defer_low_pass_cutoff(eax_all.flLowPassCutOff);
|
||||
defer_eq_center(eax_all.flEQCenter);
|
||||
defer_eq_bandwidth(eax_all.flEQBandwidth);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::defer_edge(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& edge =
|
||||
eax_call.get_value<EaxDistortionEffectException, const decltype(EAXDISTORTIONPROPERTIES::flEdge)>();
|
||||
|
||||
validate_edge(edge);
|
||||
defer_edge(edge);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::defer_gain(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& gain =
|
||||
eax_call.get_value<EaxDistortionEffectException, const decltype(EAXDISTORTIONPROPERTIES::lGain)>();
|
||||
|
||||
validate_gain(gain);
|
||||
defer_gain(gain);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::defer_low_pass_cutoff(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& lowpass_cutoff =
|
||||
eax_call.get_value<EaxDistortionEffectException, const decltype(EAXDISTORTIONPROPERTIES::flLowPassCutOff)>();
|
||||
|
||||
validate_lowpass_cutoff(lowpass_cutoff);
|
||||
defer_low_pass_cutoff(lowpass_cutoff);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::defer_eq_center(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& eq_center =
|
||||
eax_call.get_value<EaxDistortionEffectException, const decltype(EAXDISTORTIONPROPERTIES::flEQCenter)>();
|
||||
|
||||
validate_eq_center(eq_center);
|
||||
defer_eq_center(eq_center);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::defer_eq_bandwidth(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& eq_bandwidth =
|
||||
eax_call.get_value<EaxDistortionEffectException, const decltype(EAXDISTORTIONPROPERTIES::flEQBandwidth)>();
|
||||
|
||||
validate_eq_bandwidth(eq_bandwidth);
|
||||
defer_eq_bandwidth(eq_bandwidth);
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::defer_all(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& all =
|
||||
eax_call.get_value<EaxDistortionEffectException, const EAXDISTORTIONPROPERTIES>();
|
||||
|
||||
validate_all(all);
|
||||
defer_all(all);
|
||||
}
|
||||
|
||||
// [[nodiscard]]
|
||||
bool EaxDistortionEffect::apply_deferred()
|
||||
{
|
||||
if (eax_dirty_flags_ == EaxDistortionEffectDirtyFlags{})
|
||||
struct LowPassCutOffValidator {
|
||||
void operator()(float flLowPassCutOff) const
|
||||
{
|
||||
eax_validate_range<DistortionCommitter::Exception>(
|
||||
"Low-pass Cut-off",
|
||||
flLowPassCutOff,
|
||||
EAXDISTORTION_MINLOWPASSCUTOFF,
|
||||
EAXDISTORTION_MAXLOWPASSCUTOFF);
|
||||
}
|
||||
}; // LowPassCutOffValidator
|
||||
|
||||
struct EqCenterValidator {
|
||||
void operator()(float flEQCenter) const
|
||||
{
|
||||
eax_validate_range<DistortionCommitter::Exception>(
|
||||
"EQ Center",
|
||||
flEQCenter,
|
||||
EAXDISTORTION_MINEQCENTER,
|
||||
EAXDISTORTION_MAXEQCENTER);
|
||||
}
|
||||
}; // EqCenterValidator
|
||||
|
||||
struct EqBandwidthValidator {
|
||||
void operator()(float flEQBandwidth) const
|
||||
{
|
||||
eax_validate_range<DistortionCommitter::Exception>(
|
||||
"EQ Bandwidth",
|
||||
flEQBandwidth,
|
||||
EAXDISTORTION_MINEQBANDWIDTH,
|
||||
EAXDISTORTION_MAXEQBANDWIDTH);
|
||||
}
|
||||
}; // EqBandwidthValidator
|
||||
|
||||
struct AllValidator {
|
||||
void operator()(const EAXDISTORTIONPROPERTIES& all) const
|
||||
{
|
||||
EdgeValidator{}(all.flEdge);
|
||||
GainValidator{}(all.lGain);
|
||||
LowPassCutOffValidator{}(all.flLowPassCutOff);
|
||||
EqCenterValidator{}(all.flEQCenter);
|
||||
EqBandwidthValidator{}(all.flEQBandwidth);
|
||||
}
|
||||
}; // AllValidator
|
||||
|
||||
} // namespace
|
||||
|
||||
template<>
|
||||
struct DistortionCommitter::Exception : public EaxException {
|
||||
explicit Exception(const char *message) : EaxException{"EAX_DISTORTION_EFFECT", message}
|
||||
{ }
|
||||
};
|
||||
|
||||
template<>
|
||||
[[noreturn]] void DistortionCommitter::fail(const char *message)
|
||||
{
|
||||
throw Exception{message};
|
||||
}
|
||||
|
||||
template<>
|
||||
bool DistortionCommitter::commit(const EaxEffectProps &props)
|
||||
{
|
||||
if(props.mType == mEaxProps.mType && mEaxProps.mDistortion.flEdge == props.mDistortion.flEdge
|
||||
&& mEaxProps.mDistortion.lGain == props.mDistortion.lGain
|
||||
&& mEaxProps.mDistortion.flLowPassCutOff == props.mDistortion.flLowPassCutOff
|
||||
&& mEaxProps.mDistortion.flEQCenter == props.mDistortion.flEQCenter
|
||||
&& mEaxProps.mDistortion.flEQBandwidth == props.mDistortion.flEQBandwidth)
|
||||
return false;
|
||||
}
|
||||
|
||||
eax_ = eax_d_;
|
||||
mEaxProps = props;
|
||||
|
||||
if (eax_dirty_flags_.flEdge)
|
||||
{
|
||||
set_efx_edge();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.lGain)
|
||||
{
|
||||
set_efx_gain();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flLowPassCutOff)
|
||||
{
|
||||
set_efx_lowpass_cutoff();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flEQCenter)
|
||||
{
|
||||
set_efx_eq_center();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flEQBandwidth)
|
||||
{
|
||||
set_efx_eq_bandwidth();
|
||||
}
|
||||
|
||||
eax_dirty_flags_ = EaxDistortionEffectDirtyFlags{};
|
||||
mAlProps.Distortion.Edge = props.mDistortion.flEdge;
|
||||
mAlProps.Distortion.Gain = level_mb_to_gain(static_cast<float>(props.mDistortion.lGain));
|
||||
mAlProps.Distortion.LowpassCutoff = props.mDistortion.flLowPassCutOff;
|
||||
mAlProps.Distortion.EQCenter = props.mDistortion.flEQCenter;
|
||||
mAlProps.Distortion.EQBandwidth = props.mDistortion.flEdge;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EaxDistortionEffect::set(const EaxEaxCall& eax_call)
|
||||
template<>
|
||||
void DistortionCommitter::SetDefaults(EaxEffectProps &props)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
props.mType = EaxEffectType::Distortion;
|
||||
props.mDistortion.flEdge = EAXDISTORTION_DEFAULTEDGE;
|
||||
props.mDistortion.lGain = EAXDISTORTION_DEFAULTGAIN;
|
||||
props.mDistortion.flLowPassCutOff = EAXDISTORTION_DEFAULTLOWPASSCUTOFF;
|
||||
props.mDistortion.flEQCenter = EAXDISTORTION_DEFAULTEQCENTER;
|
||||
props.mDistortion.flEQBandwidth = EAXDISTORTION_DEFAULTEQBANDWIDTH;
|
||||
}
|
||||
|
||||
template<>
|
||||
void DistortionCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
|
||||
{
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXDISTORTION_NONE:
|
||||
break;
|
||||
|
||||
case EAXDISTORTION_ALLPARAMETERS:
|
||||
defer_all(eax_call);
|
||||
break;
|
||||
|
||||
case EAXDISTORTION_EDGE:
|
||||
defer_edge(eax_call);
|
||||
break;
|
||||
|
||||
case EAXDISTORTION_GAIN:
|
||||
defer_gain(eax_call);
|
||||
break;
|
||||
|
||||
case EAXDISTORTION_LOWPASSCUTOFF:
|
||||
defer_low_pass_cutoff(eax_call);
|
||||
break;
|
||||
|
||||
case EAXDISTORTION_EQCENTER:
|
||||
defer_eq_center(eax_call);
|
||||
break;
|
||||
|
||||
case EAXDISTORTION_EQBANDWIDTH:
|
||||
defer_eq_bandwidth(eax_call);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxDistortionEffectException{"Unsupported property id."};
|
||||
case EAXDISTORTION_NONE: break;
|
||||
case EAXDISTORTION_ALLPARAMETERS: call.set_value<Exception>(props.mDistortion); break;
|
||||
case EAXDISTORTION_EDGE: call.set_value<Exception>(props.mDistortion.flEdge); break;
|
||||
case EAXDISTORTION_GAIN: call.set_value<Exception>(props.mDistortion.lGain); break;
|
||||
case EAXDISTORTION_LOWPASSCUTOFF: call.set_value<Exception>(props.mDistortion.flLowPassCutOff); break;
|
||||
case EAXDISTORTION_EQCENTER: call.set_value<Exception>(props.mDistortion.flEQCenter); break;
|
||||
case EAXDISTORTION_EQBANDWIDTH: call.set_value<Exception>(props.mDistortion.flEQBandwidth); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EaxEffectUPtr eax_create_eax_distortion_effect()
|
||||
template<>
|
||||
void DistortionCommitter::Set(const EaxCall &call, EaxEffectProps &props)
|
||||
{
|
||||
return std::make_unique<EaxDistortionEffect>();
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXDISTORTION_NONE: break;
|
||||
case EAXDISTORTION_ALLPARAMETERS: defer<AllValidator>(call, props.mDistortion); break;
|
||||
case EAXDISTORTION_EDGE: defer<EdgeValidator>(call, props.mDistortion.flEdge); break;
|
||||
case EAXDISTORTION_GAIN: defer<GainValidator>(call, props.mDistortion.lGain); break;
|
||||
case EAXDISTORTION_LOWPASSCUTOFF: defer<LowPassCutOffValidator>(call, props.mDistortion.flLowPassCutOff); break;
|
||||
case EAXDISTORTION_EQCENTER: defer<EqCenterValidator>(call, props.mDistortion.flEQCenter); break;
|
||||
case EAXDISTORTION_EQBANDWIDTH: defer<EqBandwidthValidator>(call, props.mDistortion.flEQBandwidth); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ALSOFT_EAX
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@
|
|||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include "alnumeric.h"
|
||||
|
||||
#include "al/eax_exception.h"
|
||||
#include "al/eax_utils.h"
|
||||
#include "al/eax/exception.h"
|
||||
#include "al/eax/utils.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
|
||||
|
|
@ -120,450 +119,150 @@ const EffectProps EchoEffectProps{genDefaultProps()};
|
|||
#ifdef ALSOFT_EAX
|
||||
namespace {
|
||||
|
||||
using EaxEchoEffectDirtyFlagsValue = std::uint_least8_t;
|
||||
using EchoCommitter = EaxCommitter<EaxEchoCommitter>;
|
||||
|
||||
struct EaxEchoEffectDirtyFlags
|
||||
{
|
||||
using EaxIsBitFieldStruct = bool;
|
||||
|
||||
EaxEchoEffectDirtyFlagsValue flDelay : 1;
|
||||
EaxEchoEffectDirtyFlagsValue flLRDelay : 1;
|
||||
EaxEchoEffectDirtyFlagsValue flDamping : 1;
|
||||
EaxEchoEffectDirtyFlagsValue flFeedback : 1;
|
||||
EaxEchoEffectDirtyFlagsValue flSpread : 1;
|
||||
}; // EaxEchoEffectDirtyFlags
|
||||
|
||||
|
||||
class EaxEchoEffect final :
|
||||
public EaxEffect
|
||||
{
|
||||
public:
|
||||
EaxEchoEffect();
|
||||
|
||||
void dispatch(const EaxEaxCall& eax_call) override;
|
||||
|
||||
// [[nodiscard]]
|
||||
bool apply_deferred() override;
|
||||
|
||||
private:
|
||||
EAXECHOPROPERTIES eax_{};
|
||||
EAXECHOPROPERTIES eax_d_{};
|
||||
EaxEchoEffectDirtyFlags eax_dirty_flags_{};
|
||||
|
||||
void set_eax_defaults();
|
||||
|
||||
void set_efx_delay();
|
||||
void set_efx_lr_delay();
|
||||
void set_efx_damping();
|
||||
void set_efx_feedback();
|
||||
void set_efx_spread();
|
||||
void set_efx_defaults();
|
||||
|
||||
void get(const EaxEaxCall& eax_call);
|
||||
|
||||
void validate_delay(float flDelay);
|
||||
void validate_lr_delay(float flLRDelay);
|
||||
void validate_damping(float flDamping);
|
||||
void validate_feedback(float flFeedback);
|
||||
void validate_spread(float flSpread);
|
||||
void validate_all(const EAXECHOPROPERTIES& all);
|
||||
|
||||
void defer_delay(float flDelay);
|
||||
void defer_lr_delay(float flLRDelay);
|
||||
void defer_damping(float flDamping);
|
||||
void defer_feedback(float flFeedback);
|
||||
void defer_spread(float flSpread);
|
||||
void defer_all(const EAXECHOPROPERTIES& all);
|
||||
|
||||
void defer_delay(const EaxEaxCall& eax_call);
|
||||
void defer_lr_delay(const EaxEaxCall& eax_call);
|
||||
void defer_damping(const EaxEaxCall& eax_call);
|
||||
void defer_feedback(const EaxEaxCall& eax_call);
|
||||
void defer_spread(const EaxEaxCall& eax_call);
|
||||
void defer_all(const EaxEaxCall& eax_call);
|
||||
|
||||
void set(const EaxEaxCall& eax_call);
|
||||
}; // EaxEchoEffect
|
||||
|
||||
|
||||
class EaxEchoEffectException :
|
||||
public EaxException
|
||||
{
|
||||
public:
|
||||
explicit EaxEchoEffectException(
|
||||
const char* message)
|
||||
:
|
||||
EaxException{"EAX_ECHO_EFFECT", message}
|
||||
struct DelayValidator {
|
||||
void operator()(float flDelay) const
|
||||
{
|
||||
eax_validate_range<EchoCommitter::Exception>(
|
||||
"Delay",
|
||||
flDelay,
|
||||
EAXECHO_MINDELAY,
|
||||
EAXECHO_MAXDELAY);
|
||||
}
|
||||
}; // EaxEchoEffectException
|
||||
}; // DelayValidator
|
||||
|
||||
|
||||
EaxEchoEffect::EaxEchoEffect()
|
||||
: EaxEffect{AL_EFFECT_ECHO}
|
||||
{
|
||||
set_eax_defaults();
|
||||
set_efx_defaults();
|
||||
}
|
||||
|
||||
void EaxEchoEffect::dispatch(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
eax_call.is_get() ? get(eax_call) : set(eax_call);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::set_eax_defaults()
|
||||
{
|
||||
eax_.flDelay = EAXECHO_DEFAULTDELAY;
|
||||
eax_.flLRDelay = EAXECHO_DEFAULTLRDELAY;
|
||||
eax_.flDamping = EAXECHO_DEFAULTDAMPING;
|
||||
eax_.flFeedback = EAXECHO_DEFAULTFEEDBACK;
|
||||
eax_.flSpread = EAXECHO_DEFAULTSPREAD;
|
||||
|
||||
eax_d_ = eax_;
|
||||
}
|
||||
|
||||
void EaxEchoEffect::set_efx_delay()
|
||||
{
|
||||
const auto delay = clamp(
|
||||
eax_.flDelay,
|
||||
AL_ECHO_MIN_DELAY,
|
||||
AL_ECHO_MAX_DELAY);
|
||||
|
||||
al_effect_props_.Echo.Delay = delay;
|
||||
}
|
||||
|
||||
void EaxEchoEffect::set_efx_lr_delay()
|
||||
{
|
||||
const auto lr_delay = clamp(
|
||||
eax_.flLRDelay,
|
||||
AL_ECHO_MIN_LRDELAY,
|
||||
AL_ECHO_MAX_LRDELAY);
|
||||
|
||||
al_effect_props_.Echo.LRDelay = lr_delay;
|
||||
}
|
||||
|
||||
void EaxEchoEffect::set_efx_damping()
|
||||
{
|
||||
const auto damping = clamp(
|
||||
eax_.flDamping,
|
||||
AL_ECHO_MIN_DAMPING,
|
||||
AL_ECHO_MAX_DAMPING);
|
||||
|
||||
al_effect_props_.Echo.Damping = damping;
|
||||
}
|
||||
|
||||
void EaxEchoEffect::set_efx_feedback()
|
||||
{
|
||||
const auto feedback = clamp(
|
||||
eax_.flFeedback,
|
||||
AL_ECHO_MIN_FEEDBACK,
|
||||
AL_ECHO_MAX_FEEDBACK);
|
||||
|
||||
al_effect_props_.Echo.Feedback = feedback;
|
||||
}
|
||||
|
||||
void EaxEchoEffect::set_efx_spread()
|
||||
{
|
||||
const auto spread = clamp(
|
||||
eax_.flSpread,
|
||||
AL_ECHO_MIN_SPREAD,
|
||||
AL_ECHO_MAX_SPREAD);
|
||||
|
||||
al_effect_props_.Echo.Spread = spread;
|
||||
}
|
||||
|
||||
void EaxEchoEffect::set_efx_defaults()
|
||||
{
|
||||
set_efx_delay();
|
||||
set_efx_lr_delay();
|
||||
set_efx_damping();
|
||||
set_efx_feedback();
|
||||
set_efx_spread();
|
||||
}
|
||||
|
||||
void EaxEchoEffect::get(const EaxEaxCall& eax_call)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
struct LrDelayValidator {
|
||||
void operator()(float flLRDelay) const
|
||||
{
|
||||
case EAXECHO_NONE:
|
||||
break;
|
||||
|
||||
case EAXECHO_ALLPARAMETERS:
|
||||
eax_call.set_value<EaxEchoEffectException>(eax_);
|
||||
break;
|
||||
|
||||
case EAXECHO_DELAY:
|
||||
eax_call.set_value<EaxEchoEffectException>(eax_.flDelay);
|
||||
break;
|
||||
|
||||
case EAXECHO_LRDELAY:
|
||||
eax_call.set_value<EaxEchoEffectException>(eax_.flLRDelay);
|
||||
break;
|
||||
|
||||
case EAXECHO_DAMPING:
|
||||
eax_call.set_value<EaxEchoEffectException>(eax_.flDamping);
|
||||
break;
|
||||
|
||||
case EAXECHO_FEEDBACK:
|
||||
eax_call.set_value<EaxEchoEffectException>(eax_.flFeedback);
|
||||
break;
|
||||
|
||||
case EAXECHO_SPREAD:
|
||||
eax_call.set_value<EaxEchoEffectException>(eax_.flSpread);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxEchoEffectException{"Unsupported property id."};
|
||||
eax_validate_range<EchoCommitter::Exception>(
|
||||
"LR Delay",
|
||||
flLRDelay,
|
||||
EAXECHO_MINLRDELAY,
|
||||
EAXECHO_MAXLRDELAY);
|
||||
}
|
||||
}
|
||||
}; // LrDelayValidator
|
||||
|
||||
void EaxEchoEffect::validate_delay(
|
||||
float flDelay)
|
||||
{
|
||||
eax_validate_range<EaxEchoEffectException>(
|
||||
"Delay",
|
||||
flDelay,
|
||||
EAXECHO_MINDELAY,
|
||||
EAXECHO_MAXDELAY);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::validate_lr_delay(
|
||||
float flLRDelay)
|
||||
{
|
||||
eax_validate_range<EaxEchoEffectException>(
|
||||
"LR Delay",
|
||||
flLRDelay,
|
||||
EAXECHO_MINLRDELAY,
|
||||
EAXECHO_MAXLRDELAY);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::validate_damping(
|
||||
float flDamping)
|
||||
{
|
||||
eax_validate_range<EaxEchoEffectException>(
|
||||
"Damping",
|
||||
flDamping,
|
||||
EAXECHO_MINDAMPING,
|
||||
EAXECHO_MAXDAMPING);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::validate_feedback(
|
||||
float flFeedback)
|
||||
{
|
||||
eax_validate_range<EaxEchoEffectException>(
|
||||
"Feedback",
|
||||
flFeedback,
|
||||
EAXECHO_MINFEEDBACK,
|
||||
EAXECHO_MAXFEEDBACK);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::validate_spread(
|
||||
float flSpread)
|
||||
{
|
||||
eax_validate_range<EaxEchoEffectException>(
|
||||
"Spread",
|
||||
flSpread,
|
||||
EAXECHO_MINSPREAD,
|
||||
EAXECHO_MAXSPREAD);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::validate_all(
|
||||
const EAXECHOPROPERTIES& all)
|
||||
{
|
||||
validate_delay(all.flDelay);
|
||||
validate_lr_delay(all.flLRDelay);
|
||||
validate_damping(all.flDamping);
|
||||
validate_feedback(all.flFeedback);
|
||||
validate_spread(all.flSpread);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::defer_delay(
|
||||
float flDelay)
|
||||
{
|
||||
eax_d_.flDelay = flDelay;
|
||||
eax_dirty_flags_.flDelay = (eax_.flDelay != eax_d_.flDelay);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::defer_lr_delay(
|
||||
float flLRDelay)
|
||||
{
|
||||
eax_d_.flLRDelay = flLRDelay;
|
||||
eax_dirty_flags_.flLRDelay = (eax_.flLRDelay != eax_d_.flLRDelay);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::defer_damping(
|
||||
float flDamping)
|
||||
{
|
||||
eax_d_.flDamping = flDamping;
|
||||
eax_dirty_flags_.flDamping = (eax_.flDamping != eax_d_.flDamping);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::defer_feedback(
|
||||
float flFeedback)
|
||||
{
|
||||
eax_d_.flFeedback = flFeedback;
|
||||
eax_dirty_flags_.flFeedback = (eax_.flFeedback != eax_d_.flFeedback);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::defer_spread(
|
||||
float flSpread)
|
||||
{
|
||||
eax_d_.flSpread = flSpread;
|
||||
eax_dirty_flags_.flSpread = (eax_.flSpread != eax_d_.flSpread);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::defer_all(
|
||||
const EAXECHOPROPERTIES& all)
|
||||
{
|
||||
defer_delay(all.flDelay);
|
||||
defer_lr_delay(all.flLRDelay);
|
||||
defer_damping(all.flDamping);
|
||||
defer_feedback(all.flFeedback);
|
||||
defer_spread(all.flSpread);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::defer_delay(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& delay =
|
||||
eax_call.get_value<EaxEchoEffectException, const decltype(EAXECHOPROPERTIES::flDelay)>();
|
||||
|
||||
validate_delay(delay);
|
||||
defer_delay(delay);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::defer_lr_delay(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& lr_delay =
|
||||
eax_call.get_value<EaxEchoEffectException, const decltype(EAXECHOPROPERTIES::flLRDelay)>();
|
||||
|
||||
validate_lr_delay(lr_delay);
|
||||
defer_lr_delay(lr_delay);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::defer_damping(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& damping =
|
||||
eax_call.get_value<EaxEchoEffectException, const decltype(EAXECHOPROPERTIES::flDamping)>();
|
||||
|
||||
validate_damping(damping);
|
||||
defer_damping(damping);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::defer_feedback(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& feedback =
|
||||
eax_call.get_value<EaxEchoEffectException, const decltype(EAXECHOPROPERTIES::flFeedback)>();
|
||||
|
||||
validate_feedback(feedback);
|
||||
defer_feedback(feedback);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::defer_spread(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& spread =
|
||||
eax_call.get_value<EaxEchoEffectException, const decltype(EAXECHOPROPERTIES::flSpread)>();
|
||||
|
||||
validate_spread(spread);
|
||||
defer_spread(spread);
|
||||
}
|
||||
|
||||
void EaxEchoEffect::defer_all(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& all =
|
||||
eax_call.get_value<EaxEchoEffectException, const EAXECHOPROPERTIES>();
|
||||
|
||||
validate_all(all);
|
||||
defer_all(all);
|
||||
}
|
||||
|
||||
// [[nodiscard]]
|
||||
bool EaxEchoEffect::apply_deferred()
|
||||
{
|
||||
if (eax_dirty_flags_ == EaxEchoEffectDirtyFlags{})
|
||||
struct DampingValidator {
|
||||
void operator()(float flDamping) const
|
||||
{
|
||||
eax_validate_range<EchoCommitter::Exception>(
|
||||
"Damping",
|
||||
flDamping,
|
||||
EAXECHO_MINDAMPING,
|
||||
EAXECHO_MAXDAMPING);
|
||||
}
|
||||
}; // DampingValidator
|
||||
|
||||
struct FeedbackValidator {
|
||||
void operator()(float flFeedback) const
|
||||
{
|
||||
eax_validate_range<EchoCommitter::Exception>(
|
||||
"Feedback",
|
||||
flFeedback,
|
||||
EAXECHO_MINFEEDBACK,
|
||||
EAXECHO_MAXFEEDBACK);
|
||||
}
|
||||
}; // FeedbackValidator
|
||||
|
||||
struct SpreadValidator {
|
||||
void operator()(float flSpread) const
|
||||
{
|
||||
eax_validate_range<EchoCommitter::Exception>(
|
||||
"Spread",
|
||||
flSpread,
|
||||
EAXECHO_MINSPREAD,
|
||||
EAXECHO_MAXSPREAD);
|
||||
}
|
||||
}; // SpreadValidator
|
||||
|
||||
struct AllValidator {
|
||||
void operator()(const EAXECHOPROPERTIES& all) const
|
||||
{
|
||||
DelayValidator{}(all.flDelay);
|
||||
LrDelayValidator{}(all.flLRDelay);
|
||||
DampingValidator{}(all.flDamping);
|
||||
FeedbackValidator{}(all.flFeedback);
|
||||
SpreadValidator{}(all.flSpread);
|
||||
}
|
||||
}; // AllValidator
|
||||
|
||||
} // namespace
|
||||
|
||||
template<>
|
||||
struct EchoCommitter::Exception : public EaxException {
|
||||
explicit Exception(const char* message) : EaxException{"EAX_ECHO_EFFECT", message}
|
||||
{ }
|
||||
};
|
||||
|
||||
template<>
|
||||
[[noreturn]] void EchoCommitter::fail(const char *message)
|
||||
{
|
||||
throw Exception{message};
|
||||
}
|
||||
|
||||
template<>
|
||||
bool EchoCommitter::commit(const EaxEffectProps &props)
|
||||
{
|
||||
if(props.mType == mEaxProps.mType && mEaxProps.mEcho.flDelay == props.mEcho.flDelay
|
||||
&& mEaxProps.mEcho.flLRDelay == props.mEcho.flLRDelay
|
||||
&& mEaxProps.mEcho.flDamping == props.mEcho.flDamping
|
||||
&& mEaxProps.mEcho.flFeedback == props.mEcho.flFeedback
|
||||
&& mEaxProps.mEcho.flSpread == props.mEcho.flSpread)
|
||||
return false;
|
||||
}
|
||||
|
||||
eax_ = eax_d_;
|
||||
mEaxProps = props;
|
||||
|
||||
if (eax_dirty_flags_.flDelay)
|
||||
{
|
||||
set_efx_delay();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flLRDelay)
|
||||
{
|
||||
set_efx_lr_delay();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flDamping)
|
||||
{
|
||||
set_efx_damping();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flFeedback)
|
||||
{
|
||||
set_efx_feedback();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flSpread)
|
||||
{
|
||||
set_efx_spread();
|
||||
}
|
||||
|
||||
eax_dirty_flags_ = EaxEchoEffectDirtyFlags{};
|
||||
mAlProps.Echo.Delay = props.mEcho.flDelay;
|
||||
mAlProps.Echo.LRDelay = props.mEcho.flLRDelay;
|
||||
mAlProps.Echo.Damping = props.mEcho.flDamping;
|
||||
mAlProps.Echo.Feedback = props.mEcho.flFeedback;
|
||||
mAlProps.Echo.Spread = props.mEcho.flSpread;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EaxEchoEffect::set(const EaxEaxCall& eax_call)
|
||||
template<>
|
||||
void EchoCommitter::SetDefaults(EaxEffectProps &props)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
props.mType = EaxEffectType::Echo;
|
||||
props.mEcho.flDelay = EAXECHO_DEFAULTDELAY;
|
||||
props.mEcho.flLRDelay = EAXECHO_DEFAULTLRDELAY;
|
||||
props.mEcho.flDamping = EAXECHO_DEFAULTDAMPING;
|
||||
props.mEcho.flFeedback = EAXECHO_DEFAULTFEEDBACK;
|
||||
props.mEcho.flSpread = EAXECHO_DEFAULTSPREAD;
|
||||
}
|
||||
|
||||
template<>
|
||||
void EchoCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
|
||||
{
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXECHO_NONE:
|
||||
break;
|
||||
|
||||
case EAXECHO_ALLPARAMETERS:
|
||||
defer_all(eax_call);
|
||||
break;
|
||||
|
||||
case EAXECHO_DELAY:
|
||||
defer_delay(eax_call);
|
||||
break;
|
||||
|
||||
case EAXECHO_LRDELAY:
|
||||
defer_lr_delay(eax_call);
|
||||
break;
|
||||
|
||||
case EAXECHO_DAMPING:
|
||||
defer_damping(eax_call);
|
||||
break;
|
||||
|
||||
case EAXECHO_FEEDBACK:
|
||||
defer_feedback(eax_call);
|
||||
break;
|
||||
|
||||
case EAXECHO_SPREAD:
|
||||
defer_spread(eax_call);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxEchoEffectException{"Unsupported property id."};
|
||||
case EAXECHO_NONE: break;
|
||||
case EAXECHO_ALLPARAMETERS: call.set_value<Exception>(props.mEcho); break;
|
||||
case EAXECHO_DELAY: call.set_value<Exception>(props.mEcho.flDelay); break;
|
||||
case EAXECHO_LRDELAY: call.set_value<Exception>(props.mEcho.flLRDelay); break;
|
||||
case EAXECHO_DAMPING: call.set_value<Exception>(props.mEcho.flDamping); break;
|
||||
case EAXECHO_FEEDBACK: call.set_value<Exception>(props.mEcho.flFeedback); break;
|
||||
case EAXECHO_SPREAD: call.set_value<Exception>(props.mEcho.flSpread); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EaxEffectUPtr eax_create_eax_echo_effect()
|
||||
template<>
|
||||
void EchoCommitter::Set(const EaxCall &call, EaxEffectProps &props)
|
||||
{
|
||||
return std::make_unique<EaxEchoEffect>();
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXECHO_NONE: break;
|
||||
case EAXECHO_ALLPARAMETERS: defer<AllValidator>(call, props.mEcho); break;
|
||||
case EAXECHO_DELAY: defer<DelayValidator>(call, props.mEcho.flDelay); break;
|
||||
case EAXECHO_LRDELAY: defer<LrDelayValidator>(call, props.mEcho.flLRDelay); break;
|
||||
case EAXECHO_DAMPING: defer<DampingValidator>(call, props.mEcho.flDamping); break;
|
||||
case EAXECHO_FEEDBACK: defer<FeedbackValidator>(call, props.mEcho.flFeedback); break;
|
||||
case EAXECHO_SPREAD: defer<SpreadValidator>(call, props.mEcho.flSpread); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ALSOFT_EAX
|
||||
|
|
|
|||
|
|
@ -1,66 +1,9 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef ALSOFT_EAX
|
||||
|
||||
#include <cassert>
|
||||
#include "AL/efx.h"
|
||||
#include "effects.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "AL/efx.h"
|
||||
|
||||
|
||||
EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type)
|
||||
{
|
||||
#define EAX_PREFIX "[EAX_MAKE_EAX_EFFECT] "
|
||||
|
||||
switch (al_effect_type)
|
||||
{
|
||||
case AL_EFFECT_NULL:
|
||||
return eax_create_eax_null_effect();
|
||||
|
||||
case AL_EFFECT_CHORUS:
|
||||
return eax_create_eax_chorus_effect();
|
||||
|
||||
case AL_EFFECT_DISTORTION:
|
||||
return eax_create_eax_distortion_effect();
|
||||
|
||||
case AL_EFFECT_ECHO:
|
||||
return eax_create_eax_echo_effect();
|
||||
|
||||
case AL_EFFECT_FLANGER:
|
||||
return eax_create_eax_flanger_effect();
|
||||
|
||||
case AL_EFFECT_FREQUENCY_SHIFTER:
|
||||
return eax_create_eax_frequency_shifter_effect();
|
||||
|
||||
case AL_EFFECT_VOCAL_MORPHER:
|
||||
return eax_create_eax_vocal_morpher_effect();
|
||||
|
||||
case AL_EFFECT_PITCH_SHIFTER:
|
||||
return eax_create_eax_pitch_shifter_effect();
|
||||
|
||||
case AL_EFFECT_RING_MODULATOR:
|
||||
return eax_create_eax_ring_modulator_effect();
|
||||
|
||||
case AL_EFFECT_AUTOWAH:
|
||||
return eax_create_eax_auto_wah_effect();
|
||||
|
||||
case AL_EFFECT_COMPRESSOR:
|
||||
return eax_create_eax_compressor_effect();
|
||||
|
||||
case AL_EFFECT_EQUALIZER:
|
||||
return eax_create_eax_equalizer_effect();
|
||||
|
||||
case AL_EFFECT_EAXREVERB:
|
||||
return eax_create_eax_reverb_effect();
|
||||
|
||||
default:
|
||||
assert(false && "Unsupported AL effect type.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#undef EAX_PREFIX
|
||||
}
|
||||
|
||||
#endif // ALSOFT_EAX
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include "core/except.h"
|
||||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include "al/eax_effect.h"
|
||||
#include "al/eax/effect.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
union EffectProps;
|
||||
|
|
@ -22,6 +22,7 @@ public:
|
|||
[[gnu::format(printf, 3, 4)]]
|
||||
#endif
|
||||
effect_exception(ALenum code, const char *msg, ...);
|
||||
~effect_exception() override;
|
||||
|
||||
ALenum errorCode() const noexcept { return mErrorCode; }
|
||||
};
|
||||
|
|
@ -84,9 +85,4 @@ extern const EffectVtable VmorpherEffectVtable;
|
|||
extern const EffectVtable DedicatedEffectVtable;
|
||||
extern const EffectVtable ConvolutionEffectVtable;
|
||||
|
||||
|
||||
#ifdef ALSOFT_EAX
|
||||
EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type);
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
#endif /* AL_EFFECTS_EFFECTS_H */
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@
|
|||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include "alnumeric.h"
|
||||
|
||||
#include "al/eax_exception.h"
|
||||
#include "al/eax_utils.h"
|
||||
#include "al/eax/exception.h"
|
||||
#include "al/eax/utils.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
|
||||
|
|
@ -178,744 +177,235 @@ const EffectProps EqualizerEffectProps{genDefaultProps()};
|
|||
#ifdef ALSOFT_EAX
|
||||
namespace {
|
||||
|
||||
using EaxEqualizerEffectDirtyFlagsValue = std::uint_least16_t;
|
||||
using EqualizerCommitter = EaxCommitter<EaxEqualizerCommitter>;
|
||||
|
||||
struct EaxEqualizerEffectDirtyFlags
|
||||
{
|
||||
using EaxIsBitFieldStruct = bool;
|
||||
|
||||
EaxEqualizerEffectDirtyFlagsValue lLowGain : 1;
|
||||
EaxEqualizerEffectDirtyFlagsValue flLowCutOff : 1;
|
||||
EaxEqualizerEffectDirtyFlagsValue lMid1Gain : 1;
|
||||
EaxEqualizerEffectDirtyFlagsValue flMid1Center : 1;
|
||||
EaxEqualizerEffectDirtyFlagsValue flMid1Width : 1;
|
||||
EaxEqualizerEffectDirtyFlagsValue lMid2Gain : 1;
|
||||
EaxEqualizerEffectDirtyFlagsValue flMid2Center : 1;
|
||||
EaxEqualizerEffectDirtyFlagsValue flMid2Width : 1;
|
||||
EaxEqualizerEffectDirtyFlagsValue lHighGain : 1;
|
||||
EaxEqualizerEffectDirtyFlagsValue flHighCutOff : 1;
|
||||
}; // EaxEqualizerEffectDirtyFlags
|
||||
|
||||
|
||||
class EaxEqualizerEffect final :
|
||||
public EaxEffect
|
||||
{
|
||||
public:
|
||||
EaxEqualizerEffect();
|
||||
|
||||
void dispatch(const EaxEaxCall& eax_call) override;
|
||||
|
||||
// [[nodiscard]]
|
||||
bool apply_deferred() override;
|
||||
|
||||
private:
|
||||
EAXEQUALIZERPROPERTIES eax_{};
|
||||
EAXEQUALIZERPROPERTIES eax_d_{};
|
||||
EaxEqualizerEffectDirtyFlags eax_dirty_flags_{};
|
||||
|
||||
void set_eax_defaults();
|
||||
|
||||
void set_efx_low_gain();
|
||||
void set_efx_low_cutoff();
|
||||
void set_efx_mid1_gain();
|
||||
void set_efx_mid1_center();
|
||||
void set_efx_mid1_width();
|
||||
void set_efx_mid2_gain();
|
||||
void set_efx_mid2_center();
|
||||
void set_efx_mid2_width();
|
||||
void set_efx_high_gain();
|
||||
void set_efx_high_cutoff();
|
||||
void set_efx_defaults();
|
||||
|
||||
void get(const EaxEaxCall& eax_call);
|
||||
|
||||
void validate_low_gain(long lLowGain);
|
||||
void validate_low_cutoff(float flLowCutOff);
|
||||
void validate_mid1_gain(long lMid1Gain);
|
||||
void validate_mid1_center(float flMid1Center);
|
||||
void validate_mid1_width(float flMid1Width);
|
||||
void validate_mid2_gain(long lMid2Gain);
|
||||
void validate_mid2_center(float flMid2Center);
|
||||
void validate_mid2_width(float flMid2Width);
|
||||
void validate_high_gain(long lHighGain);
|
||||
void validate_high_cutoff(float flHighCutOff);
|
||||
void validate_all(const EAXEQUALIZERPROPERTIES& all);
|
||||
|
||||
void defer_low_gain(long lLowGain);
|
||||
void defer_low_cutoff(float flLowCutOff);
|
||||
void defer_mid1_gain(long lMid1Gain);
|
||||
void defer_mid1_center(float flMid1Center);
|
||||
void defer_mid1_width(float flMid1Width);
|
||||
void defer_mid2_gain(long lMid2Gain);
|
||||
void defer_mid2_center(float flMid2Center);
|
||||
void defer_mid2_width(float flMid2Width);
|
||||
void defer_high_gain(long lHighGain);
|
||||
void defer_high_cutoff(float flHighCutOff);
|
||||
void defer_all(const EAXEQUALIZERPROPERTIES& all);
|
||||
|
||||
void defer_low_gain(const EaxEaxCall& eax_call);
|
||||
void defer_low_cutoff(const EaxEaxCall& eax_call);
|
||||
void defer_mid1_gain(const EaxEaxCall& eax_call);
|
||||
void defer_mid1_center(const EaxEaxCall& eax_call);
|
||||
void defer_mid1_width(const EaxEaxCall& eax_call);
|
||||
void defer_mid2_gain(const EaxEaxCall& eax_call);
|
||||
void defer_mid2_center(const EaxEaxCall& eax_call);
|
||||
void defer_mid2_width(const EaxEaxCall& eax_call);
|
||||
void defer_high_gain(const EaxEaxCall& eax_call);
|
||||
void defer_high_cutoff(const EaxEaxCall& eax_call);
|
||||
void defer_all(const EaxEaxCall& eax_call);
|
||||
|
||||
void set(const EaxEaxCall& eax_call);
|
||||
}; // EaxEqualizerEffect
|
||||
|
||||
|
||||
class EaxEqualizerEffectException :
|
||||
public EaxException
|
||||
{
|
||||
public:
|
||||
explicit EaxEqualizerEffectException(
|
||||
const char* message)
|
||||
:
|
||||
EaxException{"EAX_EQUALIZER_EFFECT", message}
|
||||
struct LowGainValidator {
|
||||
void operator()(long lLowGain) const
|
||||
{
|
||||
eax_validate_range<EqualizerCommitter::Exception>(
|
||||
"Low Gain",
|
||||
lLowGain,
|
||||
EAXEQUALIZER_MINLOWGAIN,
|
||||
EAXEQUALIZER_MAXLOWGAIN);
|
||||
}
|
||||
}; // EaxEqualizerEffectException
|
||||
}; // LowGainValidator
|
||||
|
||||
|
||||
EaxEqualizerEffect::EaxEqualizerEffect()
|
||||
: EaxEffect{AL_EFFECT_EQUALIZER}
|
||||
{
|
||||
set_eax_defaults();
|
||||
set_efx_defaults();
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::dispatch(const EaxEaxCall& eax_call)
|
||||
{
|
||||
eax_call.is_get() ? get(eax_call) : set(eax_call);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::set_eax_defaults()
|
||||
{
|
||||
eax_.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN;
|
||||
eax_.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF;
|
||||
eax_.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN;
|
||||
eax_.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER;
|
||||
eax_.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH;
|
||||
eax_.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN;
|
||||
eax_.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER;
|
||||
eax_.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH;
|
||||
eax_.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN;
|
||||
eax_.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF;
|
||||
|
||||
eax_d_ = eax_;
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::set_efx_low_gain()
|
||||
{
|
||||
const auto low_gain = clamp(
|
||||
level_mb_to_gain(static_cast<float>(eax_.lLowGain)),
|
||||
AL_EQUALIZER_MIN_LOW_GAIN,
|
||||
AL_EQUALIZER_MAX_LOW_GAIN);
|
||||
|
||||
al_effect_props_.Equalizer.LowGain = low_gain;
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::set_efx_low_cutoff()
|
||||
{
|
||||
const auto low_cutoff = clamp(
|
||||
eax_.flLowCutOff,
|
||||
AL_EQUALIZER_MIN_LOW_CUTOFF,
|
||||
AL_EQUALIZER_MAX_LOW_CUTOFF);
|
||||
|
||||
al_effect_props_.Equalizer.LowCutoff = low_cutoff;
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::set_efx_mid1_gain()
|
||||
{
|
||||
const auto mid1_gain = clamp(
|
||||
level_mb_to_gain(static_cast<float>(eax_.lMid1Gain)),
|
||||
AL_EQUALIZER_MIN_MID1_GAIN,
|
||||
AL_EQUALIZER_MAX_MID1_GAIN);
|
||||
|
||||
al_effect_props_.Equalizer.Mid1Gain = mid1_gain;
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::set_efx_mid1_center()
|
||||
{
|
||||
const auto mid1_center = clamp(
|
||||
eax_.flMid1Center,
|
||||
AL_EQUALIZER_MIN_MID1_CENTER,
|
||||
AL_EQUALIZER_MAX_MID1_CENTER);
|
||||
|
||||
al_effect_props_.Equalizer.Mid1Center = mid1_center;
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::set_efx_mid1_width()
|
||||
{
|
||||
const auto mid1_width = clamp(
|
||||
eax_.flMid1Width,
|
||||
AL_EQUALIZER_MIN_MID1_WIDTH,
|
||||
AL_EQUALIZER_MAX_MID1_WIDTH);
|
||||
|
||||
al_effect_props_.Equalizer.Mid1Width = mid1_width;
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::set_efx_mid2_gain()
|
||||
{
|
||||
const auto mid2_gain = clamp(
|
||||
level_mb_to_gain(static_cast<float>(eax_.lMid2Gain)),
|
||||
AL_EQUALIZER_MIN_MID2_GAIN,
|
||||
AL_EQUALIZER_MAX_MID2_GAIN);
|
||||
|
||||
al_effect_props_.Equalizer.Mid2Gain = mid2_gain;
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::set_efx_mid2_center()
|
||||
{
|
||||
const auto mid2_center = clamp(
|
||||
eax_.flMid2Center,
|
||||
AL_EQUALIZER_MIN_MID2_CENTER,
|
||||
AL_EQUALIZER_MAX_MID2_CENTER);
|
||||
|
||||
al_effect_props_.Equalizer.Mid2Center = mid2_center;
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::set_efx_mid2_width()
|
||||
{
|
||||
const auto mid2_width = clamp(
|
||||
eax_.flMid2Width,
|
||||
AL_EQUALIZER_MIN_MID2_WIDTH,
|
||||
AL_EQUALIZER_MAX_MID2_WIDTH);
|
||||
|
||||
al_effect_props_.Equalizer.Mid2Width = mid2_width;
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::set_efx_high_gain()
|
||||
{
|
||||
const auto high_gain = clamp(
|
||||
level_mb_to_gain(static_cast<float>(eax_.lHighGain)),
|
||||
AL_EQUALIZER_MIN_HIGH_GAIN,
|
||||
AL_EQUALIZER_MAX_HIGH_GAIN);
|
||||
|
||||
al_effect_props_.Equalizer.HighGain = high_gain;
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::set_efx_high_cutoff()
|
||||
{
|
||||
const auto high_cutoff = clamp(
|
||||
eax_.flHighCutOff,
|
||||
AL_EQUALIZER_MIN_HIGH_CUTOFF,
|
||||
AL_EQUALIZER_MAX_HIGH_CUTOFF);
|
||||
|
||||
al_effect_props_.Equalizer.HighCutoff = high_cutoff;
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::set_efx_defaults()
|
||||
{
|
||||
set_efx_low_gain();
|
||||
set_efx_low_cutoff();
|
||||
set_efx_mid1_gain();
|
||||
set_efx_mid1_center();
|
||||
set_efx_mid1_width();
|
||||
set_efx_mid2_gain();
|
||||
set_efx_mid2_center();
|
||||
set_efx_mid2_width();
|
||||
set_efx_high_gain();
|
||||
set_efx_high_cutoff();
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::get(const EaxEaxCall& eax_call)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
struct LowCutOffValidator {
|
||||
void operator()(float flLowCutOff) const
|
||||
{
|
||||
case EAXEQUALIZER_NONE:
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_ALLPARAMETERS:
|
||||
eax_call.set_value<EaxEqualizerEffectException>(eax_);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_LOWGAIN:
|
||||
eax_call.set_value<EaxEqualizerEffectException>(eax_.lLowGain);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_LOWCUTOFF:
|
||||
eax_call.set_value<EaxEqualizerEffectException>(eax_.flLowCutOff);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_MID1GAIN:
|
||||
eax_call.set_value<EaxEqualizerEffectException>(eax_.lMid1Gain);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_MID1CENTER:
|
||||
eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid1Center);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_MID1WIDTH:
|
||||
eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid1Width);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_MID2GAIN:
|
||||
eax_call.set_value<EaxEqualizerEffectException>(eax_.lMid2Gain);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_MID2CENTER:
|
||||
eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid2Center);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_MID2WIDTH:
|
||||
eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid2Width);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_HIGHGAIN:
|
||||
eax_call.set_value<EaxEqualizerEffectException>(eax_.lHighGain);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_HIGHCUTOFF:
|
||||
eax_call.set_value<EaxEqualizerEffectException>(eax_.flHighCutOff);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxEqualizerEffectException{"Unsupported property id."};
|
||||
eax_validate_range<EqualizerCommitter::Exception>(
|
||||
"Low Cutoff",
|
||||
flLowCutOff,
|
||||
EAXEQUALIZER_MINLOWCUTOFF,
|
||||
EAXEQUALIZER_MAXLOWCUTOFF);
|
||||
}
|
||||
}
|
||||
}; // LowCutOffValidator
|
||||
|
||||
void EaxEqualizerEffect::validate_low_gain(
|
||||
long lLowGain)
|
||||
{
|
||||
eax_validate_range<EaxEqualizerEffectException>(
|
||||
"Low Gain",
|
||||
lLowGain,
|
||||
EAXEQUALIZER_MINLOWGAIN,
|
||||
EAXEQUALIZER_MAXLOWGAIN);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::validate_low_cutoff(
|
||||
float flLowCutOff)
|
||||
{
|
||||
eax_validate_range<EaxEqualizerEffectException>(
|
||||
"Low Cutoff",
|
||||
flLowCutOff,
|
||||
EAXEQUALIZER_MINLOWCUTOFF,
|
||||
EAXEQUALIZER_MAXLOWCUTOFF);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::validate_mid1_gain(
|
||||
long lMid1Gain)
|
||||
{
|
||||
eax_validate_range<EaxEqualizerEffectException>(
|
||||
"Mid1 Gain",
|
||||
lMid1Gain,
|
||||
EAXEQUALIZER_MINMID1GAIN,
|
||||
EAXEQUALIZER_MAXMID1GAIN);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::validate_mid1_center(
|
||||
float flMid1Center)
|
||||
{
|
||||
eax_validate_range<EaxEqualizerEffectException>(
|
||||
"Mid1 Center",
|
||||
flMid1Center,
|
||||
EAXEQUALIZER_MINMID1CENTER,
|
||||
EAXEQUALIZER_MAXMID1CENTER);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::validate_mid1_width(
|
||||
float flMid1Width)
|
||||
{
|
||||
eax_validate_range<EaxEqualizerEffectException>(
|
||||
"Mid1 Width",
|
||||
flMid1Width,
|
||||
EAXEQUALIZER_MINMID1WIDTH,
|
||||
EAXEQUALIZER_MAXMID1WIDTH);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::validate_mid2_gain(
|
||||
long lMid2Gain)
|
||||
{
|
||||
eax_validate_range<EaxEqualizerEffectException>(
|
||||
"Mid2 Gain",
|
||||
lMid2Gain,
|
||||
EAXEQUALIZER_MINMID2GAIN,
|
||||
EAXEQUALIZER_MAXMID2GAIN);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::validate_mid2_center(
|
||||
float flMid2Center)
|
||||
{
|
||||
eax_validate_range<EaxEqualizerEffectException>(
|
||||
"Mid2 Center",
|
||||
flMid2Center,
|
||||
EAXEQUALIZER_MINMID2CENTER,
|
||||
EAXEQUALIZER_MAXMID2CENTER);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::validate_mid2_width(
|
||||
float flMid2Width)
|
||||
{
|
||||
eax_validate_range<EaxEqualizerEffectException>(
|
||||
"Mid2 Width",
|
||||
flMid2Width,
|
||||
EAXEQUALIZER_MINMID2WIDTH,
|
||||
EAXEQUALIZER_MAXMID2WIDTH);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::validate_high_gain(
|
||||
long lHighGain)
|
||||
{
|
||||
eax_validate_range<EaxEqualizerEffectException>(
|
||||
"High Gain",
|
||||
lHighGain,
|
||||
EAXEQUALIZER_MINHIGHGAIN,
|
||||
EAXEQUALIZER_MAXHIGHGAIN);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::validate_high_cutoff(
|
||||
float flHighCutOff)
|
||||
{
|
||||
eax_validate_range<EaxEqualizerEffectException>(
|
||||
"High Cutoff",
|
||||
flHighCutOff,
|
||||
EAXEQUALIZER_MINHIGHCUTOFF,
|
||||
EAXEQUALIZER_MAXHIGHCUTOFF);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::validate_all(
|
||||
const EAXEQUALIZERPROPERTIES& all)
|
||||
{
|
||||
validate_low_gain(all.lLowGain);
|
||||
validate_low_cutoff(all.flLowCutOff);
|
||||
validate_mid1_gain(all.lMid1Gain);
|
||||
validate_mid1_center(all.flMid1Center);
|
||||
validate_mid1_width(all.flMid1Width);
|
||||
validate_mid2_gain(all.lMid2Gain);
|
||||
validate_mid2_center(all.flMid2Center);
|
||||
validate_mid2_width(all.flMid2Width);
|
||||
validate_high_gain(all.lHighGain);
|
||||
validate_high_cutoff(all.flHighCutOff);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_low_gain(
|
||||
long lLowGain)
|
||||
{
|
||||
eax_d_.lLowGain = lLowGain;
|
||||
eax_dirty_flags_.lLowGain = (eax_.lLowGain != eax_d_.lLowGain);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_low_cutoff(
|
||||
float flLowCutOff)
|
||||
{
|
||||
eax_d_.flLowCutOff = flLowCutOff;
|
||||
eax_dirty_flags_.flLowCutOff = (eax_.flLowCutOff != eax_d_.flLowCutOff);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_mid1_gain(
|
||||
long lMid1Gain)
|
||||
{
|
||||
eax_d_.lMid1Gain = lMid1Gain;
|
||||
eax_dirty_flags_.lMid1Gain = (eax_.lMid1Gain != eax_d_.lMid1Gain);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_mid1_center(
|
||||
float flMid1Center)
|
||||
{
|
||||
eax_d_.flMid1Center = flMid1Center;
|
||||
eax_dirty_flags_.flMid1Center = (eax_.flMid1Center != eax_d_.flMid1Center);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_mid1_width(
|
||||
float flMid1Width)
|
||||
{
|
||||
eax_d_.flMid1Width = flMid1Width;
|
||||
eax_dirty_flags_.flMid1Width = (eax_.flMid1Width != eax_d_.flMid1Width);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_mid2_gain(
|
||||
long lMid2Gain)
|
||||
{
|
||||
eax_d_.lMid2Gain = lMid2Gain;
|
||||
eax_dirty_flags_.lMid2Gain = (eax_.lMid2Gain != eax_d_.lMid2Gain);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_mid2_center(
|
||||
float flMid2Center)
|
||||
{
|
||||
eax_d_.flMid2Center = flMid2Center;
|
||||
eax_dirty_flags_.flMid2Center = (eax_.flMid2Center != eax_d_.flMid2Center);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_mid2_width(
|
||||
float flMid2Width)
|
||||
{
|
||||
eax_d_.flMid2Width = flMid2Width;
|
||||
eax_dirty_flags_.flMid2Width = (eax_.flMid2Width != eax_d_.flMid2Width);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_high_gain(
|
||||
long lHighGain)
|
||||
{
|
||||
eax_d_.lHighGain = lHighGain;
|
||||
eax_dirty_flags_.lHighGain = (eax_.lHighGain != eax_d_.lHighGain);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_high_cutoff(
|
||||
float flHighCutOff)
|
||||
{
|
||||
eax_d_.flHighCutOff = flHighCutOff;
|
||||
eax_dirty_flags_.flHighCutOff = (eax_.flHighCutOff != eax_d_.flHighCutOff);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_all(
|
||||
const EAXEQUALIZERPROPERTIES& all)
|
||||
{
|
||||
defer_low_gain(all.lLowGain);
|
||||
defer_low_cutoff(all.flLowCutOff);
|
||||
defer_mid1_gain(all.lMid1Gain);
|
||||
defer_mid1_center(all.flMid1Center);
|
||||
defer_mid1_width(all.flMid1Width);
|
||||
defer_mid2_gain(all.lMid2Gain);
|
||||
defer_mid2_center(all.flMid2Center);
|
||||
defer_mid2_width(all.flMid2Width);
|
||||
defer_high_gain(all.lHighGain);
|
||||
defer_high_cutoff(all.flHighCutOff);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_low_gain(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& low_gain =
|
||||
eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lLowGain)>();
|
||||
|
||||
validate_low_gain(low_gain);
|
||||
defer_low_gain(low_gain);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_low_cutoff(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& low_cutoff =
|
||||
eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flLowCutOff)>();
|
||||
|
||||
validate_low_cutoff(low_cutoff);
|
||||
defer_low_cutoff(low_cutoff);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_mid1_gain(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& mid1_gain =
|
||||
eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lMid1Gain)>();
|
||||
|
||||
validate_mid1_gain(mid1_gain);
|
||||
defer_mid1_gain(mid1_gain);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_mid1_center(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& mid1_center =
|
||||
eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid1Center)>();
|
||||
|
||||
validate_mid1_center(mid1_center);
|
||||
defer_mid1_center(mid1_center);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_mid1_width(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& mid1_width =
|
||||
eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid1Width)>();
|
||||
|
||||
validate_mid1_width(mid1_width);
|
||||
defer_mid1_width(mid1_width);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_mid2_gain(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& mid2_gain =
|
||||
eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lMid2Gain)>();
|
||||
|
||||
validate_mid2_gain(mid2_gain);
|
||||
defer_mid2_gain(mid2_gain);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_mid2_center(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& mid2_center =
|
||||
eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid2Center)>();
|
||||
|
||||
validate_mid2_center(mid2_center);
|
||||
defer_mid2_center(mid2_center);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_mid2_width(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& mid2_width =
|
||||
eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid2Width)>();
|
||||
|
||||
validate_mid2_width(mid2_width);
|
||||
defer_mid2_width(mid2_width);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_high_gain(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& high_gain =
|
||||
eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lHighGain)>();
|
||||
|
||||
validate_high_gain(high_gain);
|
||||
defer_high_gain(high_gain);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_high_cutoff(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& high_cutoff =
|
||||
eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flHighCutOff)>();
|
||||
|
||||
validate_high_cutoff(high_cutoff);
|
||||
defer_high_cutoff(high_cutoff);
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::defer_all(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& all =
|
||||
eax_call.get_value<EaxEqualizerEffectException, const EAXEQUALIZERPROPERTIES>();
|
||||
|
||||
validate_all(all);
|
||||
defer_all(all);
|
||||
}
|
||||
|
||||
// [[nodiscard]]
|
||||
bool EaxEqualizerEffect::apply_deferred()
|
||||
{
|
||||
if (eax_dirty_flags_ == EaxEqualizerEffectDirtyFlags{})
|
||||
struct Mid1GainValidator {
|
||||
void operator()(long lMid1Gain) const
|
||||
{
|
||||
eax_validate_range<EqualizerCommitter::Exception>(
|
||||
"Mid1 Gain",
|
||||
lMid1Gain,
|
||||
EAXEQUALIZER_MINMID1GAIN,
|
||||
EAXEQUALIZER_MAXMID1GAIN);
|
||||
}
|
||||
}; // Mid1GainValidator
|
||||
|
||||
struct Mid1CenterValidator {
|
||||
void operator()(float flMid1Center) const
|
||||
{
|
||||
eax_validate_range<EqualizerCommitter::Exception>(
|
||||
"Mid1 Center",
|
||||
flMid1Center,
|
||||
EAXEQUALIZER_MINMID1CENTER,
|
||||
EAXEQUALIZER_MAXMID1CENTER);
|
||||
}
|
||||
}; // Mid1CenterValidator
|
||||
|
||||
struct Mid1WidthValidator {
|
||||
void operator()(float flMid1Width) const
|
||||
{
|
||||
eax_validate_range<EqualizerCommitter::Exception>(
|
||||
"Mid1 Width",
|
||||
flMid1Width,
|
||||
EAXEQUALIZER_MINMID1WIDTH,
|
||||
EAXEQUALIZER_MAXMID1WIDTH);
|
||||
}
|
||||
}; // Mid1WidthValidator
|
||||
|
||||
struct Mid2GainValidator {
|
||||
void operator()(long lMid2Gain) const
|
||||
{
|
||||
eax_validate_range<EqualizerCommitter::Exception>(
|
||||
"Mid2 Gain",
|
||||
lMid2Gain,
|
||||
EAXEQUALIZER_MINMID2GAIN,
|
||||
EAXEQUALIZER_MAXMID2GAIN);
|
||||
}
|
||||
}; // Mid2GainValidator
|
||||
|
||||
struct Mid2CenterValidator {
|
||||
void operator()(float flMid2Center) const
|
||||
{
|
||||
eax_validate_range<EqualizerCommitter::Exception>(
|
||||
"Mid2 Center",
|
||||
flMid2Center,
|
||||
EAXEQUALIZER_MINMID2CENTER,
|
||||
EAXEQUALIZER_MAXMID2CENTER);
|
||||
}
|
||||
}; // Mid2CenterValidator
|
||||
|
||||
struct Mid2WidthValidator {
|
||||
void operator()(float flMid2Width) const
|
||||
{
|
||||
eax_validate_range<EqualizerCommitter::Exception>(
|
||||
"Mid2 Width",
|
||||
flMid2Width,
|
||||
EAXEQUALIZER_MINMID2WIDTH,
|
||||
EAXEQUALIZER_MAXMID2WIDTH);
|
||||
}
|
||||
}; // Mid2WidthValidator
|
||||
|
||||
struct HighGainValidator {
|
||||
void operator()(long lHighGain) const
|
||||
{
|
||||
eax_validate_range<EqualizerCommitter::Exception>(
|
||||
"High Gain",
|
||||
lHighGain,
|
||||
EAXEQUALIZER_MINHIGHGAIN,
|
||||
EAXEQUALIZER_MAXHIGHGAIN);
|
||||
}
|
||||
}; // HighGainValidator
|
||||
|
||||
struct HighCutOffValidator {
|
||||
void operator()(float flHighCutOff) const
|
||||
{
|
||||
eax_validate_range<EqualizerCommitter::Exception>(
|
||||
"High Cutoff",
|
||||
flHighCutOff,
|
||||
EAXEQUALIZER_MINHIGHCUTOFF,
|
||||
EAXEQUALIZER_MAXHIGHCUTOFF);
|
||||
}
|
||||
}; // HighCutOffValidator
|
||||
|
||||
struct AllValidator {
|
||||
void operator()(const EAXEQUALIZERPROPERTIES& all) const
|
||||
{
|
||||
LowGainValidator{}(all.lLowGain);
|
||||
LowCutOffValidator{}(all.flLowCutOff);
|
||||
Mid1GainValidator{}(all.lMid1Gain);
|
||||
Mid1CenterValidator{}(all.flMid1Center);
|
||||
Mid1WidthValidator{}(all.flMid1Width);
|
||||
Mid2GainValidator{}(all.lMid2Gain);
|
||||
Mid2CenterValidator{}(all.flMid2Center);
|
||||
Mid2WidthValidator{}(all.flMid2Width);
|
||||
HighGainValidator{}(all.lHighGain);
|
||||
HighCutOffValidator{}(all.flHighCutOff);
|
||||
}
|
||||
}; // AllValidator
|
||||
|
||||
} // namespace
|
||||
|
||||
template<>
|
||||
struct EqualizerCommitter::Exception : public EaxException {
|
||||
explicit Exception(const char* message) : EaxException{"EAX_EQUALIZER_EFFECT", message}
|
||||
{ }
|
||||
};
|
||||
|
||||
template<>
|
||||
[[noreturn]] void EqualizerCommitter::fail(const char *message)
|
||||
{
|
||||
throw Exception{message};
|
||||
}
|
||||
|
||||
template<>
|
||||
bool EqualizerCommitter::commit(const EaxEffectProps &props)
|
||||
{
|
||||
if(props.mType == mEaxProps.mType && mEaxProps.mEqualizer.lLowGain == props.mEqualizer.lLowGain
|
||||
&& mEaxProps.mEqualizer.flLowCutOff == props.mEqualizer.flLowCutOff
|
||||
&& mEaxProps.mEqualizer.lMid1Gain == props.mEqualizer.lMid1Gain
|
||||
&& mEaxProps.mEqualizer.flMid1Center == props.mEqualizer.flMid1Center
|
||||
&& mEaxProps.mEqualizer.flMid1Width == props.mEqualizer.flMid1Width
|
||||
&& mEaxProps.mEqualizer.lMid2Gain == props.mEqualizer.lMid2Gain
|
||||
&& mEaxProps.mEqualizer.flMid2Center == props.mEqualizer.flMid2Center
|
||||
&& mEaxProps.mEqualizer.flMid2Width == props.mEqualizer.flMid2Width
|
||||
&& mEaxProps.mEqualizer.lHighGain == props.mEqualizer.lHighGain
|
||||
&& mEaxProps.mEqualizer.flHighCutOff == props.mEqualizer.flHighCutOff)
|
||||
return false;
|
||||
}
|
||||
|
||||
eax_ = eax_d_;
|
||||
mEaxProps = props;
|
||||
|
||||
if (eax_dirty_flags_.lLowGain)
|
||||
{
|
||||
set_efx_low_gain();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flLowCutOff)
|
||||
{
|
||||
set_efx_low_cutoff();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.lMid1Gain)
|
||||
{
|
||||
set_efx_mid1_gain();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flMid1Center)
|
||||
{
|
||||
set_efx_mid1_center();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flMid1Width)
|
||||
{
|
||||
set_efx_mid1_width();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.lMid2Gain)
|
||||
{
|
||||
set_efx_mid2_gain();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flMid2Center)
|
||||
{
|
||||
set_efx_mid2_center();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flMid2Width)
|
||||
{
|
||||
set_efx_mid2_width();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.lHighGain)
|
||||
{
|
||||
set_efx_high_gain();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flHighCutOff)
|
||||
{
|
||||
set_efx_high_cutoff();
|
||||
}
|
||||
|
||||
eax_dirty_flags_ = EaxEqualizerEffectDirtyFlags{};
|
||||
mAlProps.Equalizer.LowGain = level_mb_to_gain(static_cast<float>(props.mEqualizer.lLowGain));
|
||||
mAlProps.Equalizer.LowCutoff = props.mEqualizer.flLowCutOff;
|
||||
mAlProps.Equalizer.Mid1Gain = level_mb_to_gain(static_cast<float>(props.mEqualizer.lMid1Gain));
|
||||
mAlProps.Equalizer.Mid1Center = props.mEqualizer.flMid1Center;
|
||||
mAlProps.Equalizer.Mid1Width = props.mEqualizer.flMid1Width;
|
||||
mAlProps.Equalizer.Mid2Gain = level_mb_to_gain(static_cast<float>(props.mEqualizer.lMid2Gain));
|
||||
mAlProps.Equalizer.Mid2Center = props.mEqualizer.flMid2Center;
|
||||
mAlProps.Equalizer.Mid2Width = props.mEqualizer.flMid2Width;
|
||||
mAlProps.Equalizer.HighGain = level_mb_to_gain(static_cast<float>(props.mEqualizer.lHighGain));
|
||||
mAlProps.Equalizer.HighCutoff = props.mEqualizer.flHighCutOff;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EaxEqualizerEffect::set(const EaxEaxCall& eax_call)
|
||||
template<>
|
||||
void EqualizerCommitter::SetDefaults(EaxEffectProps &props)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
props.mType = EaxEffectType::Equalizer;
|
||||
props.mEqualizer.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN;
|
||||
props.mEqualizer.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF;
|
||||
props.mEqualizer.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN;
|
||||
props.mEqualizer.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER;
|
||||
props.mEqualizer.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH;
|
||||
props.mEqualizer.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN;
|
||||
props.mEqualizer.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER;
|
||||
props.mEqualizer.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH;
|
||||
props.mEqualizer.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN;
|
||||
props.mEqualizer.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF;
|
||||
}
|
||||
|
||||
template<>
|
||||
void EqualizerCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
|
||||
{
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXEQUALIZER_NONE:
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_ALLPARAMETERS:
|
||||
defer_all(eax_call);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_LOWGAIN:
|
||||
defer_low_gain(eax_call);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_LOWCUTOFF:
|
||||
defer_low_cutoff(eax_call);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_MID1GAIN:
|
||||
defer_mid1_gain(eax_call);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_MID1CENTER:
|
||||
defer_mid1_center(eax_call);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_MID1WIDTH:
|
||||
defer_mid1_width(eax_call);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_MID2GAIN:
|
||||
defer_mid2_gain(eax_call);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_MID2CENTER:
|
||||
defer_mid2_center(eax_call);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_MID2WIDTH:
|
||||
defer_mid2_width(eax_call);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_HIGHGAIN:
|
||||
defer_high_gain(eax_call);
|
||||
break;
|
||||
|
||||
case EAXEQUALIZER_HIGHCUTOFF:
|
||||
defer_high_cutoff(eax_call);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxEqualizerEffectException{"Unsupported property id."};
|
||||
case EAXEQUALIZER_NONE: break;
|
||||
case EAXEQUALIZER_ALLPARAMETERS: call.set_value<Exception>(props.mEqualizer); break;
|
||||
case EAXEQUALIZER_LOWGAIN: call.set_value<Exception>(props.mEqualizer.lLowGain); break;
|
||||
case EAXEQUALIZER_LOWCUTOFF: call.set_value<Exception>(props.mEqualizer.flLowCutOff); break;
|
||||
case EAXEQUALIZER_MID1GAIN: call.set_value<Exception>(props.mEqualizer.lMid1Gain); break;
|
||||
case EAXEQUALIZER_MID1CENTER: call.set_value<Exception>(props.mEqualizer.flMid1Center); break;
|
||||
case EAXEQUALIZER_MID1WIDTH: call.set_value<Exception>(props.mEqualizer.flMid1Width); break;
|
||||
case EAXEQUALIZER_MID2GAIN: call.set_value<Exception>(props.mEqualizer.lMid2Gain); break;
|
||||
case EAXEQUALIZER_MID2CENTER: call.set_value<Exception>(props.mEqualizer.flMid2Center); break;
|
||||
case EAXEQUALIZER_MID2WIDTH: call.set_value<Exception>(props.mEqualizer.flMid2Width); break;
|
||||
case EAXEQUALIZER_HIGHGAIN: call.set_value<Exception>(props.mEqualizer.lHighGain); break;
|
||||
case EAXEQUALIZER_HIGHCUTOFF: call.set_value<Exception>(props.mEqualizer.flHighCutOff); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EaxEffectUPtr eax_create_eax_equalizer_effect()
|
||||
template<>
|
||||
void EqualizerCommitter::Set(const EaxCall &call, EaxEffectProps &props)
|
||||
{
|
||||
return std::make_unique<EaxEqualizerEffect>();
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXEQUALIZER_NONE: break;
|
||||
case EAXEQUALIZER_ALLPARAMETERS: defer<AllValidator>(call, props.mEqualizer); break;
|
||||
case EAXEQUALIZER_LOWGAIN: defer<LowGainValidator>(call, props.mEqualizer.lLowGain); break;
|
||||
case EAXEQUALIZER_LOWCUTOFF: defer<LowCutOffValidator>(call, props.mEqualizer.flLowCutOff); break;
|
||||
case EAXEQUALIZER_MID1GAIN: defer<Mid1GainValidator>(call, props.mEqualizer.lMid1Gain); break;
|
||||
case EAXEQUALIZER_MID1CENTER: defer<Mid1CenterValidator>(call, props.mEqualizer.flMid1Center); break;
|
||||
case EAXEQUALIZER_MID1WIDTH: defer<Mid1WidthValidator>(call, props.mEqualizer.flMid1Width); break;
|
||||
case EAXEQUALIZER_MID2GAIN: defer<Mid2GainValidator>(call, props.mEqualizer.lMid2Gain); break;
|
||||
case EAXEQUALIZER_MID2CENTER: defer<Mid2CenterValidator>(call, props.mEqualizer.flMid2Center); break;
|
||||
case EAXEQUALIZER_MID2WIDTH: defer<Mid2WidthValidator>(call, props.mEqualizer.flMid2Width); break;
|
||||
case EAXEQUALIZER_HIGHGAIN: defer<HighGainValidator>(call, props.mEqualizer.lHighGain); break;
|
||||
case EAXEQUALIZER_HIGHCUTOFF: defer<HighCutOffValidator>(call, props.mEqualizer.flHighCutOff); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ALSOFT_EAX
|
||||
|
|
|
|||
|
|
@ -12,11 +12,9 @@
|
|||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include <cassert>
|
||||
|
||||
#include "alnumeric.h"
|
||||
|
||||
#include "al/eax_exception.h"
|
||||
#include "al/eax_utils.h"
|
||||
#include "al/eax/exception.h"
|
||||
#include "al/eax/utils.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
|
||||
|
|
@ -26,9 +24,9 @@ al::optional<FShifterDirection> DirectionFromEmum(ALenum value)
|
|||
{
|
||||
switch(value)
|
||||
{
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_DOWN: return al::make_optional(FShifterDirection::Down);
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_UP: return al::make_optional(FShifterDirection::Up);
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_OFF: return al::make_optional(FShifterDirection::Off);
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_DOWN: return FShifterDirection::Down;
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_UP: return FShifterDirection::Up;
|
||||
case AL_FREQUENCY_SHIFTER_DIRECTION_OFF: return FShifterDirection::Off;
|
||||
}
|
||||
return al::nullopt;
|
||||
}
|
||||
|
|
@ -141,339 +139,126 @@ const EffectProps FshifterEffectProps{genDefaultProps()};
|
|||
#ifdef ALSOFT_EAX
|
||||
namespace {
|
||||
|
||||
using EaxFrequencyShifterEffectDirtyFlagsValue = std::uint_least8_t;
|
||||
using FrequencyShifterCommitter = EaxCommitter<EaxFrequencyShifterCommitter>;
|
||||
|
||||
struct EaxFrequencyShifterEffectDirtyFlags
|
||||
{
|
||||
using EaxIsBitFieldStruct = bool;
|
||||
|
||||
EaxFrequencyShifterEffectDirtyFlagsValue flFrequency : 1;
|
||||
EaxFrequencyShifterEffectDirtyFlagsValue ulLeftDirection : 1;
|
||||
EaxFrequencyShifterEffectDirtyFlagsValue ulRightDirection : 1;
|
||||
}; // EaxFrequencyShifterEffectDirtyFlags
|
||||
|
||||
|
||||
class EaxFrequencyShifterEffect final :
|
||||
public EaxEffect
|
||||
{
|
||||
public:
|
||||
EaxFrequencyShifterEffect();
|
||||
|
||||
void dispatch(const EaxEaxCall& eax_call) override;
|
||||
|
||||
// [[nodiscard]]
|
||||
bool apply_deferred() override;
|
||||
|
||||
private:
|
||||
EAXFREQUENCYSHIFTERPROPERTIES eax_{};
|
||||
EAXFREQUENCYSHIFTERPROPERTIES eax_d_{};
|
||||
EaxFrequencyShifterEffectDirtyFlags eax_dirty_flags_{};
|
||||
|
||||
void set_eax_defaults();
|
||||
|
||||
void set_efx_frequency();
|
||||
void set_efx_left_direction();
|
||||
void set_efx_right_direction();
|
||||
void set_efx_defaults();
|
||||
|
||||
void get(const EaxEaxCall& eax_call);
|
||||
|
||||
void validate_frequency(float flFrequency);
|
||||
void validate_left_direction(unsigned long ulLeftDirection);
|
||||
void validate_right_direction(unsigned long ulRightDirection);
|
||||
void validate_all(const EAXFREQUENCYSHIFTERPROPERTIES& all);
|
||||
|
||||
void defer_frequency(float flFrequency);
|
||||
void defer_left_direction(unsigned long ulLeftDirection);
|
||||
void defer_right_direction(unsigned long ulRightDirection);
|
||||
void defer_all(const EAXFREQUENCYSHIFTERPROPERTIES& all);
|
||||
|
||||
void defer_frequency(const EaxEaxCall& eax_call);
|
||||
void defer_left_direction(const EaxEaxCall& eax_call);
|
||||
void defer_right_direction(const EaxEaxCall& eax_call);
|
||||
void defer_all(const EaxEaxCall& eax_call);
|
||||
|
||||
void set(const EaxEaxCall& eax_call);
|
||||
}; // EaxFrequencyShifterEffect
|
||||
|
||||
|
||||
class EaxFrequencyShifterEffectException :
|
||||
public EaxException
|
||||
{
|
||||
public:
|
||||
explicit EaxFrequencyShifterEffectException(
|
||||
const char* message)
|
||||
:
|
||||
EaxException{"EAX_FREQUENCY_SHIFTER_EFFECT", message}
|
||||
struct FrequencyValidator {
|
||||
void operator()(float flFrequency) const
|
||||
{
|
||||
eax_validate_range<FrequencyShifterCommitter::Exception>(
|
||||
"Frequency",
|
||||
flFrequency,
|
||||
EAXFREQUENCYSHIFTER_MINFREQUENCY,
|
||||
EAXFREQUENCYSHIFTER_MAXFREQUENCY);
|
||||
}
|
||||
}; // EaxFrequencyShifterEffectException
|
||||
}; // FrequencyValidator
|
||||
|
||||
|
||||
EaxFrequencyShifterEffect::EaxFrequencyShifterEffect()
|
||||
: EaxEffect{AL_EFFECT_FREQUENCY_SHIFTER}
|
||||
{
|
||||
set_eax_defaults();
|
||||
set_efx_defaults();
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::dispatch(const EaxEaxCall& eax_call)
|
||||
{
|
||||
eax_call.is_get() ? get(eax_call) : set(eax_call);
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::set_eax_defaults()
|
||||
{
|
||||
eax_.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY;
|
||||
eax_.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION;
|
||||
eax_.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION;
|
||||
|
||||
eax_d_ = eax_;
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::set_efx_frequency()
|
||||
{
|
||||
const auto frequency = clamp(
|
||||
eax_.flFrequency,
|
||||
AL_FREQUENCY_SHIFTER_MIN_FREQUENCY,
|
||||
AL_FREQUENCY_SHIFTER_MAX_FREQUENCY);
|
||||
|
||||
al_effect_props_.Fshifter.Frequency = frequency;
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::set_efx_left_direction()
|
||||
{
|
||||
const auto left_direction = clamp(
|
||||
static_cast<ALint>(eax_.ulLeftDirection),
|
||||
AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION,
|
||||
AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION);
|
||||
|
||||
const auto efx_left_direction = DirectionFromEmum(left_direction);
|
||||
assert(efx_left_direction.has_value());
|
||||
al_effect_props_.Fshifter.LeftDirection = *efx_left_direction;
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::set_efx_right_direction()
|
||||
{
|
||||
const auto right_direction = clamp(
|
||||
static_cast<ALint>(eax_.ulRightDirection),
|
||||
AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION,
|
||||
AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION);
|
||||
|
||||
const auto efx_right_direction = DirectionFromEmum(right_direction);
|
||||
assert(efx_right_direction.has_value());
|
||||
al_effect_props_.Fshifter.RightDirection = *efx_right_direction;
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::set_efx_defaults()
|
||||
{
|
||||
set_efx_frequency();
|
||||
set_efx_left_direction();
|
||||
set_efx_right_direction();
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::get(const EaxEaxCall& eax_call)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
struct LeftDirectionValidator {
|
||||
void operator()(unsigned long ulLeftDirection) const
|
||||
{
|
||||
case EAXFREQUENCYSHIFTER_NONE:
|
||||
break;
|
||||
|
||||
case EAXFREQUENCYSHIFTER_ALLPARAMETERS:
|
||||
eax_call.set_value<EaxFrequencyShifterEffectException>(eax_);
|
||||
break;
|
||||
|
||||
case EAXFREQUENCYSHIFTER_FREQUENCY:
|
||||
eax_call.set_value<EaxFrequencyShifterEffectException>(eax_.flFrequency);
|
||||
break;
|
||||
|
||||
case EAXFREQUENCYSHIFTER_LEFTDIRECTION:
|
||||
eax_call.set_value<EaxFrequencyShifterEffectException>(eax_.ulLeftDirection);
|
||||
break;
|
||||
|
||||
case EAXFREQUENCYSHIFTER_RIGHTDIRECTION:
|
||||
eax_call.set_value<EaxFrequencyShifterEffectException>(eax_.ulRightDirection);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxFrequencyShifterEffectException{"Unsupported property id."};
|
||||
eax_validate_range<FrequencyShifterCommitter::Exception>(
|
||||
"Left Direction",
|
||||
ulLeftDirection,
|
||||
EAXFREQUENCYSHIFTER_MINLEFTDIRECTION,
|
||||
EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION);
|
||||
}
|
||||
}
|
||||
}; // LeftDirectionValidator
|
||||
|
||||
void EaxFrequencyShifterEffect::validate_frequency(
|
||||
float flFrequency)
|
||||
{
|
||||
eax_validate_range<EaxFrequencyShifterEffectException>(
|
||||
"Frequency",
|
||||
flFrequency,
|
||||
EAXFREQUENCYSHIFTER_MINFREQUENCY,
|
||||
EAXFREQUENCYSHIFTER_MAXFREQUENCY);
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::validate_left_direction(
|
||||
unsigned long ulLeftDirection)
|
||||
{
|
||||
eax_validate_range<EaxFrequencyShifterEffectException>(
|
||||
"Left Direction",
|
||||
ulLeftDirection,
|
||||
EAXFREQUENCYSHIFTER_MINLEFTDIRECTION,
|
||||
EAXFREQUENCYSHIFTER_MAXLEFTDIRECTION);
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::validate_right_direction(
|
||||
unsigned long ulRightDirection)
|
||||
{
|
||||
eax_validate_range<EaxFrequencyShifterEffectException>(
|
||||
"Right Direction",
|
||||
ulRightDirection,
|
||||
EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION,
|
||||
EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION);
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::validate_all(
|
||||
const EAXFREQUENCYSHIFTERPROPERTIES& all)
|
||||
{
|
||||
validate_frequency(all.flFrequency);
|
||||
validate_left_direction(all.ulLeftDirection);
|
||||
validate_right_direction(all.ulRightDirection);
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::defer_frequency(
|
||||
float flFrequency)
|
||||
{
|
||||
eax_d_.flFrequency = flFrequency;
|
||||
eax_dirty_flags_.flFrequency = (eax_.flFrequency != eax_d_.flFrequency);
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::defer_left_direction(
|
||||
unsigned long ulLeftDirection)
|
||||
{
|
||||
eax_d_.ulLeftDirection = ulLeftDirection;
|
||||
eax_dirty_flags_.ulLeftDirection = (eax_.ulLeftDirection != eax_d_.ulLeftDirection);
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::defer_right_direction(
|
||||
unsigned long ulRightDirection)
|
||||
{
|
||||
eax_d_.ulRightDirection = ulRightDirection;
|
||||
eax_dirty_flags_.ulRightDirection = (eax_.ulRightDirection != eax_d_.ulRightDirection);
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::defer_all(
|
||||
const EAXFREQUENCYSHIFTERPROPERTIES& all)
|
||||
{
|
||||
defer_frequency(all.flFrequency);
|
||||
defer_left_direction(all.ulLeftDirection);
|
||||
defer_right_direction(all.ulRightDirection);
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::defer_frequency(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& frequency =
|
||||
eax_call.get_value<
|
||||
EaxFrequencyShifterEffectException, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::flFrequency)>();
|
||||
|
||||
validate_frequency(frequency);
|
||||
defer_frequency(frequency);
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::defer_left_direction(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& left_direction =
|
||||
eax_call.get_value<
|
||||
EaxFrequencyShifterEffectException, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::ulLeftDirection)>();
|
||||
|
||||
validate_left_direction(left_direction);
|
||||
defer_left_direction(left_direction);
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::defer_right_direction(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& right_direction =
|
||||
eax_call.get_value<
|
||||
EaxFrequencyShifterEffectException, const decltype(EAXFREQUENCYSHIFTERPROPERTIES::ulRightDirection)>();
|
||||
|
||||
validate_right_direction(right_direction);
|
||||
defer_right_direction(right_direction);
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::defer_all(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& all =
|
||||
eax_call.get_value<
|
||||
EaxFrequencyShifterEffectException, const EAXFREQUENCYSHIFTERPROPERTIES>();
|
||||
|
||||
validate_all(all);
|
||||
defer_all(all);
|
||||
}
|
||||
|
||||
// [[nodiscard]]
|
||||
bool EaxFrequencyShifterEffect::apply_deferred()
|
||||
{
|
||||
if (eax_dirty_flags_ == EaxFrequencyShifterEffectDirtyFlags{})
|
||||
struct RightDirectionValidator {
|
||||
void operator()(unsigned long ulRightDirection) const
|
||||
{
|
||||
eax_validate_range<FrequencyShifterCommitter::Exception>(
|
||||
"Right Direction",
|
||||
ulRightDirection,
|
||||
EAXFREQUENCYSHIFTER_MINRIGHTDIRECTION,
|
||||
EAXFREQUENCYSHIFTER_MAXRIGHTDIRECTION);
|
||||
}
|
||||
}; // RightDirectionValidator
|
||||
|
||||
struct AllValidator {
|
||||
void operator()(const EAXFREQUENCYSHIFTERPROPERTIES& all) const
|
||||
{
|
||||
FrequencyValidator{}(all.flFrequency);
|
||||
LeftDirectionValidator{}(all.ulLeftDirection);
|
||||
RightDirectionValidator{}(all.ulRightDirection);
|
||||
}
|
||||
}; // AllValidator
|
||||
|
||||
} // namespace
|
||||
|
||||
template<>
|
||||
struct FrequencyShifterCommitter::Exception : public EaxException {
|
||||
explicit Exception(const char *message) : EaxException{"EAX_FREQUENCY_SHIFTER_EFFECT", message}
|
||||
{ }
|
||||
};
|
||||
|
||||
template<>
|
||||
[[noreturn]] void FrequencyShifterCommitter::fail(const char *message)
|
||||
{
|
||||
throw Exception{message};
|
||||
}
|
||||
|
||||
template<>
|
||||
bool FrequencyShifterCommitter::commit(const EaxEffectProps &props)
|
||||
{
|
||||
if(props.mType == mEaxProps.mType
|
||||
&& mEaxProps.mFrequencyShifter.flFrequency == props.mFrequencyShifter.flFrequency
|
||||
&& mEaxProps.mFrequencyShifter.ulLeftDirection == props.mFrequencyShifter.ulLeftDirection
|
||||
&& mEaxProps.mFrequencyShifter.ulRightDirection == props.mFrequencyShifter.ulRightDirection)
|
||||
return false;
|
||||
}
|
||||
|
||||
eax_ = eax_d_;
|
||||
mEaxProps = props;
|
||||
|
||||
if (eax_dirty_flags_.flFrequency)
|
||||
auto get_direction = [](unsigned long dir) noexcept
|
||||
{
|
||||
set_efx_frequency();
|
||||
}
|
||||
if(dir == EAX_FREQUENCYSHIFTER_DOWN)
|
||||
return FShifterDirection::Down;
|
||||
if(dir == EAX_FREQUENCYSHIFTER_UP)
|
||||
return FShifterDirection::Up;
|
||||
return FShifterDirection::Off;
|
||||
};
|
||||
|
||||
if (eax_dirty_flags_.ulLeftDirection)
|
||||
{
|
||||
set_efx_left_direction();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.ulRightDirection)
|
||||
{
|
||||
set_efx_right_direction();
|
||||
}
|
||||
|
||||
eax_dirty_flags_ = EaxFrequencyShifterEffectDirtyFlags{};
|
||||
mAlProps.Fshifter.Frequency = props.mFrequencyShifter.flFrequency;
|
||||
mAlProps.Fshifter.LeftDirection = get_direction(props.mFrequencyShifter.ulLeftDirection);
|
||||
mAlProps.Fshifter.RightDirection = get_direction(props.mFrequencyShifter.ulRightDirection);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EaxFrequencyShifterEffect::set(const EaxEaxCall& eax_call)
|
||||
template<>
|
||||
void FrequencyShifterCommitter::SetDefaults(EaxEffectProps &props)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
props.mType = EaxEffectType::FrequencyShifter;
|
||||
props.mFrequencyShifter.flFrequency = EAXFREQUENCYSHIFTER_DEFAULTFREQUENCY;
|
||||
props.mFrequencyShifter.ulLeftDirection = EAXFREQUENCYSHIFTER_DEFAULTLEFTDIRECTION;
|
||||
props.mFrequencyShifter.ulRightDirection = EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION;
|
||||
}
|
||||
|
||||
template<>
|
||||
void FrequencyShifterCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
|
||||
{
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXFREQUENCYSHIFTER_NONE:
|
||||
break;
|
||||
|
||||
case EAXFREQUENCYSHIFTER_ALLPARAMETERS:
|
||||
defer_all(eax_call);
|
||||
break;
|
||||
|
||||
case EAXFREQUENCYSHIFTER_FREQUENCY:
|
||||
defer_frequency(eax_call);
|
||||
break;
|
||||
|
||||
case EAXFREQUENCYSHIFTER_LEFTDIRECTION:
|
||||
defer_left_direction(eax_call);
|
||||
break;
|
||||
|
||||
case EAXFREQUENCYSHIFTER_RIGHTDIRECTION:
|
||||
defer_right_direction(eax_call);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxFrequencyShifterEffectException{"Unsupported property id."};
|
||||
case EAXFREQUENCYSHIFTER_NONE: break;
|
||||
case EAXFREQUENCYSHIFTER_ALLPARAMETERS: call.set_value<Exception>(props.mFrequencyShifter); break;
|
||||
case EAXFREQUENCYSHIFTER_FREQUENCY: call.set_value<Exception>(props.mFrequencyShifter.flFrequency); break;
|
||||
case EAXFREQUENCYSHIFTER_LEFTDIRECTION: call.set_value<Exception>(props.mFrequencyShifter.ulLeftDirection); break;
|
||||
case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: call.set_value<Exception>(props.mFrequencyShifter.ulRightDirection); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EaxEffectUPtr eax_create_eax_frequency_shifter_effect()
|
||||
template<>
|
||||
void FrequencyShifterCommitter::Set(const EaxCall &call, EaxEffectProps &props)
|
||||
{
|
||||
return std::make_unique<EaxFrequencyShifterEffect>();
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXFREQUENCYSHIFTER_NONE: break;
|
||||
case EAXFREQUENCYSHIFTER_ALLPARAMETERS: defer<AllValidator>(call, props.mFrequencyShifter); break;
|
||||
case EAXFREQUENCYSHIFTER_FREQUENCY: defer<FrequencyValidator>(call, props.mFrequencyShifter.flFrequency); break;
|
||||
case EAXFREQUENCYSHIFTER_LEFTDIRECTION: defer<LeftDirectionValidator>(call, props.mFrequencyShifter.ulLeftDirection); break;
|
||||
case EAXFREQUENCYSHIFTER_RIGHTDIRECTION: defer<RightDirectionValidator>(call, props.mFrequencyShifter.ulRightDirection); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ALSOFT_EAX
|
||||
|
|
|
|||
|
|
@ -12,11 +12,9 @@
|
|||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include <cassert>
|
||||
|
||||
#include "alnumeric.h"
|
||||
|
||||
#include "al/eax_exception.h"
|
||||
#include "al/eax_utils.h"
|
||||
#include "al/eax/exception.h"
|
||||
#include "al/eax/utils.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
|
||||
|
|
@ -26,9 +24,9 @@ al::optional<ModulatorWaveform> WaveformFromEmum(ALenum value)
|
|||
{
|
||||
switch(value)
|
||||
{
|
||||
case AL_RING_MODULATOR_SINUSOID: return al::make_optional(ModulatorWaveform::Sinusoid);
|
||||
case AL_RING_MODULATOR_SAWTOOTH: return al::make_optional(ModulatorWaveform::Sawtooth);
|
||||
case AL_RING_MODULATOR_SQUARE: return al::make_optional(ModulatorWaveform::Square);
|
||||
case AL_RING_MODULATOR_SINUSOID: return ModulatorWaveform::Sinusoid;
|
||||
case AL_RING_MODULATOR_SAWTOOTH: return ModulatorWaveform::Sawtooth;
|
||||
case AL_RING_MODULATOR_SQUARE: return ModulatorWaveform::Square;
|
||||
}
|
||||
return al::nullopt;
|
||||
}
|
||||
|
|
@ -147,336 +145,128 @@ const EffectProps ModulatorEffectProps{genDefaultProps()};
|
|||
#ifdef ALSOFT_EAX
|
||||
namespace {
|
||||
|
||||
using EaxRingModulatorEffectDirtyFlagsValue = std::uint_least8_t;
|
||||
using ModulatorCommitter = EaxCommitter<EaxModulatorCommitter>;
|
||||
|
||||
struct EaxRingModulatorEffectDirtyFlags
|
||||
{
|
||||
using EaxIsBitFieldStruct = bool;
|
||||
|
||||
EaxRingModulatorEffectDirtyFlagsValue flFrequency : 1;
|
||||
EaxRingModulatorEffectDirtyFlagsValue flHighPassCutOff : 1;
|
||||
EaxRingModulatorEffectDirtyFlagsValue ulWaveform : 1;
|
||||
}; // EaxPitchShifterEffectDirtyFlags
|
||||
|
||||
|
||||
class EaxRingModulatorEffect final :
|
||||
public EaxEffect
|
||||
{
|
||||
public:
|
||||
EaxRingModulatorEffect();
|
||||
|
||||
void dispatch(const EaxEaxCall& eax_call) override;
|
||||
|
||||
// [[nodiscard]]
|
||||
bool apply_deferred() override;
|
||||
|
||||
private:
|
||||
EAXRINGMODULATORPROPERTIES eax_{};
|
||||
EAXRINGMODULATORPROPERTIES eax_d_{};
|
||||
EaxRingModulatorEffectDirtyFlags eax_dirty_flags_{};
|
||||
|
||||
void set_eax_defaults();
|
||||
|
||||
void set_efx_frequency();
|
||||
void set_efx_high_pass_cutoff();
|
||||
void set_efx_waveform();
|
||||
void set_efx_defaults();
|
||||
|
||||
void get(const EaxEaxCall& eax_call);
|
||||
|
||||
void validate_frequency(float flFrequency);
|
||||
void validate_high_pass_cutoff(float flHighPassCutOff);
|
||||
void validate_waveform(unsigned long ulWaveform);
|
||||
void validate_all(const EAXRINGMODULATORPROPERTIES& all);
|
||||
|
||||
void defer_frequency(float flFrequency);
|
||||
void defer_high_pass_cutoff(float flHighPassCutOff);
|
||||
void defer_waveform(unsigned long ulWaveform);
|
||||
void defer_all(const EAXRINGMODULATORPROPERTIES& all);
|
||||
|
||||
void defer_frequency(const EaxEaxCall& eax_call);
|
||||
void defer_high_pass_cutoff(const EaxEaxCall& eax_call);
|
||||
void defer_waveform(const EaxEaxCall& eax_call);
|
||||
void defer_all(const EaxEaxCall& eax_call);
|
||||
|
||||
void set(const EaxEaxCall& eax_call);
|
||||
}; // EaxRingModulatorEffect
|
||||
|
||||
|
||||
class EaxRingModulatorEffectException :
|
||||
public EaxException
|
||||
{
|
||||
public:
|
||||
explicit EaxRingModulatorEffectException(
|
||||
const char* message)
|
||||
:
|
||||
EaxException{"EAX_RING_MODULATOR_EFFECT", message}
|
||||
struct FrequencyValidator {
|
||||
void operator()(float flFrequency) const
|
||||
{
|
||||
eax_validate_range<ModulatorCommitter::Exception>(
|
||||
"Frequency",
|
||||
flFrequency,
|
||||
EAXRINGMODULATOR_MINFREQUENCY,
|
||||
EAXRINGMODULATOR_MAXFREQUENCY);
|
||||
}
|
||||
}; // EaxRingModulatorEffectException
|
||||
}; // FrequencyValidator
|
||||
|
||||
|
||||
EaxRingModulatorEffect::EaxRingModulatorEffect()
|
||||
: EaxEffect{AL_EFFECT_RING_MODULATOR}
|
||||
{
|
||||
set_eax_defaults();
|
||||
set_efx_defaults();
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::dispatch(const EaxEaxCall& eax_call)
|
||||
{
|
||||
eax_call.is_get() ? get(eax_call) : set(eax_call);
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::set_eax_defaults()
|
||||
{
|
||||
eax_.flFrequency = EAXRINGMODULATOR_DEFAULTFREQUENCY;
|
||||
eax_.flHighPassCutOff = EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF;
|
||||
eax_.ulWaveform = EAXRINGMODULATOR_DEFAULTWAVEFORM;
|
||||
|
||||
eax_d_ = eax_;
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::set_efx_frequency()
|
||||
{
|
||||
const auto frequency = clamp(
|
||||
eax_.flFrequency,
|
||||
AL_RING_MODULATOR_MIN_FREQUENCY,
|
||||
AL_RING_MODULATOR_MAX_FREQUENCY);
|
||||
|
||||
al_effect_props_.Modulator.Frequency = frequency;
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::set_efx_high_pass_cutoff()
|
||||
{
|
||||
const auto high_pass_cutoff = clamp(
|
||||
eax_.flHighPassCutOff,
|
||||
AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF,
|
||||
AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF);
|
||||
|
||||
al_effect_props_.Modulator.HighPassCutoff = high_pass_cutoff;
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::set_efx_waveform()
|
||||
{
|
||||
const auto waveform = clamp(
|
||||
static_cast<ALint>(eax_.ulWaveform),
|
||||
AL_RING_MODULATOR_MIN_WAVEFORM,
|
||||
AL_RING_MODULATOR_MAX_WAVEFORM);
|
||||
|
||||
const auto efx_waveform = WaveformFromEmum(waveform);
|
||||
assert(efx_waveform.has_value());
|
||||
al_effect_props_.Modulator.Waveform = *efx_waveform;
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::set_efx_defaults()
|
||||
{
|
||||
set_efx_frequency();
|
||||
set_efx_high_pass_cutoff();
|
||||
set_efx_waveform();
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::get(const EaxEaxCall& eax_call)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
struct HighPassCutOffValidator {
|
||||
void operator()(float flHighPassCutOff) const
|
||||
{
|
||||
case EAXRINGMODULATOR_NONE:
|
||||
break;
|
||||
|
||||
case EAXRINGMODULATOR_ALLPARAMETERS:
|
||||
eax_call.set_value<EaxRingModulatorEffectException>(eax_);
|
||||
break;
|
||||
|
||||
case EAXRINGMODULATOR_FREQUENCY:
|
||||
eax_call.set_value<EaxRingModulatorEffectException>(eax_.flFrequency);
|
||||
break;
|
||||
|
||||
case EAXRINGMODULATOR_HIGHPASSCUTOFF:
|
||||
eax_call.set_value<EaxRingModulatorEffectException>(eax_.flHighPassCutOff);
|
||||
break;
|
||||
|
||||
case EAXRINGMODULATOR_WAVEFORM:
|
||||
eax_call.set_value<EaxRingModulatorEffectException>(eax_.ulWaveform);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxRingModulatorEffectException{"Unsupported property id."};
|
||||
eax_validate_range<ModulatorCommitter::Exception>(
|
||||
"High-Pass Cutoff",
|
||||
flHighPassCutOff,
|
||||
EAXRINGMODULATOR_MINHIGHPASSCUTOFF,
|
||||
EAXRINGMODULATOR_MAXHIGHPASSCUTOFF);
|
||||
}
|
||||
}
|
||||
}; // HighPassCutOffValidator
|
||||
|
||||
void EaxRingModulatorEffect::validate_frequency(
|
||||
float flFrequency)
|
||||
{
|
||||
eax_validate_range<EaxRingModulatorEffectException>(
|
||||
"Frequency",
|
||||
flFrequency,
|
||||
EAXRINGMODULATOR_MINFREQUENCY,
|
||||
EAXRINGMODULATOR_MAXFREQUENCY);
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::validate_high_pass_cutoff(
|
||||
float flHighPassCutOff)
|
||||
{
|
||||
eax_validate_range<EaxRingModulatorEffectException>(
|
||||
"High-Pass Cutoff",
|
||||
flHighPassCutOff,
|
||||
EAXRINGMODULATOR_MINHIGHPASSCUTOFF,
|
||||
EAXRINGMODULATOR_MAXHIGHPASSCUTOFF);
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::validate_waveform(
|
||||
unsigned long ulWaveform)
|
||||
{
|
||||
eax_validate_range<EaxRingModulatorEffectException>(
|
||||
"Waveform",
|
||||
ulWaveform,
|
||||
EAXRINGMODULATOR_MINWAVEFORM,
|
||||
EAXRINGMODULATOR_MAXWAVEFORM);
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::validate_all(
|
||||
const EAXRINGMODULATORPROPERTIES& all)
|
||||
{
|
||||
validate_frequency(all.flFrequency);
|
||||
validate_high_pass_cutoff(all.flHighPassCutOff);
|
||||
validate_waveform(all.ulWaveform);
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::defer_frequency(
|
||||
float flFrequency)
|
||||
{
|
||||
eax_d_.flFrequency = flFrequency;
|
||||
eax_dirty_flags_.flFrequency = (eax_.flFrequency != eax_d_.flFrequency);
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::defer_high_pass_cutoff(
|
||||
float flHighPassCutOff)
|
||||
{
|
||||
eax_d_.flHighPassCutOff = flHighPassCutOff;
|
||||
eax_dirty_flags_.flHighPassCutOff = (eax_.flHighPassCutOff != eax_d_.flHighPassCutOff);
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::defer_waveform(
|
||||
unsigned long ulWaveform)
|
||||
{
|
||||
eax_d_.ulWaveform = ulWaveform;
|
||||
eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform);
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::defer_all(
|
||||
const EAXRINGMODULATORPROPERTIES& all)
|
||||
{
|
||||
defer_frequency(all.flFrequency);
|
||||
defer_high_pass_cutoff(all.flHighPassCutOff);
|
||||
defer_waveform(all.ulWaveform);
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::defer_frequency(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& frequency =
|
||||
eax_call.get_value<
|
||||
EaxRingModulatorEffectException, const decltype(EAXRINGMODULATORPROPERTIES::flFrequency)>();
|
||||
|
||||
validate_frequency(frequency);
|
||||
defer_frequency(frequency);
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::defer_high_pass_cutoff(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& high_pass_cutoff =
|
||||
eax_call.get_value<
|
||||
EaxRingModulatorEffectException, const decltype(EAXRINGMODULATORPROPERTIES::flHighPassCutOff)>();
|
||||
|
||||
validate_high_pass_cutoff(high_pass_cutoff);
|
||||
defer_high_pass_cutoff(high_pass_cutoff);
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::defer_waveform(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& waveform =
|
||||
eax_call.get_value<
|
||||
EaxRingModulatorEffectException, const decltype(EAXRINGMODULATORPROPERTIES::ulWaveform)>();
|
||||
|
||||
validate_waveform(waveform);
|
||||
defer_waveform(waveform);
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::defer_all(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& all =
|
||||
eax_call.get_value<EaxRingModulatorEffectException, const EAXRINGMODULATORPROPERTIES>();
|
||||
|
||||
validate_all(all);
|
||||
defer_all(all);
|
||||
}
|
||||
|
||||
// [[nodiscard]]
|
||||
bool EaxRingModulatorEffect::apply_deferred()
|
||||
{
|
||||
if (eax_dirty_flags_ == EaxRingModulatorEffectDirtyFlags{})
|
||||
struct WaveformValidator {
|
||||
void operator()(unsigned long ulWaveform) const
|
||||
{
|
||||
eax_validate_range<ModulatorCommitter::Exception>(
|
||||
"Waveform",
|
||||
ulWaveform,
|
||||
EAXRINGMODULATOR_MINWAVEFORM,
|
||||
EAXRINGMODULATOR_MAXWAVEFORM);
|
||||
}
|
||||
}; // WaveformValidator
|
||||
|
||||
struct AllValidator {
|
||||
void operator()(const EAXRINGMODULATORPROPERTIES& all) const
|
||||
{
|
||||
FrequencyValidator{}(all.flFrequency);
|
||||
HighPassCutOffValidator{}(all.flHighPassCutOff);
|
||||
WaveformValidator{}(all.ulWaveform);
|
||||
}
|
||||
}; // AllValidator
|
||||
|
||||
} // namespace
|
||||
|
||||
template<>
|
||||
struct ModulatorCommitter::Exception : public EaxException {
|
||||
explicit Exception(const char *message) : EaxException{"EAX_RING_MODULATOR_EFFECT", message}
|
||||
{ }
|
||||
};
|
||||
|
||||
template<>
|
||||
[[noreturn]] void ModulatorCommitter::fail(const char *message)
|
||||
{
|
||||
throw Exception{message};
|
||||
}
|
||||
|
||||
template<>
|
||||
bool ModulatorCommitter::commit(const EaxEffectProps &props)
|
||||
{
|
||||
if(props.mType == mEaxProps.mType
|
||||
&& mEaxProps.mModulator.flFrequency == props.mModulator.flFrequency
|
||||
&& mEaxProps.mModulator.flHighPassCutOff == props.mModulator.flHighPassCutOff
|
||||
&& mEaxProps.mModulator.ulWaveform == props.mModulator.ulWaveform)
|
||||
return false;
|
||||
}
|
||||
|
||||
eax_ = eax_d_;
|
||||
mEaxProps = props;
|
||||
|
||||
if (eax_dirty_flags_.flFrequency)
|
||||
auto get_waveform = [](unsigned long form)
|
||||
{
|
||||
set_efx_frequency();
|
||||
}
|
||||
if(form == EAX_RINGMODULATOR_SINUSOID)
|
||||
return ModulatorWaveform::Sinusoid;
|
||||
if(form == EAX_RINGMODULATOR_SAWTOOTH)
|
||||
return ModulatorWaveform::Sawtooth;
|
||||
if(form == EAX_RINGMODULATOR_SQUARE)
|
||||
return ModulatorWaveform::Square;
|
||||
return ModulatorWaveform::Sinusoid;
|
||||
};
|
||||
|
||||
if (eax_dirty_flags_.flHighPassCutOff)
|
||||
{
|
||||
set_efx_high_pass_cutoff();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.ulWaveform)
|
||||
{
|
||||
set_efx_waveform();
|
||||
}
|
||||
|
||||
eax_dirty_flags_ = EaxRingModulatorEffectDirtyFlags{};
|
||||
mAlProps.Modulator.Frequency = props.mModulator.flFrequency;
|
||||
mAlProps.Modulator.HighPassCutoff = props.mModulator.flHighPassCutOff;
|
||||
mAlProps.Modulator.Waveform = get_waveform(props.mModulator.ulWaveform);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EaxRingModulatorEffect::set(const EaxEaxCall& eax_call)
|
||||
template<>
|
||||
void ModulatorCommitter::SetDefaults(EaxEffectProps &props)
|
||||
{
|
||||
switch (eax_call.get_property_id())
|
||||
props.mType = EaxEffectType::Modulator;
|
||||
props.mModulator.flFrequency = EAXRINGMODULATOR_DEFAULTFREQUENCY;
|
||||
props.mModulator.flHighPassCutOff = EAXRINGMODULATOR_DEFAULTHIGHPASSCUTOFF;
|
||||
props.mModulator.ulWaveform = EAXRINGMODULATOR_DEFAULTWAVEFORM;
|
||||
}
|
||||
|
||||
template<>
|
||||
void ModulatorCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
|
||||
{
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXRINGMODULATOR_NONE:
|
||||
break;
|
||||
|
||||
case EAXRINGMODULATOR_ALLPARAMETERS:
|
||||
defer_all(eax_call);
|
||||
break;
|
||||
|
||||
case EAXRINGMODULATOR_FREQUENCY:
|
||||
defer_frequency(eax_call);
|
||||
break;
|
||||
|
||||
case EAXRINGMODULATOR_HIGHPASSCUTOFF:
|
||||
defer_high_pass_cutoff(eax_call);
|
||||
break;
|
||||
|
||||
case EAXRINGMODULATOR_WAVEFORM:
|
||||
defer_waveform(eax_call);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxRingModulatorEffectException{"Unsupported property id."};
|
||||
case EAXRINGMODULATOR_NONE: break;
|
||||
case EAXRINGMODULATOR_ALLPARAMETERS: call.set_value<Exception>(props.mModulator); break;
|
||||
case EAXRINGMODULATOR_FREQUENCY: call.set_value<Exception>(props.mModulator.flFrequency); break;
|
||||
case EAXRINGMODULATOR_HIGHPASSCUTOFF: call.set_value<Exception>(props.mModulator.flHighPassCutOff); break;
|
||||
case EAXRINGMODULATOR_WAVEFORM: call.set_value<Exception>(props.mModulator.ulWaveform); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EaxEffectUPtr eax_create_eax_ring_modulator_effect()
|
||||
template<>
|
||||
void ModulatorCommitter::Set(const EaxCall &call, EaxEffectProps &props)
|
||||
{
|
||||
return std::make_unique<EaxRingModulatorEffect>();
|
||||
switch (call.get_property_id())
|
||||
{
|
||||
case EAXRINGMODULATOR_NONE: break;
|
||||
case EAXRINGMODULATOR_ALLPARAMETERS: defer<AllValidator>(call, props.mModulator); break;
|
||||
case EAXRINGMODULATOR_FREQUENCY: defer<FrequencyValidator>(call, props.mModulator.flFrequency); break;
|
||||
case EAXRINGMODULATOR_HIGHPASSCUTOFF: defer<HighPassCutOffValidator>(call, props.mModulator.flHighPassCutOff); break;
|
||||
case EAXRINGMODULATOR_WAVEFORM: defer<WaveformValidator>(call, props.mModulator.ulWaveform); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ALSOFT_EAX
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "effects.h"
|
||||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include "al/eax_exception.h"
|
||||
#include "al/eax/exception.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
|
||||
|
|
@ -100,53 +100,50 @@ const EffectProps NullEffectProps{genDefaultProps()};
|
|||
#ifdef ALSOFT_EAX
|
||||
namespace {
|
||||
|
||||
class EaxNullEffect final :
|
||||
public EaxEffect
|
||||
{
|
||||
public:
|
||||
EaxNullEffect();
|
||||
|
||||
void dispatch(const EaxEaxCall& eax_call) override;
|
||||
|
||||
// [[nodiscard]]
|
||||
bool apply_deferred() override;
|
||||
}; // EaxNullEffect
|
||||
|
||||
|
||||
class EaxNullEffectException :
|
||||
public EaxException
|
||||
{
|
||||
public:
|
||||
explicit EaxNullEffectException(
|
||||
const char* message)
|
||||
:
|
||||
EaxException{"EAX_NULL_EFFECT", message}
|
||||
{
|
||||
}
|
||||
}; // EaxNullEffectException
|
||||
|
||||
|
||||
EaxNullEffect::EaxNullEffect()
|
||||
: EaxEffect{AL_EFFECT_NULL}
|
||||
{
|
||||
}
|
||||
|
||||
void EaxNullEffect::dispatch(const EaxEaxCall& eax_call)
|
||||
{
|
||||
if(eax_call.get_property_id() != 0)
|
||||
throw EaxNullEffectException{"Unsupported property id."};
|
||||
}
|
||||
|
||||
bool EaxNullEffect::apply_deferred()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using NullCommitter = EaxCommitter<EaxNullCommitter>;
|
||||
|
||||
} // namespace
|
||||
|
||||
EaxEffectUPtr eax_create_eax_null_effect()
|
||||
template<>
|
||||
struct NullCommitter::Exception : public EaxException
|
||||
{
|
||||
return std::make_unique<EaxNullEffect>();
|
||||
explicit Exception(const char *message) : EaxException{"EAX_NULL_EFFECT", message}
|
||||
{ }
|
||||
};
|
||||
|
||||
template<>
|
||||
[[noreturn]] void NullCommitter::fail(const char *message)
|
||||
{
|
||||
throw Exception{message};
|
||||
}
|
||||
|
||||
template<>
|
||||
bool NullCommitter::commit(const EaxEffectProps &props)
|
||||
{
|
||||
const bool ret{props.mType != mEaxProps.mType};
|
||||
mEaxProps = props;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<>
|
||||
void NullCommitter::SetDefaults(EaxEffectProps &props)
|
||||
{
|
||||
props = EaxEffectProps{};
|
||||
props.mType = EaxEffectType::None;
|
||||
}
|
||||
|
||||
template<>
|
||||
void NullCommitter::Get(const EaxCall &call, const EaxEffectProps&)
|
||||
{
|
||||
if(call.get_property_id() != 0)
|
||||
fail_unknown_property_id();
|
||||
}
|
||||
|
||||
template<>
|
||||
void NullCommitter::Set(const EaxCall &call, EaxEffectProps&)
|
||||
{
|
||||
if(call.get_property_id() != 0)
|
||||
fail_unknown_property_id();
|
||||
}
|
||||
|
||||
#endif // ALSOFT_EAX
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@
|
|||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include "alnumeric.h"
|
||||
|
||||
#include "al/eax_exception.h"
|
||||
#include "al/eax_utils.h"
|
||||
#include "al/eax/exception.h"
|
||||
#include "al/eax/utils.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
|
||||
|
|
@ -93,272 +92,100 @@ const EffectProps PshifterEffectProps{genDefaultProps()};
|
|||
#ifdef ALSOFT_EAX
|
||||
namespace {
|
||||
|
||||
using EaxPitchShifterEffectDirtyFlagsValue = std::uint_least8_t;
|
||||
using PitchShifterCommitter = EaxCommitter<EaxPitchShifterCommitter>;
|
||||
|
||||
struct EaxPitchShifterEffectDirtyFlags
|
||||
{
|
||||
using EaxIsBitFieldStruct = bool;
|
||||
|
||||
EaxPitchShifterEffectDirtyFlagsValue lCoarseTune : 1;
|
||||
EaxPitchShifterEffectDirtyFlagsValue lFineTune : 1;
|
||||
}; // EaxPitchShifterEffectDirtyFlags
|
||||
|
||||
|
||||
class EaxPitchShifterEffect final :
|
||||
public EaxEffect
|
||||
{
|
||||
public:
|
||||
EaxPitchShifterEffect();
|
||||
|
||||
void dispatch(const EaxEaxCall& eax_call) override;
|
||||
|
||||
// [[nodiscard]]
|
||||
bool apply_deferred() override;
|
||||
|
||||
private:
|
||||
EAXPITCHSHIFTERPROPERTIES eax_{};
|
||||
EAXPITCHSHIFTERPROPERTIES eax_d_{};
|
||||
EaxPitchShifterEffectDirtyFlags eax_dirty_flags_{};
|
||||
|
||||
void set_eax_defaults();
|
||||
|
||||
void set_efx_coarse_tune();
|
||||
void set_efx_fine_tune();
|
||||
void set_efx_defaults();
|
||||
|
||||
void get(const EaxEaxCall& eax_call);
|
||||
|
||||
void validate_coarse_tune(long lCoarseTune);
|
||||
void validate_fine_tune(long lFineTune);
|
||||
void validate_all(const EAXPITCHSHIFTERPROPERTIES& all);
|
||||
|
||||
void defer_coarse_tune(long lCoarseTune);
|
||||
void defer_fine_tune(long lFineTune);
|
||||
void defer_all(const EAXPITCHSHIFTERPROPERTIES& all);
|
||||
|
||||
void defer_coarse_tune(const EaxEaxCall& eax_call);
|
||||
void defer_fine_tune(const EaxEaxCall& eax_call);
|
||||
void defer_all(const EaxEaxCall& eax_call);
|
||||
|
||||
void set(const EaxEaxCall& eax_call);
|
||||
}; // EaxPitchShifterEffect
|
||||
|
||||
|
||||
class EaxPitchShifterEffectException :
|
||||
public EaxException
|
||||
{
|
||||
public:
|
||||
explicit EaxPitchShifterEffectException(
|
||||
const char* message)
|
||||
:
|
||||
EaxException{"EAX_PITCH_SHIFTER_EFFECT", message}
|
||||
struct CoarseTuneValidator {
|
||||
void operator()(long lCoarseTune) const
|
||||
{
|
||||
eax_validate_range<PitchShifterCommitter::Exception>(
|
||||
"Coarse Tune",
|
||||
lCoarseTune,
|
||||
EAXPITCHSHIFTER_MINCOARSETUNE,
|
||||
EAXPITCHSHIFTER_MAXCOARSETUNE);
|
||||
}
|
||||
}; // EaxPitchShifterEffectException
|
||||
}; // CoarseTuneValidator
|
||||
|
||||
|
||||
EaxPitchShifterEffect::EaxPitchShifterEffect()
|
||||
: EaxEffect{AL_EFFECT_PITCH_SHIFTER}
|
||||
{
|
||||
set_eax_defaults();
|
||||
set_efx_defaults();
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::dispatch(const EaxEaxCall& eax_call)
|
||||
{
|
||||
eax_call.is_get() ? get(eax_call) : set(eax_call);
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::set_eax_defaults()
|
||||
{
|
||||
eax_.lCoarseTune = EAXPITCHSHIFTER_DEFAULTCOARSETUNE;
|
||||
eax_.lFineTune = EAXPITCHSHIFTER_DEFAULTFINETUNE;
|
||||
|
||||
eax_d_ = eax_;
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::set_efx_coarse_tune()
|
||||
{
|
||||
const auto coarse_tune = clamp(
|
||||
static_cast<ALint>(eax_.lCoarseTune),
|
||||
AL_PITCH_SHIFTER_MIN_COARSE_TUNE,
|
||||
AL_PITCH_SHIFTER_MAX_COARSE_TUNE);
|
||||
|
||||
al_effect_props_.Pshifter.CoarseTune = coarse_tune;
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::set_efx_fine_tune()
|
||||
{
|
||||
const auto fine_tune = clamp(
|
||||
static_cast<ALint>(eax_.lFineTune),
|
||||
AL_PITCH_SHIFTER_MIN_FINE_TUNE,
|
||||
AL_PITCH_SHIFTER_MAX_FINE_TUNE);
|
||||
|
||||
al_effect_props_.Pshifter.FineTune = fine_tune;
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::set_efx_defaults()
|
||||
{
|
||||
set_efx_coarse_tune();
|
||||
set_efx_fine_tune();
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::get(const EaxEaxCall& eax_call)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
struct FineTuneValidator {
|
||||
void operator()(long lFineTune) const
|
||||
{
|
||||
case EAXPITCHSHIFTER_NONE:
|
||||
break;
|
||||
|
||||
case EAXPITCHSHIFTER_ALLPARAMETERS:
|
||||
eax_call.set_value<EaxPitchShifterEffectException>(eax_);
|
||||
break;
|
||||
|
||||
case EAXPITCHSHIFTER_COARSETUNE:
|
||||
eax_call.set_value<EaxPitchShifterEffectException>(eax_.lCoarseTune);
|
||||
break;
|
||||
|
||||
case EAXPITCHSHIFTER_FINETUNE:
|
||||
eax_call.set_value<EaxPitchShifterEffectException>(eax_.lFineTune);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxPitchShifterEffectException{"Unsupported property id."};
|
||||
eax_validate_range<PitchShifterCommitter::Exception>(
|
||||
"Fine Tune",
|
||||
lFineTune,
|
||||
EAXPITCHSHIFTER_MINFINETUNE,
|
||||
EAXPITCHSHIFTER_MAXFINETUNE);
|
||||
}
|
||||
}
|
||||
}; // FineTuneValidator
|
||||
|
||||
void EaxPitchShifterEffect::validate_coarse_tune(
|
||||
long lCoarseTune)
|
||||
{
|
||||
eax_validate_range<EaxPitchShifterEffectException>(
|
||||
"Coarse Tune",
|
||||
lCoarseTune,
|
||||
EAXPITCHSHIFTER_MINCOARSETUNE,
|
||||
EAXPITCHSHIFTER_MAXCOARSETUNE);
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::validate_fine_tune(
|
||||
long lFineTune)
|
||||
{
|
||||
eax_validate_range<EaxPitchShifterEffectException>(
|
||||
"Fine Tune",
|
||||
lFineTune,
|
||||
EAXPITCHSHIFTER_MINFINETUNE,
|
||||
EAXPITCHSHIFTER_MAXFINETUNE);
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::validate_all(
|
||||
const EAXPITCHSHIFTERPROPERTIES& all)
|
||||
{
|
||||
validate_coarse_tune(all.lCoarseTune);
|
||||
validate_fine_tune(all.lFineTune);
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::defer_coarse_tune(
|
||||
long lCoarseTune)
|
||||
{
|
||||
eax_d_.lCoarseTune = lCoarseTune;
|
||||
eax_dirty_flags_.lCoarseTune = (eax_.lCoarseTune != eax_d_.lCoarseTune);
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::defer_fine_tune(
|
||||
long lFineTune)
|
||||
{
|
||||
eax_d_.lFineTune = lFineTune;
|
||||
eax_dirty_flags_.lFineTune = (eax_.lFineTune != eax_d_.lFineTune);
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::defer_all(
|
||||
const EAXPITCHSHIFTERPROPERTIES& all)
|
||||
{
|
||||
defer_coarse_tune(all.lCoarseTune);
|
||||
defer_fine_tune(all.lFineTune);
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::defer_coarse_tune(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& coarse_tune =
|
||||
eax_call.get_value<EaxPitchShifterEffectException, const decltype(EAXPITCHSHIFTERPROPERTIES::lCoarseTune)>();
|
||||
|
||||
validate_coarse_tune(coarse_tune);
|
||||
defer_coarse_tune(coarse_tune);
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::defer_fine_tune(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& fine_tune =
|
||||
eax_call.get_value<EaxPitchShifterEffectException, const decltype(EAXPITCHSHIFTERPROPERTIES::lFineTune)>();
|
||||
|
||||
validate_fine_tune(fine_tune);
|
||||
defer_fine_tune(fine_tune);
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::defer_all(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& all =
|
||||
eax_call.get_value<EaxPitchShifterEffectException, const EAXPITCHSHIFTERPROPERTIES>();
|
||||
|
||||
validate_all(all);
|
||||
defer_all(all);
|
||||
}
|
||||
|
||||
// [[nodiscard]]
|
||||
bool EaxPitchShifterEffect::apply_deferred()
|
||||
{
|
||||
if (eax_dirty_flags_ == EaxPitchShifterEffectDirtyFlags{})
|
||||
struct AllValidator {
|
||||
void operator()(const EAXPITCHSHIFTERPROPERTIES& all) const
|
||||
{
|
||||
CoarseTuneValidator{}(all.lCoarseTune);
|
||||
FineTuneValidator{}(all.lFineTune);
|
||||
}
|
||||
}; // AllValidator
|
||||
|
||||
} // namespace
|
||||
|
||||
template<>
|
||||
struct PitchShifterCommitter::Exception : public EaxException {
|
||||
explicit Exception(const char *message) : EaxException{"EAX_PITCH_SHIFTER_EFFECT", message}
|
||||
{ }
|
||||
};
|
||||
|
||||
template<>
|
||||
[[noreturn]] void PitchShifterCommitter::fail(const char *message)
|
||||
{
|
||||
throw Exception{message};
|
||||
}
|
||||
|
||||
template<>
|
||||
bool PitchShifterCommitter::commit(const EaxEffectProps &props)
|
||||
{
|
||||
if(props.mType == mEaxProps.mType
|
||||
&& mEaxProps.mPitchShifter.lCoarseTune == props.mPitchShifter.lCoarseTune
|
||||
&& mEaxProps.mPitchShifter.lFineTune == props.mPitchShifter.lFineTune)
|
||||
return false;
|
||||
}
|
||||
|
||||
eax_ = eax_d_;
|
||||
mEaxProps = props;
|
||||
|
||||
if (eax_dirty_flags_.lCoarseTune)
|
||||
{
|
||||
set_efx_coarse_tune();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.lFineTune)
|
||||
{
|
||||
set_efx_fine_tune();
|
||||
}
|
||||
|
||||
eax_dirty_flags_ = EaxPitchShifterEffectDirtyFlags{};
|
||||
mAlProps.Pshifter.CoarseTune = static_cast<int>(mEaxProps.mPitchShifter.lCoarseTune);
|
||||
mAlProps.Pshifter.FineTune = static_cast<int>(mEaxProps.mPitchShifter.lFineTune);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EaxPitchShifterEffect::set(const EaxEaxCall& eax_call)
|
||||
template<>
|
||||
void PitchShifterCommitter::SetDefaults(EaxEffectProps &props)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
props.mType = EaxEffectType::PitchShifter;
|
||||
props.mPitchShifter.lCoarseTune = EAXPITCHSHIFTER_DEFAULTCOARSETUNE;
|
||||
props.mPitchShifter.lFineTune = EAXPITCHSHIFTER_DEFAULTFINETUNE;
|
||||
}
|
||||
|
||||
template<>
|
||||
void PitchShifterCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
|
||||
{
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXPITCHSHIFTER_NONE:
|
||||
break;
|
||||
|
||||
case EAXPITCHSHIFTER_ALLPARAMETERS:
|
||||
defer_all(eax_call);
|
||||
break;
|
||||
|
||||
case EAXPITCHSHIFTER_COARSETUNE:
|
||||
defer_coarse_tune(eax_call);
|
||||
break;
|
||||
|
||||
case EAXPITCHSHIFTER_FINETUNE:
|
||||
defer_fine_tune(eax_call);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxPitchShifterEffectException{"Unsupported property id."};
|
||||
case EAXPITCHSHIFTER_NONE: break;
|
||||
case EAXPITCHSHIFTER_ALLPARAMETERS: call.set_value<Exception>(props.mPitchShifter); break;
|
||||
case EAXPITCHSHIFTER_COARSETUNE: call.set_value<Exception>(props.mPitchShifter.lCoarseTune); break;
|
||||
case EAXPITCHSHIFTER_FINETUNE: call.set_value<Exception>(props.mPitchShifter.lFineTune); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EaxEffectUPtr eax_create_eax_pitch_shifter_effect()
|
||||
template<>
|
||||
void PitchShifterCommitter::Set(const EaxCall &call, EaxEffectProps &props)
|
||||
{
|
||||
return std::make_unique<EaxPitchShifterEffect>();
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXPITCHSHIFTER_NONE: break;
|
||||
case EAXPITCHSHIFTER_ALLPARAMETERS: defer<AllValidator>(call, props.mPitchShifter); break;
|
||||
case EAXPITCHSHIFTER_COARSETUNE: defer<CoarseTuneValidator>(call, props.mPitchShifter.lCoarseTune); break;
|
||||
case EAXPITCHSHIFTER_FINETUNE: defer<FineTuneValidator>(call, props.mPitchShifter.lFineTune); break;
|
||||
default: fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ALSOFT_EAX
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -12,11 +12,9 @@
|
|||
|
||||
#ifdef ALSOFT_EAX
|
||||
#include <cassert>
|
||||
|
||||
#include "alnumeric.h"
|
||||
|
||||
#include "al/eax_exception.h"
|
||||
#include "al/eax_utils.h"
|
||||
#include "al/eax/exception.h"
|
||||
#include "al/eax/utils.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
|
||||
|
|
@ -25,7 +23,7 @@ namespace {
|
|||
al::optional<VMorpherPhenome> PhenomeFromEnum(ALenum val)
|
||||
{
|
||||
#define HANDLE_PHENOME(x) case AL_VOCAL_MORPHER_PHONEME_ ## x: \
|
||||
return al::make_optional(VMorpherPhenome::x)
|
||||
return VMorpherPhenome::x
|
||||
switch(val)
|
||||
{
|
||||
HANDLE_PHENOME(A);
|
||||
|
|
@ -106,9 +104,9 @@ al::optional<VMorpherWaveform> WaveformFromEmum(ALenum value)
|
|||
{
|
||||
switch(value)
|
||||
{
|
||||
case AL_VOCAL_MORPHER_WAVEFORM_SINUSOID: return al::make_optional(VMorpherWaveform::Sinusoid);
|
||||
case AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE: return al::make_optional(VMorpherWaveform::Triangle);
|
||||
case AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH: return al::make_optional(VMorpherWaveform::Sawtooth);
|
||||
case AL_VOCAL_MORPHER_WAVEFORM_SINUSOID: return VMorpherWaveform::Sinusoid;
|
||||
case AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE: return VMorpherWaveform::Triangle;
|
||||
case AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH: return VMorpherWaveform::Sawtooth;
|
||||
}
|
||||
return al::nullopt;
|
||||
}
|
||||
|
|
@ -260,527 +258,263 @@ const EffectProps VmorpherEffectProps{genDefaultProps()};
|
|||
#ifdef ALSOFT_EAX
|
||||
namespace {
|
||||
|
||||
using EaxVocalMorpherEffectDirtyFlagsValue = std::uint_least8_t;
|
||||
using VocalMorpherCommitter = EaxCommitter<EaxVocalMorpherCommitter>;
|
||||
|
||||
struct EaxVocalMorpherEffectDirtyFlags
|
||||
{
|
||||
using EaxIsBitFieldStruct = bool;
|
||||
|
||||
EaxVocalMorpherEffectDirtyFlagsValue ulPhonemeA : 1;
|
||||
EaxVocalMorpherEffectDirtyFlagsValue lPhonemeACoarseTuning : 1;
|
||||
EaxVocalMorpherEffectDirtyFlagsValue ulPhonemeB : 1;
|
||||
EaxVocalMorpherEffectDirtyFlagsValue lPhonemeBCoarseTuning : 1;
|
||||
EaxVocalMorpherEffectDirtyFlagsValue ulWaveform : 1;
|
||||
EaxVocalMorpherEffectDirtyFlagsValue flRate : 1;
|
||||
}; // EaxPitchShifterEffectDirtyFlags
|
||||
|
||||
|
||||
class EaxVocalMorpherEffect final :
|
||||
public EaxEffect
|
||||
{
|
||||
public:
|
||||
EaxVocalMorpherEffect();
|
||||
|
||||
void dispatch(const EaxEaxCall& eax_call) override;
|
||||
|
||||
// [[nodiscard]]
|
||||
bool apply_deferred() override;
|
||||
|
||||
private:
|
||||
EAXVOCALMORPHERPROPERTIES eax_{};
|
||||
EAXVOCALMORPHERPROPERTIES eax_d_{};
|
||||
EaxVocalMorpherEffectDirtyFlags eax_dirty_flags_{};
|
||||
|
||||
void set_eax_defaults();
|
||||
|
||||
void set_efx_phoneme_a();
|
||||
void set_efx_phoneme_a_coarse_tuning();
|
||||
void set_efx_phoneme_b();
|
||||
void set_efx_phoneme_b_coarse_tuning();
|
||||
void set_efx_waveform();
|
||||
void set_efx_rate();
|
||||
void set_efx_defaults();
|
||||
|
||||
void get(const EaxEaxCall& eax_call);
|
||||
|
||||
void validate_phoneme_a(unsigned long ulPhonemeA);
|
||||
void validate_phoneme_a_coarse_tuning(long lPhonemeACoarseTuning);
|
||||
void validate_phoneme_b(unsigned long ulPhonemeB);
|
||||
void validate_phoneme_b_coarse_tuning(long lPhonemeBCoarseTuning);
|
||||
void validate_waveform(unsigned long ulWaveform);
|
||||
void validate_rate(float flRate);
|
||||
void validate_all(const EAXVOCALMORPHERPROPERTIES& all);
|
||||
|
||||
void defer_phoneme_a(unsigned long ulPhonemeA);
|
||||
void defer_phoneme_a_coarse_tuning(long lPhonemeACoarseTuning);
|
||||
void defer_phoneme_b(unsigned long ulPhonemeB);
|
||||
void defer_phoneme_b_coarse_tuning(long lPhonemeBCoarseTuning);
|
||||
void defer_waveform(unsigned long ulWaveform);
|
||||
void defer_rate(float flRate);
|
||||
void defer_all(const EAXVOCALMORPHERPROPERTIES& all);
|
||||
|
||||
void defer_phoneme_a(const EaxEaxCall& eax_call);
|
||||
void defer_phoneme_a_coarse_tuning(const EaxEaxCall& eax_call);
|
||||
void defer_phoneme_b(const EaxEaxCall& eax_call);
|
||||
void defer_phoneme_b_coarse_tuning(const EaxEaxCall& eax_call);
|
||||
void defer_waveform(const EaxEaxCall& eax_call);
|
||||
void defer_rate(const EaxEaxCall& eax_call);
|
||||
void defer_all(const EaxEaxCall& eax_call);
|
||||
|
||||
void set(const EaxEaxCall& eax_call);
|
||||
}; // EaxVocalMorpherEffect
|
||||
|
||||
|
||||
class EaxVocalMorpherEffectException :
|
||||
public EaxException
|
||||
{
|
||||
public:
|
||||
explicit EaxVocalMorpherEffectException(
|
||||
const char* message)
|
||||
:
|
||||
EaxException{"EAX_VOCAL_MORPHER_EFFECT", message}
|
||||
struct PhonemeAValidator {
|
||||
void operator()(unsigned long ulPhonemeA) const
|
||||
{
|
||||
eax_validate_range<VocalMorpherCommitter::Exception>(
|
||||
"Phoneme A",
|
||||
ulPhonemeA,
|
||||
EAXVOCALMORPHER_MINPHONEMEA,
|
||||
EAXVOCALMORPHER_MAXPHONEMEA);
|
||||
}
|
||||
}; // EaxVocalMorpherEffectException
|
||||
}; // PhonemeAValidator
|
||||
|
||||
|
||||
EaxVocalMorpherEffect::EaxVocalMorpherEffect()
|
||||
: EaxEffect{AL_EFFECT_VOCAL_MORPHER}
|
||||
{
|
||||
set_eax_defaults();
|
||||
set_efx_defaults();
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::dispatch(const EaxEaxCall& eax_call)
|
||||
{
|
||||
eax_call.is_get() ? get(eax_call) : set(eax_call);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::set_eax_defaults()
|
||||
{
|
||||
eax_.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA;
|
||||
eax_.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING;
|
||||
eax_.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB;
|
||||
eax_.lPhonemeBCoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING;
|
||||
eax_.ulWaveform = EAXVOCALMORPHER_DEFAULTWAVEFORM;
|
||||
eax_.flRate = EAXVOCALMORPHER_DEFAULTRATE;
|
||||
|
||||
eax_d_ = eax_;
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::set_efx_phoneme_a()
|
||||
{
|
||||
const auto phoneme_a = clamp(
|
||||
static_cast<ALint>(eax_.ulPhonemeA),
|
||||
AL_VOCAL_MORPHER_MIN_PHONEMEA,
|
||||
AL_VOCAL_MORPHER_MAX_PHONEMEA);
|
||||
|
||||
const auto efx_phoneme_a = PhenomeFromEnum(phoneme_a);
|
||||
assert(efx_phoneme_a.has_value());
|
||||
al_effect_props_.Vmorpher.PhonemeA = *efx_phoneme_a;
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::set_efx_phoneme_a_coarse_tuning()
|
||||
{
|
||||
const auto phoneme_a_coarse_tuning = clamp(
|
||||
static_cast<ALint>(eax_.lPhonemeACoarseTuning),
|
||||
AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING,
|
||||
AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING);
|
||||
|
||||
al_effect_props_.Vmorpher.PhonemeACoarseTuning = phoneme_a_coarse_tuning;
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::set_efx_phoneme_b()
|
||||
{
|
||||
const auto phoneme_b = clamp(
|
||||
static_cast<ALint>(eax_.ulPhonemeB),
|
||||
AL_VOCAL_MORPHER_MIN_PHONEMEB,
|
||||
AL_VOCAL_MORPHER_MAX_PHONEMEB);
|
||||
|
||||
const auto efx_phoneme_b = PhenomeFromEnum(phoneme_b);
|
||||
assert(efx_phoneme_b.has_value());
|
||||
al_effect_props_.Vmorpher.PhonemeB = *efx_phoneme_b;
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::set_efx_phoneme_b_coarse_tuning()
|
||||
{
|
||||
const auto phoneme_b_coarse_tuning = clamp(
|
||||
static_cast<ALint>(eax_.lPhonemeBCoarseTuning),
|
||||
AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING,
|
||||
AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING);
|
||||
|
||||
al_effect_props_.Vmorpher.PhonemeBCoarseTuning = phoneme_b_coarse_tuning;
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::set_efx_waveform()
|
||||
{
|
||||
const auto waveform = clamp(
|
||||
static_cast<ALint>(eax_.ulWaveform),
|
||||
AL_VOCAL_MORPHER_MIN_WAVEFORM,
|
||||
AL_VOCAL_MORPHER_MAX_WAVEFORM);
|
||||
|
||||
const auto wfx_waveform = WaveformFromEmum(waveform);
|
||||
assert(wfx_waveform.has_value());
|
||||
al_effect_props_.Vmorpher.Waveform = *wfx_waveform;
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::set_efx_rate()
|
||||
{
|
||||
const auto rate = clamp(
|
||||
eax_.flRate,
|
||||
AL_VOCAL_MORPHER_MIN_RATE,
|
||||
AL_VOCAL_MORPHER_MAX_RATE);
|
||||
|
||||
al_effect_props_.Vmorpher.Rate = rate;
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::set_efx_defaults()
|
||||
{
|
||||
set_efx_phoneme_a();
|
||||
set_efx_phoneme_a_coarse_tuning();
|
||||
set_efx_phoneme_b();
|
||||
set_efx_phoneme_b_coarse_tuning();
|
||||
set_efx_waveform();
|
||||
set_efx_rate();
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::get(const EaxEaxCall& eax_call)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
struct PhonemeACoarseTuningValidator {
|
||||
void operator()(long lPhonemeACoarseTuning) const
|
||||
{
|
||||
case EAXVOCALMORPHER_NONE:
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_ALLPARAMETERS:
|
||||
eax_call.set_value<EaxVocalMorpherEffectException>(eax_);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_PHONEMEA:
|
||||
eax_call.set_value<EaxVocalMorpherEffectException>(eax_.ulPhonemeA);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_PHONEMEACOARSETUNING:
|
||||
eax_call.set_value<EaxVocalMorpherEffectException>(eax_.lPhonemeACoarseTuning);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_PHONEMEB:
|
||||
eax_call.set_value<EaxVocalMorpherEffectException>(eax_.ulPhonemeB);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_PHONEMEBCOARSETUNING:
|
||||
eax_call.set_value<EaxVocalMorpherEffectException>(eax_.lPhonemeBCoarseTuning);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_WAVEFORM:
|
||||
eax_call.set_value<EaxVocalMorpherEffectException>(eax_.ulWaveform);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_RATE:
|
||||
eax_call.set_value<EaxVocalMorpherEffectException>(eax_.flRate);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxVocalMorpherEffectException{"Unsupported property id."};
|
||||
eax_validate_range<VocalMorpherCommitter::Exception>(
|
||||
"Phoneme A Coarse Tuning",
|
||||
lPhonemeACoarseTuning,
|
||||
EAXVOCALMORPHER_MINPHONEMEACOARSETUNING,
|
||||
EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING);
|
||||
}
|
||||
}
|
||||
}; // PhonemeACoarseTuningValidator
|
||||
|
||||
void EaxVocalMorpherEffect::validate_phoneme_a(
|
||||
unsigned long ulPhonemeA)
|
||||
{
|
||||
eax_validate_range<EaxVocalMorpherEffectException>(
|
||||
"Phoneme A",
|
||||
ulPhonemeA,
|
||||
EAXVOCALMORPHER_MINPHONEMEA,
|
||||
EAXVOCALMORPHER_MAXPHONEMEA);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::validate_phoneme_a_coarse_tuning(
|
||||
long lPhonemeACoarseTuning)
|
||||
{
|
||||
eax_validate_range<EaxVocalMorpherEffectException>(
|
||||
"Phoneme A Coarse Tuning",
|
||||
lPhonemeACoarseTuning,
|
||||
EAXVOCALMORPHER_MINPHONEMEACOARSETUNING,
|
||||
EAXVOCALMORPHER_MAXPHONEMEACOARSETUNING);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::validate_phoneme_b(
|
||||
unsigned long ulPhonemeB)
|
||||
{
|
||||
eax_validate_range<EaxVocalMorpherEffectException>(
|
||||
"Phoneme B",
|
||||
ulPhonemeB,
|
||||
EAXVOCALMORPHER_MINPHONEMEB,
|
||||
EAXVOCALMORPHER_MAXPHONEMEB);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::validate_phoneme_b_coarse_tuning(
|
||||
long lPhonemeBCoarseTuning)
|
||||
{
|
||||
eax_validate_range<EaxVocalMorpherEffectException>(
|
||||
"Phoneme B Coarse Tuning",
|
||||
lPhonemeBCoarseTuning,
|
||||
EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING,
|
||||
EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::validate_waveform(
|
||||
unsigned long ulWaveform)
|
||||
{
|
||||
eax_validate_range<EaxVocalMorpherEffectException>(
|
||||
"Waveform",
|
||||
ulWaveform,
|
||||
EAXVOCALMORPHER_MINWAVEFORM,
|
||||
EAXVOCALMORPHER_MAXWAVEFORM);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::validate_rate(
|
||||
float flRate)
|
||||
{
|
||||
eax_validate_range<EaxVocalMorpherEffectException>(
|
||||
"Rate",
|
||||
flRate,
|
||||
EAXVOCALMORPHER_MINRATE,
|
||||
EAXVOCALMORPHER_MAXRATE);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::validate_all(
|
||||
const EAXVOCALMORPHERPROPERTIES& all)
|
||||
{
|
||||
validate_phoneme_a(all.ulPhonemeA);
|
||||
validate_phoneme_a_coarse_tuning(all.lPhonemeACoarseTuning);
|
||||
validate_phoneme_b(all.ulPhonemeB);
|
||||
validate_phoneme_b_coarse_tuning(all.lPhonemeBCoarseTuning);
|
||||
validate_waveform(all.ulWaveform);
|
||||
validate_rate(all.flRate);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_phoneme_a(
|
||||
unsigned long ulPhonemeA)
|
||||
{
|
||||
eax_d_.ulPhonemeA = ulPhonemeA;
|
||||
eax_dirty_flags_.ulPhonemeA = (eax_.ulPhonemeA != eax_d_.ulPhonemeA);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_phoneme_a_coarse_tuning(
|
||||
long lPhonemeACoarseTuning)
|
||||
{
|
||||
eax_d_.lPhonemeACoarseTuning = lPhonemeACoarseTuning;
|
||||
eax_dirty_flags_.lPhonemeACoarseTuning = (eax_.lPhonemeACoarseTuning != eax_d_.lPhonemeACoarseTuning);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_phoneme_b(
|
||||
unsigned long ulPhonemeB)
|
||||
{
|
||||
eax_d_.ulPhonemeB = ulPhonemeB;
|
||||
eax_dirty_flags_.ulPhonemeB = (eax_.ulPhonemeB != eax_d_.ulPhonemeB);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_phoneme_b_coarse_tuning(
|
||||
long lPhonemeBCoarseTuning)
|
||||
{
|
||||
eax_d_.lPhonemeBCoarseTuning = lPhonemeBCoarseTuning;
|
||||
eax_dirty_flags_.lPhonemeBCoarseTuning = (eax_.lPhonemeBCoarseTuning != eax_d_.lPhonemeBCoarseTuning);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_waveform(
|
||||
unsigned long ulWaveform)
|
||||
{
|
||||
eax_d_.ulWaveform = ulWaveform;
|
||||
eax_dirty_flags_.ulWaveform = (eax_.ulWaveform != eax_d_.ulWaveform);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_rate(
|
||||
float flRate)
|
||||
{
|
||||
eax_d_.flRate = flRate;
|
||||
eax_dirty_flags_.flRate = (eax_.flRate != eax_d_.flRate);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_all(
|
||||
const EAXVOCALMORPHERPROPERTIES& all)
|
||||
{
|
||||
defer_phoneme_a(all.ulPhonemeA);
|
||||
defer_phoneme_a_coarse_tuning(all.lPhonemeACoarseTuning);
|
||||
defer_phoneme_b(all.ulPhonemeB);
|
||||
defer_phoneme_b_coarse_tuning(all.lPhonemeBCoarseTuning);
|
||||
defer_waveform(all.ulWaveform);
|
||||
defer_rate(all.flRate);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_phoneme_a(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& phoneme_a = eax_call.get_value<EaxVocalMorpherEffectException,
|
||||
const decltype(EAXVOCALMORPHERPROPERTIES::ulPhonemeA)>();
|
||||
|
||||
validate_phoneme_a(phoneme_a);
|
||||
defer_phoneme_a(phoneme_a);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_phoneme_a_coarse_tuning(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& phoneme_a_coarse_tuning = eax_call.get_value<
|
||||
EaxVocalMorpherEffectException,
|
||||
const decltype(EAXVOCALMORPHERPROPERTIES::lPhonemeACoarseTuning)
|
||||
>();
|
||||
|
||||
validate_phoneme_a_coarse_tuning(phoneme_a_coarse_tuning);
|
||||
defer_phoneme_a_coarse_tuning(phoneme_a_coarse_tuning);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_phoneme_b(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& phoneme_b = eax_call.get_value<
|
||||
EaxVocalMorpherEffectException,
|
||||
const decltype(EAXVOCALMORPHERPROPERTIES::ulPhonemeB)
|
||||
>();
|
||||
|
||||
validate_phoneme_b(phoneme_b);
|
||||
defer_phoneme_b(phoneme_b);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_phoneme_b_coarse_tuning(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& phoneme_b_coarse_tuning = eax_call.get_value<
|
||||
EaxVocalMorpherEffectException,
|
||||
const decltype(EAXVOCALMORPHERPROPERTIES::lPhonemeBCoarseTuning)
|
||||
>();
|
||||
|
||||
validate_phoneme_b_coarse_tuning(phoneme_b_coarse_tuning);
|
||||
defer_phoneme_b_coarse_tuning(phoneme_b_coarse_tuning);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_waveform(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& waveform = eax_call.get_value<
|
||||
EaxVocalMorpherEffectException,
|
||||
const decltype(EAXVOCALMORPHERPROPERTIES::ulWaveform)
|
||||
>();
|
||||
|
||||
validate_waveform(waveform);
|
||||
defer_waveform(waveform);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_rate(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& rate = eax_call.get_value<
|
||||
EaxVocalMorpherEffectException,
|
||||
const decltype(EAXVOCALMORPHERPROPERTIES::flRate)
|
||||
>();
|
||||
|
||||
validate_rate(rate);
|
||||
defer_rate(rate);
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::defer_all(
|
||||
const EaxEaxCall& eax_call)
|
||||
{
|
||||
const auto& all = eax_call.get_value<
|
||||
EaxVocalMorpherEffectException,
|
||||
const EAXVOCALMORPHERPROPERTIES
|
||||
>();
|
||||
|
||||
validate_all(all);
|
||||
defer_all(all);
|
||||
}
|
||||
|
||||
// [[nodiscard]]
|
||||
bool EaxVocalMorpherEffect::apply_deferred()
|
||||
{
|
||||
if (eax_dirty_flags_ == EaxVocalMorpherEffectDirtyFlags{})
|
||||
struct PhonemeBValidator {
|
||||
void operator()(unsigned long ulPhonemeB) const
|
||||
{
|
||||
eax_validate_range<VocalMorpherCommitter::Exception>(
|
||||
"Phoneme B",
|
||||
ulPhonemeB,
|
||||
EAXVOCALMORPHER_MINPHONEMEB,
|
||||
EAXVOCALMORPHER_MAXPHONEMEB);
|
||||
}
|
||||
}; // PhonemeBValidator
|
||||
|
||||
struct PhonemeBCoarseTuningValidator {
|
||||
void operator()(long lPhonemeBCoarseTuning) const
|
||||
{
|
||||
eax_validate_range<VocalMorpherCommitter::Exception>(
|
||||
"Phoneme B Coarse Tuning",
|
||||
lPhonemeBCoarseTuning,
|
||||
EAXVOCALMORPHER_MINPHONEMEBCOARSETUNING,
|
||||
EAXVOCALMORPHER_MAXPHONEMEBCOARSETUNING);
|
||||
}
|
||||
}; // PhonemeBCoarseTuningValidator
|
||||
|
||||
struct WaveformValidator {
|
||||
void operator()(unsigned long ulWaveform) const
|
||||
{
|
||||
eax_validate_range<VocalMorpherCommitter::Exception>(
|
||||
"Waveform",
|
||||
ulWaveform,
|
||||
EAXVOCALMORPHER_MINWAVEFORM,
|
||||
EAXVOCALMORPHER_MAXWAVEFORM);
|
||||
}
|
||||
}; // WaveformValidator
|
||||
|
||||
struct RateValidator {
|
||||
void operator()(float flRate) const
|
||||
{
|
||||
eax_validate_range<VocalMorpherCommitter::Exception>(
|
||||
"Rate",
|
||||
flRate,
|
||||
EAXVOCALMORPHER_MINRATE,
|
||||
EAXVOCALMORPHER_MAXRATE);
|
||||
}
|
||||
}; // RateValidator
|
||||
|
||||
struct AllValidator {
|
||||
void operator()(const EAXVOCALMORPHERPROPERTIES& all) const
|
||||
{
|
||||
PhonemeAValidator{}(all.ulPhonemeA);
|
||||
PhonemeACoarseTuningValidator{}(all.lPhonemeACoarseTuning);
|
||||
PhonemeBValidator{}(all.ulPhonemeB);
|
||||
PhonemeBCoarseTuningValidator{}(all.lPhonemeBCoarseTuning);
|
||||
WaveformValidator{}(all.ulWaveform);
|
||||
RateValidator{}(all.flRate);
|
||||
}
|
||||
}; // AllValidator
|
||||
|
||||
} // namespace
|
||||
|
||||
template<>
|
||||
struct VocalMorpherCommitter::Exception : public EaxException {
|
||||
explicit Exception(const char *message) : EaxException{"EAX_VOCAL_MORPHER_EFFECT", message}
|
||||
{ }
|
||||
};
|
||||
|
||||
template<>
|
||||
[[noreturn]] void VocalMorpherCommitter::fail(const char *message)
|
||||
{
|
||||
throw Exception{message};
|
||||
}
|
||||
|
||||
template<>
|
||||
bool VocalMorpherCommitter::commit(const EaxEffectProps &props)
|
||||
{
|
||||
if(props.mType == mEaxProps.mType
|
||||
&& mEaxProps.mVocalMorpher.ulPhonemeA == props.mVocalMorpher.ulPhonemeA
|
||||
&& mEaxProps.mVocalMorpher.lPhonemeACoarseTuning == props.mVocalMorpher.lPhonemeACoarseTuning
|
||||
&& mEaxProps.mVocalMorpher.ulPhonemeB == props.mVocalMorpher.ulPhonemeB
|
||||
&& mEaxProps.mVocalMorpher.lPhonemeBCoarseTuning == props.mVocalMorpher.lPhonemeBCoarseTuning
|
||||
&& mEaxProps.mVocalMorpher.ulWaveform == props.mVocalMorpher.ulWaveform
|
||||
&& mEaxProps.mVocalMorpher.flRate == props.mVocalMorpher.flRate)
|
||||
return false;
|
||||
}
|
||||
|
||||
eax_ = eax_d_;
|
||||
mEaxProps = props;
|
||||
|
||||
if (eax_dirty_flags_.ulPhonemeA)
|
||||
auto get_phoneme = [](unsigned long phoneme) noexcept
|
||||
{
|
||||
set_efx_phoneme_a();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.lPhonemeACoarseTuning)
|
||||
#define HANDLE_PHENOME(x) case x: return VMorpherPhenome::x
|
||||
switch(phoneme)
|
||||
{
|
||||
HANDLE_PHENOME(A);
|
||||
HANDLE_PHENOME(E);
|
||||
HANDLE_PHENOME(I);
|
||||
HANDLE_PHENOME(O);
|
||||
HANDLE_PHENOME(U);
|
||||
HANDLE_PHENOME(AA);
|
||||
HANDLE_PHENOME(AE);
|
||||
HANDLE_PHENOME(AH);
|
||||
HANDLE_PHENOME(AO);
|
||||
HANDLE_PHENOME(EH);
|
||||
HANDLE_PHENOME(ER);
|
||||
HANDLE_PHENOME(IH);
|
||||
HANDLE_PHENOME(IY);
|
||||
HANDLE_PHENOME(UH);
|
||||
HANDLE_PHENOME(UW);
|
||||
HANDLE_PHENOME(B);
|
||||
HANDLE_PHENOME(D);
|
||||
HANDLE_PHENOME(F);
|
||||
HANDLE_PHENOME(G);
|
||||
HANDLE_PHENOME(J);
|
||||
HANDLE_PHENOME(K);
|
||||
HANDLE_PHENOME(L);
|
||||
HANDLE_PHENOME(M);
|
||||
HANDLE_PHENOME(N);
|
||||
HANDLE_PHENOME(P);
|
||||
HANDLE_PHENOME(R);
|
||||
HANDLE_PHENOME(S);
|
||||
HANDLE_PHENOME(T);
|
||||
HANDLE_PHENOME(V);
|
||||
HANDLE_PHENOME(Z);
|
||||
}
|
||||
return VMorpherPhenome::A;
|
||||
#undef HANDLE_PHENOME
|
||||
};
|
||||
auto get_waveform = [](unsigned long form) noexcept
|
||||
{
|
||||
set_efx_phoneme_a_coarse_tuning();
|
||||
}
|
||||
if(form == EAX_VOCALMORPHER_SINUSOID) return VMorpherWaveform::Sinusoid;
|
||||
if(form == EAX_VOCALMORPHER_TRIANGLE) return VMorpherWaveform::Triangle;
|
||||
if(form == EAX_VOCALMORPHER_SAWTOOTH) return VMorpherWaveform::Sawtooth;
|
||||
return VMorpherWaveform::Sinusoid;
|
||||
};
|
||||
|
||||
if (eax_dirty_flags_.ulPhonemeB)
|
||||
{
|
||||
set_efx_phoneme_b();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.lPhonemeBCoarseTuning)
|
||||
{
|
||||
set_efx_phoneme_b_coarse_tuning();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.ulWaveform)
|
||||
{
|
||||
set_efx_waveform();
|
||||
}
|
||||
|
||||
if (eax_dirty_flags_.flRate)
|
||||
{
|
||||
set_efx_rate();
|
||||
}
|
||||
|
||||
eax_dirty_flags_ = EaxVocalMorpherEffectDirtyFlags{};
|
||||
mAlProps.Vmorpher.PhonemeA = get_phoneme(props.mVocalMorpher.ulPhonemeA);
|
||||
mAlProps.Vmorpher.PhonemeACoarseTuning = static_cast<int>(props.mVocalMorpher.lPhonemeACoarseTuning);
|
||||
mAlProps.Vmorpher.PhonemeB = get_phoneme(props.mVocalMorpher.ulPhonemeB);
|
||||
mAlProps.Vmorpher.PhonemeBCoarseTuning = static_cast<int>(props.mVocalMorpher.lPhonemeBCoarseTuning);
|
||||
mAlProps.Vmorpher.Waveform = get_waveform(props.mVocalMorpher.ulWaveform);
|
||||
mAlProps.Vmorpher.Rate = props.mVocalMorpher.flRate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EaxVocalMorpherEffect::set(const EaxEaxCall& eax_call)
|
||||
template<>
|
||||
void VocalMorpherCommitter::SetDefaults(EaxEffectProps &props)
|
||||
{
|
||||
switch(eax_call.get_property_id())
|
||||
props.mType = EaxEffectType::VocalMorpher;
|
||||
props.mVocalMorpher.ulPhonemeA = EAXVOCALMORPHER_DEFAULTPHONEMEA;
|
||||
props.mVocalMorpher.lPhonemeACoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEACOARSETUNING;
|
||||
props.mVocalMorpher.ulPhonemeB = EAXVOCALMORPHER_DEFAULTPHONEMEB;
|
||||
props.mVocalMorpher.lPhonemeBCoarseTuning = EAXVOCALMORPHER_DEFAULTPHONEMEBCOARSETUNING;
|
||||
props.mVocalMorpher.ulWaveform = EAXVOCALMORPHER_DEFAULTWAVEFORM;
|
||||
props.mVocalMorpher.flRate = EAXVOCALMORPHER_DEFAULTRATE;
|
||||
}
|
||||
|
||||
template<>
|
||||
void VocalMorpherCommitter::Get(const EaxCall &call, const EaxEffectProps &props)
|
||||
{
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXVOCALMORPHER_NONE:
|
||||
break;
|
||||
case EAXVOCALMORPHER_NONE:
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_ALLPARAMETERS:
|
||||
defer_all(eax_call);
|
||||
break;
|
||||
case EAXVOCALMORPHER_ALLPARAMETERS:
|
||||
call.set_value<Exception>(props.mVocalMorpher);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_PHONEMEA:
|
||||
defer_phoneme_a(eax_call);
|
||||
break;
|
||||
case EAXVOCALMORPHER_PHONEMEA:
|
||||
call.set_value<Exception>(props.mVocalMorpher.ulPhonemeA);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_PHONEMEACOARSETUNING:
|
||||
defer_phoneme_a_coarse_tuning(eax_call);
|
||||
break;
|
||||
case EAXVOCALMORPHER_PHONEMEACOARSETUNING:
|
||||
call.set_value<Exception>(props.mVocalMorpher.lPhonemeACoarseTuning);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_PHONEMEB:
|
||||
defer_phoneme_b(eax_call);
|
||||
break;
|
||||
case EAXVOCALMORPHER_PHONEMEB:
|
||||
call.set_value<Exception>(props.mVocalMorpher.ulPhonemeB);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_PHONEMEBCOARSETUNING:
|
||||
defer_phoneme_b_coarse_tuning(eax_call);
|
||||
break;
|
||||
case EAXVOCALMORPHER_PHONEMEBCOARSETUNING:
|
||||
call.set_value<Exception>(props.mVocalMorpher.lPhonemeBCoarseTuning);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_WAVEFORM:
|
||||
defer_waveform(eax_call);
|
||||
break;
|
||||
case EAXVOCALMORPHER_WAVEFORM:
|
||||
call.set_value<Exception>(props.mVocalMorpher.ulWaveform);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_RATE:
|
||||
defer_rate(eax_call);
|
||||
break;
|
||||
case EAXVOCALMORPHER_RATE:
|
||||
call.set_value<Exception>(props.mVocalMorpher.flRate);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw EaxVocalMorpherEffectException{"Unsupported property id."};
|
||||
default:
|
||||
fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
EaxEffectUPtr eax_create_eax_vocal_morpher_effect()
|
||||
template<>
|
||||
void VocalMorpherCommitter::Set(const EaxCall &call, EaxEffectProps &props)
|
||||
{
|
||||
return std::make_unique<EaxVocalMorpherEffect>();
|
||||
switch(call.get_property_id())
|
||||
{
|
||||
case EAXVOCALMORPHER_NONE:
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_ALLPARAMETERS:
|
||||
defer<AllValidator>(call, props.mVocalMorpher);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_PHONEMEA:
|
||||
defer<PhonemeAValidator>(call, props.mVocalMorpher.ulPhonemeA);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_PHONEMEACOARSETUNING:
|
||||
defer<PhonemeACoarseTuningValidator>(call, props.mVocalMorpher.lPhonemeACoarseTuning);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_PHONEMEB:
|
||||
defer<PhonemeBValidator>(call, props.mVocalMorpher.ulPhonemeB);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_PHONEMEBCOARSETUNING:
|
||||
defer<PhonemeBCoarseTuningValidator>(call, props.mVocalMorpher.lPhonemeBCoarseTuning);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_WAVEFORM:
|
||||
defer<WaveformValidator>(call, props.mVocalMorpher.ulWaveform);
|
||||
break;
|
||||
|
||||
case EAXVOCALMORPHER_RATE:
|
||||
defer<RateValidator>(call, props.mVocalMorpher.flRate);
|
||||
break;
|
||||
|
||||
default:
|
||||
fail_unknown_property_id();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ALSOFT_EAX
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ AL_API ALenum AL_APIENTRY alGetError(void)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if(unlikely(!context))
|
||||
if(!context) UNLIKELY
|
||||
{
|
||||
static constexpr ALenum deferror{AL_INVALID_OPERATION};
|
||||
WARN("Querying error state on null context (implicitly 0x%04x)\n", deferror);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ static int EventThread(ALCcontext *context)
|
|||
{
|
||||
RingBuffer *ring{context->mAsyncEvents.get()};
|
||||
bool quitnow{false};
|
||||
while(likely(!quitnow))
|
||||
while(!quitnow)
|
||||
{
|
||||
auto evt_data = ring->getReadVector().first;
|
||||
if(evt_data.len == 0)
|
||||
|
|
@ -55,21 +55,20 @@ static int EventThread(ALCcontext *context)
|
|||
ring->readAdvance(1);
|
||||
|
||||
quitnow = evt.EnumType == AsyncEvent::KillThread;
|
||||
if(unlikely(quitnow)) break;
|
||||
if(quitnow) UNLIKELY break;
|
||||
|
||||
if(evt.EnumType == AsyncEvent::ReleaseEffectState)
|
||||
{
|
||||
evt.u.mEffectState->release();
|
||||
al::intrusive_ptr<EffectState>{evt.u.mEffectState};
|
||||
continue;
|
||||
}
|
||||
|
||||
uint enabledevts{context->mEnabledEvts.load(std::memory_order_acquire)};
|
||||
if(!context->mEventCb) continue;
|
||||
auto enabledevts = context->mEnabledEvts.load(std::memory_order_acquire);
|
||||
if(!context->mEventCb || !enabledevts.test(evt.EnumType))
|
||||
continue;
|
||||
|
||||
if(evt.EnumType == AsyncEvent::SourceStateChange)
|
||||
{
|
||||
if(!(enabledevts&AsyncEvent::SourceStateChange))
|
||||
continue;
|
||||
ALuint state{};
|
||||
std::string msg{"Source ID " + std::to_string(evt.u.srcstate.id)};
|
||||
msg += " state has changed to ";
|
||||
|
|
@ -97,8 +96,6 @@ static int EventThread(ALCcontext *context)
|
|||
}
|
||||
else if(evt.EnumType == AsyncEvent::BufferCompleted)
|
||||
{
|
||||
if(!(enabledevts&AsyncEvent::BufferCompleted))
|
||||
continue;
|
||||
std::string msg{std::to_string(evt.u.bufcomp.count)};
|
||||
if(evt.u.bufcomp.count == 1) msg += " buffer completed";
|
||||
else msg += " buffers completed";
|
||||
|
|
@ -108,8 +105,6 @@ static int EventThread(ALCcontext *context)
|
|||
}
|
||||
else if(evt.EnumType == AsyncEvent::Disconnected)
|
||||
{
|
||||
if(!(enabledevts&AsyncEvent::Disconnected))
|
||||
continue;
|
||||
context->mEventCb(AL_EVENT_TYPE_DISCONNECTED_SOFT, 0, 0,
|
||||
static_cast<ALsizei>(strlen(evt.u.disconnect.msg)), evt.u.disconnect.msg,
|
||||
context->mEventParam);
|
||||
|
|
@ -155,34 +150,34 @@ AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, A
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if(unlikely(!context)) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if(count < 0) context->setError(AL_INVALID_VALUE, "Controlling %d events", count);
|
||||
if(count <= 0) return;
|
||||
if(!types) SETERR_RETURN(context, AL_INVALID_VALUE,, "NULL pointer");
|
||||
if(!types) return context->setError(AL_INVALID_VALUE, "NULL pointer");
|
||||
|
||||
uint flags{0};
|
||||
ContextBase::AsyncEventBitset flags{};
|
||||
const ALenum *types_end = types+count;
|
||||
auto bad_type = std::find_if_not(types, types_end,
|
||||
[&flags](ALenum type) noexcept -> bool
|
||||
{
|
||||
if(type == AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT)
|
||||
flags |= AsyncEvent::BufferCompleted;
|
||||
flags.set(AsyncEvent::BufferCompleted);
|
||||
else if(type == AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT)
|
||||
flags |= AsyncEvent::SourceStateChange;
|
||||
flags.set(AsyncEvent::SourceStateChange);
|
||||
else if(type == AL_EVENT_TYPE_DISCONNECTED_SOFT)
|
||||
flags |= AsyncEvent::Disconnected;
|
||||
flags.set(AsyncEvent::Disconnected);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
);
|
||||
if(bad_type != types_end)
|
||||
SETERR_RETURN(context, AL_INVALID_ENUM,, "Invalid event type 0x%04x", *bad_type);
|
||||
return context->setError(AL_INVALID_ENUM, "Invalid event type 0x%04x", *bad_type);
|
||||
|
||||
if(enable)
|
||||
{
|
||||
uint enabledevts{context->mEnabledEvts.load(std::memory_order_relaxed)};
|
||||
auto enabledevts = context->mEnabledEvts.load(std::memory_order_relaxed);
|
||||
while(context->mEnabledEvts.compare_exchange_weak(enabledevts, enabledevts|flags,
|
||||
std::memory_order_acq_rel, std::memory_order_acquire) == 0)
|
||||
{
|
||||
|
|
@ -193,7 +188,7 @@ START_API_FUNC
|
|||
}
|
||||
else
|
||||
{
|
||||
uint enabledevts{context->mEnabledEvts.load(std::memory_order_relaxed)};
|
||||
auto enabledevts = context->mEnabledEvts.load(std::memory_order_relaxed);
|
||||
while(context->mEnabledEvts.compare_exchange_weak(enabledevts, enabledevts&~flags,
|
||||
std::memory_order_acq_rel, std::memory_order_acquire) == 0)
|
||||
{
|
||||
|
|
@ -210,7 +205,7 @@ AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *user
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if(unlikely(!context)) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
std::lock_guard<std::mutex> __{context->mEventCbLock};
|
||||
|
|
|
|||
|
|
@ -37,10 +37,13 @@ AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if(unlikely(!context)) return AL_FALSE;
|
||||
if(!context) UNLIKELY return AL_FALSE;
|
||||
|
||||
if(!extName)
|
||||
SETERR_RETURN(context, AL_INVALID_VALUE, AL_FALSE, "NULL pointer");
|
||||
if(!extName) UNLIKELY
|
||||
{
|
||||
context->setError(AL_INVALID_VALUE, "NULL pointer");
|
||||
return AL_FALSE;
|
||||
}
|
||||
|
||||
size_t len{strlen(extName)};
|
||||
const char *ptr{context->mExtensionList};
|
||||
|
|
|
|||
|
|
@ -57,16 +57,21 @@ public:
|
|||
#else
|
||||
[[gnu::format(printf, 3, 4)]]
|
||||
#endif
|
||||
filter_exception(ALenum code, const char *msg, ...) : mErrorCode{code}
|
||||
{
|
||||
std::va_list args;
|
||||
va_start(args, msg);
|
||||
setMessage(msg, args);
|
||||
va_end(args);
|
||||
}
|
||||
filter_exception(ALenum code, const char *msg, ...);
|
||||
~filter_exception() override;
|
||||
|
||||
ALenum errorCode() const noexcept { return mErrorCode; }
|
||||
};
|
||||
|
||||
filter_exception::filter_exception(ALenum code, const char* msg, ...) : mErrorCode{code}
|
||||
{
|
||||
std::va_list args;
|
||||
va_start(args, msg);
|
||||
setMessage(msg, args);
|
||||
va_end(args);
|
||||
}
|
||||
filter_exception::~filter_exception() = default;
|
||||
|
||||
|
||||
#define DEFINE_ALFILTER_VTABLE(T) \
|
||||
const ALfilter::Vtable T##_vtable = { \
|
||||
|
|
@ -331,14 +336,14 @@ bool EnsureFilters(ALCdevice *device, size_t needed)
|
|||
|
||||
while(needed > count)
|
||||
{
|
||||
if UNLIKELY(device->FilterList.size() >= 1<<25)
|
||||
if(device->FilterList.size() >= 1<<25) UNLIKELY
|
||||
return false;
|
||||
|
||||
device->FilterList.emplace_back();
|
||||
auto sublist = device->FilterList.end() - 1;
|
||||
sublist->FreeMask = ~0_u64;
|
||||
sublist->Filters = static_cast<ALfilter*>(al_calloc(alignof(ALfilter), sizeof(ALfilter)*64));
|
||||
if UNLIKELY(!sublist->Filters)
|
||||
if(!sublist->Filters) UNLIKELY
|
||||
{
|
||||
device->FilterList.pop_back();
|
||||
return false;
|
||||
|
|
@ -386,10 +391,10 @@ inline ALfilter *LookupFilter(ALCdevice *device, ALuint id)
|
|||
const size_t lidx{(id-1) >> 6};
|
||||
const ALuint slidx{(id-1) & 0x3f};
|
||||
|
||||
if UNLIKELY(lidx >= device->FilterList.size())
|
||||
if(lidx >= device->FilterList.size()) UNLIKELY
|
||||
return nullptr;
|
||||
FilterSubList &sublist = device->FilterList[lidx];
|
||||
if UNLIKELY(sublist.FreeMask & (1_u64 << slidx))
|
||||
if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY
|
||||
return nullptr;
|
||||
return sublist.Filters + slidx;
|
||||
}
|
||||
|
|
@ -400,11 +405,11 @@ AL_API void AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if UNLIKELY(n < 0)
|
||||
if(n < 0) UNLIKELY
|
||||
context->setError(AL_INVALID_VALUE, "Generating %d filters", n);
|
||||
if UNLIKELY(n <= 0) return;
|
||||
if(n <= 0) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->FilterLock};
|
||||
|
|
@ -414,7 +419,7 @@ START_API_FUNC
|
|||
return;
|
||||
}
|
||||
|
||||
if LIKELY(n == 1)
|
||||
if(n == 1) LIKELY
|
||||
{
|
||||
/* Special handling for the easy and normal case. */
|
||||
ALfilter *filter{AllocFilter(device)};
|
||||
|
|
@ -440,11 +445,11 @@ AL_API void AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if UNLIKELY(n < 0)
|
||||
if(n < 0) UNLIKELY
|
||||
context->setError(AL_INVALID_VALUE, "Deleting %d filters", n);
|
||||
if UNLIKELY(n <= 0) return;
|
||||
if(n <= 0) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->FilterLock};
|
||||
|
|
@ -455,7 +460,7 @@ START_API_FUNC
|
|||
|
||||
const ALuint *filters_end = filters + n;
|
||||
auto invflt = std::find_if_not(filters, filters_end, validate_filter);
|
||||
if UNLIKELY(invflt != filters_end)
|
||||
if(invflt != filters_end) UNLIKELY
|
||||
{
|
||||
context->setError(AL_INVALID_NAME, "Invalid filter ID %u", *invflt);
|
||||
return;
|
||||
|
|
@ -475,7 +480,7 @@ AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if LIKELY(context)
|
||||
if(context) LIKELY
|
||||
{
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->FilterLock};
|
||||
|
|
@ -491,13 +496,13 @@ AL_API void AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->FilterLock};
|
||||
|
||||
ALfilter *alfilt{LookupFilter(device, filter)};
|
||||
if UNLIKELY(!alfilt)
|
||||
if(!alfilt) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
||||
else
|
||||
{
|
||||
|
|
@ -532,13 +537,13 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->FilterLock};
|
||||
|
||||
ALfilter *alfilt{LookupFilter(device, filter)};
|
||||
if UNLIKELY(!alfilt)
|
||||
if(!alfilt) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
||||
else try
|
||||
{
|
||||
|
|
@ -555,13 +560,13 @@ AL_API void AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->FilterLock};
|
||||
|
||||
ALfilter *alfilt{LookupFilter(device, filter)};
|
||||
if UNLIKELY(!alfilt)
|
||||
if(!alfilt) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
||||
else try
|
||||
{
|
||||
|
|
@ -578,13 +583,13 @@ AL_API void AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *v
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->FilterLock};
|
||||
|
||||
ALfilter *alfilt{LookupFilter(device, filter)};
|
||||
if UNLIKELY(!alfilt)
|
||||
if(!alfilt) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
||||
else try
|
||||
{
|
||||
|
|
@ -601,13 +606,13 @@ AL_API void AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->FilterLock};
|
||||
|
||||
const ALfilter *alfilt{LookupFilter(device, filter)};
|
||||
if UNLIKELY(!alfilt)
|
||||
if(!alfilt) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
||||
else
|
||||
{
|
||||
|
|
@ -636,13 +641,13 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->FilterLock};
|
||||
|
||||
const ALfilter *alfilt{LookupFilter(device, filter)};
|
||||
if UNLIKELY(!alfilt)
|
||||
if(!alfilt) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
||||
else try
|
||||
{
|
||||
|
|
@ -659,13 +664,13 @@ AL_API void AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *value
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->FilterLock};
|
||||
|
||||
const ALfilter *alfilt{LookupFilter(device, filter)};
|
||||
if UNLIKELY(!alfilt)
|
||||
if(!alfilt) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
||||
else try
|
||||
{
|
||||
|
|
@ -682,13 +687,13 @@ AL_API void AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *valu
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALCdevice *device{context->mALDevice.get()};
|
||||
std::lock_guard<std::mutex> _{device->FilterLock};
|
||||
|
||||
const ALfilter *alfilt{LookupFilter(device, filter)};
|
||||
if UNLIKELY(!alfilt)
|
||||
if(!alfilt) UNLIKELY
|
||||
context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter);
|
||||
else try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -48,40 +48,31 @@ inline void UpdateProps(ALCcontext *context)
|
|||
context->mPropsDirty = true;
|
||||
}
|
||||
|
||||
#ifdef ALSOFT_EAX
|
||||
inline void CommitAndUpdateProps(ALCcontext *context)
|
||||
{
|
||||
if(!context->mDeferUpdates)
|
||||
{
|
||||
if(context->has_eax())
|
||||
#ifdef ALSOFT_EAX
|
||||
if(context->eaxNeedsCommit())
|
||||
{
|
||||
context->mHoldUpdates.store(true, std::memory_order_release);
|
||||
while((context->mUpdateCount.load(std::memory_order_acquire)&1) != 0) {
|
||||
/* busy-wait */
|
||||
}
|
||||
|
||||
context->eax_commit_and_update_sources();
|
||||
context->mPropsDirty = true;
|
||||
context->applyAllUpdates();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
UpdateContextProps(context);
|
||||
context->mHoldUpdates.store(false, std::memory_order_release);
|
||||
return;
|
||||
}
|
||||
context->mPropsDirty = true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void CommitAndUpdateProps(ALCcontext *context)
|
||||
{ UpdateProps(context); }
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value)
|
||||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALlistener &listener = context->mListener;
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
|
|
@ -89,14 +80,14 @@ START_API_FUNC
|
|||
{
|
||||
case AL_GAIN:
|
||||
if(!(value >= 0.0f && std::isfinite(value)))
|
||||
SETERR_RETURN(context, AL_INVALID_VALUE,, "Listener gain out of range");
|
||||
return context->setError(AL_INVALID_VALUE, "Listener gain out of range");
|
||||
listener.Gain = value;
|
||||
UpdateProps(context.get());
|
||||
break;
|
||||
|
||||
case AL_METERS_PER_UNIT:
|
||||
if(!(value >= AL_MIN_METERS_PER_UNIT && value <= AL_MAX_METERS_PER_UNIT))
|
||||
SETERR_RETURN(context, AL_INVALID_VALUE,, "Listener meters per unit out of range");
|
||||
return context->setError(AL_INVALID_VALUE, "Listener meters per unit out of range");
|
||||
listener.mMetersPerUnit = value;
|
||||
UpdateProps(context.get());
|
||||
break;
|
||||
|
|
@ -111,7 +102,7 @@ AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALlistener &listener = context->mListener;
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
|
|
@ -119,7 +110,7 @@ START_API_FUNC
|
|||
{
|
||||
case AL_POSITION:
|
||||
if(!(std::isfinite(value1) && std::isfinite(value2) && std::isfinite(value3)))
|
||||
SETERR_RETURN(context, AL_INVALID_VALUE,, "Listener position out of range");
|
||||
return context->setError(AL_INVALID_VALUE, "Listener position out of range");
|
||||
listener.Position[0] = value1;
|
||||
listener.Position[1] = value2;
|
||||
listener.Position[2] = value3;
|
||||
|
|
@ -128,7 +119,7 @@ START_API_FUNC
|
|||
|
||||
case AL_VELOCITY:
|
||||
if(!(std::isfinite(value1) && std::isfinite(value2) && std::isfinite(value3)))
|
||||
SETERR_RETURN(context, AL_INVALID_VALUE,, "Listener velocity out of range");
|
||||
return context->setError(AL_INVALID_VALUE, "Listener velocity out of range");
|
||||
listener.Velocity[0] = value1;
|
||||
listener.Velocity[1] = value2;
|
||||
listener.Velocity[2] = value3;
|
||||
|
|
@ -161,17 +152,19 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if(!values) UNLIKELY
|
||||
return context->setError(AL_INVALID_VALUE, "NULL pointer");
|
||||
|
||||
ALlistener &listener = context->mListener;
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
if(!values) SETERR_RETURN(context, AL_INVALID_VALUE,, "NULL pointer");
|
||||
switch(param)
|
||||
{
|
||||
case AL_ORIENTATION:
|
||||
if(!(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]) &&
|
||||
std::isfinite(values[3]) && std::isfinite(values[4]) && std::isfinite(values[5])))
|
||||
SETERR_RETURN(context, AL_INVALID_VALUE,, "Listener orientation out of range");
|
||||
return context->setError(AL_INVALID_VALUE, "Listener orientation out of range");
|
||||
/* AT then UP */
|
||||
listener.OrientAt[0] = values[0];
|
||||
listener.OrientAt[1] = values[1];
|
||||
|
|
@ -193,7 +186,7 @@ AL_API void AL_APIENTRY alListeneri(ALenum param, ALint /*value*/)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
switch(param)
|
||||
|
|
@ -211,12 +204,13 @@ START_API_FUNC
|
|||
{
|
||||
case AL_POSITION:
|
||||
case AL_VELOCITY:
|
||||
alListener3f(param, static_cast<ALfloat>(value1), static_cast<ALfloat>(value2), static_cast<ALfloat>(value3));
|
||||
alListener3f(param, static_cast<ALfloat>(value1), static_cast<ALfloat>(value2),
|
||||
static_cast<ALfloat>(value3));
|
||||
return;
|
||||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
switch(param)
|
||||
|
|
@ -237,7 +231,8 @@ START_API_FUNC
|
|||
{
|
||||
case AL_POSITION:
|
||||
case AL_VELOCITY:
|
||||
alListener3f(param, static_cast<ALfloat>(values[0]), static_cast<ALfloat>(values[1]), static_cast<ALfloat>(values[2]));
|
||||
alListener3f(param, static_cast<ALfloat>(values[0]), static_cast<ALfloat>(values[1]),
|
||||
static_cast<ALfloat>(values[2]));
|
||||
return;
|
||||
|
||||
case AL_ORIENTATION:
|
||||
|
|
@ -253,10 +248,10 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
if(!values)
|
||||
if(!values) UNLIKELY
|
||||
context->setError(AL_INVALID_VALUE, "NULL pointer");
|
||||
else switch(param)
|
||||
{
|
||||
|
|
@ -271,7 +266,7 @@ AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALlistener &listener = context->mListener;
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
|
|
@ -297,7 +292,7 @@ AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALlistener &listener = context->mListener;
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
|
|
@ -340,7 +335,7 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALlistener &listener = context->mListener;
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
|
|
@ -369,7 +364,7 @@ AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
if(!value)
|
||||
|
|
@ -386,7 +381,7 @@ AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *valu
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALlistener &listener = context->mListener;
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
|
|
@ -424,7 +419,7 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
ALlistener &listener = context->mListener;
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -49,8 +49,8 @@
|
|||
#ifdef ALSOFT_EAX
|
||||
#include "alc/device.h"
|
||||
|
||||
#include "eax_globals.h"
|
||||
#include "eax_x_ram.h"
|
||||
#include "eax/globals.h"
|
||||
#include "eax/x_ram.h"
|
||||
#endif // ALSOFT_EAX
|
||||
|
||||
|
||||
|
|
@ -107,13 +107,13 @@ al::optional<DistanceModel> DistanceModelFromALenum(ALenum model)
|
|||
{
|
||||
switch(model)
|
||||
{
|
||||
case AL_NONE: return al::make_optional(DistanceModel::Disable);
|
||||
case AL_INVERSE_DISTANCE: return al::make_optional(DistanceModel::Inverse);
|
||||
case AL_INVERSE_DISTANCE_CLAMPED: return al::make_optional(DistanceModel::InverseClamped);
|
||||
case AL_LINEAR_DISTANCE: return al::make_optional(DistanceModel::Linear);
|
||||
case AL_LINEAR_DISTANCE_CLAMPED: return al::make_optional(DistanceModel::LinearClamped);
|
||||
case AL_EXPONENT_DISTANCE: return al::make_optional(DistanceModel::Exponent);
|
||||
case AL_EXPONENT_DISTANCE_CLAMPED: return al::make_optional(DistanceModel::ExponentClamped);
|
||||
case AL_NONE: return DistanceModel::Disable;
|
||||
case AL_INVERSE_DISTANCE: return DistanceModel::Inverse;
|
||||
case AL_INVERSE_DISTANCE_CLAMPED: return DistanceModel::InverseClamped;
|
||||
case AL_LINEAR_DISTANCE: return DistanceModel::Linear;
|
||||
case AL_LINEAR_DISTANCE_CLAMPED: return DistanceModel::LinearClamped;
|
||||
case AL_EXPONENT_DISTANCE: return DistanceModel::Exponent;
|
||||
case AL_EXPONENT_DISTANCE_CLAMPED: return DistanceModel::ExponentClamped;
|
||||
}
|
||||
return al::nullopt;
|
||||
}
|
||||
|
|
@ -158,7 +158,7 @@ AL_API void AL_APIENTRY alEnable(ALenum capability)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
switch(capability)
|
||||
{
|
||||
|
|
@ -184,7 +184,7 @@ AL_API void AL_APIENTRY alDisable(ALenum capability)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
switch(capability)
|
||||
{
|
||||
|
|
@ -210,7 +210,7 @@ AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return AL_FALSE;
|
||||
if(!context) UNLIKELY return AL_FALSE;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
ALboolean value{AL_FALSE};
|
||||
|
|
@ -236,7 +236,7 @@ AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return AL_FALSE;
|
||||
if(!context) UNLIKELY return AL_FALSE;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
ALboolean value{AL_FALSE};
|
||||
|
|
@ -293,7 +293,7 @@ AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return 0.0;
|
||||
if(!context) UNLIKELY return 0.0;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
ALdouble value{0.0};
|
||||
|
|
@ -344,7 +344,7 @@ AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return 0.0f;
|
||||
if(!context) UNLIKELY return 0.0f;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
ALfloat value{0.0f};
|
||||
|
|
@ -395,7 +395,7 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return 0;
|
||||
if(!context) UNLIKELY return 0;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
ALint value{0};
|
||||
|
|
@ -481,7 +481,7 @@ AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return 0_i64;
|
||||
if(!context) UNLIKELY return 0_i64;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
ALint64SOFT value{0};
|
||||
|
|
@ -532,7 +532,7 @@ AL_API ALvoid* AL_APIENTRY alGetPointerSOFT(ALenum pname)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return nullptr;
|
||||
if(!context) UNLIKELY return nullptr;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
void *value{nullptr};
|
||||
|
|
@ -575,7 +575,7 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if(!values)
|
||||
context->setError(AL_INVALID_VALUE, "NULL pointer");
|
||||
|
|
@ -608,7 +608,7 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if(!values)
|
||||
context->setError(AL_INVALID_VALUE, "NULL pointer");
|
||||
|
|
@ -641,7 +641,7 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if(!values)
|
||||
context->setError(AL_INVALID_VALUE, "NULL pointer");
|
||||
|
|
@ -674,7 +674,7 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if(!values)
|
||||
context->setError(AL_INVALID_VALUE, "NULL pointer");
|
||||
|
|
@ -707,7 +707,7 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if(!values)
|
||||
context->setError(AL_INVALID_VALUE, "NULL pointer");
|
||||
|
|
@ -734,7 +734,7 @@ START_API_FUNC
|
|||
}
|
||||
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if(!values)
|
||||
context->setError(AL_INVALID_VALUE, "NULL pointer");
|
||||
|
|
@ -750,7 +750,7 @@ AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return nullptr;
|
||||
if(!context) UNLIKELY return nullptr;
|
||||
|
||||
const ALchar *value{nullptr};
|
||||
switch(pname)
|
||||
|
|
@ -806,7 +806,7 @@ AL_API void AL_APIENTRY alDopplerFactor(ALfloat value)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if(!(value >= 0.0f && std::isfinite(value)))
|
||||
context->setError(AL_INVALID_VALUE, "Doppler factor %f out of range", value);
|
||||
|
|
@ -823,7 +823,7 @@ AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if(!(value >= 0.0f && std::isfinite(value)))
|
||||
context->setError(AL_INVALID_VALUE, "Doppler velocity %f out of range", value);
|
||||
|
|
@ -840,7 +840,7 @@ AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if(!(value > 0.0f && std::isfinite(value)))
|
||||
context->setError(AL_INVALID_VALUE, "Speed of sound %f out of range", value);
|
||||
|
|
@ -857,7 +857,7 @@ AL_API void AL_APIENTRY alDistanceModel(ALenum value)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
if(auto model = DistanceModelFromALenum(value))
|
||||
{
|
||||
|
|
@ -876,7 +876,7 @@ AL_API void AL_APIENTRY alDeferUpdatesSOFT(void)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
context->deferUpdates();
|
||||
|
|
@ -887,7 +887,7 @@ AL_API void AL_APIENTRY alProcessUpdatesSOFT(void)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return;
|
||||
if(!context) UNLIKELY return;
|
||||
|
||||
std::lock_guard<std::mutex> _{context->mPropLock};
|
||||
context->processUpdates();
|
||||
|
|
@ -899,7 +899,7 @@ AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
|
|||
START_API_FUNC
|
||||
{
|
||||
ContextRef context{GetContextRef()};
|
||||
if UNLIKELY(!context) return nullptr;
|
||||
if(!context) UNLIKELY return nullptr;
|
||||
|
||||
const ALchar *value{nullptr};
|
||||
switch(pname)
|
||||
|
|
@ -943,6 +943,7 @@ void UpdateContextProps(ALCcontext *context)
|
|||
props->Gain = listener.Gain;
|
||||
props->MetersPerUnit = listener.mMetersPerUnit;
|
||||
|
||||
props->AirAbsorptionGainHF = context->mAirAbsorptionGainHF;
|
||||
props->DopplerFactor = context->mDopplerFactor;
|
||||
props->DopplerVelocity = context->mDopplerVelocity;
|
||||
props->SpeedOfSound = context->mSpeedOfSound;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue