Simplify some DSound capture math
[openal-soft.git] / al / effect.cpp
blob350d0e698099d0bea0c62634236eaf14971c9fef
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>(POPCNT64(sublist.FreeMask)); }
151 while(needed > count)
153 if UNLIKELY(device->EffectList.size() >= 1<<25)
154 return false;
156 device->EffectList.emplace_back();
157 auto sublist = device->EffectList.end() - 1;
158 sublist->FreeMask = ~0_u64;
159 sublist->Effects = static_cast<ALeffect*>(al_calloc(alignof(ALeffect), sizeof(ALeffect)*64));
160 if UNLIKELY(!sublist->Effects)
162 device->EffectList.pop_back();
163 return false;
165 count += 64;
167 return true;
170 ALeffect *AllocEffect(ALCdevice *device)
172 auto sublist = std::find_if(device->EffectList.begin(), device->EffectList.end(),
173 [](const EffectSubList &entry) noexcept -> bool
174 { return entry.FreeMask != 0; }
176 auto lidx = static_cast<ALuint>(std::distance(device->EffectList.begin(), sublist));
177 auto slidx = static_cast<ALuint>(CTZ64(sublist->FreeMask));
179 ALeffect *effect{::new (sublist->Effects + slidx) ALeffect{}};
180 InitEffectParams(effect, AL_EFFECT_NULL);
182 /* Add 1 to avoid effect ID 0. */
183 effect->id = ((lidx<<6) | slidx) + 1;
185 sublist->FreeMask &= ~(1_u64 << slidx);
187 return effect;
190 void FreeEffect(ALCdevice *device, ALeffect *effect)
192 const ALuint id{effect->id - 1};
193 const size_t lidx{id >> 6};
194 const ALuint slidx{id & 0x3f};
196 al::destroy_at(effect);
198 device->EffectList[lidx].FreeMask |= 1_u64 << slidx;
201 inline ALeffect *LookupEffect(ALCdevice *device, ALuint id)
203 const size_t lidx{(id-1) >> 6};
204 const ALuint slidx{(id-1) & 0x3f};
206 if UNLIKELY(lidx >= device->EffectList.size())
207 return nullptr;
208 EffectSubList &sublist = device->EffectList[lidx];
209 if UNLIKELY(sublist.FreeMask & (1_u64 << slidx))
210 return nullptr;
211 return sublist.Effects + slidx;
214 } // namespace
216 AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
217 START_API_FUNC
219 ContextRef context{GetContextRef()};
220 if UNLIKELY(!context) return;
222 if UNLIKELY(n < 0)
223 context->setError(AL_INVALID_VALUE, "Generating %d effects", n);
224 if UNLIKELY(n <= 0) return;
226 ALCdevice *device{context->mDevice.get()};
227 std::lock_guard<std::mutex> _{device->EffectLock};
228 if(!EnsureEffects(device, static_cast<ALuint>(n)))
230 context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d effect%s", n, (n==1)?"":"s");
231 return;
234 if LIKELY(n == 1)
236 /* Special handling for the easy and normal case. */
237 ALeffect *effect{AllocEffect(device)};
238 effects[0] = effect->id;
240 else
242 /* Store the allocated buffer IDs in a separate local list, to avoid
243 * modifying the user storage in case of failure.
245 al::vector<ALuint> ids;
246 ids.reserve(static_cast<ALuint>(n));
247 do {
248 ALeffect *effect{AllocEffect(device)};
249 ids.emplace_back(effect->id);
250 } while(--n);
251 std::copy(ids.cbegin(), ids.cend(), effects);
254 END_API_FUNC
256 AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects)
257 START_API_FUNC
259 ContextRef context{GetContextRef()};
260 if UNLIKELY(!context) return;
262 if UNLIKELY(n < 0)
263 context->setError(AL_INVALID_VALUE, "Deleting %d effects", n);
264 if UNLIKELY(n <= 0) return;
266 ALCdevice *device{context->mDevice.get()};
267 std::lock_guard<std::mutex> _{device->EffectLock};
269 /* First try to find any effects that are invalid. */
270 auto validate_effect = [device](const ALuint eid) -> bool
271 { return !eid || LookupEffect(device, eid) != nullptr; };
273 const ALuint *effects_end = effects + n;
274 auto inveffect = std::find_if_not(effects, effects_end, validate_effect);
275 if UNLIKELY(inveffect != effects_end)
277 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", *inveffect);
278 return;
281 /* All good. Delete non-0 effect IDs. */
282 auto delete_effect = [device](ALuint eid) -> void
284 ALeffect *effect{eid ? LookupEffect(device, eid) : nullptr};
285 if(effect) FreeEffect(device, effect);
287 std::for_each(effects, effects_end, delete_effect);
289 END_API_FUNC
291 AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
292 START_API_FUNC
294 ContextRef context{GetContextRef()};
295 if LIKELY(context)
297 ALCdevice *device{context->mDevice.get()};
298 std::lock_guard<std::mutex> _{device->EffectLock};
299 if(!effect || LookupEffect(device, effect))
300 return AL_TRUE;
302 return AL_FALSE;
304 END_API_FUNC
306 AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value)
307 START_API_FUNC
309 ContextRef context{GetContextRef()};
310 if UNLIKELY(!context) return;
312 ALCdevice *device{context->mDevice.get()};
313 std::lock_guard<std::mutex> _{device->EffectLock};
315 ALeffect *aleffect{LookupEffect(device, effect)};
316 if UNLIKELY(!aleffect)
317 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
318 else if(param == AL_EFFECT_TYPE)
320 bool isOk{value == AL_EFFECT_NULL};
321 if(!isOk)
323 for(const EffectList &effectitem : gEffectList)
325 if(value == effectitem.val && !DisabledEffects[effectitem.type])
327 isOk = true;
328 break;
333 if(isOk)
334 InitEffectParams(aleffect, value);
335 else
336 context->setError(AL_INVALID_VALUE, "Effect type 0x%04x not supported", value);
338 else try
340 /* Call the appropriate handler */
341 ALeffect_setParami(aleffect, param, value);
343 catch(effect_exception &e) {
344 context->setError(e.errorCode(), "%s", e.what());
347 END_API_FUNC
349 AL_API void AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *values)
350 START_API_FUNC
352 switch(param)
354 case AL_EFFECT_TYPE:
355 alEffecti(effect, param, values[0]);
356 return;
359 ContextRef context{GetContextRef()};
360 if UNLIKELY(!context) return;
362 ALCdevice *device{context->mDevice.get()};
363 std::lock_guard<std::mutex> _{device->EffectLock};
365 ALeffect *aleffect{LookupEffect(device, effect)};
366 if UNLIKELY(!aleffect)
367 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
368 else try
370 /* Call the appropriate handler */
371 ALeffect_setParamiv(aleffect, param, values);
373 catch(effect_exception &e) {
374 context->setError(e.errorCode(), "%s", e.what());
377 END_API_FUNC
379 AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat value)
380 START_API_FUNC
382 ContextRef context{GetContextRef()};
383 if UNLIKELY(!context) return;
385 ALCdevice *device{context->mDevice.get()};
386 std::lock_guard<std::mutex> _{device->EffectLock};
388 ALeffect *aleffect{LookupEffect(device, effect)};
389 if UNLIKELY(!aleffect)
390 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
391 else try
393 /* Call the appropriate handler */
394 ALeffect_setParamf(aleffect, param, value);
396 catch(effect_exception &e) {
397 context->setError(e.errorCode(), "%s", e.what());
400 END_API_FUNC
402 AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *values)
403 START_API_FUNC
405 ContextRef context{GetContextRef()};
406 if UNLIKELY(!context) return;
408 ALCdevice *device{context->mDevice.get()};
409 std::lock_guard<std::mutex> _{device->EffectLock};
411 ALeffect *aleffect{LookupEffect(device, effect)};
412 if UNLIKELY(!aleffect)
413 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
414 else try
416 /* Call the appropriate handler */
417 ALeffect_setParamfv(aleffect, param, values);
419 catch(effect_exception &e) {
420 context->setError(e.errorCode(), "%s", e.what());
423 END_API_FUNC
425 AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value)
426 START_API_FUNC
428 ContextRef context{GetContextRef()};
429 if UNLIKELY(!context) return;
431 ALCdevice *device{context->mDevice.get()};
432 std::lock_guard<std::mutex> _{device->EffectLock};
434 const ALeffect *aleffect{LookupEffect(device, effect)};
435 if UNLIKELY(!aleffect)
436 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
437 else if(param == AL_EFFECT_TYPE)
438 *value = aleffect->type;
439 else try
441 /* Call the appropriate handler */
442 ALeffect_getParami(aleffect, param, value);
444 catch(effect_exception &e) {
445 context->setError(e.errorCode(), "%s", e.what());
448 END_API_FUNC
450 AL_API void AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *values)
451 START_API_FUNC
453 switch(param)
455 case AL_EFFECT_TYPE:
456 alGetEffecti(effect, param, values);
457 return;
460 ContextRef context{GetContextRef()};
461 if UNLIKELY(!context) return;
463 ALCdevice *device{context->mDevice.get()};
464 std::lock_guard<std::mutex> _{device->EffectLock};
466 const ALeffect *aleffect{LookupEffect(device, effect)};
467 if UNLIKELY(!aleffect)
468 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
469 else try
471 /* Call the appropriate handler */
472 ALeffect_getParamiv(aleffect, param, values);
474 catch(effect_exception &e) {
475 context->setError(e.errorCode(), "%s", e.what());
478 END_API_FUNC
480 AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *value)
481 START_API_FUNC
483 ContextRef context{GetContextRef()};
484 if UNLIKELY(!context) return;
486 ALCdevice *device{context->mDevice.get()};
487 std::lock_guard<std::mutex> _{device->EffectLock};
489 const ALeffect *aleffect{LookupEffect(device, effect)};
490 if UNLIKELY(!aleffect)
491 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
492 else try
494 /* Call the appropriate handler */
495 ALeffect_getParamf(aleffect, param, value);
497 catch(effect_exception &e) {
498 context->setError(e.errorCode(), "%s", e.what());
501 END_API_FUNC
503 AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *values)
504 START_API_FUNC
506 ContextRef context{GetContextRef()};
507 if UNLIKELY(!context) return;
509 ALCdevice *device{context->mDevice.get()};
510 std::lock_guard<std::mutex> _{device->EffectLock};
512 const ALeffect *aleffect{LookupEffect(device, effect)};
513 if UNLIKELY(!aleffect)
514 context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
515 else try
517 /* Call the appropriate handler */
518 ALeffect_getParamfv(aleffect, param, values);
520 catch(effect_exception &e) {
521 context->setError(e.errorCode(), "%s", e.what());
524 END_API_FUNC
527 void InitEffect(ALeffect *effect)
529 InitEffectParams(effect, AL_EFFECT_NULL);
532 EffectSubList::~EffectSubList()
534 uint64_t usemask{~FreeMask};
535 while(usemask)
537 ALsizei idx = CTZ64(usemask);
538 al::destroy_at(Effects+idx);
539 usemask &= ~(1_u64 << idx);
541 FreeMask = ~usemask;
542 al_free(Effects);
543 Effects = nullptr;
547 EffectStateFactory *getFactoryByType(ALenum type)
549 auto iter = std::find_if(std::begin(FactoryList), std::end(FactoryList),
550 [type](const FactoryItem &item) noexcept -> bool
551 { return item.Type == type; }
553 return (iter != std::end(FactoryList)) ? iter->GetFactory() : nullptr;
557 #define DECL(x) { #x, EFX_REVERB_PRESET_##x }
558 static const struct {
559 const char name[32];
560 EFXEAXREVERBPROPERTIES props;
561 } reverblist[] = {
562 DECL(GENERIC),
563 DECL(PADDEDCELL),
564 DECL(ROOM),
565 DECL(BATHROOM),
566 DECL(LIVINGROOM),
567 DECL(STONEROOM),
568 DECL(AUDITORIUM),
569 DECL(CONCERTHALL),
570 DECL(CAVE),
571 DECL(ARENA),
572 DECL(HANGAR),
573 DECL(CARPETEDHALLWAY),
574 DECL(HALLWAY),
575 DECL(STONECORRIDOR),
576 DECL(ALLEY),
577 DECL(FOREST),
578 DECL(CITY),
579 DECL(MOUNTAINS),
580 DECL(QUARRY),
581 DECL(PLAIN),
582 DECL(PARKINGLOT),
583 DECL(SEWERPIPE),
584 DECL(UNDERWATER),
585 DECL(DRUGGED),
586 DECL(DIZZY),
587 DECL(PSYCHOTIC),
589 DECL(CASTLE_SMALLROOM),
590 DECL(CASTLE_SHORTPASSAGE),
591 DECL(CASTLE_MEDIUMROOM),
592 DECL(CASTLE_LARGEROOM),
593 DECL(CASTLE_LONGPASSAGE),
594 DECL(CASTLE_HALL),
595 DECL(CASTLE_CUPBOARD),
596 DECL(CASTLE_COURTYARD),
597 DECL(CASTLE_ALCOVE),
599 DECL(FACTORY_SMALLROOM),
600 DECL(FACTORY_SHORTPASSAGE),
601 DECL(FACTORY_MEDIUMROOM),
602 DECL(FACTORY_LARGEROOM),
603 DECL(FACTORY_LONGPASSAGE),
604 DECL(FACTORY_HALL),
605 DECL(FACTORY_CUPBOARD),
606 DECL(FACTORY_COURTYARD),
607 DECL(FACTORY_ALCOVE),
609 DECL(ICEPALACE_SMALLROOM),
610 DECL(ICEPALACE_SHORTPASSAGE),
611 DECL(ICEPALACE_MEDIUMROOM),
612 DECL(ICEPALACE_LARGEROOM),
613 DECL(ICEPALACE_LONGPASSAGE),
614 DECL(ICEPALACE_HALL),
615 DECL(ICEPALACE_CUPBOARD),
616 DECL(ICEPALACE_COURTYARD),
617 DECL(ICEPALACE_ALCOVE),
619 DECL(SPACESTATION_SMALLROOM),
620 DECL(SPACESTATION_SHORTPASSAGE),
621 DECL(SPACESTATION_MEDIUMROOM),
622 DECL(SPACESTATION_LARGEROOM),
623 DECL(SPACESTATION_LONGPASSAGE),
624 DECL(SPACESTATION_HALL),
625 DECL(SPACESTATION_CUPBOARD),
626 DECL(SPACESTATION_ALCOVE),
628 DECL(WOODEN_SMALLROOM),
629 DECL(WOODEN_SHORTPASSAGE),
630 DECL(WOODEN_MEDIUMROOM),
631 DECL(WOODEN_LARGEROOM),
632 DECL(WOODEN_LONGPASSAGE),
633 DECL(WOODEN_HALL),
634 DECL(WOODEN_CUPBOARD),
635 DECL(WOODEN_COURTYARD),
636 DECL(WOODEN_ALCOVE),
638 DECL(SPORT_EMPTYSTADIUM),
639 DECL(SPORT_SQUASHCOURT),
640 DECL(SPORT_SMALLSWIMMINGPOOL),
641 DECL(SPORT_LARGESWIMMINGPOOL),
642 DECL(SPORT_GYMNASIUM),
643 DECL(SPORT_FULLSTADIUM),
644 DECL(SPORT_STADIUMTANNOY),
646 DECL(PREFAB_WORKSHOP),
647 DECL(PREFAB_SCHOOLROOM),
648 DECL(PREFAB_PRACTISEROOM),
649 DECL(PREFAB_OUTHOUSE),
650 DECL(PREFAB_CARAVAN),
652 DECL(DOME_TOMB),
653 DECL(PIPE_SMALL),
654 DECL(DOME_SAINTPAULS),
655 DECL(PIPE_LONGTHIN),
656 DECL(PIPE_LARGE),
657 DECL(PIPE_RESONANT),
659 DECL(OUTDOORS_BACKYARD),
660 DECL(OUTDOORS_ROLLINGPLAINS),
661 DECL(OUTDOORS_DEEPCANYON),
662 DECL(OUTDOORS_CREEK),
663 DECL(OUTDOORS_VALLEY),
665 DECL(MOOD_HEAVEN),
666 DECL(MOOD_HELL),
667 DECL(MOOD_MEMORY),
669 DECL(DRIVING_COMMENTATOR),
670 DECL(DRIVING_PITGARAGE),
671 DECL(DRIVING_INCAR_RACER),
672 DECL(DRIVING_INCAR_SPORTS),
673 DECL(DRIVING_INCAR_LUXURY),
674 DECL(DRIVING_FULLGRANDSTAND),
675 DECL(DRIVING_EMPTYGRANDSTAND),
676 DECL(DRIVING_TUNNEL),
678 DECL(CITY_STREETS),
679 DECL(CITY_SUBWAY),
680 DECL(CITY_MUSEUM),
681 DECL(CITY_LIBRARY),
682 DECL(CITY_UNDERPASS),
683 DECL(CITY_ABANDONED),
685 DECL(DUSTYROOM),
686 DECL(CHAPEL),
687 DECL(SMALLWATERROOM),
689 #undef DECL
691 void LoadReverbPreset(const char *name, ALeffect *effect)
693 if(al::strcasecmp(name, "NONE") == 0)
695 InitEffectParams(effect, AL_EFFECT_NULL);
696 TRACE("Loading reverb '%s'\n", "NONE");
697 return;
700 if(!DisabledEffects[EAXREVERB_EFFECT])
701 InitEffectParams(effect, AL_EFFECT_EAXREVERB);
702 else if(!DisabledEffects[REVERB_EFFECT])
703 InitEffectParams(effect, AL_EFFECT_REVERB);
704 else
705 InitEffectParams(effect, AL_EFFECT_NULL);
706 for(const auto &reverbitem : reverblist)
708 const EFXEAXREVERBPROPERTIES *props;
710 if(al::strcasecmp(name, reverbitem.name) != 0)
711 continue;
713 TRACE("Loading reverb '%s'\n", reverbitem.name);
714 props = &reverbitem.props;
715 effect->Props.Reverb.Density = props->flDensity;
716 effect->Props.Reverb.Diffusion = props->flDiffusion;
717 effect->Props.Reverb.Gain = props->flGain;
718 effect->Props.Reverb.GainHF = props->flGainHF;
719 effect->Props.Reverb.GainLF = props->flGainLF;
720 effect->Props.Reverb.DecayTime = props->flDecayTime;
721 effect->Props.Reverb.DecayHFRatio = props->flDecayHFRatio;
722 effect->Props.Reverb.DecayLFRatio = props->flDecayLFRatio;
723 effect->Props.Reverb.ReflectionsGain = props->flReflectionsGain;
724 effect->Props.Reverb.ReflectionsDelay = props->flReflectionsDelay;
725 effect->Props.Reverb.ReflectionsPan[0] = props->flReflectionsPan[0];
726 effect->Props.Reverb.ReflectionsPan[1] = props->flReflectionsPan[1];
727 effect->Props.Reverb.ReflectionsPan[2] = props->flReflectionsPan[2];
728 effect->Props.Reverb.LateReverbGain = props->flLateReverbGain;
729 effect->Props.Reverb.LateReverbDelay = props->flLateReverbDelay;
730 effect->Props.Reverb.LateReverbPan[0] = props->flLateReverbPan[0];
731 effect->Props.Reverb.LateReverbPan[1] = props->flLateReverbPan[1];
732 effect->Props.Reverb.LateReverbPan[2] = props->flLateReverbPan[2];
733 effect->Props.Reverb.EchoTime = props->flEchoTime;
734 effect->Props.Reverb.EchoDepth = props->flEchoDepth;
735 effect->Props.Reverb.ModulationTime = props->flModulationTime;
736 effect->Props.Reverb.ModulationDepth = props->flModulationDepth;
737 effect->Props.Reverb.AirAbsorptionGainHF = props->flAirAbsorptionGainHF;
738 effect->Props.Reverb.HFReference = props->flHFReference;
739 effect->Props.Reverb.LFReference = props->flLFReference;
740 effect->Props.Reverb.RoomRolloffFactor = props->flRoomRolloffFactor;
741 effect->Props.Reverb.DecayHFLimit = props->iDecayHFLimit ? AL_TRUE : AL_FALSE;
742 return;
745 WARN("Reverb preset '%s' not found\n", name);