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
36 #include "alc/context.h"
37 #include "alc/inprogext.h"
38 #include "alnumeric.h"
39 #include "aloptional.h"
41 #include "core/context.h"
42 #include "core/except.h"
43 #include "core/mixer/defs.h"
44 #include "core/voice.h"
45 #include "intrusive_ptr.h"
46 #include "opthelpers.h"
50 #include "alc/device.h"
52 #include "eax_globals.h"
53 #include "eax_x_ram.h"
59 constexpr ALchar alVendor
[] = "OpenAL Community";
60 constexpr ALchar alVersion
[] = "1.1 ALSOFT " ALSOFT_VERSION
;
61 constexpr ALchar alRenderer
[] = "OpenAL Soft";
64 constexpr ALchar alNoError
[] = "No Error";
65 constexpr ALchar alErrInvalidName
[] = "Invalid Name";
66 constexpr ALchar alErrInvalidEnum
[] = "Invalid Enum";
67 constexpr ALchar alErrInvalidValue
[] = "Invalid Value";
68 constexpr ALchar alErrInvalidOp
[] = "Invalid Operation";
69 constexpr ALchar alErrOutOfMemory
[] = "Out of Memory";
71 /* Resampler strings */
72 template<Resampler rtype
> struct ResamplerName
{ };
73 template<> struct ResamplerName
<Resampler::Point
>
74 { static constexpr const ALchar
*Get() noexcept
{ return "Nearest"; } };
75 template<> struct ResamplerName
<Resampler::Linear
>
76 { static constexpr const ALchar
*Get() noexcept
{ return "Linear"; } };
77 template<> struct ResamplerName
<Resampler::Cubic
>
78 { static constexpr const ALchar
*Get() noexcept
{ return "Cubic"; } };
79 template<> struct ResamplerName
<Resampler::FastBSinc12
>
80 { static constexpr const ALchar
*Get() noexcept
{ return "11th order Sinc (fast)"; } };
81 template<> struct ResamplerName
<Resampler::BSinc12
>
82 { static constexpr const ALchar
*Get() noexcept
{ return "11th order Sinc"; } };
83 template<> struct ResamplerName
<Resampler::FastBSinc24
>
84 { static constexpr const ALchar
*Get() noexcept
{ return "23rd order Sinc (fast)"; } };
85 template<> struct ResamplerName
<Resampler::BSinc24
>
86 { static constexpr const ALchar
*Get() noexcept
{ return "23rd order Sinc"; } };
88 const ALchar
*GetResamplerName(const Resampler rtype
)
90 #define HANDLE_RESAMPLER(r) case r: return ResamplerName<r>::Get()
93 HANDLE_RESAMPLER(Resampler::Point
);
94 HANDLE_RESAMPLER(Resampler::Linear
);
95 HANDLE_RESAMPLER(Resampler::Cubic
);
96 HANDLE_RESAMPLER(Resampler::FastBSinc12
);
97 HANDLE_RESAMPLER(Resampler::BSinc12
);
98 HANDLE_RESAMPLER(Resampler::FastBSinc24
);
99 HANDLE_RESAMPLER(Resampler::BSinc24
);
101 #undef HANDLE_RESAMPLER
102 /* Should never get here. */
103 throw std::runtime_error
{"Unexpected resampler index"};
106 al::optional
<DistanceModel
> DistanceModelFromALenum(ALenum model
)
110 case AL_NONE
: return al::make_optional(DistanceModel::Disable
);
111 case AL_INVERSE_DISTANCE
: return al::make_optional(DistanceModel::Inverse
);
112 case AL_INVERSE_DISTANCE_CLAMPED
: return al::make_optional(DistanceModel::InverseClamped
);
113 case AL_LINEAR_DISTANCE
: return al::make_optional(DistanceModel::Linear
);
114 case AL_LINEAR_DISTANCE_CLAMPED
: return al::make_optional(DistanceModel::LinearClamped
);
115 case AL_EXPONENT_DISTANCE
: return al::make_optional(DistanceModel::Exponent
);
116 case AL_EXPONENT_DISTANCE_CLAMPED
: return al::make_optional(DistanceModel::ExponentClamped
);
120 ALenum
ALenumFromDistanceModel(DistanceModel model
)
124 case DistanceModel::Disable
: return AL_NONE
;
125 case DistanceModel::Inverse
: return AL_INVERSE_DISTANCE
;
126 case DistanceModel::InverseClamped
: return AL_INVERSE_DISTANCE_CLAMPED
;
127 case DistanceModel::Linear
: return AL_LINEAR_DISTANCE
;
128 case DistanceModel::LinearClamped
: return AL_LINEAR_DISTANCE_CLAMPED
;
129 case DistanceModel::Exponent
: return AL_EXPONENT_DISTANCE
;
130 case DistanceModel::ExponentClamped
: return AL_EXPONENT_DISTANCE_CLAMPED
;
132 throw std::runtime_error
{"Unexpected distance model "+std::to_string(static_cast<int>(model
))};
137 /* WARNING: Non-standard export! Not part of any extension, or exposed in the
140 extern "C" AL_API
const ALchar
* AL_APIENTRY
alsoft_get_version(void)
143 static const auto spoof
= al::getenv("ALSOFT_SPOOF_VERSION");
144 if(spoof
) return spoof
->c_str();
145 return ALSOFT_VERSION
;
149 #define DO_UPDATEPROPS() do { \
150 if(!context->mDeferUpdates) \
151 UpdateContextProps(context.get()); \
153 context->mPropsDirty = true; \
157 AL_API
void AL_APIENTRY
alEnable(ALenum capability
)
160 ContextRef context
{GetContextRef()};
161 if UNLIKELY(!context
) return;
165 case AL_SOURCE_DISTANCE_MODEL
:
167 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
168 context
->mSourceDistanceModel
= true;
173 case AL_STOP_SOURCES_ON_DISCONNECT_SOFT
:
174 context
->setError(AL_INVALID_OPERATION
, "Re-enabling AL_STOP_SOURCES_ON_DISCONNECT_SOFT not yet supported");
178 context
->setError(AL_INVALID_VALUE
, "Invalid enable property 0x%04x", capability
);
183 AL_API
void AL_APIENTRY
alDisable(ALenum capability
)
186 ContextRef context
{GetContextRef()};
187 if UNLIKELY(!context
) return;
191 case AL_SOURCE_DISTANCE_MODEL
:
193 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
194 context
->mSourceDistanceModel
= false;
199 case AL_STOP_SOURCES_ON_DISCONNECT_SOFT
:
200 context
->mStopVoicesOnDisconnect
= false;
204 context
->setError(AL_INVALID_VALUE
, "Invalid disable property 0x%04x", capability
);
209 AL_API ALboolean AL_APIENTRY
alIsEnabled(ALenum capability
)
212 ContextRef context
{GetContextRef()};
213 if UNLIKELY(!context
) return AL_FALSE
;
215 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
216 ALboolean value
{AL_FALSE
};
219 case AL_SOURCE_DISTANCE_MODEL
:
220 value
= context
->mSourceDistanceModel
? AL_TRUE
: AL_FALSE
;
223 case AL_STOP_SOURCES_ON_DISCONNECT_SOFT
:
224 value
= context
->mStopVoicesOnDisconnect
? AL_TRUE
: AL_FALSE
;
228 context
->setError(AL_INVALID_VALUE
, "Invalid is enabled property 0x%04x", capability
);
235 AL_API ALboolean AL_APIENTRY
alGetBoolean(ALenum pname
)
238 ContextRef context
{GetContextRef()};
239 if UNLIKELY(!context
) return AL_FALSE
;
241 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
242 ALboolean value
{AL_FALSE
};
245 case AL_DOPPLER_FACTOR
:
246 if(context
->mDopplerFactor
!= 0.0f
)
250 case AL_DOPPLER_VELOCITY
:
251 if(context
->mDopplerVelocity
!= 0.0f
)
255 case AL_DISTANCE_MODEL
:
256 if(context
->mDistanceModel
== DistanceModel::Default
)
260 case AL_SPEED_OF_SOUND
:
261 if(context
->mSpeedOfSound
!= 0.0f
)
265 case AL_DEFERRED_UPDATES_SOFT
:
266 if(context
->mDeferUpdates
)
270 case AL_GAIN_LIMIT_SOFT
:
271 if(GainMixMax
/context
->mGainBoost
!= 0.0f
)
275 case AL_NUM_RESAMPLERS_SOFT
:
280 case AL_DEFAULT_RESAMPLER_SOFT
:
281 value
= static_cast<int>(ResamplerDefault
) ? AL_TRUE
: AL_FALSE
;
285 context
->setError(AL_INVALID_VALUE
, "Invalid boolean property 0x%04x", pname
);
292 AL_API ALdouble AL_APIENTRY
alGetDouble(ALenum pname
)
295 ContextRef context
{GetContextRef()};
296 if UNLIKELY(!context
) return 0.0;
298 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
302 case AL_DOPPLER_FACTOR
:
303 value
= context
->mDopplerFactor
;
306 case AL_DOPPLER_VELOCITY
:
307 value
= context
->mDopplerVelocity
;
310 case AL_DISTANCE_MODEL
:
311 value
= static_cast<ALdouble
>(ALenumFromDistanceModel(context
->mDistanceModel
));
314 case AL_SPEED_OF_SOUND
:
315 value
= context
->mSpeedOfSound
;
318 case AL_DEFERRED_UPDATES_SOFT
:
319 if(context
->mDeferUpdates
)
320 value
= static_cast<ALdouble
>(AL_TRUE
);
323 case AL_GAIN_LIMIT_SOFT
:
324 value
= ALdouble
{GainMixMax
}/context
->mGainBoost
;
327 case AL_NUM_RESAMPLERS_SOFT
:
328 value
= static_cast<ALdouble
>(Resampler::Max
) + 1.0;
331 case AL_DEFAULT_RESAMPLER_SOFT
:
332 value
= static_cast<ALdouble
>(ResamplerDefault
);
336 context
->setError(AL_INVALID_VALUE
, "Invalid double property 0x%04x", pname
);
343 AL_API ALfloat AL_APIENTRY
alGetFloat(ALenum pname
)
346 ContextRef context
{GetContextRef()};
347 if UNLIKELY(!context
) return 0.0f
;
349 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
353 case AL_DOPPLER_FACTOR
:
354 value
= context
->mDopplerFactor
;
357 case AL_DOPPLER_VELOCITY
:
358 value
= context
->mDopplerVelocity
;
361 case AL_DISTANCE_MODEL
:
362 value
= static_cast<ALfloat
>(ALenumFromDistanceModel(context
->mDistanceModel
));
365 case AL_SPEED_OF_SOUND
:
366 value
= context
->mSpeedOfSound
;
369 case AL_DEFERRED_UPDATES_SOFT
:
370 if(context
->mDeferUpdates
)
371 value
= static_cast<ALfloat
>(AL_TRUE
);
374 case AL_GAIN_LIMIT_SOFT
:
375 value
= GainMixMax
/context
->mGainBoost
;
378 case AL_NUM_RESAMPLERS_SOFT
:
379 value
= static_cast<ALfloat
>(Resampler::Max
) + 1.0f
;
382 case AL_DEFAULT_RESAMPLER_SOFT
:
383 value
= static_cast<ALfloat
>(ResamplerDefault
);
387 context
->setError(AL_INVALID_VALUE
, "Invalid float property 0x%04x", pname
);
394 AL_API ALint AL_APIENTRY
alGetInteger(ALenum pname
)
397 ContextRef context
{GetContextRef()};
398 if UNLIKELY(!context
) return 0;
400 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
404 case AL_DOPPLER_FACTOR
:
405 value
= static_cast<ALint
>(context
->mDopplerFactor
);
408 case AL_DOPPLER_VELOCITY
:
409 value
= static_cast<ALint
>(context
->mDopplerVelocity
);
412 case AL_DISTANCE_MODEL
:
413 value
= ALenumFromDistanceModel(context
->mDistanceModel
);
416 case AL_SPEED_OF_SOUND
:
417 value
= static_cast<ALint
>(context
->mSpeedOfSound
);
420 case AL_DEFERRED_UPDATES_SOFT
:
421 if(context
->mDeferUpdates
)
425 case AL_GAIN_LIMIT_SOFT
:
426 value
= static_cast<ALint
>(GainMixMax
/context
->mGainBoost
);
429 case AL_NUM_RESAMPLERS_SOFT
:
430 value
= static_cast<int>(Resampler::Max
) + 1;
433 case AL_DEFAULT_RESAMPLER_SOFT
:
434 value
= static_cast<int>(ResamplerDefault
);
439 #define EAX_ERROR "[alGetInteger] EAX not enabled."
441 case AL_EAX_RAM_SIZE
:
442 if (eax_g_is_enabled
)
444 value
= eax_x_ram_max_size
;
448 context
->setError(AL_INVALID_VALUE
, EAX_ERROR
);
453 case AL_EAX_RAM_FREE
:
454 if (eax_g_is_enabled
)
456 auto device
= context
->mALDevice
.get();
457 std::lock_guard
<std::mutex
> device_lock
{device
->BufferLock
};
459 value
= static_cast<ALint
>(device
->eax_x_ram_free_size
);
463 context
->setError(AL_INVALID_VALUE
, EAX_ERROR
);
473 context
->setError(AL_INVALID_VALUE
, "Invalid integer property 0x%04x", pname
);
480 extern "C" AL_API ALint64SOFT AL_APIENTRY
alGetInteger64SOFT(ALenum pname
)
483 ContextRef context
{GetContextRef()};
484 if UNLIKELY(!context
) return 0_i64
;
486 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
487 ALint64SOFT value
{0};
490 case AL_DOPPLER_FACTOR
:
491 value
= static_cast<ALint64SOFT
>(context
->mDopplerFactor
);
494 case AL_DOPPLER_VELOCITY
:
495 value
= static_cast<ALint64SOFT
>(context
->mDopplerVelocity
);
498 case AL_DISTANCE_MODEL
:
499 value
= ALenumFromDistanceModel(context
->mDistanceModel
);
502 case AL_SPEED_OF_SOUND
:
503 value
= static_cast<ALint64SOFT
>(context
->mSpeedOfSound
);
506 case AL_DEFERRED_UPDATES_SOFT
:
507 if(context
->mDeferUpdates
)
511 case AL_GAIN_LIMIT_SOFT
:
512 value
= static_cast<ALint64SOFT
>(GainMixMax
/context
->mGainBoost
);
515 case AL_NUM_RESAMPLERS_SOFT
:
516 value
= static_cast<ALint64SOFT
>(Resampler::Max
) + 1;
519 case AL_DEFAULT_RESAMPLER_SOFT
:
520 value
= static_cast<ALint64SOFT
>(ResamplerDefault
);
524 context
->setError(AL_INVALID_VALUE
, "Invalid integer64 property 0x%04x", pname
);
531 AL_API ALvoid
* AL_APIENTRY
alGetPointerSOFT(ALenum pname
)
534 ContextRef context
{GetContextRef()};
535 if UNLIKELY(!context
) return nullptr;
537 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
538 void *value
{nullptr};
541 case AL_EVENT_CALLBACK_FUNCTION_SOFT
:
542 value
= reinterpret_cast<void*>(context
->mEventCb
);
545 case AL_EVENT_CALLBACK_USER_PARAM_SOFT
:
546 value
= context
->mEventParam
;
550 context
->setError(AL_INVALID_VALUE
, "Invalid pointer property 0x%04x", pname
);
557 AL_API
void AL_APIENTRY
alGetBooleanv(ALenum pname
, ALboolean
*values
)
564 case AL_DOPPLER_FACTOR
:
565 case AL_DOPPLER_VELOCITY
:
566 case AL_DISTANCE_MODEL
:
567 case AL_SPEED_OF_SOUND
:
568 case AL_DEFERRED_UPDATES_SOFT
:
569 case AL_GAIN_LIMIT_SOFT
:
570 case AL_NUM_RESAMPLERS_SOFT
:
571 case AL_DEFAULT_RESAMPLER_SOFT
:
572 values
[0] = alGetBoolean(pname
);
577 ContextRef context
{GetContextRef()};
578 if UNLIKELY(!context
) return;
581 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
585 context
->setError(AL_INVALID_VALUE
, "Invalid boolean-vector property 0x%04x", pname
);
590 AL_API
void AL_APIENTRY
alGetDoublev(ALenum pname
, ALdouble
*values
)
597 case AL_DOPPLER_FACTOR
:
598 case AL_DOPPLER_VELOCITY
:
599 case AL_DISTANCE_MODEL
:
600 case AL_SPEED_OF_SOUND
:
601 case AL_DEFERRED_UPDATES_SOFT
:
602 case AL_GAIN_LIMIT_SOFT
:
603 case AL_NUM_RESAMPLERS_SOFT
:
604 case AL_DEFAULT_RESAMPLER_SOFT
:
605 values
[0] = alGetDouble(pname
);
610 ContextRef context
{GetContextRef()};
611 if UNLIKELY(!context
) return;
614 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
618 context
->setError(AL_INVALID_VALUE
, "Invalid double-vector property 0x%04x", pname
);
623 AL_API
void AL_APIENTRY
alGetFloatv(ALenum pname
, ALfloat
*values
)
630 case AL_DOPPLER_FACTOR
:
631 case AL_DOPPLER_VELOCITY
:
632 case AL_DISTANCE_MODEL
:
633 case AL_SPEED_OF_SOUND
:
634 case AL_DEFERRED_UPDATES_SOFT
:
635 case AL_GAIN_LIMIT_SOFT
:
636 case AL_NUM_RESAMPLERS_SOFT
:
637 case AL_DEFAULT_RESAMPLER_SOFT
:
638 values
[0] = alGetFloat(pname
);
643 ContextRef context
{GetContextRef()};
644 if UNLIKELY(!context
) return;
647 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
651 context
->setError(AL_INVALID_VALUE
, "Invalid float-vector property 0x%04x", pname
);
656 AL_API
void AL_APIENTRY
alGetIntegerv(ALenum pname
, ALint
*values
)
663 case AL_DOPPLER_FACTOR
:
664 case AL_DOPPLER_VELOCITY
:
665 case AL_DISTANCE_MODEL
:
666 case AL_SPEED_OF_SOUND
:
667 case AL_DEFERRED_UPDATES_SOFT
:
668 case AL_GAIN_LIMIT_SOFT
:
669 case AL_NUM_RESAMPLERS_SOFT
:
670 case AL_DEFAULT_RESAMPLER_SOFT
:
671 values
[0] = alGetInteger(pname
);
676 ContextRef context
{GetContextRef()};
677 if UNLIKELY(!context
) return;
680 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
684 context
->setError(AL_INVALID_VALUE
, "Invalid integer-vector property 0x%04x", pname
);
689 extern "C" AL_API
void AL_APIENTRY
alGetInteger64vSOFT(ALenum pname
, ALint64SOFT
*values
)
696 case AL_DOPPLER_FACTOR
:
697 case AL_DOPPLER_VELOCITY
:
698 case AL_DISTANCE_MODEL
:
699 case AL_SPEED_OF_SOUND
:
700 case AL_DEFERRED_UPDATES_SOFT
:
701 case AL_GAIN_LIMIT_SOFT
:
702 case AL_NUM_RESAMPLERS_SOFT
:
703 case AL_DEFAULT_RESAMPLER_SOFT
:
704 values
[0] = alGetInteger64SOFT(pname
);
709 ContextRef context
{GetContextRef()};
710 if UNLIKELY(!context
) return;
713 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
717 context
->setError(AL_INVALID_VALUE
, "Invalid integer64-vector property 0x%04x", pname
);
722 AL_API
void AL_APIENTRY
alGetPointervSOFT(ALenum pname
, ALvoid
**values
)
729 case AL_EVENT_CALLBACK_FUNCTION_SOFT
:
730 case AL_EVENT_CALLBACK_USER_PARAM_SOFT
:
731 values
[0] = alGetPointerSOFT(pname
);
736 ContextRef context
{GetContextRef()};
737 if UNLIKELY(!context
) return;
740 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
744 context
->setError(AL_INVALID_VALUE
, "Invalid pointer-vector property 0x%04x", pname
);
749 AL_API
const ALchar
* AL_APIENTRY
alGetString(ALenum pname
)
752 ContextRef context
{GetContextRef()};
753 if UNLIKELY(!context
) return nullptr;
755 const ALchar
*value
{nullptr};
771 value
= context
->mExtensionList
;
778 case AL_INVALID_NAME
:
779 value
= alErrInvalidName
;
782 case AL_INVALID_ENUM
:
783 value
= alErrInvalidEnum
;
786 case AL_INVALID_VALUE
:
787 value
= alErrInvalidValue
;
790 case AL_INVALID_OPERATION
:
791 value
= alErrInvalidOp
;
794 case AL_OUT_OF_MEMORY
:
795 value
= alErrOutOfMemory
;
799 context
->setError(AL_INVALID_VALUE
, "Invalid string property 0x%04x", pname
);
805 AL_API
void AL_APIENTRY
alDopplerFactor(ALfloat value
)
808 ContextRef context
{GetContextRef()};
809 if UNLIKELY(!context
) return;
811 if(!(value
>= 0.0f
&& std::isfinite(value
)))
812 context
->setError(AL_INVALID_VALUE
, "Doppler factor %f out of range", value
);
815 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
816 context
->mDopplerFactor
= value
;
822 AL_API
void AL_APIENTRY
alDopplerVelocity(ALfloat value
)
825 ContextRef context
{GetContextRef()};
826 if UNLIKELY(!context
) return;
828 if(!(value
>= 0.0f
&& std::isfinite(value
)))
829 context
->setError(AL_INVALID_VALUE
, "Doppler velocity %f out of range", value
);
832 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
833 context
->mDopplerVelocity
= value
;
839 AL_API
void AL_APIENTRY
alSpeedOfSound(ALfloat value
)
842 ContextRef context
{GetContextRef()};
843 if UNLIKELY(!context
) return;
845 if(!(value
> 0.0f
&& std::isfinite(value
)))
846 context
->setError(AL_INVALID_VALUE
, "Speed of sound %f out of range", value
);
849 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
850 context
->mSpeedOfSound
= value
;
856 AL_API
void AL_APIENTRY
alDistanceModel(ALenum value
)
859 ContextRef context
{GetContextRef()};
860 if UNLIKELY(!context
) return;
862 if(auto model
= DistanceModelFromALenum(value
))
864 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
865 context
->mDistanceModel
= *model
;
866 if(!context
->mSourceDistanceModel
)
870 context
->setError(AL_INVALID_VALUE
, "Distance model 0x%04x out of range", value
);
875 AL_API
void AL_APIENTRY
alDeferUpdatesSOFT(void)
878 ContextRef context
{GetContextRef()};
879 if UNLIKELY(!context
) return;
881 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
882 context
->deferUpdates();
886 AL_API
void AL_APIENTRY
alProcessUpdatesSOFT(void)
889 ContextRef context
{GetContextRef()};
890 if UNLIKELY(!context
) return;
892 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
893 context
->processUpdates();
898 AL_API
const ALchar
* AL_APIENTRY
alGetStringiSOFT(ALenum pname
, ALsizei index
)
901 ContextRef context
{GetContextRef()};
902 if UNLIKELY(!context
) return nullptr;
904 const ALchar
*value
{nullptr};
907 case AL_RESAMPLER_NAME_SOFT
:
908 if(index
< 0 || index
> static_cast<ALint
>(Resampler::Max
))
909 context
->setError(AL_INVALID_VALUE
, "Resampler name index %d out of range", index
);
911 value
= GetResamplerName(static_cast<Resampler
>(index
));
915 context
->setError(AL_INVALID_VALUE
, "Invalid string indexed property");
922 void UpdateContextProps(ALCcontext
*context
)
924 /* Get an unused proprty container, or allocate a new one as needed. */
925 ContextProps
*props
{context
->mFreeContextProps
.load(std::memory_order_acquire
)};
927 props
= new ContextProps
{};
932 next
= props
->next
.load(std::memory_order_relaxed
);
933 } while(context
->mFreeContextProps
.compare_exchange_weak(props
, next
,
934 std::memory_order_seq_cst
, std::memory_order_acquire
) == 0);
937 /* Copy in current property values. */
938 ALlistener
&listener
= context
->mListener
;
939 props
->Position
= listener
.Position
;
940 props
->Velocity
= listener
.Velocity
;
941 props
->OrientAt
= listener
.OrientAt
;
942 props
->OrientUp
= listener
.OrientUp
;
943 props
->Gain
= listener
.Gain
;
944 props
->MetersPerUnit
= listener
.mMetersPerUnit
;
946 props
->DopplerFactor
= context
->mDopplerFactor
;
947 props
->DopplerVelocity
= context
->mDopplerVelocity
;
948 props
->SpeedOfSound
= context
->mSpeedOfSound
;
950 props
->SourceDistanceModel
= context
->mSourceDistanceModel
;
951 props
->mDistanceModel
= context
->mDistanceModel
;
953 /* Set the new container for updating internal parameters. */
954 props
= context
->mParams
.ContextUpdate
.exchange(props
, std::memory_order_acq_rel
);
957 /* If there was an unused update container, put it back in the
960 AtomicReplaceHead(context
->mFreeContextProps
, props
);