Merge pull request #483 from jhasse/silence-nodiscard
[openal-soft.git] / al / effect.cpp
bloba90adf3c21da9dc76d1f11bdc66abc136e08954d
1 /**
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
21 #include "config.h"
23 #include "effect.h"
25 #include <algorithm>
26 #include <cstdint>
27 #include <cstring>
28 #include <iterator>
29 #include <memory>
30 #include <mutex>
31 #include <new>
32 #include <numeric>
33 #include <utility>
35 #include "AL/al.h"
36 #include "AL/alc.h"
37 #include "AL/alext.h"
38 #include "AL/efx-presets.h"
39 #include "AL/efx.h"
41 #include "alcmain.h"
42 #include "alcontext.h"
43 #include "alexcpt.h"
44 #include "almalloc.h"
45 #include "alnumeric.h"
46 #include "alstring.h"
47 #include "effects/base.h"
48 #include "logging.h"
49 #include "opthelpers.h"
50 #include "vector.h"
53 const EffectList gEffectList[16]{
54 { "eaxreverb", EAXREVERB_EFFECT, AL_EFFECT_EAXREVERB },
55 { "reverb", REVERB_EFFECT, AL_EFFECT_REVERB },
56 { "autowah", AUTOWAH_EFFECT, AL_EFFECT_AUTOWAH },
57 { "chorus", CHORUS_EFFECT, AL_EFFECT_CHORUS },
58 { "compressor", COMPRESSOR_EFFECT, AL_EFFECT_COMPRESSOR },
59 { "distortion", DISTORTION_EFFECT, AL_EFFECT_DISTORTION },
60 { "echo", ECHO_EFFECT, AL_EFFECT_ECHO },
61 { "equalizer", EQUALIZER_EFFECT, AL_EFFECT_EQUALIZER },
62 { "flanger", FLANGER_EFFECT, AL_EFFECT_FLANGER },
63 { "fshifter", FSHIFTER_EFFECT, AL_EFFECT_FREQUENCY_SHIFTER },
64 { "modulator", MODULATOR_EFFECT, AL_EFFECT_RING_MODULATOR },
65 { "pshifter", PSHIFTER_EFFECT, AL_EFFECT_PITCH_SHIFTER },
66 { "vmorpher", VMORPHER_EFFECT, AL_EFFECT_VOCAL_MORPHER },
67 { "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT },
68 { "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_DIALOGUE },
69 { "convolution", CONVOLUTION_EFFECT, AL_EFFECT_CONVOLUTION_REVERB_SOFT },
72 bool DisabledEffects[MAX_EFFECTS];
75 effect_exception::effect_exception(ALenum code, const char *msg, ...) : base_exception{code}
77 std::va_list args;
78 va_start(args, msg);
79 setMessage(msg, args);
80 va_end(args);
83 namespace {
85 constexpr struct FactoryItem {
86 ALenum Type;
87 EffectStateFactory* (&GetFactory)(void);
88 } FactoryList[] = {
89 { AL_EFFECT_NULL, NullStateFactory_getFactory },
90 { AL_EFFECT_EAXREVERB, ReverbStateFactory_getFactory },
91 { AL_EFFECT_REVERB, StdReverbStateFactory_getFactory },
92 { AL_EFFECT_AUTOWAH, AutowahStateFactory_getFactory },
93 { AL_EFFECT_CHORUS, ChorusStateFactory_getFactory },
94 { AL_EFFECT_COMPRESSOR, CompressorStateFactory_getFactory },
95 { AL_EFFECT_DISTORTION, DistortionStateFactory_getFactory },
96 { AL_EFFECT_ECHO, EchoStateFactory_getFactory },
97 { AL_EFFECT_EQUALIZER, EqualizerStateFactory_getFactory },
98 { AL_EFFECT_FLANGER, FlangerStateFactory_getFactory },
99 { AL_EFFECT_FREQUENCY_SHIFTER, FshifterStateFactory_getFactory },
100 { AL_EFFECT_RING_MODULATOR, ModulatorStateFactory_getFactory },
101 { AL_EFFECT_PITCH_SHIFTER, PshifterStateFactory_getFactory},
102 { AL_EFFECT_VOCAL_MORPHER, VmorpherStateFactory_getFactory},
103 { AL_EFFECT_DEDICATED_DIALOGUE, DedicatedStateFactory_getFactory },
104 { AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, DedicatedStateFactory_getFactory },
105 { AL_EFFECT_CONVOLUTION_REVERB_SOFT, ConvolutionStateFactory_getFactory }
109 void ALeffect_setParami(ALeffect *effect, ALenum param, int value)
110 { effect->vtab->setParami(&effect->Props, param, value); }
111 void ALeffect_setParamiv(ALeffect *effect, ALenum param, const int *values)
112 { effect->vtab->setParamiv(&effect->Props, param, values); }
113 void ALeffect_setParamf(ALeffect *effect, ALenum param, float value)
114 { effect->vtab->setParamf(&effect->Props, param, value); }
115 void ALeffect_setParamfv(ALeffect *effect, ALenum param, const float *values)
116 { effect->vtab->setParamfv(&effect->Props, param, values); }
118 void ALeffect_getParami(const ALeffect *effect, ALenum param, int *value)
119 { effect->vtab->getParami(&effect->Props, param, value); }
120 void ALeffect_getParamiv(const ALeffect *effect, ALenum param, int *values)
121 { effect->vtab->getParamiv(&effect->Props, param, values); }
122 void ALeffect_getParamf(const ALeffect *effect, ALenum param, float *value)
123 { effect->vtab->getParamf(&effect->Props, param, value); }
124 void ALeffect_getParamfv(const ALeffect *effect, ALenum param, float *values)
125 { effect->vtab->getParamfv(&effect->Props, param, values); }
128 void InitEffectParams(ALeffect *effect, ALenum type)
130 EffectStateFactory *factory = getFactoryByType(type);
131 if(factory)
133 effect->Props = factory->getDefaultProps();
134 effect->vtab = factory->getEffectVtable();
136 else
138 effect->Props = EffectProps{};
139 effect->vtab = nullptr;
141 effect->type = type;
144 bool EnsureEffects(ALCdevice *device, size_t needed)
146 size_t count{std::accumulate(device->EffectList.cbegin(), device->EffectList.cend(), size_t{0},
147 [](size_t cur, const EffectSubList &sublist) noexcept -> size_t
148 { return cur + static_cast<ALuint>(PopCount(sublist.FreeMask)); })};
150 while(needed > count)
152 if UNLIKELY(device->EffectList.size() >= 1<<25)
153 return false;
155 device->EffectList.emplace_back();
156 auto sublist = device->EffectList.end() - 1;
157 sublist->FreeMask = ~0_u64;
158 sublist->Effects = static_cast<ALeffect*>(al_calloc(alignof(ALeffect), sizeof(ALeffect)*64));
159 if UNLIKELY(!sublist->Effects)
161 device->EffectList.pop_back();
162 return false;
164 count += 64;
166 return true;
169 ALeffect *AllocEffect(ALCdevice *device)
171 auto sublist = std::find_if(device->EffectList.begin(), device->EffectList.end(),
172 [](const EffectSubList &entry) noexcept -> bool
173 { return entry.FreeMask != 0; }
175 auto lidx = static_cast<ALuint>(std::distance(device->EffectList.begin(), sublist));
176 auto slidx = static_cast<ALuint>(CountTrailingZeros(sublist->FreeMask));
178 ALeffect *effect{::new (sublist->Effects + slidx) ALeffect{}};
179 InitEffectParams(effect, AL_EFFECT_NULL);
181 /* Add 1 to avoid effect ID 0. */
182 effect->id = ((lidx<<6) | slidx) + 1;
184 sublist->FreeMask &= ~(1_u64 << slidx);
186 return effect;
189 void FreeEffect(ALCdevice *device, ALeffect *effect)
191 const ALuint id{effect->id - 1};
192 const size_t lidx{id >> 6};
193 const ALuint slidx{id & 0x3f};
195 al::destroy_at(effect);
197 device->EffectList[lidx].FreeMask |= 1_u64 << slidx;
200 inline ALeffect *LookupEffect(ALCdevice *device, ALuint id)
202 const size_t lidx{(id-1) >> 6};
203 const ALuint slidx{(id-1) & 0x3f};
205 if UNLIKELY(lidx >= device->EffectList.size())
206 return nullptr;
207 EffectSubList &sublist = device->EffectList[lidx];
208 if UNLIKELY(sublist.FreeMask & (1_u64 << slidx))
209 return nullptr;
210 return sublist.Effects + slidx;
213 } // namespace
215 AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
216 START_API_FUNC
218 ContextRef context{GetContextRef()};
219 if UNLIKELY(!context) return;
221 if UNLIKELY(n < 0)
222 context->setError(AL_INVALID_VALUE, "Generating %d effects", n);
223 if UNLIKELY(n <= 0) return;
225 ALCdevice *device{context->mDevice.get()};
226 std::lock_guard<std::mutex> _{device->EffectLock};
227 if(!EnsureEffects(device, static_cast<ALuint>(n)))
229 context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d effect%s", n, (n==1)?"":"s");
230 return;
233 if LIKELY(n == 1)
235 /* Special handling for the easy and normal case. */
236 ALeffect *effect{AllocEffect(device)};
237 effects[0] = effect->id;
239 else
241 /* Store the allocated buffer IDs in a separate local list, to avoid
242 * modifying the user storage in case of failure.
244 al::vector<ALuint> ids;
245 ids.reserve(static_cast<ALuint>(n));
246 do {
247 ALeffect *effect{AllocEffect(device)};
248 ids.emplace_back(effect->id);
249 } while(--n);
250 std::copy(ids.cbegin(), ids.cend(), effects);
253 END_API_FUNC
255 AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects)
256 START_API_FUNC
258 ContextRef context{GetContextRef()};
259 if UNLIKELY(!context) return;
261 if UNLIKELY(n < 0)
262 context->setError(AL_INVALID_VALUE, "Deleting %d effects", n);
263 if UNLIKELY(n <= 0) return;
265 ALCdevice *device{context->mDevice.get()};
266 std::lock_guard<std::mutex> _{device->EffectLock};
268 /* First try to find any effects that are invalid. */
269 auto validate_effect = [device](const ALuint eid) -> bool
270 { return !eid || LookupEffect(device, eid) != nullptr; };
272 const ALuint *effects_end = effects + n;
273 auto inveffect = std::find_if_not(effects, effects_end, validate_effect);
274 if UNLIKELY(inveffect != effects_end)
276 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", *inveffect);
277 return;
280 /* All good. Delete non-0 effect IDs. */
281 auto delete_effect = [device](ALuint eid) -> void
283 ALeffect *effect{eid ? LookupEffect(device, eid) : nullptr};
284 if(effect) FreeEffect(device, effect);
286 std::for_each(effects, effects_end, delete_effect);
288 END_API_FUNC
290 AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
291 START_API_FUNC
293 ContextRef context{GetContextRef()};
294 if LIKELY(context)
296 ALCdevice *device{context->mDevice.get()};
297 std::lock_guard<std::mutex> _{device->EffectLock};
298 if(!effect || LookupEffect(device, effect))
299 return AL_TRUE;
301 return AL_FALSE;
303 END_API_FUNC
305 AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value)
306 START_API_FUNC
308 ContextRef context{GetContextRef()};
309 if UNLIKELY(!context) return;
311 ALCdevice *device{context->mDevice.get()};
312 std::lock_guard<std::mutex> _{device->EffectLock};
314 ALeffect *aleffect{LookupEffect(device, effect)};
315 if UNLIKELY(!aleffect)
316 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
317 else if(param == AL_EFFECT_TYPE)
319 bool isOk{value == AL_EFFECT_NULL};
320 if(!isOk)
322 for(const EffectList &effectitem : gEffectList)
324 if(value == effectitem.val && !DisabledEffects[effectitem.type])
326 isOk = true;
327 break;
332 if(isOk)
333 InitEffectParams(aleffect, value);
334 else
335 context->setError(AL_INVALID_VALUE, "Effect type 0x%04x not supported", value);
337 else try
339 /* Call the appropriate handler */
340 ALeffect_setParami(aleffect, param, value);
342 catch(effect_exception &e) {
343 context->setError(e.errorCode(), "%s", e.what());
346 END_API_FUNC
348 AL_API void AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *values)
349 START_API_FUNC
351 switch(param)
353 case AL_EFFECT_TYPE:
354 alEffecti(effect, param, values[0]);
355 return;
358 ContextRef context{GetContextRef()};
359 if UNLIKELY(!context) return;
361 ALCdevice *device{context->mDevice.get()};
362 std::lock_guard<std::mutex> _{device->EffectLock};
364 ALeffect *aleffect{LookupEffect(device, effect)};
365 if UNLIKELY(!aleffect)
366 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
367 else try
369 /* Call the appropriate handler */
370 ALeffect_setParamiv(aleffect, param, values);
372 catch(effect_exception &e) {
373 context->setError(e.errorCode(), "%s", e.what());
376 END_API_FUNC
378 AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat value)
379 START_API_FUNC
381 ContextRef context{GetContextRef()};
382 if UNLIKELY(!context) return;
384 ALCdevice *device{context->mDevice.get()};
385 std::lock_guard<std::mutex> _{device->EffectLock};
387 ALeffect *aleffect{LookupEffect(device, effect)};
388 if UNLIKELY(!aleffect)
389 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
390 else try
392 /* Call the appropriate handler */
393 ALeffect_setParamf(aleffect, param, value);
395 catch(effect_exception &e) {
396 context->setError(e.errorCode(), "%s", e.what());
399 END_API_FUNC
401 AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *values)
402 START_API_FUNC
404 ContextRef context{GetContextRef()};
405 if UNLIKELY(!context) return;
407 ALCdevice *device{context->mDevice.get()};
408 std::lock_guard<std::mutex> _{device->EffectLock};
410 ALeffect *aleffect{LookupEffect(device, effect)};
411 if UNLIKELY(!aleffect)
412 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
413 else try
415 /* Call the appropriate handler */
416 ALeffect_setParamfv(aleffect, param, values);
418 catch(effect_exception &e) {
419 context->setError(e.errorCode(), "%s", e.what());
422 END_API_FUNC
424 AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value)
425 START_API_FUNC
427 ContextRef context{GetContextRef()};
428 if UNLIKELY(!context) return;
430 ALCdevice *device{context->mDevice.get()};
431 std::lock_guard<std::mutex> _{device->EffectLock};
433 const ALeffect *aleffect{LookupEffect(device, effect)};
434 if UNLIKELY(!aleffect)
435 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
436 else if(param == AL_EFFECT_TYPE)
437 *value = aleffect->type;
438 else try
440 /* Call the appropriate handler */
441 ALeffect_getParami(aleffect, param, value);
443 catch(effect_exception &e) {
444 context->setError(e.errorCode(), "%s", e.what());
447 END_API_FUNC
449 AL_API void AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *values)
450 START_API_FUNC
452 switch(param)
454 case AL_EFFECT_TYPE:
455 alGetEffecti(effect, param, values);
456 return;
459 ContextRef context{GetContextRef()};
460 if UNLIKELY(!context) return;
462 ALCdevice *device{context->mDevice.get()};
463 std::lock_guard<std::mutex> _{device->EffectLock};
465 const ALeffect *aleffect{LookupEffect(device, effect)};
466 if UNLIKELY(!aleffect)
467 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
468 else try
470 /* Call the appropriate handler */
471 ALeffect_getParamiv(aleffect, param, values);
473 catch(effect_exception &e) {
474 context->setError(e.errorCode(), "%s", e.what());
477 END_API_FUNC
479 AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *value)
480 START_API_FUNC
482 ContextRef context{GetContextRef()};
483 if UNLIKELY(!context) return;
485 ALCdevice *device{context->mDevice.get()};
486 std::lock_guard<std::mutex> _{device->EffectLock};
488 const ALeffect *aleffect{LookupEffect(device, effect)};
489 if UNLIKELY(!aleffect)
490 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
491 else try
493 /* Call the appropriate handler */
494 ALeffect_getParamf(aleffect, param, value);
496 catch(effect_exception &e) {
497 context->setError(e.errorCode(), "%s", e.what());
500 END_API_FUNC
502 AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *values)
503 START_API_FUNC
505 ContextRef context{GetContextRef()};
506 if UNLIKELY(!context) return;
508 ALCdevice *device{context->mDevice.get()};
509 std::lock_guard<std::mutex> _{device->EffectLock};
511 const ALeffect *aleffect{LookupEffect(device, effect)};
512 if UNLIKELY(!aleffect)
513 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
514 else try
516 /* Call the appropriate handler */
517 ALeffect_getParamfv(aleffect, param, values);
519 catch(effect_exception &e) {
520 context->setError(e.errorCode(), "%s", e.what());
523 END_API_FUNC
526 void InitEffect(ALeffect *effect)
528 InitEffectParams(effect, AL_EFFECT_NULL);
531 EffectSubList::~EffectSubList()
533 uint64_t usemask{~FreeMask};
534 while(usemask)
536 const ALsizei idx{CountTrailingZeros(usemask)};
537 al::destroy_at(Effects+idx);
538 usemask &= ~(1_u64 << idx);
540 FreeMask = ~usemask;
541 al_free(Effects);
542 Effects = nullptr;
546 EffectStateFactory *getFactoryByType(ALenum type)
548 auto iter = std::find_if(std::begin(FactoryList), std::end(FactoryList),
549 [type](const FactoryItem &item) noexcept -> bool
550 { return item.Type == type; }
552 return (iter != std::end(FactoryList)) ? iter->GetFactory() : nullptr;
556 #define DECL(x) { #x, EFX_REVERB_PRESET_##x }
557 static const struct {
558 const char name[32];
559 EFXEAXREVERBPROPERTIES props;
560 } reverblist[] = {
561 DECL(GENERIC),
562 DECL(PADDEDCELL),
563 DECL(ROOM),
564 DECL(BATHROOM),
565 DECL(LIVINGROOM),
566 DECL(STONEROOM),
567 DECL(AUDITORIUM),
568 DECL(CONCERTHALL),
569 DECL(CAVE),
570 DECL(ARENA),
571 DECL(HANGAR),
572 DECL(CARPETEDHALLWAY),
573 DECL(HALLWAY),
574 DECL(STONECORRIDOR),
575 DECL(ALLEY),
576 DECL(FOREST),
577 DECL(CITY),
578 DECL(MOUNTAINS),
579 DECL(QUARRY),
580 DECL(PLAIN),
581 DECL(PARKINGLOT),
582 DECL(SEWERPIPE),
583 DECL(UNDERWATER),
584 DECL(DRUGGED),
585 DECL(DIZZY),
586 DECL(PSYCHOTIC),
588 DECL(CASTLE_SMALLROOM),
589 DECL(CASTLE_SHORTPASSAGE),
590 DECL(CASTLE_MEDIUMROOM),
591 DECL(CASTLE_LARGEROOM),
592 DECL(CASTLE_LONGPASSAGE),
593 DECL(CASTLE_HALL),
594 DECL(CASTLE_CUPBOARD),
595 DECL(CASTLE_COURTYARD),
596 DECL(CASTLE_ALCOVE),
598 DECL(FACTORY_SMALLROOM),
599 DECL(FACTORY_SHORTPASSAGE),
600 DECL(FACTORY_MEDIUMROOM),
601 DECL(FACTORY_LARGEROOM),
602 DECL(FACTORY_LONGPASSAGE),
603 DECL(FACTORY_HALL),
604 DECL(FACTORY_CUPBOARD),
605 DECL(FACTORY_COURTYARD),
606 DECL(FACTORY_ALCOVE),
608 DECL(ICEPALACE_SMALLROOM),
609 DECL(ICEPALACE_SHORTPASSAGE),
610 DECL(ICEPALACE_MEDIUMROOM),
611 DECL(ICEPALACE_LARGEROOM),
612 DECL(ICEPALACE_LONGPASSAGE),
613 DECL(ICEPALACE_HALL),
614 DECL(ICEPALACE_CUPBOARD),
615 DECL(ICEPALACE_COURTYARD),
616 DECL(ICEPALACE_ALCOVE),
618 DECL(SPACESTATION_SMALLROOM),
619 DECL(SPACESTATION_SHORTPASSAGE),
620 DECL(SPACESTATION_MEDIUMROOM),
621 DECL(SPACESTATION_LARGEROOM),
622 DECL(SPACESTATION_LONGPASSAGE),
623 DECL(SPACESTATION_HALL),
624 DECL(SPACESTATION_CUPBOARD),
625 DECL(SPACESTATION_ALCOVE),
627 DECL(WOODEN_SMALLROOM),
628 DECL(WOODEN_SHORTPASSAGE),
629 DECL(WOODEN_MEDIUMROOM),
630 DECL(WOODEN_LARGEROOM),
631 DECL(WOODEN_LONGPASSAGE),
632 DECL(WOODEN_HALL),
633 DECL(WOODEN_CUPBOARD),
634 DECL(WOODEN_COURTYARD),
635 DECL(WOODEN_ALCOVE),
637 DECL(SPORT_EMPTYSTADIUM),
638 DECL(SPORT_SQUASHCOURT),
639 DECL(SPORT_SMALLSWIMMINGPOOL),
640 DECL(SPORT_LARGESWIMMINGPOOL),
641 DECL(SPORT_GYMNASIUM),
642 DECL(SPORT_FULLSTADIUM),
643 DECL(SPORT_STADIUMTANNOY),
645 DECL(PREFAB_WORKSHOP),
646 DECL(PREFAB_SCHOOLROOM),
647 DECL(PREFAB_PRACTISEROOM),
648 DECL(PREFAB_OUTHOUSE),
649 DECL(PREFAB_CARAVAN),
651 DECL(DOME_TOMB),
652 DECL(PIPE_SMALL),
653 DECL(DOME_SAINTPAULS),
654 DECL(PIPE_LONGTHIN),
655 DECL(PIPE_LARGE),
656 DECL(PIPE_RESONANT),
658 DECL(OUTDOORS_BACKYARD),
659 DECL(OUTDOORS_ROLLINGPLAINS),
660 DECL(OUTDOORS_DEEPCANYON),
661 DECL(OUTDOORS_CREEK),
662 DECL(OUTDOORS_VALLEY),
664 DECL(MOOD_HEAVEN),
665 DECL(MOOD_HELL),
666 DECL(MOOD_MEMORY),
668 DECL(DRIVING_COMMENTATOR),
669 DECL(DRIVING_PITGARAGE),
670 DECL(DRIVING_INCAR_RACER),
671 DECL(DRIVING_INCAR_SPORTS),
672 DECL(DRIVING_INCAR_LUXURY),
673 DECL(DRIVING_FULLGRANDSTAND),
674 DECL(DRIVING_EMPTYGRANDSTAND),
675 DECL(DRIVING_TUNNEL),
677 DECL(CITY_STREETS),
678 DECL(CITY_SUBWAY),
679 DECL(CITY_MUSEUM),
680 DECL(CITY_LIBRARY),
681 DECL(CITY_UNDERPASS),
682 DECL(CITY_ABANDONED),
684 DECL(DUSTYROOM),
685 DECL(CHAPEL),
686 DECL(SMALLWATERROOM),
688 #undef DECL
690 void LoadReverbPreset(const char *name, ALeffect *effect)
692 if(al::strcasecmp(name, "NONE") == 0)
694 InitEffectParams(effect, AL_EFFECT_NULL);
695 TRACE("Loading reverb '%s'\n", "NONE");
696 return;
699 if(!DisabledEffects[EAXREVERB_EFFECT])
700 InitEffectParams(effect, AL_EFFECT_EAXREVERB);
701 else if(!DisabledEffects[REVERB_EFFECT])
702 InitEffectParams(effect, AL_EFFECT_REVERB);
703 else
704 InitEffectParams(effect, AL_EFFECT_NULL);
705 for(const auto &reverbitem : reverblist)
707 const EFXEAXREVERBPROPERTIES *props;
709 if(al::strcasecmp(name, reverbitem.name) != 0)
710 continue;
712 TRACE("Loading reverb '%s'\n", reverbitem.name);
713 props = &reverbitem.props;
714 effect->Props.Reverb.Density = props->flDensity;
715 effect->Props.Reverb.Diffusion = props->flDiffusion;
716 effect->Props.Reverb.Gain = props->flGain;
717 effect->Props.Reverb.GainHF = props->flGainHF;
718 effect->Props.Reverb.GainLF = props->flGainLF;
719 effect->Props.Reverb.DecayTime = props->flDecayTime;
720 effect->Props.Reverb.DecayHFRatio = props->flDecayHFRatio;
721 effect->Props.Reverb.DecayLFRatio = props->flDecayLFRatio;
722 effect->Props.Reverb.ReflectionsGain = props->flReflectionsGain;
723 effect->Props.Reverb.ReflectionsDelay = props->flReflectionsDelay;
724 effect->Props.Reverb.ReflectionsPan[0] = props->flReflectionsPan[0];
725 effect->Props.Reverb.ReflectionsPan[1] = props->flReflectionsPan[1];
726 effect->Props.Reverb.ReflectionsPan[2] = props->flReflectionsPan[2];
727 effect->Props.Reverb.LateReverbGain = props->flLateReverbGain;
728 effect->Props.Reverb.LateReverbDelay = props->flLateReverbDelay;
729 effect->Props.Reverb.LateReverbPan[0] = props->flLateReverbPan[0];
730 effect->Props.Reverb.LateReverbPan[1] = props->flLateReverbPan[1];
731 effect->Props.Reverb.LateReverbPan[2] = props->flLateReverbPan[2];
732 effect->Props.Reverb.EchoTime = props->flEchoTime;
733 effect->Props.Reverb.EchoDepth = props->flEchoDepth;
734 effect->Props.Reverb.ModulationTime = props->flModulationTime;
735 effect->Props.Reverb.ModulationDepth = props->flModulationDepth;
736 effect->Props.Reverb.AirAbsorptionGainHF = props->flAirAbsorptionGainHF;
737 effect->Props.Reverb.HFReference = props->flHFReference;
738 effect->Props.Reverb.LFReference = props->flLFReference;
739 effect->Props.Reverb.RoomRolloffFactor = props->flRoomRolloffFactor;
740 effect->Props.Reverb.DecayHFLimit = props->iDecayHFLimit ? AL_TRUE : AL_FALSE;
741 return;
744 WARN("Reverb preset '%s' not found\n", name);