Redo resampler strings to be safer
[openal-soft.git] / al / state.cpp
blob3d7388b2dbac4bad99203a6a36b5857429a9e925
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 <atomic>
26 #include <cmath>
27 #include <cstdlib>
28 #include <cstring>
29 #include <mutex>
31 #include "AL/al.h"
32 #include "AL/alc.h"
33 #include "AL/alext.h"
35 #include "alcontext.h"
36 #include "alexcpt.h"
37 #include "almalloc.h"
38 #include "alnumeric.h"
39 #include "alspan.h"
40 #include "alu.h"
41 #include "atomic.h"
42 #include "event.h"
43 #include "inprogext.h"
44 #include "opthelpers.h"
45 #include "strutils.h"
48 namespace {
50 constexpr ALchar alVendor[] = "OpenAL Community";
51 constexpr ALchar alVersion[] = "1.1 ALSOFT " ALSOFT_VERSION;
52 constexpr ALchar alRenderer[] = "OpenAL Soft";
54 // Error Messages
55 constexpr ALchar alNoError[] = "No Error";
56 constexpr ALchar alErrInvalidName[] = "Invalid Name";
57 constexpr ALchar alErrInvalidEnum[] = "Invalid Enum";
58 constexpr ALchar alErrInvalidValue[] = "Invalid Value";
59 constexpr ALchar alErrInvalidOp[] = "Invalid Operation";
60 constexpr ALchar alErrOutOfMemory[] = "Out of Memory";
62 /* Resampler strings */
63 template<Resampler rtype> struct ResamplerName { };
64 template<> struct ResamplerName<Resampler::Point>
65 { static const ALchar *Get() noexcept { return "Nearest"; } };
66 template<> struct ResamplerName<Resampler::Linear>
67 { static const ALchar *Get() noexcept { return "Linear"; } };
68 template<> struct ResamplerName<Resampler::Cubic>
69 { static const ALchar *Get() noexcept { return "Cubic"; } };
70 template<> struct ResamplerName<Resampler::FastBSinc12>
71 { static const ALchar *Get() noexcept { return "11th order Sinc (fast)"; } };
72 template<> struct ResamplerName<Resampler::BSinc12>
73 { static const ALchar *Get() noexcept { return "11th order Sinc"; } };
74 template<> struct ResamplerName<Resampler::FastBSinc24>
75 { static const ALchar *Get() noexcept { return "23rd order Sinc (fast)"; } };
76 template<> struct ResamplerName<Resampler::BSinc24>
77 { static const ALchar *Get() noexcept { return "23rd order Sinc"; } };
79 const ALchar *GetResamplerName(const Resampler rtype) noexcept
81 #define HANDLE_RESAMPLER(r) case r: return ResamplerName<r>::Get()
82 switch(rtype)
84 HANDLE_RESAMPLER(Resampler::Point);
85 HANDLE_RESAMPLER(Resampler::Linear);
86 HANDLE_RESAMPLER(Resampler::Cubic);
87 HANDLE_RESAMPLER(Resampler::FastBSinc12);
88 HANDLE_RESAMPLER(Resampler::BSinc12);
89 HANDLE_RESAMPLER(Resampler::FastBSinc24);
90 HANDLE_RESAMPLER(Resampler::BSinc24);
92 #undef HANDLE_RESAMPLER
95 } // namespace
97 /* WARNING: Non-standard export! Not part of any extension, or exposed in the
98 * alcFunctions list.
100 extern "C" AL_API const ALchar* AL_APIENTRY alsoft_get_version(void)
101 START_API_FUNC
103 static const auto spoof = al::getenv("ALSOFT_SPOOF_VERSION");
104 if(spoof) return spoof->c_str();
105 return ALSOFT_VERSION;
107 END_API_FUNC
109 #define DO_UPDATEPROPS() do { \
110 if(!context->mDeferUpdates.load(std::memory_order_acquire)) \
111 UpdateContextProps(context.get()); \
112 else \
113 context->mPropsClean.clear(std::memory_order_release); \
114 } while(0)
117 AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
118 START_API_FUNC
120 ContextRef context{GetContextRef()};
121 if UNLIKELY(!context) return;
123 std::lock_guard<std::mutex> _{context->mPropLock};
124 switch(capability)
126 case AL_SOURCE_DISTANCE_MODEL:
127 context->mSourceDistanceModel = AL_TRUE;
128 DO_UPDATEPROPS();
129 break;
131 default:
132 context->setError(AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability);
135 END_API_FUNC
137 AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
138 START_API_FUNC
140 ContextRef context{GetContextRef()};
141 if UNLIKELY(!context) return;
143 std::lock_guard<std::mutex> _{context->mPropLock};
144 switch(capability)
146 case AL_SOURCE_DISTANCE_MODEL:
147 context->mSourceDistanceModel = AL_FALSE;
148 DO_UPDATEPROPS();
149 break;
151 default:
152 context->setError(AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability);
155 END_API_FUNC
157 AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
158 START_API_FUNC
160 ContextRef context{GetContextRef()};
161 if UNLIKELY(!context) return AL_FALSE;
163 std::lock_guard<std::mutex> _{context->mPropLock};
164 ALboolean value{AL_FALSE};
165 switch(capability)
167 case AL_SOURCE_DISTANCE_MODEL:
168 value = context->mSourceDistanceModel;
169 break;
171 default:
172 context->setError(AL_INVALID_VALUE, "Invalid is enabled property 0x%04x", capability);
175 return value;
177 END_API_FUNC
179 AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
180 START_API_FUNC
182 ContextRef context{GetContextRef()};
183 if UNLIKELY(!context) return AL_FALSE;
185 std::lock_guard<std::mutex> _{context->mPropLock};
186 ALboolean value{AL_FALSE};
187 switch(pname)
189 case AL_DOPPLER_FACTOR:
190 if(context->mDopplerFactor != 0.0f)
191 value = AL_TRUE;
192 break;
194 case AL_DOPPLER_VELOCITY:
195 if(context->mDopplerVelocity != 0.0f)
196 value = AL_TRUE;
197 break;
199 case AL_DISTANCE_MODEL:
200 if(context->mDistanceModel == DistanceModel::Default)
201 value = AL_TRUE;
202 break;
204 case AL_SPEED_OF_SOUND:
205 if(context->mSpeedOfSound != 0.0f)
206 value = AL_TRUE;
207 break;
209 case AL_DEFERRED_UPDATES_SOFT:
210 if(context->mDeferUpdates.load(std::memory_order_acquire))
211 value = AL_TRUE;
212 break;
214 case AL_GAIN_LIMIT_SOFT:
215 if(GAIN_MIX_MAX/context->mGainBoost != 0.0f)
216 value = AL_TRUE;
217 break;
219 case AL_NUM_RESAMPLERS_SOFT:
220 /* Always non-0. */
221 value = AL_TRUE;
222 break;
224 case AL_DEFAULT_RESAMPLER_SOFT:
225 value = static_cast<int>(ResamplerDefault) ? AL_TRUE : AL_FALSE;
226 break;
228 default:
229 context->setError(AL_INVALID_VALUE, "Invalid boolean property 0x%04x", pname);
232 return value;
234 END_API_FUNC
236 AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
237 START_API_FUNC
239 ContextRef context{GetContextRef()};
240 if UNLIKELY(!context) return 0.0;
242 std::lock_guard<std::mutex> _{context->mPropLock};
243 ALdouble value{0.0};
244 switch(pname)
246 case AL_DOPPLER_FACTOR:
247 value = context->mDopplerFactor;
248 break;
250 case AL_DOPPLER_VELOCITY:
251 value = context->mDopplerVelocity;
252 break;
254 case AL_DISTANCE_MODEL:
255 value = static_cast<ALdouble>(context->mDistanceModel);
256 break;
258 case AL_SPEED_OF_SOUND:
259 value = context->mSpeedOfSound;
260 break;
262 case AL_DEFERRED_UPDATES_SOFT:
263 if(context->mDeferUpdates.load(std::memory_order_acquire))
264 value = static_cast<ALdouble>(AL_TRUE);
265 break;
267 case AL_GAIN_LIMIT_SOFT:
268 value = ALdouble{GAIN_MIX_MAX}/context->mGainBoost;
269 break;
271 case AL_NUM_RESAMPLERS_SOFT:
272 value = static_cast<ALdouble>(Resampler::Max) + 1.0;
273 break;
275 case AL_DEFAULT_RESAMPLER_SOFT:
276 value = static_cast<ALdouble>(ResamplerDefault);
277 break;
279 default:
280 context->setError(AL_INVALID_VALUE, "Invalid double property 0x%04x", pname);
283 return value;
285 END_API_FUNC
287 AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
288 START_API_FUNC
290 ContextRef context{GetContextRef()};
291 if UNLIKELY(!context) return 0.0f;
293 std::lock_guard<std::mutex> _{context->mPropLock};
294 ALfloat value{0.0f};
295 switch(pname)
297 case AL_DOPPLER_FACTOR:
298 value = context->mDopplerFactor;
299 break;
301 case AL_DOPPLER_VELOCITY:
302 value = context->mDopplerVelocity;
303 break;
305 case AL_DISTANCE_MODEL:
306 value = static_cast<ALfloat>(context->mDistanceModel);
307 break;
309 case AL_SPEED_OF_SOUND:
310 value = context->mSpeedOfSound;
311 break;
313 case AL_DEFERRED_UPDATES_SOFT:
314 if(context->mDeferUpdates.load(std::memory_order_acquire))
315 value = static_cast<ALfloat>(AL_TRUE);
316 break;
318 case AL_GAIN_LIMIT_SOFT:
319 value = GAIN_MIX_MAX/context->mGainBoost;
320 break;
322 case AL_NUM_RESAMPLERS_SOFT:
323 value = static_cast<ALfloat>(Resampler::Max) + 1.0f;
324 break;
326 case AL_DEFAULT_RESAMPLER_SOFT:
327 value = static_cast<ALfloat>(ResamplerDefault);
328 break;
330 default:
331 context->setError(AL_INVALID_VALUE, "Invalid float property 0x%04x", pname);
334 return value;
336 END_API_FUNC
338 AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
339 START_API_FUNC
341 ContextRef context{GetContextRef()};
342 if UNLIKELY(!context) return 0;
344 std::lock_guard<std::mutex> _{context->mPropLock};
345 ALint value{0};
346 switch(pname)
348 case AL_DOPPLER_FACTOR:
349 value = static_cast<ALint>(context->mDopplerFactor);
350 break;
352 case AL_DOPPLER_VELOCITY:
353 value = static_cast<ALint>(context->mDopplerVelocity);
354 break;
356 case AL_DISTANCE_MODEL:
357 value = static_cast<ALint>(context->mDistanceModel);
358 break;
360 case AL_SPEED_OF_SOUND:
361 value = static_cast<ALint>(context->mSpeedOfSound);
362 break;
364 case AL_DEFERRED_UPDATES_SOFT:
365 if(context->mDeferUpdates.load(std::memory_order_acquire))
366 value = AL_TRUE;
367 break;
369 case AL_GAIN_LIMIT_SOFT:
370 value = static_cast<ALint>(GAIN_MIX_MAX/context->mGainBoost);
371 break;
373 case AL_NUM_RESAMPLERS_SOFT:
374 value = static_cast<int>(Resampler::Max) + 1;
375 break;
377 case AL_DEFAULT_RESAMPLER_SOFT:
378 value = static_cast<int>(ResamplerDefault);
379 break;
381 default:
382 context->setError(AL_INVALID_VALUE, "Invalid integer property 0x%04x", pname);
385 return value;
387 END_API_FUNC
389 extern "C" AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
390 START_API_FUNC
392 ContextRef context{GetContextRef()};
393 if UNLIKELY(!context) return 0_i64;
395 std::lock_guard<std::mutex> _{context->mPropLock};
396 ALint64SOFT value{0};
397 switch(pname)
399 case AL_DOPPLER_FACTOR:
400 value = static_cast<ALint64SOFT>(context->mDopplerFactor);
401 break;
403 case AL_DOPPLER_VELOCITY:
404 value = static_cast<ALint64SOFT>(context->mDopplerVelocity);
405 break;
407 case AL_DISTANCE_MODEL:
408 value = static_cast<ALint64SOFT>(context->mDistanceModel);
409 break;
411 case AL_SPEED_OF_SOUND:
412 value = static_cast<ALint64SOFT>(context->mSpeedOfSound);
413 break;
415 case AL_DEFERRED_UPDATES_SOFT:
416 if(context->mDeferUpdates.load(std::memory_order_acquire))
417 value = AL_TRUE;
418 break;
420 case AL_GAIN_LIMIT_SOFT:
421 value = static_cast<ALint64SOFT>(GAIN_MIX_MAX/context->mGainBoost);
422 break;
424 case AL_NUM_RESAMPLERS_SOFT:
425 value = static_cast<ALint64SOFT>(Resampler::Max) + 1;
426 break;
428 case AL_DEFAULT_RESAMPLER_SOFT:
429 value = static_cast<ALint64SOFT>(ResamplerDefault);
430 break;
432 default:
433 context->setError(AL_INVALID_VALUE, "Invalid integer64 property 0x%04x", pname);
436 return value;
438 END_API_FUNC
440 AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname)
441 START_API_FUNC
443 ContextRef context{GetContextRef()};
444 if UNLIKELY(!context) return nullptr;
446 std::lock_guard<std::mutex> _{context->mPropLock};
447 void *value{nullptr};
448 switch(pname)
450 case AL_EVENT_CALLBACK_FUNCTION_SOFT:
451 value = reinterpret_cast<void*>(context->mEventCb);
452 break;
454 case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
455 value = context->mEventParam;
456 break;
458 default:
459 context->setError(AL_INVALID_VALUE, "Invalid pointer property 0x%04x", pname);
462 return value;
464 END_API_FUNC
466 AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
467 START_API_FUNC
469 if(values)
471 switch(pname)
473 case AL_DOPPLER_FACTOR:
474 case AL_DOPPLER_VELOCITY:
475 case AL_DISTANCE_MODEL:
476 case AL_SPEED_OF_SOUND:
477 case AL_DEFERRED_UPDATES_SOFT:
478 case AL_GAIN_LIMIT_SOFT:
479 case AL_NUM_RESAMPLERS_SOFT:
480 case AL_DEFAULT_RESAMPLER_SOFT:
481 values[0] = alGetBoolean(pname);
482 return;
486 ContextRef context{GetContextRef()};
487 if UNLIKELY(!context) return;
489 if(!values)
490 context->setError(AL_INVALID_VALUE, "NULL pointer");
491 else switch(pname)
493 default:
494 context->setError(AL_INVALID_VALUE, "Invalid boolean-vector property 0x%04x", pname);
497 END_API_FUNC
499 AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
500 START_API_FUNC
502 if(values)
504 switch(pname)
506 case AL_DOPPLER_FACTOR:
507 case AL_DOPPLER_VELOCITY:
508 case AL_DISTANCE_MODEL:
509 case AL_SPEED_OF_SOUND:
510 case AL_DEFERRED_UPDATES_SOFT:
511 case AL_GAIN_LIMIT_SOFT:
512 case AL_NUM_RESAMPLERS_SOFT:
513 case AL_DEFAULT_RESAMPLER_SOFT:
514 values[0] = alGetDouble(pname);
515 return;
519 ContextRef context{GetContextRef()};
520 if UNLIKELY(!context) return;
522 if(!values)
523 context->setError(AL_INVALID_VALUE, "NULL pointer");
524 else switch(pname)
526 default:
527 context->setError(AL_INVALID_VALUE, "Invalid double-vector property 0x%04x", pname);
530 END_API_FUNC
532 AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
533 START_API_FUNC
535 if(values)
537 switch(pname)
539 case AL_DOPPLER_FACTOR:
540 case AL_DOPPLER_VELOCITY:
541 case AL_DISTANCE_MODEL:
542 case AL_SPEED_OF_SOUND:
543 case AL_DEFERRED_UPDATES_SOFT:
544 case AL_GAIN_LIMIT_SOFT:
545 case AL_NUM_RESAMPLERS_SOFT:
546 case AL_DEFAULT_RESAMPLER_SOFT:
547 values[0] = alGetFloat(pname);
548 return;
552 ContextRef context{GetContextRef()};
553 if UNLIKELY(!context) return;
555 if(!values)
556 context->setError(AL_INVALID_VALUE, "NULL pointer");
557 else switch(pname)
559 default:
560 context->setError(AL_INVALID_VALUE, "Invalid float-vector property 0x%04x", pname);
563 END_API_FUNC
565 AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
566 START_API_FUNC
568 if(values)
570 switch(pname)
572 case AL_DOPPLER_FACTOR:
573 case AL_DOPPLER_VELOCITY:
574 case AL_DISTANCE_MODEL:
575 case AL_SPEED_OF_SOUND:
576 case AL_DEFERRED_UPDATES_SOFT:
577 case AL_GAIN_LIMIT_SOFT:
578 case AL_NUM_RESAMPLERS_SOFT:
579 case AL_DEFAULT_RESAMPLER_SOFT:
580 values[0] = alGetInteger(pname);
581 return;
585 ContextRef context{GetContextRef()};
586 if UNLIKELY(!context) return;
588 if(!values)
589 context->setError(AL_INVALID_VALUE, "NULL pointer");
590 else switch(pname)
592 default:
593 context->setError(AL_INVALID_VALUE, "Invalid integer-vector property 0x%04x", pname);
596 END_API_FUNC
598 extern "C" AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
599 START_API_FUNC
601 if(values)
603 switch(pname)
605 case AL_DOPPLER_FACTOR:
606 case AL_DOPPLER_VELOCITY:
607 case AL_DISTANCE_MODEL:
608 case AL_SPEED_OF_SOUND:
609 case AL_DEFERRED_UPDATES_SOFT:
610 case AL_GAIN_LIMIT_SOFT:
611 case AL_NUM_RESAMPLERS_SOFT:
612 case AL_DEFAULT_RESAMPLER_SOFT:
613 values[0] = alGetInteger64SOFT(pname);
614 return;
618 ContextRef context{GetContextRef()};
619 if UNLIKELY(!context) return;
621 if(!values)
622 context->setError(AL_INVALID_VALUE, "NULL pointer");
623 else switch(pname)
625 default:
626 context->setError(AL_INVALID_VALUE, "Invalid integer64-vector property 0x%04x", pname);
629 END_API_FUNC
631 AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values)
632 START_API_FUNC
634 if(values)
636 switch(pname)
638 case AL_EVENT_CALLBACK_FUNCTION_SOFT:
639 case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
640 values[0] = alGetPointerSOFT(pname);
641 return;
645 ContextRef context{GetContextRef()};
646 if UNLIKELY(!context) return;
648 if(!values)
649 context->setError(AL_INVALID_VALUE, "NULL pointer");
650 else switch(pname)
652 default:
653 context->setError(AL_INVALID_VALUE, "Invalid pointer-vector property 0x%04x", pname);
656 END_API_FUNC
658 AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
659 START_API_FUNC
661 ContextRef context{GetContextRef()};
662 if UNLIKELY(!context) return nullptr;
664 const ALchar *value{nullptr};
665 switch(pname)
667 case AL_VENDOR:
668 value = alVendor;
669 break;
671 case AL_VERSION:
672 value = alVersion;
673 break;
675 case AL_RENDERER:
676 value = alRenderer;
677 break;
679 case AL_EXTENSIONS:
680 value = context->mExtensionList;
681 break;
683 case AL_NO_ERROR:
684 value = alNoError;
685 break;
687 case AL_INVALID_NAME:
688 value = alErrInvalidName;
689 break;
691 case AL_INVALID_ENUM:
692 value = alErrInvalidEnum;
693 break;
695 case AL_INVALID_VALUE:
696 value = alErrInvalidValue;
697 break;
699 case AL_INVALID_OPERATION:
700 value = alErrInvalidOp;
701 break;
703 case AL_OUT_OF_MEMORY:
704 value = alErrOutOfMemory;
705 break;
707 default:
708 context->setError(AL_INVALID_VALUE, "Invalid string property 0x%04x", pname);
710 return value;
712 END_API_FUNC
714 AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
715 START_API_FUNC
717 ContextRef context{GetContextRef()};
718 if UNLIKELY(!context) return;
720 if(!(value >= 0.0f && std::isfinite(value)))
721 context->setError(AL_INVALID_VALUE, "Doppler factor %f out of range", value);
722 else
724 std::lock_guard<std::mutex> _{context->mPropLock};
725 context->mDopplerFactor = value;
726 DO_UPDATEPROPS();
729 END_API_FUNC
731 AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
732 START_API_FUNC
734 ContextRef context{GetContextRef()};
735 if UNLIKELY(!context) return;
737 if((context->mEnabledEvts.load(std::memory_order_relaxed)&EventType_Deprecated))
739 std::lock_guard<std::mutex> _{context->mEventCbLock};
740 ALbitfieldSOFT enabledevts{context->mEnabledEvts.load(std::memory_order_relaxed)};
741 if((enabledevts&EventType_Deprecated) && context->mEventCb)
743 static constexpr ALCchar msg[] =
744 "alDopplerVelocity is deprecated in AL1.1, use alSpeedOfSound";
745 const ALsizei msglen{sizeof(msg)-1};
746 (*context->mEventCb)(AL_EVENT_TYPE_DEPRECATED_SOFT, 0, 0, msglen, msg,
747 context->mEventParam);
751 if(!(value >= 0.0f && std::isfinite(value)))
752 context->setError(AL_INVALID_VALUE, "Doppler velocity %f out of range", value);
753 else
755 std::lock_guard<std::mutex> _{context->mPropLock};
756 context->mDopplerVelocity = value;
757 DO_UPDATEPROPS();
760 END_API_FUNC
762 AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
763 START_API_FUNC
765 ContextRef context{GetContextRef()};
766 if UNLIKELY(!context) return;
768 if(!(value > 0.0f && std::isfinite(value)))
769 context->setError(AL_INVALID_VALUE, "Speed of sound %f out of range", value);
770 else
772 std::lock_guard<std::mutex> _{context->mPropLock};
773 context->mSpeedOfSound = value;
774 DO_UPDATEPROPS();
777 END_API_FUNC
779 AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
780 START_API_FUNC
782 ContextRef context{GetContextRef()};
783 if UNLIKELY(!context) return;
785 if(!(value == AL_INVERSE_DISTANCE || value == AL_INVERSE_DISTANCE_CLAMPED ||
786 value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED ||
787 value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED ||
788 value == AL_NONE))
789 context->setError(AL_INVALID_VALUE, "Distance model 0x%04x out of range", value);
790 else
792 std::lock_guard<std::mutex> _{context->mPropLock};
793 context->mDistanceModel = static_cast<DistanceModel>(value);
794 if(!context->mSourceDistanceModel)
795 DO_UPDATEPROPS();
798 END_API_FUNC
801 AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
802 START_API_FUNC
804 ContextRef context{GetContextRef()};
805 if UNLIKELY(!context) return;
807 context->deferUpdates();
809 END_API_FUNC
811 AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
812 START_API_FUNC
814 ContextRef context{GetContextRef()};
815 if UNLIKELY(!context) return;
817 context->processUpdates();
819 END_API_FUNC
822 AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
823 START_API_FUNC
825 ContextRef context{GetContextRef()};
826 if UNLIKELY(!context) return nullptr;
828 const ALchar *value{nullptr};
829 switch(pname)
831 case AL_RESAMPLER_NAME_SOFT:
832 if(index < 0 || index > static_cast<ALint>(Resampler::Max))
833 context->setError(AL_INVALID_VALUE, "Resampler name index %d out of range", index);
834 else
835 value = GetResamplerName(static_cast<Resampler>(index));
836 break;
838 default:
839 context->setError(AL_INVALID_VALUE, "Invalid string indexed property");
841 return value;
843 END_API_FUNC
846 void UpdateContextProps(ALCcontext *context)
848 /* Get an unused proprty container, or allocate a new one as needed. */
849 ALcontextProps *props{context->mFreeContextProps.load(std::memory_order_acquire)};
850 if(!props)
851 props = new ALcontextProps{};
852 else
854 ALcontextProps *next;
855 do {
856 next = props->next.load(std::memory_order_relaxed);
857 } while(context->mFreeContextProps.compare_exchange_weak(props, next,
858 std::memory_order_seq_cst, std::memory_order_acquire) == 0);
861 /* Copy in current property values. */
862 props->DopplerFactor = context->mDopplerFactor;
863 props->DopplerVelocity = context->mDopplerVelocity;
864 props->SpeedOfSound = context->mSpeedOfSound;
866 props->SourceDistanceModel = context->mSourceDistanceModel;
867 props->mDistanceModel = context->mDistanceModel;
869 /* Set the new container for updating internal parameters. */
870 props = context->mUpdate.exchange(props, std::memory_order_acq_rel);
871 if(props)
873 /* If there was an unused update container, put it back in the
874 * freelist.
876 AtomicReplaceHead(context->mFreeContextProps, props);