2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
33 #include "alcontext.h"
38 const EffectList gEffectList
[14]{
39 { "eaxreverb", EAXREVERB_EFFECT
, AL_EFFECT_EAXREVERB
},
40 { "reverb", REVERB_EFFECT
, AL_EFFECT_REVERB
},
41 { "autowah", AUTOWAH_EFFECT
, AL_EFFECT_AUTOWAH
},
42 { "chorus", CHORUS_EFFECT
, AL_EFFECT_CHORUS
},
43 { "compressor", COMPRESSOR_EFFECT
, AL_EFFECT_COMPRESSOR
},
44 { "distortion", DISTORTION_EFFECT
, AL_EFFECT_DISTORTION
},
45 { "echo", ECHO_EFFECT
, AL_EFFECT_ECHO
},
46 { "equalizer", EQUALIZER_EFFECT
, AL_EFFECT_EQUALIZER
},
47 { "flanger", FLANGER_EFFECT
, AL_EFFECT_FLANGER
},
48 { "fshifter", FSHIFTER_EFFECT
, AL_EFFECT_FREQUENCY_SHIFTER
},
49 { "modulator", MODULATOR_EFFECT
, AL_EFFECT_RING_MODULATOR
},
50 { "pshifter", PSHIFTER_EFFECT
, AL_EFFECT_PITCH_SHIFTER
},
51 { "dedicated", DEDICATED_EFFECT
, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
},
52 { "dedicated", DEDICATED_EFFECT
, AL_EFFECT_DEDICATED_DIALOGUE
},
55 ALboolean DisabledEffects
[MAX_EFFECTS
];
59 void InitEffectParams(ALeffect
*effect
, ALenum type
)
63 case AL_EFFECT_EAXREVERB
:
64 effect
->Props
.Reverb
.Density
= AL_EAXREVERB_DEFAULT_DENSITY
;
65 effect
->Props
.Reverb
.Diffusion
= AL_EAXREVERB_DEFAULT_DIFFUSION
;
66 effect
->Props
.Reverb
.Gain
= AL_EAXREVERB_DEFAULT_GAIN
;
67 effect
->Props
.Reverb
.GainHF
= AL_EAXREVERB_DEFAULT_GAINHF
;
68 effect
->Props
.Reverb
.GainLF
= AL_EAXREVERB_DEFAULT_GAINLF
;
69 effect
->Props
.Reverb
.DecayTime
= AL_EAXREVERB_DEFAULT_DECAY_TIME
;
70 effect
->Props
.Reverb
.DecayHFRatio
= AL_EAXREVERB_DEFAULT_DECAY_HFRATIO
;
71 effect
->Props
.Reverb
.DecayLFRatio
= AL_EAXREVERB_DEFAULT_DECAY_LFRATIO
;
72 effect
->Props
.Reverb
.ReflectionsGain
= AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN
;
73 effect
->Props
.Reverb
.ReflectionsDelay
= AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY
;
74 effect
->Props
.Reverb
.ReflectionsPan
[0] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ
;
75 effect
->Props
.Reverb
.ReflectionsPan
[1] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ
;
76 effect
->Props
.Reverb
.ReflectionsPan
[2] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ
;
77 effect
->Props
.Reverb
.LateReverbGain
= AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN
;
78 effect
->Props
.Reverb
.LateReverbDelay
= AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY
;
79 effect
->Props
.Reverb
.LateReverbPan
[0] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ
;
80 effect
->Props
.Reverb
.LateReverbPan
[1] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ
;
81 effect
->Props
.Reverb
.LateReverbPan
[2] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ
;
82 effect
->Props
.Reverb
.EchoTime
= AL_EAXREVERB_DEFAULT_ECHO_TIME
;
83 effect
->Props
.Reverb
.EchoDepth
= AL_EAXREVERB_DEFAULT_ECHO_DEPTH
;
84 effect
->Props
.Reverb
.ModulationTime
= AL_EAXREVERB_DEFAULT_MODULATION_TIME
;
85 effect
->Props
.Reverb
.ModulationDepth
= AL_EAXREVERB_DEFAULT_MODULATION_DEPTH
;
86 effect
->Props
.Reverb
.AirAbsorptionGainHF
= AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF
;
87 effect
->Props
.Reverb
.HFReference
= AL_EAXREVERB_DEFAULT_HFREFERENCE
;
88 effect
->Props
.Reverb
.LFReference
= AL_EAXREVERB_DEFAULT_LFREFERENCE
;
89 effect
->Props
.Reverb
.RoomRolloffFactor
= AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR
;
90 effect
->Props
.Reverb
.DecayHFLimit
= AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT
;
91 effect
->vtab
= &ALeaxreverb_vtable
;
93 case AL_EFFECT_REVERB
:
94 effect
->Props
.Reverb
.Density
= AL_REVERB_DEFAULT_DENSITY
;
95 effect
->Props
.Reverb
.Diffusion
= AL_REVERB_DEFAULT_DIFFUSION
;
96 effect
->Props
.Reverb
.Gain
= AL_REVERB_DEFAULT_GAIN
;
97 effect
->Props
.Reverb
.GainHF
= AL_REVERB_DEFAULT_GAINHF
;
98 effect
->Props
.Reverb
.GainLF
= 1.0f
;
99 effect
->Props
.Reverb
.DecayTime
= AL_REVERB_DEFAULT_DECAY_TIME
;
100 effect
->Props
.Reverb
.DecayHFRatio
= AL_REVERB_DEFAULT_DECAY_HFRATIO
;
101 effect
->Props
.Reverb
.DecayLFRatio
= 1.0f
;
102 effect
->Props
.Reverb
.ReflectionsGain
= AL_REVERB_DEFAULT_REFLECTIONS_GAIN
;
103 effect
->Props
.Reverb
.ReflectionsDelay
= AL_REVERB_DEFAULT_REFLECTIONS_DELAY
;
104 effect
->Props
.Reverb
.ReflectionsPan
[0] = 0.0f
;
105 effect
->Props
.Reverb
.ReflectionsPan
[1] = 0.0f
;
106 effect
->Props
.Reverb
.ReflectionsPan
[2] = 0.0f
;
107 effect
->Props
.Reverb
.LateReverbGain
= AL_REVERB_DEFAULT_LATE_REVERB_GAIN
;
108 effect
->Props
.Reverb
.LateReverbDelay
= AL_REVERB_DEFAULT_LATE_REVERB_DELAY
;
109 effect
->Props
.Reverb
.LateReverbPan
[0] = 0.0f
;
110 effect
->Props
.Reverb
.LateReverbPan
[1] = 0.0f
;
111 effect
->Props
.Reverb
.LateReverbPan
[2] = 0.0f
;
112 effect
->Props
.Reverb
.EchoTime
= 0.25f
;
113 effect
->Props
.Reverb
.EchoDepth
= 0.0f
;
114 effect
->Props
.Reverb
.ModulationTime
= 0.25f
;
115 effect
->Props
.Reverb
.ModulationDepth
= 0.0f
;
116 effect
->Props
.Reverb
.AirAbsorptionGainHF
= AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF
;
117 effect
->Props
.Reverb
.HFReference
= 5000.0f
;
118 effect
->Props
.Reverb
.LFReference
= 250.0f
;
119 effect
->Props
.Reverb
.RoomRolloffFactor
= AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR
;
120 effect
->Props
.Reverb
.DecayHFLimit
= AL_REVERB_DEFAULT_DECAY_HFLIMIT
;
121 effect
->vtab
= &ALreverb_vtable
;
123 case AL_EFFECT_AUTOWAH
:
124 effect
->Props
.Autowah
.AttackTime
= AL_AUTOWAH_DEFAULT_ATTACK_TIME
;
125 effect
->Props
.Autowah
.ReleaseTime
= AL_AUTOWAH_DEFAULT_RELEASE_TIME
;
126 effect
->Props
.Autowah
.Resonance
= AL_AUTOWAH_DEFAULT_RESONANCE
;
127 effect
->Props
.Autowah
.PeakGain
= AL_AUTOWAH_DEFAULT_PEAK_GAIN
;
128 effect
->vtab
= &ALautowah_vtable
;
130 case AL_EFFECT_CHORUS
:
131 effect
->Props
.Chorus
.Waveform
= AL_CHORUS_DEFAULT_WAVEFORM
;
132 effect
->Props
.Chorus
.Phase
= AL_CHORUS_DEFAULT_PHASE
;
133 effect
->Props
.Chorus
.Rate
= AL_CHORUS_DEFAULT_RATE
;
134 effect
->Props
.Chorus
.Depth
= AL_CHORUS_DEFAULT_DEPTH
;
135 effect
->Props
.Chorus
.Feedback
= AL_CHORUS_DEFAULT_FEEDBACK
;
136 effect
->Props
.Chorus
.Delay
= AL_CHORUS_DEFAULT_DELAY
;
137 effect
->vtab
= &ALchorus_vtable
;
139 case AL_EFFECT_COMPRESSOR
:
140 effect
->Props
.Compressor
.OnOff
= AL_COMPRESSOR_DEFAULT_ONOFF
;
141 effect
->vtab
= &ALcompressor_vtable
;
143 case AL_EFFECT_DISTORTION
:
144 effect
->Props
.Distortion
.Edge
= AL_DISTORTION_DEFAULT_EDGE
;
145 effect
->Props
.Distortion
.Gain
= AL_DISTORTION_DEFAULT_GAIN
;
146 effect
->Props
.Distortion
.LowpassCutoff
= AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF
;
147 effect
->Props
.Distortion
.EQCenter
= AL_DISTORTION_DEFAULT_EQCENTER
;
148 effect
->Props
.Distortion
.EQBandwidth
= AL_DISTORTION_DEFAULT_EQBANDWIDTH
;
149 effect
->vtab
= &ALdistortion_vtable
;
152 effect
->Props
.Echo
.Delay
= AL_ECHO_DEFAULT_DELAY
;
153 effect
->Props
.Echo
.LRDelay
= AL_ECHO_DEFAULT_LRDELAY
;
154 effect
->Props
.Echo
.Damping
= AL_ECHO_DEFAULT_DAMPING
;
155 effect
->Props
.Echo
.Feedback
= AL_ECHO_DEFAULT_FEEDBACK
;
156 effect
->Props
.Echo
.Spread
= AL_ECHO_DEFAULT_SPREAD
;
157 effect
->vtab
= &ALecho_vtable
;
159 case AL_EFFECT_EQUALIZER
:
160 effect
->Props
.Equalizer
.LowCutoff
= AL_EQUALIZER_DEFAULT_LOW_CUTOFF
;
161 effect
->Props
.Equalizer
.LowGain
= AL_EQUALIZER_DEFAULT_LOW_GAIN
;
162 effect
->Props
.Equalizer
.Mid1Center
= AL_EQUALIZER_DEFAULT_MID1_CENTER
;
163 effect
->Props
.Equalizer
.Mid1Gain
= AL_EQUALIZER_DEFAULT_MID1_GAIN
;
164 effect
->Props
.Equalizer
.Mid1Width
= AL_EQUALIZER_DEFAULT_MID1_WIDTH
;
165 effect
->Props
.Equalizer
.Mid2Center
= AL_EQUALIZER_DEFAULT_MID2_CENTER
;
166 effect
->Props
.Equalizer
.Mid2Gain
= AL_EQUALIZER_DEFAULT_MID2_GAIN
;
167 effect
->Props
.Equalizer
.Mid2Width
= AL_EQUALIZER_DEFAULT_MID2_WIDTH
;
168 effect
->Props
.Equalizer
.HighCutoff
= AL_EQUALIZER_DEFAULT_HIGH_CUTOFF
;
169 effect
->Props
.Equalizer
.HighGain
= AL_EQUALIZER_DEFAULT_HIGH_GAIN
;
170 effect
->vtab
= &ALequalizer_vtable
;
172 case AL_EFFECT_FLANGER
:
173 effect
->Props
.Chorus
.Waveform
= AL_FLANGER_DEFAULT_WAVEFORM
;
174 effect
->Props
.Chorus
.Phase
= AL_FLANGER_DEFAULT_PHASE
;
175 effect
->Props
.Chorus
.Rate
= AL_FLANGER_DEFAULT_RATE
;
176 effect
->Props
.Chorus
.Depth
= AL_FLANGER_DEFAULT_DEPTH
;
177 effect
->Props
.Chorus
.Feedback
= AL_FLANGER_DEFAULT_FEEDBACK
;
178 effect
->Props
.Chorus
.Delay
= AL_FLANGER_DEFAULT_DELAY
;
179 effect
->vtab
= &ALflanger_vtable
;
181 case AL_EFFECT_FREQUENCY_SHIFTER
:
182 effect
->Props
.Fshifter
.Frequency
= AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY
;
183 effect
->Props
.Fshifter
.LeftDirection
= AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION
;
184 effect
->Props
.Fshifter
.RightDirection
= AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION
;
185 effect
->vtab
= &ALfshifter_vtable
;
187 case AL_EFFECT_RING_MODULATOR
:
188 effect
->Props
.Modulator
.Frequency
= AL_RING_MODULATOR_DEFAULT_FREQUENCY
;
189 effect
->Props
.Modulator
.HighPassCutoff
= AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF
;
190 effect
->Props
.Modulator
.Waveform
= AL_RING_MODULATOR_DEFAULT_WAVEFORM
;
191 effect
->vtab
= &ALmodulator_vtable
;
193 case AL_EFFECT_PITCH_SHIFTER
:
194 effect
->Props
.Pshifter
.CoarseTune
= AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE
;
195 effect
->Props
.Pshifter
.FineTune
= AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE
;
196 effect
->vtab
= &ALpshifter_vtable
;
198 case AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
:
199 case AL_EFFECT_DEDICATED_DIALOGUE
:
200 effect
->Props
.Dedicated
.Gain
= 1.0f
;
201 effect
->vtab
= &ALdedicated_vtable
;
204 effect
->vtab
= &ALnull_vtable
;
210 ALeffect
*AllocEffect(ALCcontext
*context
)
212 ALCdevice
*device
{context
->Device
};
213 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
214 auto sublist
= std::find_if(device
->EffectList
.begin(), device
->EffectList
.end(),
215 [](const EffectSubList
&entry
) noexcept
-> bool
216 { return entry
.FreeMask
!= 0; }
219 auto lidx
= static_cast<ALsizei
>(std::distance(device
->EffectList
.begin(), sublist
));
220 ALeffect
*effect
{nullptr};
222 if(LIKELY(sublist
!= device
->EffectList
.end()))
224 slidx
= CTZ64(sublist
->FreeMask
);
225 effect
= sublist
->Effects
+ slidx
;
229 /* Don't allocate so many list entries that the 32-bit ID could
232 if(UNLIKELY(device
->EffectList
.size() >= 1<<25))
234 alSetError(context
, AL_OUT_OF_MEMORY
, "Too many effects allocated");
237 device
->EffectList
.emplace_back();
238 sublist
= device
->EffectList
.end() - 1;
239 sublist
->FreeMask
= ~0_u64
;
240 sublist
->Effects
= static_cast<ALeffect
*>(al_calloc(16, sizeof(ALeffect
)*64));
241 if(UNLIKELY(!sublist
->Effects
))
243 device
->EffectList
.pop_back();
244 alSetError(context
, AL_OUT_OF_MEMORY
, "Failed to allocate effect batch");
249 effect
= sublist
->Effects
+ slidx
;
252 effect
= new (effect
) ALeffect
{};
253 InitEffectParams(effect
, AL_EFFECT_NULL
);
255 /* Add 1 to avoid effect ID 0. */
256 effect
->id
= ((lidx
<<6) | slidx
) + 1;
258 sublist
->FreeMask
&= ~(1_u64
<< slidx
);
263 void FreeEffect(ALCdevice
*device
, ALeffect
*effect
)
265 ALuint id
= effect
->id
- 1;
266 ALsizei lidx
= id
>> 6;
267 ALsizei slidx
= id
& 0x3f;
271 device
->EffectList
[lidx
].FreeMask
|= 1_u64
<< slidx
;
274 inline ALeffect
*LookupEffect(ALCdevice
*device
, ALuint id
)
276 ALuint lidx
= (id
-1) >> 6;
277 ALsizei slidx
= (id
-1) & 0x3f;
279 if(UNLIKELY(lidx
>= device
->EffectList
.size()))
281 EffectSubList
&sublist
= device
->EffectList
[lidx
];
282 if(UNLIKELY(sublist
.FreeMask
& (1_u64
<< slidx
)))
284 return sublist
.Effects
+ slidx
;
289 AL_API ALvoid AL_APIENTRY
alGenEffects(ALsizei n
, ALuint
*effects
)
291 ContextRef context
{GetContextRef()};
292 if(UNLIKELY(!context
)) return;
296 alSetError(context
.get(), AL_INVALID_VALUE
, "Generating %d effects", n
);
302 /* Special handling for the easy and normal case. */
303 ALeffect
*effect
= AllocEffect(context
.get());
304 if(effect
) effects
[0] = effect
->id
;
308 /* Store the allocated buffer IDs in a separate local list, to avoid
309 * modifying the user storage in case of failure.
311 al::vector
<ALuint
> ids
;
314 ALeffect
*effect
= AllocEffect(context
.get());
317 alDeleteEffects(static_cast<ALsizei
>(ids
.size()), ids
.data());
321 ids
.emplace_back(effect
->id
);
323 std::copy(ids
.begin(), ids
.end(), effects
);
327 AL_API ALvoid AL_APIENTRY
alDeleteEffects(ALsizei n
, const ALuint
*effects
)
329 ContextRef context
{GetContextRef()};
330 if(UNLIKELY(!context
)) return;
334 alSetError(context
.get(), AL_INVALID_VALUE
, "Deleting %d effects", n
);
340 ALCdevice
*device
{context
->Device
};
341 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
343 /* First try to find any effects that are invalid. */
344 const ALuint
*effects_end
= effects
+ n
;
345 auto inveffect
= std::find_if(effects
, effects_end
,
346 [device
, &context
](ALuint eid
) -> bool
348 if(!eid
) return false;
349 ALeffect
*effect
{LookupEffect(device
, eid
)};
350 if(UNLIKELY(!effect
))
352 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid effect ID %u", eid
);
358 if(LIKELY(inveffect
== effects_end
))
360 /* All good. Delete non-0 effect IDs. */
361 std::for_each(effects
, effects_end
,
362 [device
](ALuint eid
) -> void
364 ALeffect
*effect
{eid
? LookupEffect(device
, eid
) : nullptr};
365 if(effect
) FreeEffect(device
, effect
);
371 AL_API ALboolean AL_APIENTRY
alIsEffect(ALuint effect
)
373 ContextRef context
{GetContextRef()};
376 ALCdevice
*device
{context
->Device
};
377 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
378 if(!effect
|| LookupEffect(device
, effect
))
384 AL_API ALvoid AL_APIENTRY
alEffecti(ALuint effect
, ALenum param
, ALint value
)
386 ContextRef context
{GetContextRef()};
387 if(UNLIKELY(!context
)) return;
389 ALCdevice
*device
{context
->Device
};
390 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
392 ALeffect
*aleffect
{LookupEffect(device
, effect
)};
393 if(UNLIKELY(!aleffect
))
394 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
397 if(param
== AL_EFFECT_TYPE
)
399 ALboolean isOk
= (value
== AL_EFFECT_NULL
);
400 for(size_t i
{0u};!isOk
&& i
< countof(gEffectList
);i
++)
402 if(value
== gEffectList
[i
].val
&& !DisabledEffects
[gEffectList
[i
].type
])
407 InitEffectParams(aleffect
, value
);
409 alSetError(context
.get(), AL_INVALID_VALUE
, "Effect type 0x%04x not supported", value
);
413 /* Call the appropriate handler */
414 ALeffect_setParami(aleffect
, context
.get(), param
, value
);
419 AL_API ALvoid AL_APIENTRY
alEffectiv(ALuint effect
, ALenum param
, const ALint
*values
)
424 alEffecti(effect
, param
, values
[0]);
428 ContextRef context
{GetContextRef()};
429 if(UNLIKELY(!context
)) return;
431 ALCdevice
*device
{context
->Device
};
432 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
434 ALeffect
*aleffect
{LookupEffect(device
, effect
)};
435 if(UNLIKELY(!aleffect
))
436 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
439 /* Call the appropriate handler */
440 ALeffect_setParamiv(aleffect
, context
.get(), param
, values
);
444 AL_API ALvoid AL_APIENTRY
alEffectf(ALuint effect
, ALenum param
, ALfloat value
)
446 ContextRef context
{GetContextRef()};
447 if(UNLIKELY(!context
)) return;
449 ALCdevice
*device
{context
->Device
};
450 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
452 ALeffect
*aleffect
{LookupEffect(device
, effect
)};
453 if(UNLIKELY(!aleffect
))
454 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
457 /* Call the appropriate handler */
458 ALeffect_setParamf(aleffect
, context
.get(), param
, value
);
462 AL_API ALvoid AL_APIENTRY
alEffectfv(ALuint effect
, ALenum param
, const ALfloat
*values
)
464 ContextRef context
{GetContextRef()};
465 if(UNLIKELY(!context
)) return;
467 ALCdevice
*device
{context
->Device
};
468 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
470 ALeffect
*aleffect
{LookupEffect(device
, effect
)};
471 if(UNLIKELY(!aleffect
))
472 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
475 /* Call the appropriate handler */
476 ALeffect_setParamfv(aleffect
, context
.get(), param
, values
);
480 AL_API ALvoid AL_APIENTRY
alGetEffecti(ALuint effect
, ALenum param
, ALint
*value
)
482 ContextRef context
{GetContextRef()};
483 if(UNLIKELY(!context
)) return;
485 ALCdevice
*device
{context
->Device
};
486 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
488 const ALeffect
*aleffect
{LookupEffect(device
, effect
)};
489 if(UNLIKELY(!aleffect
))
490 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
493 if(param
== AL_EFFECT_TYPE
)
494 *value
= aleffect
->type
;
497 /* Call the appropriate handler */
498 ALeffect_getParami(aleffect
, context
.get(), param
, value
);
503 AL_API ALvoid AL_APIENTRY
alGetEffectiv(ALuint effect
, ALenum param
, ALint
*values
)
508 alGetEffecti(effect
, param
, values
);
512 ContextRef context
{GetContextRef()};
513 if(UNLIKELY(!context
)) return;
515 ALCdevice
*device
{context
->Device
};
516 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
518 const ALeffect
*aleffect
{LookupEffect(device
, effect
)};
519 if(UNLIKELY(!aleffect
))
520 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
523 /* Call the appropriate handler */
524 ALeffect_getParamiv(aleffect
, context
.get(), param
, values
);
528 AL_API ALvoid AL_APIENTRY
alGetEffectf(ALuint effect
, ALenum param
, ALfloat
*value
)
530 ContextRef context
{GetContextRef()};
531 if(UNLIKELY(!context
)) return;
533 ALCdevice
*device
{context
->Device
};
534 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
536 const ALeffect
*aleffect
{LookupEffect(device
, effect
)};
537 if(UNLIKELY(!aleffect
))
538 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
541 /* Call the appropriate handler */
542 ALeffect_getParamf(aleffect
, context
.get(), param
, value
);
546 AL_API ALvoid AL_APIENTRY
alGetEffectfv(ALuint effect
, ALenum param
, ALfloat
*values
)
548 ContextRef context
{GetContextRef()};
549 if(UNLIKELY(!context
)) return;
551 ALCdevice
*device
{context
->Device
};
552 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
554 const ALeffect
*aleffect
{LookupEffect(device
, effect
)};
555 if(UNLIKELY(!aleffect
))
556 alSetError(context
.get(), AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
559 /* Call the appropriate handler */
560 ALeffect_getParamfv(aleffect
, context
.get(), param
, values
);
565 void InitEffect(ALeffect
*effect
)
567 InitEffectParams(effect
, AL_EFFECT_NULL
);
570 EffectSubList::~EffectSubList()
572 ALuint64 usemask
= ~FreeMask
;
575 ALsizei idx
= CTZ64(usemask
);
576 Effects
[idx
].~ALeffect();
577 usemask
&= ~(1_u64
<< idx
);
585 #include "AL/efx-presets.h"
587 #define DECL(x) { #x, EFX_REVERB_PRESET_##x }
588 static const struct {
590 EFXEAXREVERBPROPERTIES props
;
603 DECL(CARPETEDHALLWAY
),
619 DECL(CASTLE_SMALLROOM
),
620 DECL(CASTLE_SHORTPASSAGE
),
621 DECL(CASTLE_MEDIUMROOM
),
622 DECL(CASTLE_LARGEROOM
),
623 DECL(CASTLE_LONGPASSAGE
),
625 DECL(CASTLE_CUPBOARD
),
626 DECL(CASTLE_COURTYARD
),
629 DECL(FACTORY_SMALLROOM
),
630 DECL(FACTORY_SHORTPASSAGE
),
631 DECL(FACTORY_MEDIUMROOM
),
632 DECL(FACTORY_LARGEROOM
),
633 DECL(FACTORY_LONGPASSAGE
),
635 DECL(FACTORY_CUPBOARD
),
636 DECL(FACTORY_COURTYARD
),
637 DECL(FACTORY_ALCOVE
),
639 DECL(ICEPALACE_SMALLROOM
),
640 DECL(ICEPALACE_SHORTPASSAGE
),
641 DECL(ICEPALACE_MEDIUMROOM
),
642 DECL(ICEPALACE_LARGEROOM
),
643 DECL(ICEPALACE_LONGPASSAGE
),
644 DECL(ICEPALACE_HALL
),
645 DECL(ICEPALACE_CUPBOARD
),
646 DECL(ICEPALACE_COURTYARD
),
647 DECL(ICEPALACE_ALCOVE
),
649 DECL(SPACESTATION_SMALLROOM
),
650 DECL(SPACESTATION_SHORTPASSAGE
),
651 DECL(SPACESTATION_MEDIUMROOM
),
652 DECL(SPACESTATION_LARGEROOM
),
653 DECL(SPACESTATION_LONGPASSAGE
),
654 DECL(SPACESTATION_HALL
),
655 DECL(SPACESTATION_CUPBOARD
),
656 DECL(SPACESTATION_ALCOVE
),
658 DECL(WOODEN_SMALLROOM
),
659 DECL(WOODEN_SHORTPASSAGE
),
660 DECL(WOODEN_MEDIUMROOM
),
661 DECL(WOODEN_LARGEROOM
),
662 DECL(WOODEN_LONGPASSAGE
),
664 DECL(WOODEN_CUPBOARD
),
665 DECL(WOODEN_COURTYARD
),
668 DECL(SPORT_EMPTYSTADIUM
),
669 DECL(SPORT_SQUASHCOURT
),
670 DECL(SPORT_SMALLSWIMMINGPOOL
),
671 DECL(SPORT_LARGESWIMMINGPOOL
),
672 DECL(SPORT_GYMNASIUM
),
673 DECL(SPORT_FULLSTADIUM
),
674 DECL(SPORT_STADIUMTANNOY
),
676 DECL(PREFAB_WORKSHOP
),
677 DECL(PREFAB_SCHOOLROOM
),
678 DECL(PREFAB_PRACTISEROOM
),
679 DECL(PREFAB_OUTHOUSE
),
680 DECL(PREFAB_CARAVAN
),
684 DECL(DOME_SAINTPAULS
),
689 DECL(OUTDOORS_BACKYARD
),
690 DECL(OUTDOORS_ROLLINGPLAINS
),
691 DECL(OUTDOORS_DEEPCANYON
),
692 DECL(OUTDOORS_CREEK
),
693 DECL(OUTDOORS_VALLEY
),
699 DECL(DRIVING_COMMENTATOR
),
700 DECL(DRIVING_PITGARAGE
),
701 DECL(DRIVING_INCAR_RACER
),
702 DECL(DRIVING_INCAR_SPORTS
),
703 DECL(DRIVING_INCAR_LUXURY
),
704 DECL(DRIVING_FULLGRANDSTAND
),
705 DECL(DRIVING_EMPTYGRANDSTAND
),
706 DECL(DRIVING_TUNNEL
),
712 DECL(CITY_UNDERPASS
),
713 DECL(CITY_ABANDONED
),
717 DECL(SMALLWATERROOM
),
721 void LoadReverbPreset(const char *name
, ALeffect
*effect
)
725 if(strcasecmp(name
, "NONE") == 0)
727 InitEffectParams(effect
, AL_EFFECT_NULL
);
728 TRACE("Loading reverb '%s'\n", "NONE");
732 if(!DisabledEffects
[EAXREVERB_EFFECT
])
733 InitEffectParams(effect
, AL_EFFECT_EAXREVERB
);
734 else if(!DisabledEffects
[REVERB_EFFECT
])
735 InitEffectParams(effect
, AL_EFFECT_REVERB
);
737 InitEffectParams(effect
, AL_EFFECT_NULL
);
738 for(i
= 0;i
< COUNTOF(reverblist
);i
++)
740 const EFXEAXREVERBPROPERTIES
*props
;
742 if(strcasecmp(name
, reverblist
[i
].name
) != 0)
745 TRACE("Loading reverb '%s'\n", reverblist
[i
].name
);
746 props
= &reverblist
[i
].props
;
747 effect
->Props
.Reverb
.Density
= props
->flDensity
;
748 effect
->Props
.Reverb
.Diffusion
= props
->flDiffusion
;
749 effect
->Props
.Reverb
.Gain
= props
->flGain
;
750 effect
->Props
.Reverb
.GainHF
= props
->flGainHF
;
751 effect
->Props
.Reverb
.GainLF
= props
->flGainLF
;
752 effect
->Props
.Reverb
.DecayTime
= props
->flDecayTime
;
753 effect
->Props
.Reverb
.DecayHFRatio
= props
->flDecayHFRatio
;
754 effect
->Props
.Reverb
.DecayLFRatio
= props
->flDecayLFRatio
;
755 effect
->Props
.Reverb
.ReflectionsGain
= props
->flReflectionsGain
;
756 effect
->Props
.Reverb
.ReflectionsDelay
= props
->flReflectionsDelay
;
757 effect
->Props
.Reverb
.ReflectionsPan
[0] = props
->flReflectionsPan
[0];
758 effect
->Props
.Reverb
.ReflectionsPan
[1] = props
->flReflectionsPan
[1];
759 effect
->Props
.Reverb
.ReflectionsPan
[2] = props
->flReflectionsPan
[2];
760 effect
->Props
.Reverb
.LateReverbGain
= props
->flLateReverbGain
;
761 effect
->Props
.Reverb
.LateReverbDelay
= props
->flLateReverbDelay
;
762 effect
->Props
.Reverb
.LateReverbPan
[0] = props
->flLateReverbPan
[0];
763 effect
->Props
.Reverb
.LateReverbPan
[1] = props
->flLateReverbPan
[1];
764 effect
->Props
.Reverb
.LateReverbPan
[2] = props
->flLateReverbPan
[2];
765 effect
->Props
.Reverb
.EchoTime
= props
->flEchoTime
;
766 effect
->Props
.Reverb
.EchoDepth
= props
->flEchoDepth
;
767 effect
->Props
.Reverb
.ModulationTime
= props
->flModulationTime
;
768 effect
->Props
.Reverb
.ModulationDepth
= props
->flModulationDepth
;
769 effect
->Props
.Reverb
.AirAbsorptionGainHF
= props
->flAirAbsorptionGainHF
;
770 effect
->Props
.Reverb
.HFReference
= props
->flHFReference
;
771 effect
->Props
.Reverb
.LFReference
= props
->flLFReference
;
772 effect
->Props
.Reverb
.RoomRolloffFactor
= props
->flRoomRolloffFactor
;
773 effect
->Props
.Reverb
.DecayHFLimit
= props
->iDecayHFLimit
;
777 WARN("Reverb preset '%s' not found\n", name
);