🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

727 lines
22 KiB

  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 <cstdlib>
  22. #include <cmath>
  23. #include <cfloat>
  24. #include <algorithm>
  25. #include "AL/al.h"
  26. #include "AL/alc.h"
  27. #include "alMain.h"
  28. #include "alcontext.h"
  29. #include "alEffect.h"
  30. #include "alError.h"
  31. #include "alexcpt.h"
  32. #include "effects/base.h"
  33. const EffectList gEffectList[14]{
  34. { "eaxreverb", EAXREVERB_EFFECT, AL_EFFECT_EAXREVERB },
  35. { "reverb", REVERB_EFFECT, AL_EFFECT_REVERB },
  36. { "autowah", AUTOWAH_EFFECT, AL_EFFECT_AUTOWAH },
  37. { "chorus", CHORUS_EFFECT, AL_EFFECT_CHORUS },
  38. { "compressor", COMPRESSOR_EFFECT, AL_EFFECT_COMPRESSOR },
  39. { "distortion", DISTORTION_EFFECT, AL_EFFECT_DISTORTION },
  40. { "echo", ECHO_EFFECT, AL_EFFECT_ECHO },
  41. { "equalizer", EQUALIZER_EFFECT, AL_EFFECT_EQUALIZER },
  42. { "flanger", FLANGER_EFFECT, AL_EFFECT_FLANGER },
  43. { "fshifter", FSHIFTER_EFFECT, AL_EFFECT_FREQUENCY_SHIFTER },
  44. { "modulator", MODULATOR_EFFECT, AL_EFFECT_RING_MODULATOR },
  45. { "pshifter", PSHIFTER_EFFECT, AL_EFFECT_PITCH_SHIFTER },
  46. { "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT },
  47. { "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_DIALOGUE },
  48. };
  49. ALboolean DisabledEffects[MAX_EFFECTS];
  50. namespace {
  51. constexpr struct FactoryItem {
  52. ALenum Type;
  53. EffectStateFactory* (&GetFactory)(void);
  54. } FactoryList[] = {
  55. { AL_EFFECT_NULL, NullStateFactory_getFactory },
  56. { AL_EFFECT_EAXREVERB, ReverbStateFactory_getFactory },
  57. { AL_EFFECT_REVERB, StdReverbStateFactory_getFactory },
  58. { AL_EFFECT_AUTOWAH, AutowahStateFactory_getFactory },
  59. { AL_EFFECT_CHORUS, ChorusStateFactory_getFactory },
  60. { AL_EFFECT_COMPRESSOR, CompressorStateFactory_getFactory },
  61. { AL_EFFECT_DISTORTION, DistortionStateFactory_getFactory },
  62. { AL_EFFECT_ECHO, EchoStateFactory_getFactory },
  63. { AL_EFFECT_EQUALIZER, EqualizerStateFactory_getFactory },
  64. { AL_EFFECT_FLANGER, FlangerStateFactory_getFactory },
  65. { AL_EFFECT_FREQUENCY_SHIFTER, FshifterStateFactory_getFactory },
  66. { AL_EFFECT_RING_MODULATOR, ModulatorStateFactory_getFactory },
  67. { AL_EFFECT_PITCH_SHIFTER, PshifterStateFactory_getFactory},
  68. { AL_EFFECT_DEDICATED_DIALOGUE, DedicatedStateFactory_getFactory },
  69. { AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, DedicatedStateFactory_getFactory }
  70. };
  71. template<typename... T>
  72. void ALeffect_setParami(ALeffect *effect, T&& ...args)
  73. { effect->vtab->setParami(&effect->Props, std::forward<T>(args)...); }
  74. template<typename... T>
  75. void ALeffect_setParamiv(ALeffect *effect, T&& ...args)
  76. { effect->vtab->setParamiv(&effect->Props, std::forward<T>(args)...); }
  77. template<typename... T>
  78. void ALeffect_setParamf(ALeffect *effect, T&& ...args)
  79. { effect->vtab->setParamf(&effect->Props, std::forward<T>(args)...); }
  80. template<typename... T>
  81. void ALeffect_setParamfv(ALeffect *effect, T&& ...args)
  82. { effect->vtab->setParamfv(&effect->Props, std::forward<T>(args)...); }
  83. template<typename... T>
  84. void ALeffect_getParami(const ALeffect *effect, T&& ...args)
  85. { effect->vtab->getParami(&effect->Props, std::forward<T>(args)...); }
  86. template<typename... T>
  87. void ALeffect_getParamiv(const ALeffect *effect, T&& ...args)
  88. { effect->vtab->getParamiv(&effect->Props, std::forward<T>(args)...); }
  89. template<typename... T>
  90. void ALeffect_getParamf(const ALeffect *effect, T&& ...args)
  91. { effect->vtab->getParamf(&effect->Props, std::forward<T>(args)...); }
  92. template<typename... T>
  93. void ALeffect_getParamfv(const ALeffect *effect, T&& ...args)
  94. { effect->vtab->getParamfv(&effect->Props, std::forward<T>(args)...); }
  95. void InitEffectParams(ALeffect *effect, ALenum type)
  96. {
  97. EffectStateFactory *factory = getFactoryByType(type);
  98. if(factory)
  99. {
  100. effect->Props = factory->getDefaultProps();
  101. effect->vtab = factory->getEffectVtable();
  102. }
  103. else
  104. {
  105. effect->Props = EffectProps {};
  106. effect->vtab = nullptr;
  107. }
  108. effect->type = type;
  109. }
  110. ALeffect *AllocEffect(ALCcontext *context)
  111. {
  112. ALCdevice *device{context->Device};
  113. std::lock_guard<std::mutex> _{device->EffectLock};
  114. auto sublist = std::find_if(device->EffectList.begin(), device->EffectList.end(),
  115. [](const EffectSubList &entry) noexcept -> bool
  116. { return entry.FreeMask != 0; }
  117. );
  118. auto lidx = static_cast<ALsizei>(std::distance(device->EffectList.begin(), sublist));
  119. ALeffect *effect{nullptr};
  120. ALsizei slidx{0};
  121. if(LIKELY(sublist != device->EffectList.end()))
  122. {
  123. slidx = CTZ64(sublist->FreeMask);
  124. effect = sublist->Effects + slidx;
  125. }
  126. else
  127. {
  128. /* Don't allocate so many list entries that the 32-bit ID could
  129. * overflow...
  130. */
  131. if(UNLIKELY(device->EffectList.size() >= 1<<25))
  132. {
  133. alSetError(context, AL_OUT_OF_MEMORY, "Too many effects allocated");
  134. return nullptr;
  135. }
  136. device->EffectList.emplace_back();
  137. sublist = device->EffectList.end() - 1;
  138. sublist->FreeMask = ~0_u64;
  139. sublist->Effects = static_cast<ALeffect*>(al_calloc(16, sizeof(ALeffect)*64));
  140. if(UNLIKELY(!sublist->Effects))
  141. {
  142. device->EffectList.pop_back();
  143. alSetError(context, AL_OUT_OF_MEMORY, "Failed to allocate effect batch");
  144. return nullptr;
  145. }
  146. slidx = 0;
  147. effect = sublist->Effects + slidx;
  148. }
  149. effect = new (effect) ALeffect{};
  150. InitEffectParams(effect, AL_EFFECT_NULL);
  151. /* Add 1 to avoid effect ID 0. */
  152. effect->id = ((lidx<<6) | slidx) + 1;
  153. sublist->FreeMask &= ~(1_u64 << slidx);
  154. return effect;
  155. }
  156. void FreeEffect(ALCdevice *device, ALeffect *effect)
  157. {
  158. ALuint id = effect->id - 1;
  159. ALsizei lidx = id >> 6;
  160. ALsizei slidx = id & 0x3f;
  161. effect->~ALeffect();
  162. device->EffectList[lidx].FreeMask |= 1_u64 << slidx;
  163. }
  164. inline ALeffect *LookupEffect(ALCdevice *device, ALuint id)
  165. {
  166. ALuint lidx = (id-1) >> 6;
  167. ALsizei slidx = (id-1) & 0x3f;
  168. if(UNLIKELY(lidx >= device->EffectList.size()))
  169. return nullptr;
  170. EffectSubList &sublist = device->EffectList[lidx];
  171. if(UNLIKELY(sublist.FreeMask & (1_u64 << slidx)))
  172. return nullptr;
  173. return sublist.Effects + slidx;
  174. }
  175. } // namespace
  176. AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
  177. START_API_FUNC
  178. {
  179. ContextRef context{GetContextRef()};
  180. if(UNLIKELY(!context)) return;
  181. if(UNLIKELY(n < 0))
  182. {
  183. alSetError(context.get(), AL_INVALID_VALUE, "Generating %d effects", n);
  184. return;
  185. }
  186. if(LIKELY(n == 1))
  187. {
  188. /* Special handling for the easy and normal case. */
  189. ALeffect *effect = AllocEffect(context.get());
  190. if(effect) effects[0] = effect->id;
  191. }
  192. else if(n > 1)
  193. {
  194. /* Store the allocated buffer IDs in a separate local list, to avoid
  195. * modifying the user storage in case of failure.
  196. */
  197. al::vector<ALuint> ids;
  198. ids.reserve(n);
  199. do {
  200. ALeffect *effect = AllocEffect(context.get());
  201. if(!effect)
  202. {
  203. alDeleteEffects(static_cast<ALsizei>(ids.size()), ids.data());
  204. return;
  205. }
  206. ids.emplace_back(effect->id);
  207. } while(--n);
  208. std::copy(ids.begin(), ids.end(), effects);
  209. }
  210. }
  211. END_API_FUNC
  212. AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects)
  213. START_API_FUNC
  214. {
  215. ContextRef context{GetContextRef()};
  216. if(UNLIKELY(!context)) return;
  217. if(UNLIKELY(n < 0))
  218. {
  219. alSetError(context.get(), AL_INVALID_VALUE, "Deleting %d effects", n);
  220. return;
  221. }
  222. if(UNLIKELY(n == 0))
  223. return;
  224. ALCdevice *device{context->Device};
  225. std::lock_guard<std::mutex> _{device->EffectLock};
  226. /* First try to find any effects that are invalid. */
  227. const ALuint *effects_end = effects + n;
  228. auto inveffect = std::find_if(effects, effects_end,
  229. [device, &context](ALuint eid) -> bool
  230. {
  231. if(!eid) return false;
  232. ALeffect *effect{LookupEffect(device, eid)};
  233. if(UNLIKELY(!effect))
  234. {
  235. alSetError(context.get(), AL_INVALID_NAME, "Invalid effect ID %u", eid);
  236. return true;
  237. }
  238. return false;
  239. }
  240. );
  241. if(LIKELY(inveffect == effects_end))
  242. {
  243. /* All good. Delete non-0 effect IDs. */
  244. std::for_each(effects, effects_end,
  245. [device](ALuint eid) -> void
  246. {
  247. ALeffect *effect{eid ? LookupEffect(device, eid) : nullptr};
  248. if(effect) FreeEffect(device, effect);
  249. }
  250. );
  251. }
  252. }
  253. END_API_FUNC
  254. AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
  255. START_API_FUNC
  256. {
  257. ContextRef context{GetContextRef()};
  258. if(LIKELY(context))
  259. {
  260. ALCdevice *device{context->Device};
  261. std::lock_guard<std::mutex> _{device->EffectLock};
  262. if(!effect || LookupEffect(device, effect))
  263. return AL_TRUE;
  264. }
  265. return AL_FALSE;
  266. }
  267. END_API_FUNC
  268. AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value)
  269. START_API_FUNC
  270. {
  271. ContextRef context{GetContextRef()};
  272. if(UNLIKELY(!context)) return;
  273. ALCdevice *device{context->Device};
  274. std::lock_guard<std::mutex> _{device->EffectLock};
  275. ALeffect *aleffect{LookupEffect(device, effect)};
  276. if(UNLIKELY(!aleffect))
  277. alSetError(context.get(), AL_INVALID_NAME, "Invalid effect ID %u", effect);
  278. else
  279. {
  280. if(param == AL_EFFECT_TYPE)
  281. {
  282. ALboolean isOk = (value == AL_EFFECT_NULL);
  283. for(size_t i{0u};!isOk && i < countof(gEffectList);i++)
  284. {
  285. if(value == gEffectList[i].val && !DisabledEffects[gEffectList[i].type])
  286. isOk = AL_TRUE;
  287. }
  288. if(isOk)
  289. InitEffectParams(aleffect, value);
  290. else
  291. alSetError(context.get(), 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->Device};
  313. std::lock_guard<std::mutex> _{device->EffectLock};
  314. ALeffect *aleffect{LookupEffect(device, effect)};
  315. if(UNLIKELY(!aleffect))
  316. alSetError(context.get(), 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->Device};
  330. std::lock_guard<std::mutex> _{device->EffectLock};
  331. ALeffect *aleffect{LookupEffect(device, effect)};
  332. if(UNLIKELY(!aleffect))
  333. alSetError(context.get(), 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->Device};
  347. std::lock_guard<std::mutex> _{device->EffectLock};
  348. ALeffect *aleffect{LookupEffect(device, effect)};
  349. if(UNLIKELY(!aleffect))
  350. alSetError(context.get(), 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->Device};
  364. std::lock_guard<std::mutex> _{device->EffectLock};
  365. const ALeffect *aleffect{LookupEffect(device, effect)};
  366. if(UNLIKELY(!aleffect))
  367. alSetError(context.get(), 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->Device};
  392. std::lock_guard<std::mutex> _{device->EffectLock};
  393. const ALeffect *aleffect{LookupEffect(device, effect)};
  394. if(UNLIKELY(!aleffect))
  395. alSetError(context.get(), 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->Device};
  409. std::lock_guard<std::mutex> _{device->EffectLock};
  410. const ALeffect *aleffect{LookupEffect(device, effect)};
  411. if(UNLIKELY(!aleffect))
  412. alSetError(context.get(), 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->Device};
  426. std::lock_guard<std::mutex> _{device->EffectLock};
  427. const ALeffect *aleffect{LookupEffect(device, effect)};
  428. if(UNLIKELY(!aleffect))
  429. alSetError(context.get(), 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. Effects[idx].~ALeffect();
  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. #include "AL/efx-presets.h"
  463. #define DECL(x) { #x, EFX_REVERB_PRESET_##x }
  464. static const struct {
  465. const char name[32];
  466. EFXEAXREVERBPROPERTIES props;
  467. } reverblist[] = {
  468. DECL(GENERIC),
  469. DECL(PADDEDCELL),
  470. DECL(ROOM),
  471. DECL(BATHROOM),
  472. DECL(LIVINGROOM),
  473. DECL(STONEROOM),
  474. DECL(AUDITORIUM),
  475. DECL(CONCERTHALL),
  476. DECL(CAVE),
  477. DECL(ARENA),
  478. DECL(HANGAR),
  479. DECL(CARPETEDHALLWAY),
  480. DECL(HALLWAY),
  481. DECL(STONECORRIDOR),
  482. DECL(ALLEY),
  483. DECL(FOREST),
  484. DECL(CITY),
  485. DECL(MOUNTAINS),
  486. DECL(QUARRY),
  487. DECL(PLAIN),
  488. DECL(PARKINGLOT),
  489. DECL(SEWERPIPE),
  490. DECL(UNDERWATER),
  491. DECL(DRUGGED),
  492. DECL(DIZZY),
  493. DECL(PSYCHOTIC),
  494. DECL(CASTLE_SMALLROOM),
  495. DECL(CASTLE_SHORTPASSAGE),
  496. DECL(CASTLE_MEDIUMROOM),
  497. DECL(CASTLE_LARGEROOM),
  498. DECL(CASTLE_LONGPASSAGE),
  499. DECL(CASTLE_HALL),
  500. DECL(CASTLE_CUPBOARD),
  501. DECL(CASTLE_COURTYARD),
  502. DECL(CASTLE_ALCOVE),
  503. DECL(FACTORY_SMALLROOM),
  504. DECL(FACTORY_SHORTPASSAGE),
  505. DECL(FACTORY_MEDIUMROOM),
  506. DECL(FACTORY_LARGEROOM),
  507. DECL(FACTORY_LONGPASSAGE),
  508. DECL(FACTORY_HALL),
  509. DECL(FACTORY_CUPBOARD),
  510. DECL(FACTORY_COURTYARD),
  511. DECL(FACTORY_ALCOVE),
  512. DECL(ICEPALACE_SMALLROOM),
  513. DECL(ICEPALACE_SHORTPASSAGE),
  514. DECL(ICEPALACE_MEDIUMROOM),
  515. DECL(ICEPALACE_LARGEROOM),
  516. DECL(ICEPALACE_LONGPASSAGE),
  517. DECL(ICEPALACE_HALL),
  518. DECL(ICEPALACE_CUPBOARD),
  519. DECL(ICEPALACE_COURTYARD),
  520. DECL(ICEPALACE_ALCOVE),
  521. DECL(SPACESTATION_SMALLROOM),
  522. DECL(SPACESTATION_SHORTPASSAGE),
  523. DECL(SPACESTATION_MEDIUMROOM),
  524. DECL(SPACESTATION_LARGEROOM),
  525. DECL(SPACESTATION_LONGPASSAGE),
  526. DECL(SPACESTATION_HALL),
  527. DECL(SPACESTATION_CUPBOARD),
  528. DECL(SPACESTATION_ALCOVE),
  529. DECL(WOODEN_SMALLROOM),
  530. DECL(WOODEN_SHORTPASSAGE),
  531. DECL(WOODEN_MEDIUMROOM),
  532. DECL(WOODEN_LARGEROOM),
  533. DECL(WOODEN_LONGPASSAGE),
  534. DECL(WOODEN_HALL),
  535. DECL(WOODEN_CUPBOARD),
  536. DECL(WOODEN_COURTYARD),
  537. DECL(WOODEN_ALCOVE),
  538. DECL(SPORT_EMPTYSTADIUM),
  539. DECL(SPORT_SQUASHCOURT),
  540. DECL(SPORT_SMALLSWIMMINGPOOL),
  541. DECL(SPORT_LARGESWIMMINGPOOL),
  542. DECL(SPORT_GYMNASIUM),
  543. DECL(SPORT_FULLSTADIUM),
  544. DECL(SPORT_STADIUMTANNOY),
  545. DECL(PREFAB_WORKSHOP),
  546. DECL(PREFAB_SCHOOLROOM),
  547. DECL(PREFAB_PRACTISEROOM),
  548. DECL(PREFAB_OUTHOUSE),
  549. DECL(PREFAB_CARAVAN),
  550. DECL(DOME_TOMB),
  551. DECL(PIPE_SMALL),
  552. DECL(DOME_SAINTPAULS),
  553. DECL(PIPE_LONGTHIN),
  554. DECL(PIPE_LARGE),
  555. DECL(PIPE_RESONANT),
  556. DECL(OUTDOORS_BACKYARD),
  557. DECL(OUTDOORS_ROLLINGPLAINS),
  558. DECL(OUTDOORS_DEEPCANYON),
  559. DECL(OUTDOORS_CREEK),
  560. DECL(OUTDOORS_VALLEY),
  561. DECL(MOOD_HEAVEN),
  562. DECL(MOOD_HELL),
  563. DECL(MOOD_MEMORY),
  564. DECL(DRIVING_COMMENTATOR),
  565. DECL(DRIVING_PITGARAGE),
  566. DECL(DRIVING_INCAR_RACER),
  567. DECL(DRIVING_INCAR_SPORTS),
  568. DECL(DRIVING_INCAR_LUXURY),
  569. DECL(DRIVING_FULLGRANDSTAND),
  570. DECL(DRIVING_EMPTYGRANDSTAND),
  571. DECL(DRIVING_TUNNEL),
  572. DECL(CITY_STREETS),
  573. DECL(CITY_SUBWAY),
  574. DECL(CITY_MUSEUM),
  575. DECL(CITY_LIBRARY),
  576. DECL(CITY_UNDERPASS),
  577. DECL(CITY_ABANDONED),
  578. DECL(DUSTYROOM),
  579. DECL(CHAPEL),
  580. DECL(SMALLWATERROOM),
  581. };
  582. #undef DECL
  583. void LoadReverbPreset(const char *name, ALeffect *effect)
  584. {
  585. size_t i;
  586. if(strcasecmp(name, "NONE") == 0)
  587. {
  588. InitEffectParams(effect, AL_EFFECT_NULL);
  589. TRACE("Loading reverb '%s'\n", "NONE");
  590. return;
  591. }
  592. if(!DisabledEffects[EAXREVERB_EFFECT])
  593. InitEffectParams(effect, AL_EFFECT_EAXREVERB);
  594. else if(!DisabledEffects[REVERB_EFFECT])
  595. InitEffectParams(effect, AL_EFFECT_REVERB);
  596. else
  597. InitEffectParams(effect, AL_EFFECT_NULL);
  598. for(i = 0;i < COUNTOF(reverblist);i++)
  599. {
  600. const EFXEAXREVERBPROPERTIES *props;
  601. if(strcasecmp(name, reverblist[i].name) != 0)
  602. continue;
  603. TRACE("Loading reverb '%s'\n", reverblist[i].name);
  604. props = &reverblist[i].props;
  605. effect->Props.Reverb.Density = props->flDensity;
  606. effect->Props.Reverb.Diffusion = props->flDiffusion;
  607. effect->Props.Reverb.Gain = props->flGain;
  608. effect->Props.Reverb.GainHF = props->flGainHF;
  609. effect->Props.Reverb.GainLF = props->flGainLF;
  610. effect->Props.Reverb.DecayTime = props->flDecayTime;
  611. effect->Props.Reverb.DecayHFRatio = props->flDecayHFRatio;
  612. effect->Props.Reverb.DecayLFRatio = props->flDecayLFRatio;
  613. effect->Props.Reverb.ReflectionsGain = props->flReflectionsGain;
  614. effect->Props.Reverb.ReflectionsDelay = props->flReflectionsDelay;
  615. effect->Props.Reverb.ReflectionsPan[0] = props->flReflectionsPan[0];
  616. effect->Props.Reverb.ReflectionsPan[1] = props->flReflectionsPan[1];
  617. effect->Props.Reverb.ReflectionsPan[2] = props->flReflectionsPan[2];
  618. effect->Props.Reverb.LateReverbGain = props->flLateReverbGain;
  619. effect->Props.Reverb.LateReverbDelay = props->flLateReverbDelay;
  620. effect->Props.Reverb.LateReverbPan[0] = props->flLateReverbPan[0];
  621. effect->Props.Reverb.LateReverbPan[1] = props->flLateReverbPan[1];
  622. effect->Props.Reverb.LateReverbPan[2] = props->flLateReverbPan[2];
  623. effect->Props.Reverb.EchoTime = props->flEchoTime;
  624. effect->Props.Reverb.EchoDepth = props->flEchoDepth;
  625. effect->Props.Reverb.ModulationTime = props->flModulationTime;
  626. effect->Props.Reverb.ModulationDepth = props->flModulationDepth;
  627. effect->Props.Reverb.AirAbsorptionGainHF = props->flAirAbsorptionGainHF;
  628. effect->Props.Reverb.HFReference = props->flHFReference;
  629. effect->Props.Reverb.LFReference = props->flLFReference;
  630. effect->Props.Reverb.RoomRolloffFactor = props->flRoomRolloffFactor;
  631. effect->Props.Reverb.DecayHFLimit = props->iDecayHFLimit;
  632. return;
  633. }
  634. WARN("Reverb preset '%s' not found\n", name);
  635. }