alAuxEffectSlot.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  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 <stdlib.h>
  22. #include <math.h>
  23. #include "AL/al.h"
  24. #include "AL/alc.h"
  25. #include "alMain.h"
  26. #include "alAuxEffectSlot.h"
  27. #include "alThunk.h"
  28. #include "alError.h"
  29. #include "alListener.h"
  30. #include "alSource.h"
  31. #include "almalloc.h"
  32. extern inline void LockEffectSlotsRead(ALCcontext *context);
  33. extern inline void UnlockEffectSlotsRead(ALCcontext *context);
  34. extern inline void LockEffectSlotsWrite(ALCcontext *context);
  35. extern inline void UnlockEffectSlotsWrite(ALCcontext *context);
  36. extern inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id);
  37. extern inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id);
  38. static UIntMap EffectStateFactoryMap;
  39. static inline ALeffectStateFactory *getFactoryByType(ALenum type)
  40. {
  41. ALeffectStateFactory* (*getFactory)(void) = LookupUIntMapKey(&EffectStateFactoryMap, type);
  42. if(getFactory != NULL)
  43. return getFactory();
  44. return NULL;
  45. }
  46. static void ALeffectState_IncRef(ALeffectState *state);
  47. static void ALeffectState_DecRef(ALeffectState *state);
  48. #define DO_UPDATEPROPS() do { \
  49. if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
  50. UpdateEffectSlotProps(slot); \
  51. else \
  52. ATOMIC_FLAG_CLEAR(&slot->PropsClean, almemory_order_release); \
  53. } while(0)
  54. AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
  55. {
  56. ALCcontext *context;
  57. ALeffectslot **tmpslots = NULL;
  58. ALsizei cur;
  59. ALenum err;
  60. context = GetContextRef();
  61. if(!context) return;
  62. if(!(n >= 0))
  63. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  64. tmpslots = al_malloc(DEF_ALIGN, sizeof(ALeffectslot*)*n);
  65. LockEffectSlotsWrite(context);
  66. for(cur = 0;cur < n;cur++)
  67. {
  68. ALeffectslot *slot = al_calloc(16, sizeof(ALeffectslot));
  69. err = AL_OUT_OF_MEMORY;
  70. if(!slot || (err=InitEffectSlot(slot)) != AL_NO_ERROR)
  71. {
  72. al_free(slot);
  73. UnlockEffectSlotsWrite(context);
  74. alDeleteAuxiliaryEffectSlots(cur, effectslots);
  75. SET_ERROR_AND_GOTO(context, err, done);
  76. }
  77. err = NewThunkEntry(&slot->id);
  78. if(err == AL_NO_ERROR)
  79. err = InsertUIntMapEntryNoLock(&context->EffectSlotMap, slot->id, slot);
  80. if(err != AL_NO_ERROR)
  81. {
  82. FreeThunkEntry(slot->id);
  83. ALeffectState_DecRef(slot->Effect.State);
  84. if(slot->Params.EffectState)
  85. ALeffectState_DecRef(slot->Params.EffectState);
  86. al_free(slot);
  87. UnlockEffectSlotsWrite(context);
  88. alDeleteAuxiliaryEffectSlots(cur, effectslots);
  89. SET_ERROR_AND_GOTO(context, err, done);
  90. }
  91. aluInitEffectPanning(slot);
  92. tmpslots[cur] = slot;
  93. effectslots[cur] = slot->id;
  94. }
  95. if(n > 0)
  96. {
  97. struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
  98. struct ALeffectslotArray *newarray = NULL;
  99. ALsizei newcount = curarray->count + n;
  100. ALCdevice *device;
  101. newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
  102. newarray->count = newcount;
  103. memcpy(newarray->slot, tmpslots, sizeof(ALeffectslot*)*n);
  104. if(curarray)
  105. memcpy(newarray->slot+n, curarray->slot, sizeof(ALeffectslot*)*curarray->count);
  106. newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
  107. almemory_order_acq_rel);
  108. device = context->Device;
  109. while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
  110. althrd_yield();
  111. al_free(newarray);
  112. }
  113. UnlockEffectSlotsWrite(context);
  114. done:
  115. al_free(tmpslots);
  116. ALCcontext_DecRef(context);
  117. }
  118. AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots)
  119. {
  120. ALCcontext *context;
  121. ALeffectslot *slot;
  122. ALsizei i;
  123. context = GetContextRef();
  124. if(!context) return;
  125. LockEffectSlotsWrite(context);
  126. if(!(n >= 0))
  127. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  128. for(i = 0;i < n;i++)
  129. {
  130. if((slot=LookupEffectSlot(context, effectslots[i])) == NULL)
  131. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  132. if(ReadRef(&slot->ref) != 0)
  133. SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
  134. }
  135. // All effectslots are valid
  136. if(n > 0)
  137. {
  138. struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
  139. struct ALeffectslotArray *newarray = NULL;
  140. ALsizei newcount = curarray->count - n;
  141. ALCdevice *device;
  142. ALsizei j, k;
  143. assert(newcount >= 0);
  144. newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
  145. newarray->count = newcount;
  146. for(i = j = 0;i < newarray->count;)
  147. {
  148. slot = curarray->slot[j++];
  149. for(k = 0;k < n;k++)
  150. {
  151. if(slot->id == effectslots[k])
  152. break;
  153. }
  154. if(k == n)
  155. newarray->slot[i++] = slot;
  156. }
  157. newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
  158. almemory_order_acq_rel);
  159. device = context->Device;
  160. while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
  161. althrd_yield();
  162. al_free(newarray);
  163. }
  164. for(i = 0;i < n;i++)
  165. {
  166. if((slot=RemoveEffectSlot(context, effectslots[i])) == NULL)
  167. continue;
  168. FreeThunkEntry(slot->id);
  169. DeinitEffectSlot(slot);
  170. memset(slot, 0, sizeof(*slot));
  171. al_free(slot);
  172. }
  173. done:
  174. UnlockEffectSlotsWrite(context);
  175. ALCcontext_DecRef(context);
  176. }
  177. AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
  178. {
  179. ALCcontext *context;
  180. ALboolean ret;
  181. context = GetContextRef();
  182. if(!context) return AL_FALSE;
  183. LockEffectSlotsRead(context);
  184. ret = (LookupEffectSlot(context, effectslot) ? AL_TRUE : AL_FALSE);
  185. UnlockEffectSlotsRead(context);
  186. ALCcontext_DecRef(context);
  187. return ret;
  188. }
  189. AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint value)
  190. {
  191. ALCdevice *device;
  192. ALCcontext *context;
  193. ALeffectslot *slot;
  194. ALeffect *effect = NULL;
  195. ALenum err;
  196. context = GetContextRef();
  197. if(!context) return;
  198. WriteLock(&context->PropLock);
  199. LockEffectSlotsRead(context);
  200. if((slot=LookupEffectSlot(context, effectslot)) == NULL)
  201. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  202. switch(param)
  203. {
  204. case AL_EFFECTSLOT_EFFECT:
  205. device = context->Device;
  206. LockEffectsRead(device);
  207. effect = (value ? LookupEffect(device, value) : NULL);
  208. if(!(value == 0 || effect != NULL))
  209. {
  210. UnlockEffectsRead(device);
  211. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  212. }
  213. err = InitializeEffect(device, slot, effect);
  214. UnlockEffectsRead(device);
  215. if(err != AL_NO_ERROR)
  216. SET_ERROR_AND_GOTO(context, err, done);
  217. break;
  218. case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
  219. if(!(value == AL_TRUE || value == AL_FALSE))
  220. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  221. slot->AuxSendAuto = value;
  222. break;
  223. default:
  224. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  225. }
  226. DO_UPDATEPROPS();
  227. done:
  228. UnlockEffectSlotsRead(context);
  229. WriteUnlock(&context->PropLock);
  230. ALCcontext_DecRef(context);
  231. }
  232. AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *values)
  233. {
  234. ALCcontext *context;
  235. switch(param)
  236. {
  237. case AL_EFFECTSLOT_EFFECT:
  238. case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
  239. alAuxiliaryEffectSloti(effectslot, param, values[0]);
  240. return;
  241. }
  242. context = GetContextRef();
  243. if(!context) return;
  244. LockEffectSlotsRead(context);
  245. if(LookupEffectSlot(context, effectslot) == NULL)
  246. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  247. switch(param)
  248. {
  249. default:
  250. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  251. }
  252. done:
  253. UnlockEffectSlotsRead(context);
  254. ALCcontext_DecRef(context);
  255. }
  256. AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat value)
  257. {
  258. ALCcontext *context;
  259. ALeffectslot *slot;
  260. context = GetContextRef();
  261. if(!context) return;
  262. WriteLock(&context->PropLock);
  263. LockEffectSlotsRead(context);
  264. if((slot=LookupEffectSlot(context, effectslot)) == NULL)
  265. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  266. switch(param)
  267. {
  268. case AL_EFFECTSLOT_GAIN:
  269. if(!(value >= 0.0f && value <= 1.0f))
  270. SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
  271. slot->Gain = value;
  272. break;
  273. default:
  274. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  275. }
  276. DO_UPDATEPROPS();
  277. done:
  278. UnlockEffectSlotsRead(context);
  279. WriteUnlock(&context->PropLock);
  280. ALCcontext_DecRef(context);
  281. }
  282. AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *values)
  283. {
  284. ALCcontext *context;
  285. switch(param)
  286. {
  287. case AL_EFFECTSLOT_GAIN:
  288. alAuxiliaryEffectSlotf(effectslot, param, values[0]);
  289. return;
  290. }
  291. context = GetContextRef();
  292. if(!context) return;
  293. LockEffectSlotsRead(context);
  294. if(LookupEffectSlot(context, effectslot) == NULL)
  295. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  296. switch(param)
  297. {
  298. default:
  299. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  300. }
  301. done:
  302. UnlockEffectSlotsRead(context);
  303. ALCcontext_DecRef(context);
  304. }
  305. AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *value)
  306. {
  307. ALCcontext *context;
  308. ALeffectslot *slot;
  309. context = GetContextRef();
  310. if(!context) return;
  311. LockEffectSlotsRead(context);
  312. if((slot=LookupEffectSlot(context, effectslot)) == NULL)
  313. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  314. switch(param)
  315. {
  316. case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
  317. *value = slot->AuxSendAuto;
  318. break;
  319. default:
  320. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  321. }
  322. done:
  323. UnlockEffectSlotsRead(context);
  324. ALCcontext_DecRef(context);
  325. }
  326. AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *values)
  327. {
  328. ALCcontext *context;
  329. switch(param)
  330. {
  331. case AL_EFFECTSLOT_EFFECT:
  332. case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
  333. alGetAuxiliaryEffectSloti(effectslot, param, values);
  334. return;
  335. }
  336. context = GetContextRef();
  337. if(!context) return;
  338. LockEffectSlotsRead(context);
  339. if(LookupEffectSlot(context, effectslot) == NULL)
  340. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  341. switch(param)
  342. {
  343. default:
  344. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  345. }
  346. done:
  347. UnlockEffectSlotsRead(context);
  348. ALCcontext_DecRef(context);
  349. }
  350. AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *value)
  351. {
  352. ALCcontext *context;
  353. ALeffectslot *slot;
  354. context = GetContextRef();
  355. if(!context) return;
  356. LockEffectSlotsRead(context);
  357. if((slot=LookupEffectSlot(context, effectslot)) == NULL)
  358. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  359. switch(param)
  360. {
  361. case AL_EFFECTSLOT_GAIN:
  362. *value = slot->Gain;
  363. break;
  364. default:
  365. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  366. }
  367. done:
  368. UnlockEffectSlotsRead(context);
  369. ALCcontext_DecRef(context);
  370. }
  371. AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *values)
  372. {
  373. ALCcontext *context;
  374. switch(param)
  375. {
  376. case AL_EFFECTSLOT_GAIN:
  377. alGetAuxiliaryEffectSlotf(effectslot, param, values);
  378. return;
  379. }
  380. context = GetContextRef();
  381. if(!context) return;
  382. LockEffectSlotsRead(context);
  383. if(LookupEffectSlot(context, effectslot) == NULL)
  384. SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
  385. switch(param)
  386. {
  387. default:
  388. SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
  389. }
  390. done:
  391. UnlockEffectSlotsRead(context);
  392. ALCcontext_DecRef(context);
  393. }
  394. void InitEffectFactoryMap(void)
  395. {
  396. InitUIntMap(&EffectStateFactoryMap, INT_MAX);
  397. InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_NULL, ALnullStateFactory_getFactory);
  398. InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_EAXREVERB, ALreverbStateFactory_getFactory);
  399. InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_REVERB, ALreverbStateFactory_getFactory);
  400. InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_CHORUS, ALchorusStateFactory_getFactory);
  401. InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_COMPRESSOR, ALcompressorStateFactory_getFactory);
  402. InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DISTORTION, ALdistortionStateFactory_getFactory);
  403. InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_ECHO, ALechoStateFactory_getFactory);
  404. InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_EQUALIZER, ALequalizerStateFactory_getFactory);
  405. InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_FLANGER, ALflangerStateFactory_getFactory);
  406. InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_RING_MODULATOR, ALmodulatorStateFactory_getFactory);
  407. InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DEDICATED_DIALOGUE, ALdedicatedStateFactory_getFactory);
  408. InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, ALdedicatedStateFactory_getFactory);
  409. }
  410. void DeinitEffectFactoryMap(void)
  411. {
  412. ResetUIntMap(&EffectStateFactoryMap);
  413. }
  414. ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect)
  415. {
  416. ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
  417. struct ALeffectslotProps *props;
  418. ALeffectState *State;
  419. if(newtype != EffectSlot->Effect.Type)
  420. {
  421. ALeffectStateFactory *factory;
  422. factory = getFactoryByType(newtype);
  423. if(!factory)
  424. {
  425. ERR("Failed to find factory for effect type 0x%04x\n", newtype);
  426. return AL_INVALID_ENUM;
  427. }
  428. State = V0(factory,create)();
  429. if(!State) return AL_OUT_OF_MEMORY;
  430. START_MIXER_MODE();
  431. almtx_lock(&Device->BackendLock);
  432. State->OutBuffer = Device->Dry.Buffer;
  433. State->OutChannels = Device->Dry.NumChannels;
  434. if(V(State,deviceUpdate)(Device) == AL_FALSE)
  435. {
  436. almtx_unlock(&Device->BackendLock);
  437. LEAVE_MIXER_MODE();
  438. ALeffectState_DecRef(State);
  439. return AL_OUT_OF_MEMORY;
  440. }
  441. almtx_unlock(&Device->BackendLock);
  442. END_MIXER_MODE();
  443. if(!effect)
  444. {
  445. EffectSlot->Effect.Type = AL_EFFECT_NULL;
  446. memset(&EffectSlot->Effect.Props, 0, sizeof(EffectSlot->Effect.Props));
  447. }
  448. else
  449. {
  450. EffectSlot->Effect.Type = effect->type;
  451. EffectSlot->Effect.Props = effect->Props;
  452. }
  453. ALeffectState_DecRef(EffectSlot->Effect.State);
  454. EffectSlot->Effect.State = State;
  455. }
  456. else if(effect)
  457. EffectSlot->Effect.Props = effect->Props;
  458. /* Remove state references from old effect slot property updates. */
  459. props = ATOMIC_LOAD_SEQ(&EffectSlot->FreeList);
  460. while(props)
  461. {
  462. if(props->State)
  463. ALeffectState_DecRef(props->State);
  464. props->State = NULL;
  465. props = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
  466. }
  467. return AL_NO_ERROR;
  468. }
  469. static void ALeffectState_IncRef(ALeffectState *state)
  470. {
  471. uint ref;
  472. ref = IncrementRef(&state->Ref);
  473. TRACEREF("%p increasing refcount to %u\n", state, ref);
  474. }
  475. static void ALeffectState_DecRef(ALeffectState *state)
  476. {
  477. uint ref;
  478. ref = DecrementRef(&state->Ref);
  479. TRACEREF("%p decreasing refcount to %u\n", state, ref);
  480. if(ref == 0) DELETE_OBJ(state);
  481. }
  482. void ALeffectState_Construct(ALeffectState *state)
  483. {
  484. InitRef(&state->Ref, 1);
  485. state->OutBuffer = NULL;
  486. state->OutChannels = 0;
  487. }
  488. void ALeffectState_Destruct(ALeffectState *UNUSED(state))
  489. {
  490. }
  491. ALenum InitEffectSlot(ALeffectslot *slot)
  492. {
  493. ALeffectStateFactory *factory;
  494. slot->Effect.Type = AL_EFFECT_NULL;
  495. factory = getFactoryByType(AL_EFFECT_NULL);
  496. if(!(slot->Effect.State=V0(factory,create)()))
  497. return AL_OUT_OF_MEMORY;
  498. slot->Gain = 1.0;
  499. slot->AuxSendAuto = AL_TRUE;
  500. ATOMIC_FLAG_TEST_AND_SET(&slot->PropsClean, almemory_order_relaxed);
  501. InitRef(&slot->ref, 0);
  502. ATOMIC_INIT(&slot->Update, NULL);
  503. ATOMIC_INIT(&slot->FreeList, NULL);
  504. slot->Params.Gain = 1.0f;
  505. slot->Params.AuxSendAuto = AL_TRUE;
  506. ALeffectState_IncRef(slot->Effect.State);
  507. slot->Params.EffectState = slot->Effect.State;
  508. slot->Params.RoomRolloff = 0.0f;
  509. slot->Params.DecayTime = 0.0f;
  510. slot->Params.DecayHFRatio = 0.0f;
  511. slot->Params.DecayHFLimit = AL_FALSE;
  512. slot->Params.AirAbsorptionGainHF = 1.0f;
  513. return AL_NO_ERROR;
  514. }
  515. void DeinitEffectSlot(ALeffectslot *slot)
  516. {
  517. struct ALeffectslotProps *props;
  518. size_t count = 0;
  519. props = ATOMIC_LOAD_SEQ(&slot->Update);
  520. if(props)
  521. {
  522. if(props->State) ALeffectState_DecRef(props->State);
  523. TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", props);
  524. al_free(props);
  525. }
  526. props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed);
  527. while(props)
  528. {
  529. struct ALeffectslotProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
  530. if(props->State) ALeffectState_DecRef(props->State);
  531. al_free(props);
  532. props = next;
  533. ++count;
  534. }
  535. TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
  536. ALeffectState_DecRef(slot->Effect.State);
  537. if(slot->Params.EffectState)
  538. ALeffectState_DecRef(slot->Params.EffectState);
  539. }
  540. void UpdateEffectSlotProps(ALeffectslot *slot)
  541. {
  542. struct ALeffectslotProps *props;
  543. ALeffectState *oldstate;
  544. /* Get an unused property container, or allocate a new one as needed. */
  545. props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed);
  546. if(!props)
  547. props = al_calloc(16, sizeof(*props));
  548. else
  549. {
  550. struct ALeffectslotProps *next;
  551. do {
  552. next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
  553. } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&slot->FreeList, &props, next,
  554. almemory_order_seq_cst, almemory_order_acquire) == 0);
  555. }
  556. /* Copy in current property values. */
  557. props->Gain = slot->Gain;
  558. props->AuxSendAuto = slot->AuxSendAuto;
  559. props->Type = slot->Effect.Type;
  560. props->Props = slot->Effect.Props;
  561. /* Swap out any stale effect state object there may be in the container, to
  562. * delete it.
  563. */
  564. ALeffectState_IncRef(slot->Effect.State);
  565. oldstate = props->State;
  566. props->State = slot->Effect.State;
  567. /* Set the new container for updating internal parameters. */
  568. props = ATOMIC_EXCHANGE_PTR(&slot->Update, props, almemory_order_acq_rel);
  569. if(props)
  570. {
  571. /* If there was an unused update container, put it back in the
  572. * freelist.
  573. */
  574. ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &slot->FreeList, props);
  575. }
  576. if(oldstate)
  577. ALeffectState_DecRef(oldstate);
  578. }
  579. void UpdateAllEffectSlotProps(ALCcontext *context)
  580. {
  581. struct ALeffectslotArray *auxslots;
  582. ALsizei i;
  583. LockEffectSlotsRead(context);
  584. auxslots = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
  585. for(i = 0;i < auxslots->count;i++)
  586. {
  587. ALeffectslot *slot = auxslots->slot[i];
  588. if(!ATOMIC_FLAG_TEST_AND_SET(&slot->PropsClean, almemory_order_acq_rel))
  589. UpdateEffectSlotProps(slot);
  590. }
  591. UnlockEffectSlotsRead(context);
  592. }
  593. ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
  594. {
  595. ALsizei pos;
  596. for(pos = 0;pos < Context->EffectSlotMap.size;pos++)
  597. {
  598. ALeffectslot *temp = Context->EffectSlotMap.values[pos];
  599. Context->EffectSlotMap.values[pos] = NULL;
  600. DeinitEffectSlot(temp);
  601. FreeThunkEntry(temp->id);
  602. memset(temp, 0, sizeof(ALeffectslot));
  603. al_free(temp);
  604. }
  605. }