Correctly apply reverb coefficient fading over the entire fade length
[openal-soft.git] / OpenAL32 / alState.c
blobce93e143811fb7d259457974c9ec1fb27bc3a476
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2000 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 "version.h"
25 #include <stdlib.h>
26 #include "alMain.h"
27 #include "AL/alc.h"
28 #include "AL/al.h"
29 #include "AL/alext.h"
30 #include "alError.h"
31 #include "alListener.h"
32 #include "alSource.h"
33 #include "alAuxEffectSlot.h"
35 #include "backends/base.h"
38 static const ALchar alVendor[] = "OpenAL Community";
39 static const ALchar alVersion[] = "1.1 ALSOFT "ALSOFT_VERSION;
40 static const ALchar alRenderer[] = "OpenAL Soft";
42 // Error Messages
43 static const ALchar alNoError[] = "No Error";
44 static const ALchar alErrInvalidName[] = "Invalid Name";
45 static const ALchar alErrInvalidEnum[] = "Invalid Enum";
46 static const ALchar alErrInvalidValue[] = "Invalid Value";
47 static const ALchar alErrInvalidOp[] = "Invalid Operation";
48 static const ALchar alErrOutOfMemory[] = "Out of Memory";
50 /* Resampler strings */
51 static const ALchar alPointResampler[] = "Nearest";
52 static const ALchar alLinearResampler[] = "Linear";
53 static const ALchar alCubicResampler[] = "Cubic";
54 static const ALchar alBSinc12Resampler[] = "11th order Sinc";
55 static const ALchar alBSinc24Resampler[] = "23rd order Sinc";
57 /* WARNING: Non-standard export! Not part of any extension, or exposed in the
58 * alcFunctions list.
60 AL_API const ALchar* AL_APIENTRY alsoft_get_version(void)
62 const char *spoof = getenv("ALSOFT_SPOOF_VERSION");
63 if(spoof && spoof[0] != '\0') return spoof;
64 return ALSOFT_VERSION;
67 #define DO_UPDATEPROPS() do { \
68 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
69 UpdateContextProps(context); \
70 else \
71 ATOMIC_FLAG_CLEAR(&context->PropsClean, almemory_order_release); \
72 } while(0)
75 AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
77 ALCcontext *context;
79 context = GetContextRef();
80 if(!context) return;
82 almtx_lock(&context->PropLock);
83 switch(capability)
85 case AL_SOURCE_DISTANCE_MODEL:
86 context->SourceDistanceModel = AL_TRUE;
87 DO_UPDATEPROPS();
88 break;
90 default:
91 alSetError(context, AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability);
93 almtx_unlock(&context->PropLock);
95 ALCcontext_DecRef(context);
98 AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
100 ALCcontext *context;
102 context = GetContextRef();
103 if(!context) return;
105 almtx_lock(&context->PropLock);
106 switch(capability)
108 case AL_SOURCE_DISTANCE_MODEL:
109 context->SourceDistanceModel = AL_FALSE;
110 DO_UPDATEPROPS();
111 break;
113 default:
114 alSetError(context, AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability);
116 almtx_unlock(&context->PropLock);
118 ALCcontext_DecRef(context);
121 AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
123 ALCcontext *context;
124 ALboolean value=AL_FALSE;
126 context = GetContextRef();
127 if(!context) return AL_FALSE;
129 almtx_lock(&context->PropLock);
130 switch(capability)
132 case AL_SOURCE_DISTANCE_MODEL:
133 value = context->SourceDistanceModel;
134 break;
136 default:
137 alSetError(context, AL_INVALID_VALUE, "Invalid is enabled property 0x%04x", capability);
139 almtx_unlock(&context->PropLock);
141 ALCcontext_DecRef(context);
142 return value;
145 AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
147 ALCcontext *context;
148 ALboolean value=AL_FALSE;
150 context = GetContextRef();
151 if(!context) return AL_FALSE;
153 almtx_lock(&context->PropLock);
154 switch(pname)
156 case AL_DOPPLER_FACTOR:
157 if(context->DopplerFactor != 0.0f)
158 value = AL_TRUE;
159 break;
161 case AL_DOPPLER_VELOCITY:
162 if(context->DopplerVelocity != 0.0f)
163 value = AL_TRUE;
164 break;
166 case AL_DISTANCE_MODEL:
167 if(context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED)
168 value = AL_TRUE;
169 break;
171 case AL_SPEED_OF_SOUND:
172 if(context->SpeedOfSound != 0.0f)
173 value = AL_TRUE;
174 break;
176 case AL_DEFERRED_UPDATES_SOFT:
177 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
178 value = AL_TRUE;
179 break;
181 case AL_GAIN_LIMIT_SOFT:
182 if(GAIN_MIX_MAX/context->GainBoost != 0.0f)
183 value = AL_TRUE;
184 break;
186 case AL_NUM_RESAMPLERS_SOFT:
187 /* Always non-0. */
188 value = AL_TRUE;
189 break;
191 case AL_DEFAULT_RESAMPLER_SOFT:
192 value = ResamplerDefault ? AL_TRUE : AL_FALSE;
193 break;
195 default:
196 alSetError(context, AL_INVALID_VALUE, "Invalid boolean property 0x%04x", pname);
198 almtx_unlock(&context->PropLock);
200 ALCcontext_DecRef(context);
201 return value;
204 AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
206 ALCcontext *context;
207 ALdouble value = 0.0;
209 context = GetContextRef();
210 if(!context) return 0.0;
212 almtx_lock(&context->PropLock);
213 switch(pname)
215 case AL_DOPPLER_FACTOR:
216 value = (ALdouble)context->DopplerFactor;
217 break;
219 case AL_DOPPLER_VELOCITY:
220 value = (ALdouble)context->DopplerVelocity;
221 break;
223 case AL_DISTANCE_MODEL:
224 value = (ALdouble)context->DistanceModel;
225 break;
227 case AL_SPEED_OF_SOUND:
228 value = (ALdouble)context->SpeedOfSound;
229 break;
231 case AL_DEFERRED_UPDATES_SOFT:
232 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
233 value = (ALdouble)AL_TRUE;
234 break;
236 case AL_GAIN_LIMIT_SOFT:
237 value = (ALdouble)GAIN_MIX_MAX/context->GainBoost;
238 break;
240 case AL_NUM_RESAMPLERS_SOFT:
241 value = (ALdouble)(ResamplerMax + 1);
242 break;
244 case AL_DEFAULT_RESAMPLER_SOFT:
245 value = (ALdouble)ResamplerDefault;
246 break;
248 default:
249 alSetError(context, AL_INVALID_VALUE, "Invalid double property 0x%04x", pname);
251 almtx_unlock(&context->PropLock);
253 ALCcontext_DecRef(context);
254 return value;
257 AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
259 ALCcontext *context;
260 ALfloat value = 0.0f;
262 context = GetContextRef();
263 if(!context) return 0.0f;
265 almtx_lock(&context->PropLock);
266 switch(pname)
268 case AL_DOPPLER_FACTOR:
269 value = context->DopplerFactor;
270 break;
272 case AL_DOPPLER_VELOCITY:
273 value = context->DopplerVelocity;
274 break;
276 case AL_DISTANCE_MODEL:
277 value = (ALfloat)context->DistanceModel;
278 break;
280 case AL_SPEED_OF_SOUND:
281 value = context->SpeedOfSound;
282 break;
284 case AL_DEFERRED_UPDATES_SOFT:
285 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
286 value = (ALfloat)AL_TRUE;
287 break;
289 case AL_GAIN_LIMIT_SOFT:
290 value = GAIN_MIX_MAX/context->GainBoost;
291 break;
293 case AL_NUM_RESAMPLERS_SOFT:
294 value = (ALfloat)(ResamplerMax + 1);
295 break;
297 case AL_DEFAULT_RESAMPLER_SOFT:
298 value = (ALfloat)ResamplerDefault;
299 break;
301 default:
302 alSetError(context, AL_INVALID_VALUE, "Invalid float property 0x%04x", pname);
304 almtx_unlock(&context->PropLock);
306 ALCcontext_DecRef(context);
307 return value;
310 AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
312 ALCcontext *context;
313 ALint value = 0;
315 context = GetContextRef();
316 if(!context) return 0;
318 almtx_lock(&context->PropLock);
319 switch(pname)
321 case AL_DOPPLER_FACTOR:
322 value = (ALint)context->DopplerFactor;
323 break;
325 case AL_DOPPLER_VELOCITY:
326 value = (ALint)context->DopplerVelocity;
327 break;
329 case AL_DISTANCE_MODEL:
330 value = (ALint)context->DistanceModel;
331 break;
333 case AL_SPEED_OF_SOUND:
334 value = (ALint)context->SpeedOfSound;
335 break;
337 case AL_DEFERRED_UPDATES_SOFT:
338 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
339 value = (ALint)AL_TRUE;
340 break;
342 case AL_GAIN_LIMIT_SOFT:
343 value = (ALint)(GAIN_MIX_MAX/context->GainBoost);
344 break;
346 case AL_NUM_RESAMPLERS_SOFT:
347 value = ResamplerMax + 1;
348 break;
350 case AL_DEFAULT_RESAMPLER_SOFT:
351 value = ResamplerDefault;
352 break;
354 default:
355 alSetError(context, AL_INVALID_VALUE, "Invalid integer property 0x%04x", pname);
357 almtx_unlock(&context->PropLock);
359 ALCcontext_DecRef(context);
360 return value;
363 AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
365 ALCcontext *context;
366 ALint64SOFT value = 0;
368 context = GetContextRef();
369 if(!context) return 0;
371 almtx_lock(&context->PropLock);
372 switch(pname)
374 case AL_DOPPLER_FACTOR:
375 value = (ALint64SOFT)context->DopplerFactor;
376 break;
378 case AL_DOPPLER_VELOCITY:
379 value = (ALint64SOFT)context->DopplerVelocity;
380 break;
382 case AL_DISTANCE_MODEL:
383 value = (ALint64SOFT)context->DistanceModel;
384 break;
386 case AL_SPEED_OF_SOUND:
387 value = (ALint64SOFT)context->SpeedOfSound;
388 break;
390 case AL_DEFERRED_UPDATES_SOFT:
391 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
392 value = (ALint64SOFT)AL_TRUE;
393 break;
395 case AL_GAIN_LIMIT_SOFT:
396 value = (ALint64SOFT)(GAIN_MIX_MAX/context->GainBoost);
397 break;
399 case AL_NUM_RESAMPLERS_SOFT:
400 value = (ALint64SOFT)(ResamplerMax + 1);
401 break;
403 case AL_DEFAULT_RESAMPLER_SOFT:
404 value = (ALint64SOFT)ResamplerDefault;
405 break;
407 default:
408 alSetError(context, AL_INVALID_VALUE, "Invalid integer64 property 0x%04x", pname);
410 almtx_unlock(&context->PropLock);
412 ALCcontext_DecRef(context);
413 return value;
416 AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname)
418 ALCcontext *context;
419 void *value = NULL;
421 context = GetContextRef();
422 if(!context) return NULL;
424 almtx_lock(&context->PropLock);
425 switch(pname)
427 case AL_EVENT_CALLBACK_FUNCTION_SOFT:
428 value = context->EventCb;
429 break;
431 case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
432 value = context->EventParam;
433 break;
435 default:
436 alSetError(context, AL_INVALID_VALUE, "Invalid pointer property 0x%04x", pname);
438 almtx_unlock(&context->PropLock);
440 ALCcontext_DecRef(context);
441 return value;
444 AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
446 ALCcontext *context;
448 if(values)
450 switch(pname)
452 case AL_DOPPLER_FACTOR:
453 case AL_DOPPLER_VELOCITY:
454 case AL_DISTANCE_MODEL:
455 case AL_SPEED_OF_SOUND:
456 case AL_DEFERRED_UPDATES_SOFT:
457 case AL_GAIN_LIMIT_SOFT:
458 case AL_NUM_RESAMPLERS_SOFT:
459 case AL_DEFAULT_RESAMPLER_SOFT:
460 values[0] = alGetBoolean(pname);
461 return;
465 context = GetContextRef();
466 if(!context) return;
468 if(!values)
469 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
470 switch(pname)
472 default:
473 alSetError(context, AL_INVALID_VALUE, "Invalid boolean-vector property 0x%04x", pname);
476 ALCcontext_DecRef(context);
479 AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
481 ALCcontext *context;
483 if(values)
485 switch(pname)
487 case AL_DOPPLER_FACTOR:
488 case AL_DOPPLER_VELOCITY:
489 case AL_DISTANCE_MODEL:
490 case AL_SPEED_OF_SOUND:
491 case AL_DEFERRED_UPDATES_SOFT:
492 case AL_GAIN_LIMIT_SOFT:
493 case AL_NUM_RESAMPLERS_SOFT:
494 case AL_DEFAULT_RESAMPLER_SOFT:
495 values[0] = alGetDouble(pname);
496 return;
500 context = GetContextRef();
501 if(!context) return;
503 if(!values)
504 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
505 switch(pname)
507 default:
508 alSetError(context, AL_INVALID_VALUE, "Invalid double-vector property 0x%04x", pname);
511 ALCcontext_DecRef(context);
514 AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
516 ALCcontext *context;
518 if(values)
520 switch(pname)
522 case AL_DOPPLER_FACTOR:
523 case AL_DOPPLER_VELOCITY:
524 case AL_DISTANCE_MODEL:
525 case AL_SPEED_OF_SOUND:
526 case AL_DEFERRED_UPDATES_SOFT:
527 case AL_GAIN_LIMIT_SOFT:
528 case AL_NUM_RESAMPLERS_SOFT:
529 case AL_DEFAULT_RESAMPLER_SOFT:
530 values[0] = alGetFloat(pname);
531 return;
535 context = GetContextRef();
536 if(!context) return;
538 if(!values)
539 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
540 switch(pname)
542 default:
543 alSetError(context, AL_INVALID_VALUE, "Invalid float-vector property 0x%04x", pname);
546 ALCcontext_DecRef(context);
549 AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
551 ALCcontext *context;
553 if(values)
555 switch(pname)
557 case AL_DOPPLER_FACTOR:
558 case AL_DOPPLER_VELOCITY:
559 case AL_DISTANCE_MODEL:
560 case AL_SPEED_OF_SOUND:
561 case AL_DEFERRED_UPDATES_SOFT:
562 case AL_GAIN_LIMIT_SOFT:
563 case AL_NUM_RESAMPLERS_SOFT:
564 case AL_DEFAULT_RESAMPLER_SOFT:
565 values[0] = alGetInteger(pname);
566 return;
570 context = GetContextRef();
571 if(!context) return;
573 if(!values)
574 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
575 switch(pname)
577 default:
578 alSetError(context, AL_INVALID_VALUE, "Invalid integer-vector property 0x%04x", pname);
581 ALCcontext_DecRef(context);
584 AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
586 ALCcontext *context;
588 if(values)
590 switch(pname)
592 case AL_DOPPLER_FACTOR:
593 case AL_DOPPLER_VELOCITY:
594 case AL_DISTANCE_MODEL:
595 case AL_SPEED_OF_SOUND:
596 case AL_DEFERRED_UPDATES_SOFT:
597 case AL_GAIN_LIMIT_SOFT:
598 case AL_NUM_RESAMPLERS_SOFT:
599 case AL_DEFAULT_RESAMPLER_SOFT:
600 values[0] = alGetInteger64SOFT(pname);
601 return;
605 context = GetContextRef();
606 if(!context) return;
608 if(!values)
609 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
610 switch(pname)
612 default:
613 alSetError(context, AL_INVALID_VALUE, "Invalid integer64-vector property 0x%04x", pname);
616 ALCcontext_DecRef(context);
619 AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values)
621 ALCcontext *context;
623 if(values)
625 switch(pname)
627 case AL_EVENT_CALLBACK_FUNCTION_SOFT:
628 case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
629 values[0] = alGetPointerSOFT(pname);
630 return;
634 context = GetContextRef();
635 if(!context) return;
637 if(!values)
638 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
639 switch(pname)
641 default:
642 alSetError(context, AL_INVALID_VALUE, "Invalid pointer-vector property 0x%04x", pname);
645 ALCcontext_DecRef(context);
648 AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
650 const ALchar *value = NULL;
651 ALCcontext *context;
653 context = GetContextRef();
654 if(!context) return NULL;
656 switch(pname)
658 case AL_VENDOR:
659 value = alVendor;
660 break;
662 case AL_VERSION:
663 value = alVersion;
664 break;
666 case AL_RENDERER:
667 value = alRenderer;
668 break;
670 case AL_EXTENSIONS:
671 value = context->ExtensionList;
672 break;
674 case AL_NO_ERROR:
675 value = alNoError;
676 break;
678 case AL_INVALID_NAME:
679 value = alErrInvalidName;
680 break;
682 case AL_INVALID_ENUM:
683 value = alErrInvalidEnum;
684 break;
686 case AL_INVALID_VALUE:
687 value = alErrInvalidValue;
688 break;
690 case AL_INVALID_OPERATION:
691 value = alErrInvalidOp;
692 break;
694 case AL_OUT_OF_MEMORY:
695 value = alErrOutOfMemory;
696 break;
698 default:
699 alSetError(context, AL_INVALID_VALUE, "Invalid string property 0x%04x", pname);
702 ALCcontext_DecRef(context);
703 return value;
706 AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
708 ALCcontext *context;
710 context = GetContextRef();
711 if(!context) return;
713 if(!(value >= 0.0f && isfinite(value)))
714 alSetError(context, AL_INVALID_VALUE, "Doppler factor %f out of range", value);
715 else
717 almtx_lock(&context->PropLock);
718 context->DopplerFactor = value;
719 DO_UPDATEPROPS();
720 almtx_unlock(&context->PropLock);
723 ALCcontext_DecRef(context);
726 AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
728 ALCcontext *context;
730 context = GetContextRef();
731 if(!context) return;
733 if((ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed)&EventType_Deprecated))
735 static const ALCchar msg[] =
736 "alDopplerVelocity is deprecated in AL1.1, use alSpeedOfSound";
737 const ALsizei msglen = (ALsizei)strlen(msg);
738 ALbitfieldSOFT enabledevts;
739 almtx_lock(&context->EventCbLock);
740 enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed);
741 if((enabledevts&EventType_Deprecated) && context->EventCb)
742 (*context->EventCb)(AL_EVENT_TYPE_DEPRECATED_SOFT, 0, 0, msglen, msg,
743 context->EventParam);
744 almtx_unlock(&context->EventCbLock);
747 if(!(value >= 0.0f && isfinite(value)))
748 alSetError(context, AL_INVALID_VALUE, "Doppler velocity %f out of range", value);
749 else
751 almtx_lock(&context->PropLock);
752 context->DopplerVelocity = value;
753 DO_UPDATEPROPS();
754 almtx_unlock(&context->PropLock);
757 ALCcontext_DecRef(context);
760 AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
762 ALCcontext *context;
764 context = GetContextRef();
765 if(!context) return;
767 if(!(value > 0.0f && isfinite(value)))
768 alSetError(context, AL_INVALID_VALUE, "Speed of sound %f out of range", value);
769 else
771 almtx_lock(&context->PropLock);
772 context->SpeedOfSound = value;
773 DO_UPDATEPROPS();
774 almtx_unlock(&context->PropLock);
777 ALCcontext_DecRef(context);
780 AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
782 ALCcontext *context;
784 context = GetContextRef();
785 if(!context) return;
787 if(!(value == AL_INVERSE_DISTANCE || value == AL_INVERSE_DISTANCE_CLAMPED ||
788 value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED ||
789 value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED ||
790 value == AL_NONE))
791 alSetError(context, AL_INVALID_VALUE, "Distance model 0x%04x out of range", value);
792 else
794 almtx_lock(&context->PropLock);
795 context->DistanceModel = value;
796 if(!context->SourceDistanceModel)
797 DO_UPDATEPROPS();
798 almtx_unlock(&context->PropLock);
801 ALCcontext_DecRef(context);
805 AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
807 ALCcontext *context;
809 context = GetContextRef();
810 if(!context) return;
812 ALCcontext_DeferUpdates(context);
814 ALCcontext_DecRef(context);
817 AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
819 ALCcontext *context;
821 context = GetContextRef();
822 if(!context) return;
824 ALCcontext_ProcessUpdates(context);
826 ALCcontext_DecRef(context);
830 AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
832 const char *ResamplerNames[] = {
833 alPointResampler, alLinearResampler,
834 alCubicResampler, alBSinc12Resampler,
835 alBSinc24Resampler,
837 const ALchar *value = NULL;
838 ALCcontext *context;
840 static_assert(COUNTOF(ResamplerNames) == ResamplerMax+1, "Incorrect ResamplerNames list");
842 context = GetContextRef();
843 if(!context) return NULL;
845 switch(pname)
847 case AL_RESAMPLER_NAME_SOFT:
848 if(index < 0 || (size_t)index >= COUNTOF(ResamplerNames))
849 SETERR_GOTO(context, AL_INVALID_VALUE, done, "Resampler name index %d out of range",
850 index);
851 value = ResamplerNames[index];
852 break;
854 default:
855 alSetError(context, AL_INVALID_VALUE, "Invalid string indexed property");
858 done:
859 ALCcontext_DecRef(context);
860 return value;
864 void UpdateContextProps(ALCcontext *context)
866 struct ALcontextProps *props;
868 /* Get an unused proprty container, or allocate a new one as needed. */
869 props = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire);
870 if(!props)
871 props = al_calloc(16, sizeof(*props));
872 else
874 struct ALcontextProps *next;
875 do {
876 next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
877 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context->FreeContextProps, &props, next,
878 almemory_order_seq_cst, almemory_order_acquire) == 0);
881 /* Copy in current property values. */
882 props->MetersPerUnit = context->MetersPerUnit;
884 props->DopplerFactor = context->DopplerFactor;
885 props->DopplerVelocity = context->DopplerVelocity;
886 props->SpeedOfSound = context->SpeedOfSound;
888 props->SourceDistanceModel = context->SourceDistanceModel;
889 props->DistanceModel = context->DistanceModel;
891 /* Set the new container for updating internal parameters. */
892 props = ATOMIC_EXCHANGE_PTR(&context->Update, props, almemory_order_acq_rel);
893 if(props)
895 /* If there was an unused update container, put it back in the
896 * freelist.
898 ATOMIC_REPLACE_HEAD(struct ALcontextProps*, &context->FreeContextProps, props);