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
38 #include "AL/efx-presets.h"
42 #include "alc/context.h"
43 #include "alc/device.h"
44 #include "alc/effects/base.h"
45 #include "alc/inprogext.h"
47 #include "alnumeric.h"
49 #include "core/except.h"
50 #include "core/logging.h"
51 #include "opthelpers.h"
57 #include "eax_exception.h"
60 const EffectList gEffectList
[16]{
61 { "eaxreverb", EAXREVERB_EFFECT
, AL_EFFECT_EAXREVERB
},
62 { "reverb", REVERB_EFFECT
, AL_EFFECT_REVERB
},
63 { "autowah", AUTOWAH_EFFECT
, AL_EFFECT_AUTOWAH
},
64 { "chorus", CHORUS_EFFECT
, AL_EFFECT_CHORUS
},
65 { "compressor", COMPRESSOR_EFFECT
, AL_EFFECT_COMPRESSOR
},
66 { "distortion", DISTORTION_EFFECT
, AL_EFFECT_DISTORTION
},
67 { "echo", ECHO_EFFECT
, AL_EFFECT_ECHO
},
68 { "equalizer", EQUALIZER_EFFECT
, AL_EFFECT_EQUALIZER
},
69 { "flanger", FLANGER_EFFECT
, AL_EFFECT_FLANGER
},
70 { "fshifter", FSHIFTER_EFFECT
, AL_EFFECT_FREQUENCY_SHIFTER
},
71 { "modulator", MODULATOR_EFFECT
, AL_EFFECT_RING_MODULATOR
},
72 { "pshifter", PSHIFTER_EFFECT
, AL_EFFECT_PITCH_SHIFTER
},
73 { "vmorpher", VMORPHER_EFFECT
, AL_EFFECT_VOCAL_MORPHER
},
74 { "dedicated", DEDICATED_EFFECT
, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
},
75 { "dedicated", DEDICATED_EFFECT
, AL_EFFECT_DEDICATED_DIALOGUE
},
76 { "convolution", CONVOLUTION_EFFECT
, AL_EFFECT_CONVOLUTION_REVERB_SOFT
},
79 bool DisabledEffects
[MAX_EFFECTS
];
82 effect_exception::effect_exception(ALenum code
, const char *msg
, ...) : mErrorCode
{code
}
86 setMessage(msg
, args
);
92 struct EffectPropsItem
{
94 const EffectProps
&DefaultProps
;
95 const EffectVtable
&Vtable
;
97 constexpr EffectPropsItem EffectPropsList
[] = {
98 { AL_EFFECT_NULL
, NullEffectProps
, NullEffectVtable
},
99 { AL_EFFECT_EAXREVERB
, ReverbEffectProps
, ReverbEffectVtable
},
100 { AL_EFFECT_REVERB
, StdReverbEffectProps
, StdReverbEffectVtable
},
101 { AL_EFFECT_AUTOWAH
, AutowahEffectProps
, AutowahEffectVtable
},
102 { AL_EFFECT_CHORUS
, ChorusEffectProps
, ChorusEffectVtable
},
103 { AL_EFFECT_COMPRESSOR
, CompressorEffectProps
, CompressorEffectVtable
},
104 { AL_EFFECT_DISTORTION
, DistortionEffectProps
, DistortionEffectVtable
},
105 { AL_EFFECT_ECHO
, EchoEffectProps
, EchoEffectVtable
},
106 { AL_EFFECT_EQUALIZER
, EqualizerEffectProps
, EqualizerEffectVtable
},
107 { AL_EFFECT_FLANGER
, FlangerEffectProps
, FlangerEffectVtable
},
108 { AL_EFFECT_FREQUENCY_SHIFTER
, FshifterEffectProps
, FshifterEffectVtable
},
109 { AL_EFFECT_RING_MODULATOR
, ModulatorEffectProps
, ModulatorEffectVtable
},
110 { AL_EFFECT_PITCH_SHIFTER
, PshifterEffectProps
, PshifterEffectVtable
},
111 { AL_EFFECT_VOCAL_MORPHER
, VmorpherEffectProps
, VmorpherEffectVtable
},
112 { AL_EFFECT_DEDICATED_DIALOGUE
, DedicatedEffectProps
, DedicatedEffectVtable
},
113 { AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
, DedicatedEffectProps
, DedicatedEffectVtable
},
114 { AL_EFFECT_CONVOLUTION_REVERB_SOFT
, ConvolutionEffectProps
, ConvolutionEffectVtable
},
118 void ALeffect_setParami(ALeffect
*effect
, ALenum param
, int value
)
119 { effect
->vtab
->setParami(&effect
->Props
, param
, value
); }
120 void ALeffect_setParamiv(ALeffect
*effect
, ALenum param
, const int *values
)
121 { effect
->vtab
->setParamiv(&effect
->Props
, param
, values
); }
122 void ALeffect_setParamf(ALeffect
*effect
, ALenum param
, float value
)
123 { effect
->vtab
->setParamf(&effect
->Props
, param
, value
); }
124 void ALeffect_setParamfv(ALeffect
*effect
, ALenum param
, const float *values
)
125 { effect
->vtab
->setParamfv(&effect
->Props
, param
, values
); }
127 void ALeffect_getParami(const ALeffect
*effect
, ALenum param
, int *value
)
128 { effect
->vtab
->getParami(&effect
->Props
, param
, value
); }
129 void ALeffect_getParamiv(const ALeffect
*effect
, ALenum param
, int *values
)
130 { effect
->vtab
->getParamiv(&effect
->Props
, param
, values
); }
131 void ALeffect_getParamf(const ALeffect
*effect
, ALenum param
, float *value
)
132 { effect
->vtab
->getParamf(&effect
->Props
, param
, value
); }
133 void ALeffect_getParamfv(const ALeffect
*effect
, ALenum param
, float *values
)
134 { effect
->vtab
->getParamfv(&effect
->Props
, param
, values
); }
137 const EffectPropsItem
*getEffectPropsItemByType(ALenum type
)
139 auto iter
= std::find_if(std::begin(EffectPropsList
), std::end(EffectPropsList
),
140 [type
](const EffectPropsItem
&item
) noexcept
-> bool
141 { return item
.Type
== type
; });
142 return (iter
!= std::end(EffectPropsList
)) ? std::addressof(*iter
) : nullptr;
145 void InitEffectParams(ALeffect
*effect
, ALenum type
)
147 const EffectPropsItem
*item
{getEffectPropsItemByType(type
)};
150 effect
->Props
= item
->DefaultProps
;
151 effect
->vtab
= &item
->Vtable
;
155 effect
->Props
= EffectProps
{};
156 effect
->vtab
= &NullEffectVtable
;
161 bool EnsureEffects(ALCdevice
*device
, size_t needed
)
163 size_t count
{std::accumulate(device
->EffectList
.cbegin(), device
->EffectList
.cend(), size_t{0},
164 [](size_t cur
, const EffectSubList
&sublist
) noexcept
-> size_t
165 { return cur
+ static_cast<ALuint
>(al::popcount(sublist
.FreeMask
)); })};
167 while(needed
> count
)
169 if UNLIKELY(device
->EffectList
.size() >= 1<<25)
172 device
->EffectList
.emplace_back();
173 auto sublist
= device
->EffectList
.end() - 1;
174 sublist
->FreeMask
= ~0_u64
;
175 sublist
->Effects
= static_cast<ALeffect
*>(al_calloc(alignof(ALeffect
), sizeof(ALeffect
)*64));
176 if UNLIKELY(!sublist
->Effects
)
178 device
->EffectList
.pop_back();
186 ALeffect
*AllocEffect(ALCdevice
*device
)
188 auto sublist
= std::find_if(device
->EffectList
.begin(), device
->EffectList
.end(),
189 [](const EffectSubList
&entry
) noexcept
-> bool
190 { return entry
.FreeMask
!= 0; });
191 auto lidx
= static_cast<ALuint
>(std::distance(device
->EffectList
.begin(), sublist
));
192 auto slidx
= static_cast<ALuint
>(al::countr_zero(sublist
->FreeMask
));
195 ALeffect
*effect
{al::construct_at(sublist
->Effects
+ slidx
)};
196 InitEffectParams(effect
, AL_EFFECT_NULL
);
198 /* Add 1 to avoid effect ID 0. */
199 effect
->id
= ((lidx
<<6) | slidx
) + 1;
201 sublist
->FreeMask
&= ~(1_u64
<< slidx
);
206 void FreeEffect(ALCdevice
*device
, ALeffect
*effect
)
208 const ALuint id
{effect
->id
- 1};
209 const size_t lidx
{id
>> 6};
210 const ALuint slidx
{id
& 0x3f};
212 al::destroy_at(effect
);
214 device
->EffectList
[lidx
].FreeMask
|= 1_u64
<< slidx
;
217 inline ALeffect
*LookupEffect(ALCdevice
*device
, ALuint id
)
219 const size_t lidx
{(id
-1) >> 6};
220 const ALuint slidx
{(id
-1) & 0x3f};
222 if UNLIKELY(lidx
>= device
->EffectList
.size())
224 EffectSubList
&sublist
= device
->EffectList
[lidx
];
225 if UNLIKELY(sublist
.FreeMask
& (1_u64
<< slidx
))
227 return sublist
.Effects
+ slidx
;
232 AL_API
void AL_APIENTRY
alGenEffects(ALsizei n
, ALuint
*effects
)
235 ContextRef context
{GetContextRef()};
236 if UNLIKELY(!context
) return;
239 context
->setError(AL_INVALID_VALUE
, "Generating %d effects", n
);
240 if UNLIKELY(n
<= 0) return;
242 ALCdevice
*device
{context
->mALDevice
.get()};
243 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
244 if(!EnsureEffects(device
, static_cast<ALuint
>(n
)))
246 context
->setError(AL_OUT_OF_MEMORY
, "Failed to allocate %d effect%s", n
, (n
==1)?"":"s");
252 /* Special handling for the easy and normal case. */
253 ALeffect
*effect
{AllocEffect(device
)};
254 effects
[0] = effect
->id
;
258 /* Store the allocated buffer IDs in a separate local list, to avoid
259 * modifying the user storage in case of failure.
261 al::vector
<ALuint
> ids
;
262 ids
.reserve(static_cast<ALuint
>(n
));
264 ALeffect
*effect
{AllocEffect(device
)};
265 ids
.emplace_back(effect
->id
);
267 std::copy(ids
.cbegin(), ids
.cend(), effects
);
272 AL_API
void AL_APIENTRY
alDeleteEffects(ALsizei n
, const ALuint
*effects
)
275 ContextRef context
{GetContextRef()};
276 if UNLIKELY(!context
) return;
279 context
->setError(AL_INVALID_VALUE
, "Deleting %d effects", n
);
280 if UNLIKELY(n
<= 0) return;
282 ALCdevice
*device
{context
->mALDevice
.get()};
283 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
285 /* First try to find any effects that are invalid. */
286 auto validate_effect
= [device
](const ALuint eid
) -> bool
287 { return !eid
|| LookupEffect(device
, eid
) != nullptr; };
289 const ALuint
*effects_end
= effects
+ n
;
290 auto inveffect
= std::find_if_not(effects
, effects_end
, validate_effect
);
291 if UNLIKELY(inveffect
!= effects_end
)
293 context
->setError(AL_INVALID_NAME
, "Invalid effect ID %u", *inveffect
);
297 /* All good. Delete non-0 effect IDs. */
298 auto delete_effect
= [device
](ALuint eid
) -> void
300 ALeffect
*effect
{eid
? LookupEffect(device
, eid
) : nullptr};
301 if(effect
) FreeEffect(device
, effect
);
303 std::for_each(effects
, effects_end
, delete_effect
);
307 AL_API ALboolean AL_APIENTRY
alIsEffect(ALuint effect
)
310 ContextRef context
{GetContextRef()};
313 ALCdevice
*device
{context
->mALDevice
.get()};
314 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
315 if(!effect
|| LookupEffect(device
, effect
))
322 AL_API
void AL_APIENTRY
alEffecti(ALuint effect
, ALenum param
, ALint value
)
325 ContextRef context
{GetContextRef()};
326 if UNLIKELY(!context
) return;
328 ALCdevice
*device
{context
->mALDevice
.get()};
329 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
331 ALeffect
*aleffect
{LookupEffect(device
, effect
)};
332 if UNLIKELY(!aleffect
)
333 context
->setError(AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
334 else if(param
== AL_EFFECT_TYPE
)
336 bool isOk
{value
== AL_EFFECT_NULL
};
339 for(const EffectList
&effectitem
: gEffectList
)
341 if(value
== effectitem
.val
&& !DisabledEffects
[effectitem
.type
])
350 InitEffectParams(aleffect
, value
);
352 context
->setError(AL_INVALID_VALUE
, "Effect type 0x%04x not supported", value
);
356 /* Call the appropriate handler */
357 ALeffect_setParami(aleffect
, param
, value
);
359 catch(effect_exception
&e
) {
360 context
->setError(e
.errorCode(), "%s", e
.what());
365 AL_API
void AL_APIENTRY
alEffectiv(ALuint effect
, ALenum param
, const ALint
*values
)
371 alEffecti(effect
, param
, values
[0]);
375 ContextRef context
{GetContextRef()};
376 if UNLIKELY(!context
) return;
378 ALCdevice
*device
{context
->mALDevice
.get()};
379 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
381 ALeffect
*aleffect
{LookupEffect(device
, effect
)};
382 if UNLIKELY(!aleffect
)
383 context
->setError(AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
386 /* Call the appropriate handler */
387 ALeffect_setParamiv(aleffect
, param
, values
);
389 catch(effect_exception
&e
) {
390 context
->setError(e
.errorCode(), "%s", e
.what());
395 AL_API
void AL_APIENTRY
alEffectf(ALuint effect
, ALenum param
, ALfloat value
)
398 ContextRef context
{GetContextRef()};
399 if UNLIKELY(!context
) return;
401 ALCdevice
*device
{context
->mALDevice
.get()};
402 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
404 ALeffect
*aleffect
{LookupEffect(device
, effect
)};
405 if UNLIKELY(!aleffect
)
406 context
->setError(AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
409 /* Call the appropriate handler */
410 ALeffect_setParamf(aleffect
, param
, value
);
412 catch(effect_exception
&e
) {
413 context
->setError(e
.errorCode(), "%s", e
.what());
418 AL_API
void AL_APIENTRY
alEffectfv(ALuint effect
, ALenum param
, const ALfloat
*values
)
421 ContextRef context
{GetContextRef()};
422 if UNLIKELY(!context
) return;
424 ALCdevice
*device
{context
->mALDevice
.get()};
425 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
427 ALeffect
*aleffect
{LookupEffect(device
, effect
)};
428 if UNLIKELY(!aleffect
)
429 context
->setError(AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
432 /* Call the appropriate handler */
433 ALeffect_setParamfv(aleffect
, param
, values
);
435 catch(effect_exception
&e
) {
436 context
->setError(e
.errorCode(), "%s", e
.what());
441 AL_API
void AL_APIENTRY
alGetEffecti(ALuint effect
, ALenum param
, ALint
*value
)
444 ContextRef context
{GetContextRef()};
445 if UNLIKELY(!context
) return;
447 ALCdevice
*device
{context
->mALDevice
.get()};
448 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
450 const ALeffect
*aleffect
{LookupEffect(device
, effect
)};
451 if UNLIKELY(!aleffect
)
452 context
->setError(AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
453 else if(param
== AL_EFFECT_TYPE
)
454 *value
= aleffect
->type
;
457 /* Call the appropriate handler */
458 ALeffect_getParami(aleffect
, param
, value
);
460 catch(effect_exception
&e
) {
461 context
->setError(e
.errorCode(), "%s", e
.what());
466 AL_API
void AL_APIENTRY
alGetEffectiv(ALuint effect
, ALenum param
, ALint
*values
)
472 alGetEffecti(effect
, param
, values
);
476 ContextRef context
{GetContextRef()};
477 if UNLIKELY(!context
) return;
479 ALCdevice
*device
{context
->mALDevice
.get()};
480 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
482 const ALeffect
*aleffect
{LookupEffect(device
, effect
)};
483 if UNLIKELY(!aleffect
)
484 context
->setError(AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
487 /* Call the appropriate handler */
488 ALeffect_getParamiv(aleffect
, param
, values
);
490 catch(effect_exception
&e
) {
491 context
->setError(e
.errorCode(), "%s", e
.what());
496 AL_API
void AL_APIENTRY
alGetEffectf(ALuint effect
, ALenum param
, ALfloat
*value
)
499 ContextRef context
{GetContextRef()};
500 if UNLIKELY(!context
) return;
502 ALCdevice
*device
{context
->mALDevice
.get()};
503 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
505 const ALeffect
*aleffect
{LookupEffect(device
, effect
)};
506 if UNLIKELY(!aleffect
)
507 context
->setError(AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
510 /* Call the appropriate handler */
511 ALeffect_getParamf(aleffect
, param
, value
);
513 catch(effect_exception
&e
) {
514 context
->setError(e
.errorCode(), "%s", e
.what());
519 AL_API
void AL_APIENTRY
alGetEffectfv(ALuint effect
, ALenum param
, ALfloat
*values
)
522 ContextRef context
{GetContextRef()};
523 if UNLIKELY(!context
) return;
525 ALCdevice
*device
{context
->mALDevice
.get()};
526 std::lock_guard
<std::mutex
> _
{device
->EffectLock
};
528 const ALeffect
*aleffect
{LookupEffect(device
, effect
)};
529 if UNLIKELY(!aleffect
)
530 context
->setError(AL_INVALID_NAME
, "Invalid effect ID %u", effect
);
533 /* Call the appropriate handler */
534 ALeffect_getParamfv(aleffect
, param
, values
);
536 catch(effect_exception
&e
) {
537 context
->setError(e
.errorCode(), "%s", e
.what());
543 void InitEffect(ALeffect
*effect
)
545 InitEffectParams(effect
, AL_EFFECT_NULL
);
548 EffectSubList::~EffectSubList()
550 uint64_t usemask
{~FreeMask
};
553 const int idx
{al::countr_zero(usemask
)};
554 al::destroy_at(Effects
+idx
);
555 usemask
&= ~(1_u64
<< idx
);
563 #define DECL(x) { #x, EFX_REVERB_PRESET_##x }
564 static const struct {
566 EFXEAXREVERBPROPERTIES props
;
579 DECL(CARPETEDHALLWAY
),
595 DECL(CASTLE_SMALLROOM
),
596 DECL(CASTLE_SHORTPASSAGE
),
597 DECL(CASTLE_MEDIUMROOM
),
598 DECL(CASTLE_LARGEROOM
),
599 DECL(CASTLE_LONGPASSAGE
),
601 DECL(CASTLE_CUPBOARD
),
602 DECL(CASTLE_COURTYARD
),
605 DECL(FACTORY_SMALLROOM
),
606 DECL(FACTORY_SHORTPASSAGE
),
607 DECL(FACTORY_MEDIUMROOM
),
608 DECL(FACTORY_LARGEROOM
),
609 DECL(FACTORY_LONGPASSAGE
),
611 DECL(FACTORY_CUPBOARD
),
612 DECL(FACTORY_COURTYARD
),
613 DECL(FACTORY_ALCOVE
),
615 DECL(ICEPALACE_SMALLROOM
),
616 DECL(ICEPALACE_SHORTPASSAGE
),
617 DECL(ICEPALACE_MEDIUMROOM
),
618 DECL(ICEPALACE_LARGEROOM
),
619 DECL(ICEPALACE_LONGPASSAGE
),
620 DECL(ICEPALACE_HALL
),
621 DECL(ICEPALACE_CUPBOARD
),
622 DECL(ICEPALACE_COURTYARD
),
623 DECL(ICEPALACE_ALCOVE
),
625 DECL(SPACESTATION_SMALLROOM
),
626 DECL(SPACESTATION_SHORTPASSAGE
),
627 DECL(SPACESTATION_MEDIUMROOM
),
628 DECL(SPACESTATION_LARGEROOM
),
629 DECL(SPACESTATION_LONGPASSAGE
),
630 DECL(SPACESTATION_HALL
),
631 DECL(SPACESTATION_CUPBOARD
),
632 DECL(SPACESTATION_ALCOVE
),
634 DECL(WOODEN_SMALLROOM
),
635 DECL(WOODEN_SHORTPASSAGE
),
636 DECL(WOODEN_MEDIUMROOM
),
637 DECL(WOODEN_LARGEROOM
),
638 DECL(WOODEN_LONGPASSAGE
),
640 DECL(WOODEN_CUPBOARD
),
641 DECL(WOODEN_COURTYARD
),
644 DECL(SPORT_EMPTYSTADIUM
),
645 DECL(SPORT_SQUASHCOURT
),
646 DECL(SPORT_SMALLSWIMMINGPOOL
),
647 DECL(SPORT_LARGESWIMMINGPOOL
),
648 DECL(SPORT_GYMNASIUM
),
649 DECL(SPORT_FULLSTADIUM
),
650 DECL(SPORT_STADIUMTANNOY
),
652 DECL(PREFAB_WORKSHOP
),
653 DECL(PREFAB_SCHOOLROOM
),
654 DECL(PREFAB_PRACTISEROOM
),
655 DECL(PREFAB_OUTHOUSE
),
656 DECL(PREFAB_CARAVAN
),
660 DECL(DOME_SAINTPAULS
),
665 DECL(OUTDOORS_BACKYARD
),
666 DECL(OUTDOORS_ROLLINGPLAINS
),
667 DECL(OUTDOORS_DEEPCANYON
),
668 DECL(OUTDOORS_CREEK
),
669 DECL(OUTDOORS_VALLEY
),
675 DECL(DRIVING_COMMENTATOR
),
676 DECL(DRIVING_PITGARAGE
),
677 DECL(DRIVING_INCAR_RACER
),
678 DECL(DRIVING_INCAR_SPORTS
),
679 DECL(DRIVING_INCAR_LUXURY
),
680 DECL(DRIVING_FULLGRANDSTAND
),
681 DECL(DRIVING_EMPTYGRANDSTAND
),
682 DECL(DRIVING_TUNNEL
),
688 DECL(CITY_UNDERPASS
),
689 DECL(CITY_ABANDONED
),
693 DECL(SMALLWATERROOM
),
697 void LoadReverbPreset(const char *name
, ALeffect
*effect
)
699 if(al::strcasecmp(name
, "NONE") == 0)
701 InitEffectParams(effect
, AL_EFFECT_NULL
);
702 TRACE("Loading reverb '%s'\n", "NONE");
706 if(!DisabledEffects
[EAXREVERB_EFFECT
])
707 InitEffectParams(effect
, AL_EFFECT_EAXREVERB
);
708 else if(!DisabledEffects
[REVERB_EFFECT
])
709 InitEffectParams(effect
, AL_EFFECT_REVERB
);
711 InitEffectParams(effect
, AL_EFFECT_NULL
);
712 for(const auto &reverbitem
: reverblist
)
714 const EFXEAXREVERBPROPERTIES
*props
;
716 if(al::strcasecmp(name
, reverbitem
.name
) != 0)
719 TRACE("Loading reverb '%s'\n", reverbitem
.name
);
720 props
= &reverbitem
.props
;
721 effect
->Props
.Reverb
.Density
= props
->flDensity
;
722 effect
->Props
.Reverb
.Diffusion
= props
->flDiffusion
;
723 effect
->Props
.Reverb
.Gain
= props
->flGain
;
724 effect
->Props
.Reverb
.GainHF
= props
->flGainHF
;
725 effect
->Props
.Reverb
.GainLF
= props
->flGainLF
;
726 effect
->Props
.Reverb
.DecayTime
= props
->flDecayTime
;
727 effect
->Props
.Reverb
.DecayHFRatio
= props
->flDecayHFRatio
;
728 effect
->Props
.Reverb
.DecayLFRatio
= props
->flDecayLFRatio
;
729 effect
->Props
.Reverb
.ReflectionsGain
= props
->flReflectionsGain
;
730 effect
->Props
.Reverb
.ReflectionsDelay
= props
->flReflectionsDelay
;
731 effect
->Props
.Reverb
.ReflectionsPan
[0] = props
->flReflectionsPan
[0];
732 effect
->Props
.Reverb
.ReflectionsPan
[1] = props
->flReflectionsPan
[1];
733 effect
->Props
.Reverb
.ReflectionsPan
[2] = props
->flReflectionsPan
[2];
734 effect
->Props
.Reverb
.LateReverbGain
= props
->flLateReverbGain
;
735 effect
->Props
.Reverb
.LateReverbDelay
= props
->flLateReverbDelay
;
736 effect
->Props
.Reverb
.LateReverbPan
[0] = props
->flLateReverbPan
[0];
737 effect
->Props
.Reverb
.LateReverbPan
[1] = props
->flLateReverbPan
[1];
738 effect
->Props
.Reverb
.LateReverbPan
[2] = props
->flLateReverbPan
[2];
739 effect
->Props
.Reverb
.EchoTime
= props
->flEchoTime
;
740 effect
->Props
.Reverb
.EchoDepth
= props
->flEchoDepth
;
741 effect
->Props
.Reverb
.ModulationTime
= props
->flModulationTime
;
742 effect
->Props
.Reverb
.ModulationDepth
= props
->flModulationDepth
;
743 effect
->Props
.Reverb
.AirAbsorptionGainHF
= props
->flAirAbsorptionGainHF
;
744 effect
->Props
.Reverb
.HFReference
= props
->flHFReference
;
745 effect
->Props
.Reverb
.LFReference
= props
->flLFReference
;
746 effect
->Props
.Reverb
.RoomRolloffFactor
= props
->flRoomRolloffFactor
;
747 effect
->Props
.Reverb
.DecayHFLimit
= props
->iDecayHFLimit
? AL_TRUE
: AL_FALSE
;
751 WARN("Reverb preset '%s' not found\n", name
);
754 bool IsValidEffectType(ALenum type
) noexcept
756 if(type
== AL_EFFECT_NULL
)
759 for(const auto &effect_item
: gEffectList
)
761 if(type
== effect_item
.val
&& !DisabledEffects
[effect_item
.type
])