Properly handle buffer name hash collisions
[alure.git] / src / effect.cpp
blobddde0d4fa93879aa58a5af52e6a127c72cdd197e
2 #include "config.h"
4 #include "effect.h"
6 #include <stdexcept>
8 #include "context.h"
11 namespace {
13 template<typename T>
14 inline T clamp(const T& val, const T& min, const T& max)
15 { return std::min<T>(std::max<T>(val, min), max); }
17 } // namespace
19 namespace alure {
21 EffectImpl::EffectImpl(ContextImpl &context) : mContext(context)
23 alGetError();
24 mContext.alGenEffects(1, &mId);
25 throw_al_error("Failed to create Effect");
28 EffectImpl::~EffectImpl()
30 if(UNLIKELY(mId != 0) && ContextImpl::GetCurrent() == &mContext)
32 mContext.alDeleteEffects(1, &mId);
33 mId = 0;
38 DECL_THUNK1(void, Effect, setReverbProperties,, const EFXEAXREVERBPROPERTIES&)
39 void EffectImpl::setReverbProperties(const EFXEAXREVERBPROPERTIES &props)
41 CheckContext(mContext);
43 if(mType != AL_EFFECT_EAXREVERB && mType != AL_EFFECT_REVERB)
45 alGetError();
46 mContext.alEffecti(mId, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
47 if(alGetError() == AL_NO_ERROR)
48 mType = AL_EFFECT_EAXREVERB;
49 else
51 mContext.alEffecti(mId, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
52 throw_al_error("Failed to set reverb type");
53 mType = AL_EFFECT_REVERB;
57 if(mType == AL_EFFECT_EAXREVERB)
59 #define SETPARAM(e,t,v) mContext.alEffectf((e), AL_EAXREVERB_##t, clamp((v), AL_EAXREVERB_MIN_##t, AL_EAXREVERB_MAX_##t))
60 SETPARAM(mId, DENSITY, props.flDensity);
61 SETPARAM(mId, DIFFUSION, props.flDiffusion);
62 SETPARAM(mId, GAIN, props.flGain);
63 SETPARAM(mId, GAINHF, props.flGainHF);
64 SETPARAM(mId, GAINLF, props.flGainLF);
65 SETPARAM(mId, DECAY_TIME, props.flDecayTime);
66 SETPARAM(mId, DECAY_HFRATIO, props.flDecayHFRatio);
67 SETPARAM(mId, DECAY_LFRATIO, props.flDecayLFRatio);
68 SETPARAM(mId, REFLECTIONS_GAIN, props.flReflectionsGain);
69 SETPARAM(mId, REFLECTIONS_DELAY, props.flReflectionsDelay);
70 mContext.alEffectfv(mId, AL_EAXREVERB_REFLECTIONS_PAN, props.flReflectionsPan);
71 SETPARAM(mId, LATE_REVERB_GAIN, props.flLateReverbGain);
72 SETPARAM(mId, LATE_REVERB_DELAY, props.flLateReverbDelay);
73 mContext.alEffectfv(mId, AL_EAXREVERB_LATE_REVERB_PAN, props.flLateReverbPan);
74 SETPARAM(mId, ECHO_TIME, props.flEchoTime);
75 SETPARAM(mId, ECHO_DEPTH, props.flEchoDepth);
76 SETPARAM(mId, MODULATION_TIME, props.flModulationTime);
77 SETPARAM(mId, MODULATION_DEPTH, props.flModulationDepth);
78 SETPARAM(mId, AIR_ABSORPTION_GAINHF, props.flAirAbsorptionGainHF);
79 SETPARAM(mId, HFREFERENCE, props.flHFReference);
80 SETPARAM(mId, LFREFERENCE, props.flLFReference);
81 SETPARAM(mId, ROOM_ROLLOFF_FACTOR, props.flRoomRolloffFactor);
82 mContext.alEffecti(mId, AL_EAXREVERB_DECAY_HFLIMIT, (props.iDecayHFLimit ? AL_TRUE : AL_FALSE));
83 #undef SETPARAM
85 else if(mType == AL_EFFECT_REVERB)
87 #define SETPARAM(e,t,v) mContext.alEffectf((e), AL_REVERB_##t, clamp((v), AL_REVERB_MIN_##t, AL_REVERB_MAX_##t))
88 SETPARAM(mId, DENSITY, props.flDensity);
89 SETPARAM(mId, DIFFUSION, props.flDiffusion);
90 SETPARAM(mId, GAIN, props.flGain);
91 SETPARAM(mId, GAINHF, props.flGainHF);
92 SETPARAM(mId, DECAY_TIME, props.flDecayTime);
93 SETPARAM(mId, DECAY_HFRATIO, props.flDecayHFRatio);
94 SETPARAM(mId, REFLECTIONS_GAIN, props.flReflectionsGain);
95 SETPARAM(mId, REFLECTIONS_DELAY, props.flReflectionsDelay);
96 SETPARAM(mId, LATE_REVERB_GAIN, props.flLateReverbGain);
97 SETPARAM(mId, LATE_REVERB_DELAY, props.flLateReverbDelay);
98 SETPARAM(mId, AIR_ABSORPTION_GAINHF, props.flAirAbsorptionGainHF);
99 SETPARAM(mId, ROOM_ROLLOFF_FACTOR, props.flRoomRolloffFactor);
100 mContext.alEffecti(mId, AL_REVERB_DECAY_HFLIMIT, (props.iDecayHFLimit ? AL_TRUE : AL_FALSE));
101 #undef SETPARAM
105 DECL_THUNK1(void, Effect, setChorusProperties,, const EFXCHORUSPROPERTIES&)
106 void EffectImpl::setChorusProperties(const EFXCHORUSPROPERTIES &props)
108 CheckContext(mContext);
110 if(mType != AL_EFFECT_CHORUS)
112 alGetError();
113 mContext.alEffecti(mId, AL_EFFECT_TYPE, AL_EFFECT_CHORUS);
114 throw_al_error("Failed to set chorus type");
115 mType = AL_EFFECT_REVERB;
118 #define SETPARAM(t,v) AL_CHORUS_##t, clamp((v), AL_CHORUS_MIN_##t, AL_CHORUS_MAX_##t)
119 mContext.alEffecti(mId, SETPARAM(WAVEFORM, props.iWaveform));
120 mContext.alEffecti(mId, SETPARAM(PHASE, props.iPhase));
121 mContext.alEffectf(mId, SETPARAM(RATE, props.flRate));
122 mContext.alEffectf(mId, SETPARAM(DEPTH, props.flDepth));
123 mContext.alEffectf(mId, SETPARAM(FEEDBACK, props.flFeedback));
124 mContext.alEffectf(mId, SETPARAM(DELAY, props.flDelay));
125 #undef SETPARAM
128 void Effect::destroy()
130 EffectImpl *i = pImpl;
131 pImpl = nullptr;
132 i->destroy();
134 void EffectImpl::destroy()
136 CheckContext(mContext);
138 alGetError();
139 mContext.alDeleteEffects(1, &mId);
140 throw_al_error("Effect failed to delete");
141 mId = 0;
143 mContext.freeEffect(this);