14 inline T
clamp(const T
& val
, const T
& min
, const T
& max
)
15 { return std::min
<T
>(std::max
<T
>(val
, min
), max
); }
21 EffectImpl::EffectImpl(ContextImpl
&context
) : mContext(context
)
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
);
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
)
46 mContext
.alEffecti(mId
, AL_EFFECT_TYPE
, AL_EFFECT_EAXREVERB
);
47 if(alGetError() == AL_NO_ERROR
)
48 mType
= AL_EFFECT_EAXREVERB
;
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
));
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
));
105 DECL_THUNK1(void, Effect
, setChorusProperties
,, const EFXCHORUSPROPERTIES
&)
106 void EffectImpl::setChorusProperties(const EFXCHORUSPROPERTIES
&props
)
108 CheckContext(mContext
);
110 if(mType
!= AL_EFFECT_CHORUS
)
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
));
128 void Effect::destroy()
130 EffectImpl
*i
= pImpl
;
134 void EffectImpl::destroy()
136 CheckContext(mContext
);
139 mContext
.alDeleteEffects(1, &mId
);
140 throw_al_error("Effect failed to delete");
143 mContext
.freeEffect(this);