effect.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  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.
  8. *
  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.
  13. *
  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
  19. */
  20. #include "config.h"
  21. #include "effect.h"
  22. #include <algorithm>
  23. #include <cstdint>
  24. #include <cstring>
  25. #include <iterator>
  26. #include <memory>
  27. #include <mutex>
  28. #include <new>
  29. #include <numeric>
  30. #include <utility>
  31. #include "AL/al.h"
  32. #include "AL/alc.h"
  33. #include "AL/alext.h"
  34. #include "AL/efx-presets.h"
  35. #include "AL/efx.h"
  36. #include "alcmain.h"
  37. #include "alcontext.h"
  38. #include "alexcpt.h"
  39. #include "almalloc.h"
  40. #include "alnumeric.h"
  41. #include "alstring.h"
  42. #include "effects/base.h"
  43. #include "logging.h"
  44. #include "opthelpers.h"
  45. #include "vector.h"
  46. const EffectList gEffectList[15]{
  47. { "eaxreverb", EAXREVERB_EFFECT, AL_EFFECT_EAXREVERB },
  48. { "reverb", REVERB_EFFECT, AL_EFFECT_REVERB },
  49. { "autowah", AUTOWAH_EFFECT, AL_EFFECT_AUTOWAH },
  50. { "chorus", CHORUS_EFFECT, AL_EFFECT_CHORUS },
  51. { "compressor", COMPRESSOR_EFFECT, AL_EFFECT_COMPRESSOR },
  52. { "distortion", DISTORTION_EFFECT, AL_EFFECT_DISTORTION },
  53. { "echo", ECHO_EFFECT, AL_EFFECT_ECHO },
  54. { "equalizer", EQUALIZER_EFFECT, AL_EFFECT_EQUALIZER },
  55. { "flanger", FLANGER_EFFECT, AL_EFFECT_FLANGER },
  56. { "fshifter", FSHIFTER_EFFECT, AL_EFFECT_FREQUENCY_SHIFTER },
  57. { "modulator", MODULATOR_EFFECT, AL_EFFECT_RING_MODULATOR },
  58. { "pshifter", PSHIFTER_EFFECT, AL_EFFECT_PITCH_SHIFTER },
  59. { "vmorpher", VMORPHER_EFFECT, AL_EFFECT_VOCAL_MORPHER },
  60. { "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT },
  61. { "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_DIALOGUE },
  62. };
  63. ALboolean DisabledEffects[MAX_EFFECTS];
  64. namespace {
  65. constexpr struct FactoryItem {
  66. ALenum Type;
  67. EffectStateFactory* (&GetFactory)(void);
  68. } FactoryList[] = {
  69. { AL_EFFECT_NULL, NullStateFactory_getFactory },
  70. { AL_EFFECT_EAXREVERB, ReverbStateFactory_getFactory },
  71. { AL_EFFECT_REVERB, StdReverbStateFactory_getFactory },
  72. { AL_EFFECT_AUTOWAH, AutowahStateFactory_getFactory },
  73. { AL_EFFECT_CHORUS, ChorusStateFactory_getFactory },
  74. { AL_EFFECT_COMPRESSOR, CompressorStateFactory_getFactory },
  75. { AL_EFFECT_DISTORTION, DistortionStateFactory_getFactory },
  76. { AL_EFFECT_ECHO, EchoStateFactory_getFactory },
  77. { AL_EFFECT_EQUALIZER, EqualizerStateFactory_getFactory },
  78. { AL_EFFECT_FLANGER, FlangerStateFactory_getFactory },
  79. { AL_EFFECT_FREQUENCY_SHIFTER, FshifterStateFactory_getFactory },
  80. { AL_EFFECT_RING_MODULATOR, ModulatorStateFactory_getFactory },
  81. { AL_EFFECT_PITCH_SHIFTER, PshifterStateFactory_getFactory},
  82. { AL_EFFECT_VOCAL_MORPHER, VmorpherStateFactory_getFactory},
  83. { AL_EFFECT_DEDICATED_DIALOGUE, DedicatedStateFactory_getFactory },
  84. { AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, DedicatedStateFactory_getFactory }
  85. };
  86. template<typename... T>
  87. void ALeffect_setParami(ALeffect *effect, T&& ...args)
  88. { effect->vtab->setParami(&effect->Props, std::forward<T>(args)...); }
  89. template<typename... T>
  90. void ALeffect_setParamiv(ALeffect *effect, T&& ...args)
  91. { effect->vtab->setParamiv(&effect->Props, std::forward<T>(args)...); }
  92. template<typename... T>
  93. void ALeffect_setParamf(ALeffect *effect, T&& ...args)
  94. { effect->vtab->setParamf(&effect->Props, std::forward<T>(args)...); }
  95. template<typename... T>
  96. void ALeffect_setParamfv(ALeffect *effect, T&& ...args)
  97. { effect->vtab->setParamfv(&effect->Props, std::forward<T>(args)...); }
  98. template<typename... T>
  99. void ALeffect_getParami(const ALeffect *effect, T&& ...args)
  100. { effect->vtab->getParami(&effect->Props, std::forward<T>(args)...); }
  101. template<typename... T>
  102. void ALeffect_getParamiv(const ALeffect *effect, T&& ...args)
  103. { effect->vtab->getParamiv(&effect->Props, std::forward<T>(args)...); }
  104. template<typename... T>
  105. void ALeffect_getParamf(const ALeffect *effect, T&& ...args)
  106. { effect->vtab->getParamf(&effect->Props, std::forward<T>(args)...); }
  107. template<typename... T>
  108. void ALeffect_getParamfv(const ALeffect *effect, T&& ...args)
  109. { effect->vtab->getParamfv(&effect->Props, std::forward<T>(args)...); }
  110. void InitEffectParams(ALeffect *effect, ALenum type)
  111. {
  112. EffectStateFactory *factory = getFactoryByType(type);
  113. if(factory)
  114. {
  115. effect->Props = factory->getDefaultProps();
  116. effect->vtab = factory->getEffectVtable();
  117. }
  118. else
  119. {
  120. effect->Props = EffectProps{};
  121. effect->vtab = nullptr;
  122. }
  123. effect->type = type;
  124. }
  125. bool EnsureEffects(ALCdevice *device, size_t needed)
  126. {
  127. size_t count{std::accumulate(device->EffectList.cbegin(), device->EffectList.cend(), size_t{0},
  128. [](size_t cur, const EffectSubList &sublist) noexcept -> size_t
  129. { return cur + static_cast<ALuint>(POPCNT64(sublist.FreeMask)); }
  130. )};
  131. while(needed > count)
  132. {
  133. if UNLIKELY(device->EffectList.size() >= 1<<25)
  134. return false;
  135. device->EffectList.emplace_back();
  136. auto sublist = device->EffectList.end() - 1;
  137. sublist->FreeMask = ~0_u64;
  138. sublist->Effects = static_cast<ALeffect*>(al_calloc(alignof(ALeffect), sizeof(ALeffect)*64));
  139. if UNLIKELY(!sublist->Effects)
  140. {
  141. device->EffectList.pop_back();
  142. return false;
  143. }
  144. count += 64;
  145. }
  146. return true;
  147. }
  148. ALeffect *AllocEffect(ALCdevice *device)
  149. {
  150. auto sublist = std::find_if(device->EffectList.begin(), device->EffectList.end(),
  151. [](const EffectSubList &entry) noexcept -> bool
  152. { return entry.FreeMask != 0; }
  153. );
  154. auto lidx = static_cast<ALuint>(std::distance(device->EffectList.begin(), sublist));
  155. auto slidx = static_cast<ALuint>(CTZ64(sublist->FreeMask));
  156. ALeffect *effect{::new (sublist->Effects + slidx) ALeffect{}};
  157. InitEffectParams(effect, AL_EFFECT_NULL);
  158. /* Add 1 to avoid effect ID 0. */
  159. effect->id = ((lidx<<6) | slidx) + 1;
  160. sublist->FreeMask &= ~(1_u64 << slidx);
  161. return effect;
  162. }
  163. void FreeEffect(ALCdevice *device, ALeffect *effect)
  164. {
  165. const ALuint id{effect->id - 1};
  166. const size_t lidx{id >> 6};
  167. const ALuint slidx{id & 0x3f};
  168. al::destroy_at(effect);
  169. device->EffectList[lidx].FreeMask |= 1_u64 << slidx;
  170. }
  171. inline ALeffect *LookupEffect(ALCdevice *device, ALuint id)
  172. {
  173. const size_t lidx{(id-1) >> 6};
  174. const ALuint slidx{(id-1) & 0x3f};
  175. if UNLIKELY(lidx >= device->EffectList.size())
  176. return nullptr;
  177. EffectSubList &sublist = device->EffectList[lidx];
  178. if UNLIKELY(sublist.FreeMask & (1_u64 << slidx))
  179. return nullptr;
  180. return sublist.Effects + slidx;
  181. }
  182. } // namespace
  183. AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
  184. START_API_FUNC
  185. {
  186. ContextRef context{GetContextRef()};
  187. if UNLIKELY(!context) return;
  188. if UNLIKELY(n < 0)
  189. context->setError(AL_INVALID_VALUE, "Generating %d effects", n);
  190. if UNLIKELY(n <= 0) return;
  191. ALCdevice *device{context->mDevice.get()};
  192. std::lock_guard<std::mutex> _{device->EffectLock};
  193. if(!EnsureEffects(device, static_cast<ALuint>(n)))
  194. {
  195. context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d effect%s", n, (n==1)?"":"s");
  196. return;
  197. }
  198. if LIKELY(n == 1)
  199. {
  200. /* Special handling for the easy and normal case. */
  201. ALeffect *effect{AllocEffect(device)};
  202. effects[0] = effect->id;
  203. }
  204. else
  205. {
  206. /* Store the allocated buffer IDs in a separate local list, to avoid
  207. * modifying the user storage in case of failure.
  208. */
  209. al::vector<ALuint> ids;
  210. ids.reserve(static_cast<ALuint>(n));
  211. do {
  212. ALeffect *effect{AllocEffect(device)};
  213. ids.emplace_back(effect->id);
  214. } while(--n);
  215. std::copy(ids.cbegin(), ids.cend(), effects);
  216. }
  217. }
  218. END_API_FUNC
  219. AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects)
  220. START_API_FUNC
  221. {
  222. ContextRef context{GetContextRef()};
  223. if UNLIKELY(!context) return;
  224. if UNLIKELY(n < 0)
  225. context->setError(AL_INVALID_VALUE, "Deleting %d effects", n);
  226. if UNLIKELY(n <= 0) return;
  227. ALCdevice *device{context->mDevice.get()};
  228. std::lock_guard<std::mutex> _{device->EffectLock};
  229. /* First try to find any effects that are invalid. */
  230. auto validate_effect = [device](const ALuint eid) -> bool
  231. { return !eid || LookupEffect(device, eid) != nullptr; };
  232. const ALuint *effects_end = effects + n;
  233. auto inveffect = std::find_if_not(effects, effects_end, validate_effect);
  234. if UNLIKELY(inveffect != effects_end)
  235. {
  236. context->setError(AL_INVALID_NAME, "Invalid effect ID %u", *inveffect);
  237. return;
  238. }
  239. /* All good. Delete non-0 effect IDs. */
  240. auto delete_effect = [device](ALuint eid) -> void
  241. {
  242. ALeffect *effect{eid ? LookupEffect(device, eid) : nullptr};
  243. if(effect) FreeEffect(device, effect);
  244. };
  245. std::for_each(effects, effects_end, delete_effect);
  246. }
  247. END_API_FUNC
  248. AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
  249. START_API_FUNC
  250. {
  251. ContextRef context{GetContextRef()};
  252. if LIKELY(context)
  253. {
  254. ALCdevice *device{context->mDevice.get()};
  255. std::lock_guard<std::mutex> _{device->EffectLock};
  256. if(!effect || LookupEffect(device, effect))
  257. return AL_TRUE;
  258. }
  259. return AL_FALSE;
  260. }
  261. END_API_FUNC
  262. AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value)
  263. START_API_FUNC
  264. {
  265. ContextRef context{GetContextRef()};
  266. if UNLIKELY(!context) return;
  267. ALCdevice *device{context->mDevice.get()};
  268. std::lock_guard<std::mutex> _{device->EffectLock};
  269. ALeffect *aleffect{LookupEffect(device, effect)};
  270. if UNLIKELY(!aleffect)
  271. context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
  272. else
  273. {
  274. if(param == AL_EFFECT_TYPE)
  275. {
  276. ALboolean isOk{value == AL_EFFECT_NULL};
  277. if(!isOk)
  278. {
  279. for(const EffectList &effectitem : gEffectList)
  280. {
  281. if(value == effectitem.val && !DisabledEffects[effectitem.type])
  282. {
  283. isOk = AL_TRUE;
  284. break;
  285. }
  286. }
  287. }
  288. if(isOk)
  289. InitEffectParams(aleffect, value);
  290. else
  291. context->setError(AL_INVALID_VALUE, "Effect type 0x%04x not supported", value);
  292. }
  293. else
  294. {
  295. /* Call the appropriate handler */
  296. ALeffect_setParami(aleffect, context.get(), param, value);
  297. }
  298. }
  299. }
  300. END_API_FUNC
  301. AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *values)
  302. START_API_FUNC
  303. {
  304. switch(param)
  305. {
  306. case AL_EFFECT_TYPE:
  307. alEffecti(effect, param, values[0]);
  308. return;
  309. }
  310. ContextRef context{GetContextRef()};
  311. if UNLIKELY(!context) return;
  312. ALCdevice *device{context->mDevice.get()};
  313. 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
  318. {
  319. /* Call the appropriate handler */
  320. ALeffect_setParamiv(aleffect, context.get(), param, values);
  321. }
  322. }
  323. END_API_FUNC
  324. AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat value)
  325. START_API_FUNC
  326. {
  327. ContextRef context{GetContextRef()};
  328. if UNLIKELY(!context) return;
  329. ALCdevice *device{context->mDevice.get()};
  330. 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
  335. {
  336. /* Call the appropriate handler */
  337. ALeffect_setParamf(aleffect, context.get(), param, value);
  338. }
  339. }
  340. END_API_FUNC
  341. AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *values)
  342. START_API_FUNC
  343. {
  344. ContextRef context{GetContextRef()};
  345. if UNLIKELY(!context) return;
  346. ALCdevice *device{context->mDevice.get()};
  347. std::lock_guard<std::mutex> _{device->EffectLock};
  348. ALeffect *aleffect{LookupEffect(device, effect)};
  349. if UNLIKELY(!aleffect)
  350. context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
  351. else
  352. {
  353. /* Call the appropriate handler */
  354. ALeffect_setParamfv(aleffect, context.get(), param, values);
  355. }
  356. }
  357. END_API_FUNC
  358. AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value)
  359. START_API_FUNC
  360. {
  361. ContextRef context{GetContextRef()};
  362. if UNLIKELY(!context) return;
  363. ALCdevice *device{context->mDevice.get()};
  364. std::lock_guard<std::mutex> _{device->EffectLock};
  365. const ALeffect *aleffect{LookupEffect(device, effect)};
  366. if UNLIKELY(!aleffect)
  367. context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
  368. else
  369. {
  370. if(param == AL_EFFECT_TYPE)
  371. *value = aleffect->type;
  372. else
  373. {
  374. /* Call the appropriate handler */
  375. ALeffect_getParami(aleffect, context.get(), param, value);
  376. }
  377. }
  378. }
  379. END_API_FUNC
  380. AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *values)
  381. START_API_FUNC
  382. {
  383. switch(param)
  384. {
  385. case AL_EFFECT_TYPE:
  386. alGetEffecti(effect, param, values);
  387. return;
  388. }
  389. ContextRef context{GetContextRef()};
  390. if UNLIKELY(!context) return;
  391. ALCdevice *device{context->mDevice.get()};
  392. std::lock_guard<std::mutex> _{device->EffectLock};
  393. const ALeffect *aleffect{LookupEffect(device, effect)};
  394. if UNLIKELY(!aleffect)
  395. context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
  396. else
  397. {
  398. /* Call the appropriate handler */
  399. ALeffect_getParamiv(aleffect, context.get(), param, values);
  400. }
  401. }
  402. END_API_FUNC
  403. AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *value)
  404. START_API_FUNC
  405. {
  406. ContextRef context{GetContextRef()};
  407. if UNLIKELY(!context) return;
  408. ALCdevice *device{context->mDevice.get()};
  409. std::lock_guard<std::mutex> _{device->EffectLock};
  410. const ALeffect *aleffect{LookupEffect(device, effect)};
  411. if UNLIKELY(!aleffect)
  412. context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
  413. else
  414. {
  415. /* Call the appropriate handler */
  416. ALeffect_getParamf(aleffect, context.get(), param, value);
  417. }
  418. }
  419. END_API_FUNC
  420. AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *values)
  421. START_API_FUNC
  422. {
  423. ContextRef context{GetContextRef()};
  424. if UNLIKELY(!context) return;
  425. ALCdevice *device{context->mDevice.get()};
  426. std::lock_guard<std::mutex> _{device->EffectLock};
  427. const ALeffect *aleffect{LookupEffect(device, effect)};
  428. if UNLIKELY(!aleffect)
  429. context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
  430. else
  431. {
  432. /* Call the appropriate handler */
  433. ALeffect_getParamfv(aleffect, context.get(), param, values);
  434. }
  435. }
  436. END_API_FUNC
  437. void InitEffect(ALeffect *effect)
  438. {
  439. InitEffectParams(effect, AL_EFFECT_NULL);
  440. }
  441. EffectSubList::~EffectSubList()
  442. {
  443. uint64_t usemask{~FreeMask};
  444. while(usemask)
  445. {
  446. ALsizei idx = CTZ64(usemask);
  447. al::destroy_at(Effects+idx);
  448. usemask &= ~(1_u64 << idx);
  449. }
  450. FreeMask = ~usemask;
  451. al_free(Effects);
  452. Effects = nullptr;
  453. }
  454. EffectStateFactory *getFactoryByType(ALenum type)
  455. {
  456. auto iter = std::find_if(std::begin(FactoryList), std::end(FactoryList),
  457. [type](const FactoryItem &item) noexcept -> bool
  458. { return item.Type == type; }
  459. );
  460. return (iter != std::end(FactoryList)) ? iter->GetFactory() : nullptr;
  461. }
  462. #define DECL(x) { #x, EFX_REVERB_PRESET_##x }
  463. static const struct {
  464. const char name[32];
  465. EFXEAXREVERBPROPERTIES props;
  466. } reverblist[] = {
  467. DECL(GENERIC),
  468. DECL(PADDEDCELL),
  469. DECL(ROOM),
  470. DECL(BATHROOM),
  471. DECL(LIVINGROOM),
  472. DECL(STONEROOM),
  473. DECL(AUDITORIUM),
  474. DECL(CONCERTHALL),
  475. DECL(CAVE),
  476. DECL(ARENA),
  477. DECL(HANGAR),
  478. DECL(CARPETEDHALLWAY),
  479. DECL(HALLWAY),
  480. DECL(STONECORRIDOR),
  481. DECL(ALLEY),
  482. DECL(FOREST),
  483. DECL(CITY),
  484. DECL(MOUNTAINS),
  485. DECL(QUARRY),
  486. DECL(PLAIN),
  487. DECL(PARKINGLOT),
  488. DECL(SEWERPIPE),
  489. DECL(UNDERWATER),
  490. DECL(DRUGGED),
  491. DECL(DIZZY),
  492. DECL(PSYCHOTIC),
  493. DECL(CASTLE_SMALLROOM),
  494. DECL(CASTLE_SHORTPASSAGE),
  495. DECL(CASTLE_MEDIUMROOM),
  496. DECL(CASTLE_LARGEROOM),
  497. DECL(CASTLE_LONGPASSAGE),
  498. DECL(CASTLE_HALL),
  499. DECL(CASTLE_CUPBOARD),
  500. DECL(CASTLE_COURTYARD),
  501. DECL(CASTLE_ALCOVE),
  502. DECL(FACTORY_SMALLROOM),
  503. DECL(FACTORY_SHORTPASSAGE),
  504. DECL(FACTORY_MEDIUMROOM),
  505. DECL(FACTORY_LARGEROOM),
  506. DECL(FACTORY_LONGPASSAGE),
  507. DECL(FACTORY_HALL),
  508. DECL(FACTORY_CUPBOARD),
  509. DECL(FACTORY_COURTYARD),
  510. DECL(FACTORY_ALCOVE),
  511. DECL(ICEPALACE_SMALLROOM),
  512. DECL(ICEPALACE_SHORTPASSAGE),
  513. DECL(ICEPALACE_MEDIUMROOM),
  514. DECL(ICEPALACE_LARGEROOM),
  515. DECL(ICEPALACE_LONGPASSAGE),
  516. DECL(ICEPALACE_HALL),
  517. DECL(ICEPALACE_CUPBOARD),
  518. DECL(ICEPALACE_COURTYARD),
  519. DECL(ICEPALACE_ALCOVE),
  520. DECL(SPACESTATION_SMALLROOM),
  521. DECL(SPACESTATION_SHORTPASSAGE),
  522. DECL(SPACESTATION_MEDIUMROOM),
  523. DECL(SPACESTATION_LARGEROOM),
  524. DECL(SPACESTATION_LONGPASSAGE),
  525. DECL(SPACESTATION_HALL),
  526. DECL(SPACESTATION_CUPBOARD),
  527. DECL(SPACESTATION_ALCOVE),
  528. DECL(WOODEN_SMALLROOM),
  529. DECL(WOODEN_SHORTPASSAGE),
  530. DECL(WOODEN_MEDIUMROOM),
  531. DECL(WOODEN_LARGEROOM),
  532. DECL(WOODEN_LONGPASSAGE),
  533. DECL(WOODEN_HALL),
  534. DECL(WOODEN_CUPBOARD),
  535. DECL(WOODEN_COURTYARD),
  536. DECL(WOODEN_ALCOVE),
  537. DECL(SPORT_EMPTYSTADIUM),
  538. DECL(SPORT_SQUASHCOURT),
  539. DECL(SPORT_SMALLSWIMMINGPOOL),
  540. DECL(SPORT_LARGESWIMMINGPOOL),
  541. DECL(SPORT_GYMNASIUM),
  542. DECL(SPORT_FULLSTADIUM),
  543. DECL(SPORT_STADIUMTANNOY),
  544. DECL(PREFAB_WORKSHOP),
  545. DECL(PREFAB_SCHOOLROOM),
  546. DECL(PREFAB_PRACTISEROOM),
  547. DECL(PREFAB_OUTHOUSE),
  548. DECL(PREFAB_CARAVAN),
  549. DECL(DOME_TOMB),
  550. DECL(PIPE_SMALL),
  551. DECL(DOME_SAINTPAULS),
  552. DECL(PIPE_LONGTHIN),
  553. DECL(PIPE_LARGE),
  554. DECL(PIPE_RESONANT),
  555. DECL(OUTDOORS_BACKYARD),
  556. DECL(OUTDOORS_ROLLINGPLAINS),
  557. DECL(OUTDOORS_DEEPCANYON),
  558. DECL(OUTDOORS_CREEK),
  559. DECL(OUTDOORS_VALLEY),
  560. DECL(MOOD_HEAVEN),
  561. DECL(MOOD_HELL),
  562. DECL(MOOD_MEMORY),
  563. DECL(DRIVING_COMMENTATOR),
  564. DECL(DRIVING_PITGARAGE),
  565. DECL(DRIVING_INCAR_RACER),
  566. DECL(DRIVING_INCAR_SPORTS),
  567. DECL(DRIVING_INCAR_LUXURY),
  568. DECL(DRIVING_FULLGRANDSTAND),
  569. DECL(DRIVING_EMPTYGRANDSTAND),
  570. DECL(DRIVING_TUNNEL),
  571. DECL(CITY_STREETS),
  572. DECL(CITY_SUBWAY),
  573. DECL(CITY_MUSEUM),
  574. DECL(CITY_LIBRARY),
  575. DECL(CITY_UNDERPASS),
  576. DECL(CITY_ABANDONED),
  577. DECL(DUSTYROOM),
  578. DECL(CHAPEL),
  579. DECL(SMALLWATERROOM),
  580. };
  581. #undef DECL
  582. void LoadReverbPreset(const char *name, ALeffect *effect)
  583. {
  584. if(al::strcasecmp(name, "NONE") == 0)
  585. {
  586. InitEffectParams(effect, AL_EFFECT_NULL);
  587. TRACE("Loading reverb '%s'\n", "NONE");
  588. return;
  589. }
  590. if(!DisabledEffects[EAXREVERB_EFFECT])
  591. InitEffectParams(effect, AL_EFFECT_EAXREVERB);
  592. else if(!DisabledEffects[REVERB_EFFECT])
  593. InitEffectParams(effect, AL_EFFECT_REVERB);
  594. else
  595. InitEffectParams(effect, AL_EFFECT_NULL);
  596. for(const auto &reverbitem : reverblist)
  597. {
  598. const EFXEAXREVERBPROPERTIES *props;
  599. if(al::strcasecmp(name, reverbitem.name) != 0)
  600. continue;
  601. TRACE("Loading reverb '%s'\n", reverbitem.name);
  602. props = &reverbitem.props;
  603. effect->Props.Reverb.Density = props->flDensity;
  604. effect->Props.Reverb.Diffusion = props->flDiffusion;
  605. effect->Props.Reverb.Gain = props->flGain;
  606. effect->Props.Reverb.GainHF = props->flGainHF;
  607. effect->Props.Reverb.GainLF = props->flGainLF;
  608. effect->Props.Reverb.DecayTime = props->flDecayTime;
  609. effect->Props.Reverb.DecayHFRatio = props->flDecayHFRatio;
  610. effect->Props.Reverb.DecayLFRatio = props->flDecayLFRatio;
  611. effect->Props.Reverb.ReflectionsGain = props->flReflectionsGain;
  612. effect->Props.Reverb.ReflectionsDelay = props->flReflectionsDelay;
  613. effect->Props.Reverb.ReflectionsPan[0] = props->flReflectionsPan[0];
  614. effect->Props.Reverb.ReflectionsPan[1] = props->flReflectionsPan[1];
  615. effect->Props.Reverb.ReflectionsPan[2] = props->flReflectionsPan[2];
  616. effect->Props.Reverb.LateReverbGain = props->flLateReverbGain;
  617. effect->Props.Reverb.LateReverbDelay = props->flLateReverbDelay;
  618. effect->Props.Reverb.LateReverbPan[0] = props->flLateReverbPan[0];
  619. effect->Props.Reverb.LateReverbPan[1] = props->flLateReverbPan[1];
  620. effect->Props.Reverb.LateReverbPan[2] = props->flLateReverbPan[2];
  621. effect->Props.Reverb.EchoTime = props->flEchoTime;
  622. effect->Props.Reverb.EchoDepth = props->flEchoDepth;
  623. effect->Props.Reverb.ModulationTime = props->flModulationTime;
  624. effect->Props.Reverb.ModulationDepth = props->flModulationDepth;
  625. effect->Props.Reverb.AirAbsorptionGainHF = props->flAirAbsorptionGainHF;
  626. effect->Props.Reverb.HFReference = props->flHFReference;
  627. effect->Props.Reverb.LFReference = props->flLFReference;
  628. effect->Props.Reverb.RoomRolloffFactor = props->flRoomRolloffFactor;
  629. effect->Props.Reverb.DecayHFLimit = props->iDecayHFLimit ? AL_TRUE : AL_FALSE;
  630. return;
  631. }
  632. WARN("Reverb preset '%s' not found\n", name);
  633. }