🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

296 lines
6.8 KiB

#include "config.h"
#include "AL/al.h"
#include "AL/efx.h"
#include "alc/effects/base.h"
#include "effects.h"
#ifdef ALSOFT_EAX
#include "alnumeric.h"
#include "al/eax_exception.h"
#include "al/eax_utils.h"
#endif // ALSOFT_EAX
namespace {
void Compressor_setParami(EffectProps *props, ALenum param, int val)
{
switch(param)
{
case AL_COMPRESSOR_ONOFF:
if(!(val >= AL_COMPRESSOR_MIN_ONOFF && val <= AL_COMPRESSOR_MAX_ONOFF))
throw effect_exception{AL_INVALID_VALUE, "Compressor state out of range"};
props->Compressor.OnOff = (val != AL_FALSE);
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid compressor integer property 0x%04x",
param};
}
}
void Compressor_setParamiv(EffectProps *props, ALenum param, const int *vals)
{ Compressor_setParami(props, param, vals[0]); }
void Compressor_setParamf(EffectProps*, ALenum param, float)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param}; }
void Compressor_setParamfv(EffectProps*, ALenum param, const float*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float-vector property 0x%04x",
param};
}
void Compressor_getParami(const EffectProps *props, ALenum param, int *val)
{
switch(param)
{
case AL_COMPRESSOR_ONOFF:
*val = props->Compressor.OnOff;
break;
default:
throw effect_exception{AL_INVALID_ENUM, "Invalid compressor integer property 0x%04x",
param};
}
}
void Compressor_getParamiv(const EffectProps *props, ALenum param, int *vals)
{ Compressor_getParami(props, param, vals); }
void Compressor_getParamf(const EffectProps*, ALenum param, float*)
{ throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param}; }
void Compressor_getParamfv(const EffectProps*, ALenum param, float*)
{
throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float-vector property 0x%04x",
param};
}
EffectProps genDefaultProps() noexcept
{
EffectProps props{};
props.Compressor.OnOff = AL_COMPRESSOR_DEFAULT_ONOFF;
return props;
}
} // namespace
DEFINE_ALEFFECT_VTABLE(Compressor);
const EffectProps CompressorEffectProps{genDefaultProps()};
#ifdef ALSOFT_EAX
namespace {
using EaxCompressorEffectDirtyFlagsValue = std::uint_least8_t;
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}
{
}
}; // EaxCompressorEffectException
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())
{
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."};
}
}
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."};
}
}
} // namespace
EaxEffectUPtr eax_create_eax_compressor_effect()
{
return std::make_unique<EaxCompressorEffect>();
}
#endif // ALSOFT_EAX