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
40 #include "al/listener.h"
42 #include "alc/context.h"
43 #include "alc/device.h"
44 #include "alc/inprogext.h"
45 #include "alnumeric.h"
47 #include "core/context.h"
48 #include "core/logging.h"
49 #include "core/mixer/defs.h"
50 #include "core/voice.h"
51 #include "direct_defs.h"
52 #include "intrusive_ptr.h"
53 #include "opthelpers.h"
57 #include "alc/device.h"
59 #include "eax/globals.h"
60 #include "eax/x_ram.h"
66 [[nodiscard
]] constexpr auto GetVendorString() noexcept
{ return "OpenAL Community"; }
67 [[nodiscard
]] constexpr auto GetVersionString() noexcept
{ return "1.1 ALSOFT " ALSOFT_VERSION
; }
68 [[nodiscard
]] constexpr auto GetRendererString() noexcept
{ return "OpenAL Soft"; }
71 [[nodiscard
]] constexpr auto GetNoErrorString() noexcept
{ return "No Error"; }
72 [[nodiscard
]] constexpr auto GetInvalidNameString() noexcept
{ return "Invalid Name"; }
73 [[nodiscard
]] constexpr auto GetInvalidEnumString() noexcept
{ return "Invalid Enum"; }
74 [[nodiscard
]] constexpr auto GetInvalidValueString() noexcept
{ return "Invalid Value"; }
75 [[nodiscard
]] constexpr auto GetInvalidOperationString() noexcept
{ return "Invalid Operation"; }
76 [[nodiscard
]] constexpr auto GetOutOfMemoryString() noexcept
{ return "Out of Memory"; }
77 [[nodiscard
]] constexpr auto GetStackOverflowString() noexcept
{ return "Stack Overflow"; }
78 [[nodiscard
]] constexpr auto GetStackUnderflowString() noexcept
{ return "Stack Underflow"; }
80 /* Resampler strings */
81 template<Resampler rtype
> struct ResamplerName
{ };
82 template<> struct ResamplerName
<Resampler::Point
>
83 { static constexpr const ALchar
*Get() noexcept
{ return "Nearest"; } };
84 template<> struct ResamplerName
<Resampler::Linear
>
85 { static constexpr const ALchar
*Get() noexcept
{ return "Linear"; } };
86 template<> struct ResamplerName
<Resampler::Spline
>
87 { static constexpr const ALchar
*Get() noexcept
{ return "Cubic Spline"; } };
88 template<> struct ResamplerName
<Resampler::Gaussian
>
89 { static constexpr const ALchar
*Get() noexcept
{ return "4-point Gaussian"; } };
90 template<> struct ResamplerName
<Resampler::FastBSinc12
>
91 { static constexpr const ALchar
*Get() noexcept
{ return "11th order Sinc (fast)"; } };
92 template<> struct ResamplerName
<Resampler::BSinc12
>
93 { static constexpr const ALchar
*Get() noexcept
{ return "11th order Sinc"; } };
94 template<> struct ResamplerName
<Resampler::FastBSinc24
>
95 { static constexpr const ALchar
*Get() noexcept
{ return "23rd order Sinc (fast)"; } };
96 template<> struct ResamplerName
<Resampler::BSinc24
>
97 { static constexpr const ALchar
*Get() noexcept
{ return "23rd order Sinc"; } };
99 const ALchar
*GetResamplerName(const Resampler rtype
)
101 #define HANDLE_RESAMPLER(r) case r: return ResamplerName<r>::Get()
104 HANDLE_RESAMPLER(Resampler::Point
);
105 HANDLE_RESAMPLER(Resampler::Linear
);
106 HANDLE_RESAMPLER(Resampler::Spline
);
107 HANDLE_RESAMPLER(Resampler::Gaussian
);
108 HANDLE_RESAMPLER(Resampler::FastBSinc12
);
109 HANDLE_RESAMPLER(Resampler::BSinc12
);
110 HANDLE_RESAMPLER(Resampler::FastBSinc24
);
111 HANDLE_RESAMPLER(Resampler::BSinc24
);
113 #undef HANDLE_RESAMPLER
114 /* Should never get here. */
115 throw std::runtime_error
{"Unexpected resampler index"};
118 constexpr auto DistanceModelFromALenum(ALenum model
) noexcept
-> std::optional
<DistanceModel
>
122 case AL_NONE
: return DistanceModel::Disable
;
123 case AL_INVERSE_DISTANCE
: return DistanceModel::Inverse
;
124 case AL_INVERSE_DISTANCE_CLAMPED
: return DistanceModel::InverseClamped
;
125 case AL_LINEAR_DISTANCE
: return DistanceModel::Linear
;
126 case AL_LINEAR_DISTANCE_CLAMPED
: return DistanceModel::LinearClamped
;
127 case AL_EXPONENT_DISTANCE
: return DistanceModel::Exponent
;
128 case AL_EXPONENT_DISTANCE_CLAMPED
: return DistanceModel::ExponentClamped
;
132 constexpr auto ALenumFromDistanceModel(DistanceModel model
) -> ALenum
136 case DistanceModel::Disable
: return AL_NONE
;
137 case DistanceModel::Inverse
: return AL_INVERSE_DISTANCE
;
138 case DistanceModel::InverseClamped
: return AL_INVERSE_DISTANCE_CLAMPED
;
139 case DistanceModel::Linear
: return AL_LINEAR_DISTANCE
;
140 case DistanceModel::LinearClamped
: return AL_LINEAR_DISTANCE_CLAMPED
;
141 case DistanceModel::Exponent
: return AL_EXPONENT_DISTANCE
;
142 case DistanceModel::ExponentClamped
: return AL_EXPONENT_DISTANCE_CLAMPED
;
144 throw std::runtime_error
{"Unexpected distance model "+std::to_string(static_cast<int>(model
))};
147 enum PropertyValue
: ALenum
{
148 DopplerFactor
= AL_DOPPLER_FACTOR
,
149 DopplerVelocity
= AL_DOPPLER_VELOCITY
,
150 DistanceModel
= AL_DISTANCE_MODEL
,
151 SpeedOfSound
= AL_SPEED_OF_SOUND
,
152 DeferredUpdates
= AL_DEFERRED_UPDATES_SOFT
,
153 GainLimit
= AL_GAIN_LIMIT_SOFT
,
154 NumResamplers
= AL_NUM_RESAMPLERS_SOFT
,
155 DefaultResampler
= AL_DEFAULT_RESAMPLER_SOFT
,
156 DebugLoggedMessages
= AL_DEBUG_LOGGED_MESSAGES_EXT
,
157 DebugNextLoggedMessageLength
= AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT
,
158 MaxDebugMessageLength
= AL_MAX_DEBUG_MESSAGE_LENGTH_EXT
,
159 MaxDebugLoggedMessages
= AL_MAX_DEBUG_LOGGED_MESSAGES_EXT
,
160 MaxDebugGroupDepth
= AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT
,
161 MaxLabelLength
= AL_MAX_LABEL_LENGTH_EXT
,
162 ContextFlags
= AL_CONTEXT_FLAGS_EXT
,
164 EaxRamSize
= AL_EAX_RAM_SIZE
,
165 EaxRamFree
= AL_EAX_RAM_FREE
,
170 struct PropertyCastType
{
172 constexpr auto operator()(U
&& value
) const noexcept
173 { return static_cast<T
>(std::forward
<U
>(value
)); }
175 /* Special-case ALboolean to be an actual bool instead of a char type. */
177 struct PropertyCastType
<ALboolean
> {
179 constexpr ALboolean
operator()(U
&& value
) const noexcept
180 { return static_cast<bool>(std::forward
<U
>(value
)) ? AL_TRUE
: AL_FALSE
; }
185 void GetValue(ALCcontext
*context
, ALenum pname
, T
*values
)
187 auto cast_value
= PropertyCastType
<T
>{};
189 switch(static_cast<PropertyValue
>(pname
))
191 case AL_DOPPLER_FACTOR
:
192 *values
= cast_value(context
->mDopplerFactor
);
195 case AL_DOPPLER_VELOCITY
:
196 if(context
->mContextFlags
.test(ContextFlags::DebugBit
)) UNLIKELY
197 context
->debugMessage(DebugSource::API
, DebugType::DeprecatedBehavior
, 0,
198 DebugSeverity::Medium
,
199 "AL_DOPPLER_VELOCITY is deprecated in AL 1.1, use AL_SPEED_OF_SOUND; "
200 "AL_DOPPLER_VELOCITY -> AL_SPEED_OF_SOUND / 343.3f");
201 *values
= cast_value(context
->mDopplerVelocity
);
204 case AL_SPEED_OF_SOUND
:
205 *values
= cast_value(context
->mSpeedOfSound
);
208 case AL_GAIN_LIMIT_SOFT
:
209 *values
= cast_value(GainMixMax
/ context
->mGainBoost
);
212 case AL_DEFERRED_UPDATES_SOFT
:
213 *values
= cast_value(context
->mDeferUpdates
? AL_TRUE
: AL_FALSE
);
216 case AL_DISTANCE_MODEL
:
217 *values
= cast_value(ALenumFromDistanceModel(context
->mDistanceModel
));
220 case AL_NUM_RESAMPLERS_SOFT
:
221 *values
= cast_value(al::to_underlying(Resampler::Max
) + 1);
224 case AL_DEFAULT_RESAMPLER_SOFT
:
225 *values
= cast_value(al::to_underlying(ResamplerDefault
));
228 case AL_DEBUG_LOGGED_MESSAGES_EXT
:
230 std::lock_guard
<std::mutex
> debuglock
{context
->mDebugCbLock
};
231 *values
= cast_value(context
->mDebugLog
.size());
235 case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT
:
237 std::lock_guard
<std::mutex
> debuglock
{context
->mDebugCbLock
};
238 *values
= cast_value(context
->mDebugLog
.empty() ? 0_uz
239 : (context
->mDebugLog
.front().mMessage
.size()+1));
243 case AL_MAX_DEBUG_MESSAGE_LENGTH_EXT
:
244 *values
= cast_value(MaxDebugMessageLength
);
247 case AL_MAX_DEBUG_LOGGED_MESSAGES_EXT
:
248 *values
= cast_value(MaxDebugLoggedMessages
);
251 case AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT
:
252 *values
= cast_value(MaxDebugGroupDepth
);
255 case AL_MAX_LABEL_LENGTH_EXT
:
256 *values
= cast_value(MaxObjectLabelLength
);
259 case AL_CONTEXT_FLAGS_EXT
:
260 *values
= cast_value(context
->mContextFlags
.to_ulong());
264 #define EAX_ERROR "[alGetInteger] EAX not enabled"
266 case AL_EAX_RAM_SIZE
:
269 *values
= cast_value(eax_x_ram_max_size
);
275 case AL_EAX_RAM_FREE
:
278 auto device
= context
->mALDevice
.get();
279 std::lock_guard
<std::mutex
> device_lock
{device
->BufferLock
};
280 *values
= cast_value(device
->eax_x_ram_free_size
);
289 context
->setError(AL_INVALID_ENUM
, "Invalid context property 0x%04x", pname
);
293 inline void UpdateProps(ALCcontext
*context
)
295 if(!context
->mDeferUpdates
)
296 UpdateContextProps(context
);
298 context
->mPropsDirty
= true;
303 /* WARNING: Non-standard export! Not part of any extension, or exposed in the
306 AL_API
auto AL_APIENTRY
alsoft_get_version() noexcept
-> const ALchar
*
308 static const auto spoof
= al::getenv("ALSOFT_SPOOF_VERSION");
309 if(spoof
) return spoof
->c_str();
310 return ALSOFT_VERSION
;
314 AL_API
DECL_FUNC1(void, alEnable
, ALenum
,capability
)
315 FORCE_ALIGN
void AL_APIENTRY
alEnableDirect(ALCcontext
*context
, ALenum capability
) noexcept
319 case AL_SOURCE_DISTANCE_MODEL
:
321 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
322 context
->mSourceDistanceModel
= true;
323 UpdateProps(context
);
327 case AL_DEBUG_OUTPUT_EXT
:
328 context
->mDebugEnabled
.store(true);
331 case AL_STOP_SOURCES_ON_DISCONNECT_SOFT
:
332 context
->setError(AL_INVALID_OPERATION
, "Re-enabling AL_STOP_SOURCES_ON_DISCONNECT_SOFT not yet supported");
335 context
->setError(AL_INVALID_VALUE
, "Invalid enable property 0x%04x", capability
);
338 AL_API
DECL_FUNC1(void, alDisable
, ALenum
,capability
)
339 FORCE_ALIGN
void AL_APIENTRY
alDisableDirect(ALCcontext
*context
, ALenum capability
) noexcept
343 case AL_SOURCE_DISTANCE_MODEL
:
345 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
346 context
->mSourceDistanceModel
= false;
347 UpdateProps(context
);
351 case AL_DEBUG_OUTPUT_EXT
:
352 context
->mDebugEnabled
.store(false);
355 case AL_STOP_SOURCES_ON_DISCONNECT_SOFT
:
356 context
->mStopVoicesOnDisconnect
.store(false);
359 context
->setError(AL_INVALID_VALUE
, "Invalid disable property 0x%04x", capability
);
362 AL_API
DECL_FUNC1(ALboolean
, alIsEnabled
, ALenum
,capability
)
363 FORCE_ALIGN ALboolean AL_APIENTRY
alIsEnabledDirect(ALCcontext
*context
, ALenum capability
) noexcept
365 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
368 case AL_SOURCE_DISTANCE_MODEL
: return context
->mSourceDistanceModel
? AL_TRUE
: AL_FALSE
;
369 case AL_DEBUG_OUTPUT_EXT
: return context
->mDebugEnabled
? AL_TRUE
: AL_FALSE
;
370 case AL_STOP_SOURCES_ON_DISCONNECT_SOFT
:
371 return context
->mStopVoicesOnDisconnect
.load() ? AL_TRUE
: AL_FALSE
;
373 context
->setError(AL_INVALID_VALUE
, "Invalid is enabled property 0x%04x", capability
);
377 #define DECL_GETFUNC(R, Name, Ext) \
378 AL_API auto AL_APIENTRY Name##Ext(ALenum pname) noexcept -> R \
381 auto context = GetContextRef(); \
382 if(!context) UNLIKELY return value; \
383 Name##vDirect##Ext(GetContextRef().get(), pname, &value); \
386 FORCE_ALIGN auto AL_APIENTRY Name##Direct##Ext(ALCcontext *context, ALenum pname) noexcept -> R \
389 Name##vDirect##Ext(context, pname, &value); \
393 DECL_GETFUNC(ALboolean
, alGetBoolean
,)
394 DECL_GETFUNC(ALdouble
, alGetDouble
,)
395 DECL_GETFUNC(ALfloat
, alGetFloat
,)
396 DECL_GETFUNC(ALint
, alGetInteger
,)
398 DECL_GETFUNC(ALint64SOFT
, alGetInteger64
,SOFT
)
399 DECL_GETFUNC(ALvoid
*, alGetPointer
,SOFT
)
404 AL_API
DECL_FUNC2(void, alGetBooleanv
, ALenum
,pname
, ALboolean
*,values
)
405 FORCE_ALIGN
void AL_APIENTRY
alGetBooleanvDirect(ALCcontext
*context
, ALenum pname
, ALboolean
*values
) noexcept
408 return context
->setError(AL_INVALID_VALUE
, "NULL pointer");
409 GetValue(context
, pname
, values
);
412 AL_API
DECL_FUNC2(void, alGetDoublev
, ALenum
,pname
, ALdouble
*,values
)
413 FORCE_ALIGN
void AL_APIENTRY
alGetDoublevDirect(ALCcontext
*context
, ALenum pname
, ALdouble
*values
) noexcept
416 return context
->setError(AL_INVALID_VALUE
, "NULL pointer");
417 GetValue(context
, pname
, values
);
420 AL_API
DECL_FUNC2(void, alGetFloatv
, ALenum
,pname
, ALfloat
*,values
)
421 FORCE_ALIGN
void AL_APIENTRY
alGetFloatvDirect(ALCcontext
*context
, ALenum pname
, ALfloat
*values
) noexcept
424 return context
->setError(AL_INVALID_VALUE
, "NULL pointer");
425 GetValue(context
, pname
, values
);
428 AL_API
DECL_FUNC2(void, alGetIntegerv
, ALenum
,pname
, ALint
*,values
)
429 FORCE_ALIGN
void AL_APIENTRY
alGetIntegervDirect(ALCcontext
*context
, ALenum pname
, ALint
*values
) noexcept
432 return context
->setError(AL_INVALID_VALUE
, "NULL pointer");
433 GetValue(context
, pname
, values
);
436 AL_API
DECL_FUNCEXT2(void, alGetInteger64v
,SOFT
, ALenum
,pname
, ALint64SOFT
*,values
)
437 FORCE_ALIGN
void AL_APIENTRY
alGetInteger64vDirectSOFT(ALCcontext
*context
, ALenum pname
, ALint64SOFT
*values
) noexcept
440 return context
->setError(AL_INVALID_VALUE
, "NULL pointer");
441 GetValue(context
, pname
, values
);
444 AL_API
DECL_FUNCEXT2(void, alGetPointerv
,SOFT
, ALenum
,pname
, ALvoid
**,values
)
445 FORCE_ALIGN
void AL_APIENTRY
alGetPointervDirectSOFT(ALCcontext
*context
, ALenum pname
, ALvoid
**values
) noexcept
448 return context
->setError(AL_INVALID_VALUE
, "NULL pointer");
452 case AL_EVENT_CALLBACK_FUNCTION_SOFT
:
453 *values
= reinterpret_cast<void*>(context
->mEventCb
);
456 case AL_EVENT_CALLBACK_USER_PARAM_SOFT
:
457 *values
= context
->mEventParam
;
460 case AL_DEBUG_CALLBACK_FUNCTION_EXT
:
461 *values
= reinterpret_cast<void*>(context
->mDebugCb
);
464 case AL_DEBUG_CALLBACK_USER_PARAM_EXT
:
465 *values
= context
->mDebugParam
;
468 context
->setError(AL_INVALID_ENUM
, "Invalid context pointer property 0x%04x", pname
);
471 AL_API
DECL_FUNC1(const ALchar
*, alGetString
, ALenum
,pname
)
472 FORCE_ALIGN
const ALchar
* AL_APIENTRY
alGetStringDirect(ALCcontext
*context
, ALenum pname
) noexcept
477 if(auto device
= context
->mALDevice
.get(); !device
->mVendorOverride
.empty())
478 return device
->mVendorOverride
.c_str();
479 return GetVendorString();
481 if(auto device
= context
->mALDevice
.get(); !device
->mVersionOverride
.empty())
482 return device
->mVersionOverride
.c_str();
483 return GetVersionString();
485 if(auto device
= context
->mALDevice
.get(); !device
->mRendererOverride
.empty())
486 return device
->mRendererOverride
.c_str();
487 return GetRendererString();
488 case AL_EXTENSIONS
: return context
->mExtensionsString
.c_str();
489 case AL_NO_ERROR
: return GetNoErrorString();
490 case AL_INVALID_NAME
: return GetInvalidNameString();
491 case AL_INVALID_ENUM
: return GetInvalidEnumString();
492 case AL_INVALID_VALUE
: return GetInvalidValueString();
493 case AL_INVALID_OPERATION
: return GetInvalidOperationString();
494 case AL_OUT_OF_MEMORY
: return GetOutOfMemoryString();
495 case AL_STACK_OVERFLOW_EXT
: return GetStackOverflowString();
496 case AL_STACK_UNDERFLOW_EXT
: return GetStackUnderflowString();
498 context
->setError(AL_INVALID_VALUE
, "Invalid string property 0x%04x", pname
);
502 AL_API
DECL_FUNC1(void, alDopplerFactor
, ALfloat
,value
)
503 FORCE_ALIGN
void AL_APIENTRY
alDopplerFactorDirect(ALCcontext
*context
, ALfloat value
) noexcept
505 if(!(value
>= 0.0f
&& std::isfinite(value
)))
506 context
->setError(AL_INVALID_VALUE
, "Doppler factor %f out of range", value
);
509 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
510 context
->mDopplerFactor
= value
;
511 UpdateProps(context
);
515 AL_API
DECL_FUNC1(void, alSpeedOfSound
, ALfloat
,value
)
516 FORCE_ALIGN
void AL_APIENTRY
alSpeedOfSoundDirect(ALCcontext
*context
, ALfloat value
) noexcept
518 if(!(value
> 0.0f
&& std::isfinite(value
)))
519 context
->setError(AL_INVALID_VALUE
, "Speed of sound %f out of range", value
);
522 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
523 context
->mSpeedOfSound
= value
;
524 UpdateProps(context
);
528 AL_API
DECL_FUNC1(void, alDistanceModel
, ALenum
,value
)
529 FORCE_ALIGN
void AL_APIENTRY
alDistanceModelDirect(ALCcontext
*context
, ALenum value
) noexcept
531 if(auto model
= DistanceModelFromALenum(value
))
533 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
534 context
->mDistanceModel
= *model
;
535 if(!context
->mSourceDistanceModel
)
536 UpdateProps(context
);
539 context
->setError(AL_INVALID_VALUE
, "Distance model 0x%04x out of range", value
);
543 AL_API
DECL_FUNCEXT(void, alDeferUpdates
,SOFT
)
544 FORCE_ALIGN
void AL_APIENTRY
alDeferUpdatesDirectSOFT(ALCcontext
*context
) noexcept
546 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
547 context
->deferUpdates();
550 AL_API
DECL_FUNCEXT(void, alProcessUpdates
,SOFT
)
551 FORCE_ALIGN
void AL_APIENTRY
alProcessUpdatesDirectSOFT(ALCcontext
*context
) noexcept
553 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
554 context
->processUpdates();
558 AL_API
DECL_FUNCEXT2(const ALchar
*, alGetStringi
,SOFT
, ALenum
,pname
, ALsizei
,index
)
559 FORCE_ALIGN
const ALchar
* AL_APIENTRY
alGetStringiDirectSOFT(ALCcontext
*context
, ALenum pname
, ALsizei index
) noexcept
563 case AL_RESAMPLER_NAME_SOFT
:
564 if(index
>= 0 && index
<= static_cast<ALint
>(Resampler::Max
))
565 return GetResamplerName(static_cast<Resampler
>(index
));
566 context
->setError(AL_INVALID_VALUE
, "Resampler name index %d out of range", index
);
569 context
->setError(AL_INVALID_VALUE
, "Invalid string indexed property");
574 AL_API
void AL_APIENTRY
alDopplerVelocity(ALfloat value
) noexcept
576 ContextRef context
{GetContextRef()};
577 if(!context
) UNLIKELY
return;
579 if(context
->mContextFlags
.test(ContextFlags::DebugBit
)) UNLIKELY
580 context
->debugMessage(DebugSource::API
, DebugType::DeprecatedBehavior
, 0,
581 DebugSeverity::Medium
,
582 "alDopplerVelocity is deprecated in AL 1.1, use alSpeedOfSound; "
583 "alDopplerVelocity(x) -> alSpeedOfSound(343.3f * x)");
585 if(!(value
>= 0.0f
&& std::isfinite(value
)))
586 context
->setError(AL_INVALID_VALUE
, "Doppler velocity %f out of range", value
);
589 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
590 context
->mDopplerVelocity
= value
;
591 UpdateProps(context
.get());
596 void UpdateContextProps(ALCcontext
*context
)
598 /* Get an unused property container, or allocate a new one as needed. */
599 ContextProps
*props
{context
->mFreeContextProps
.load(std::memory_order_acquire
)};
602 context
->allocContextProps();
603 props
= context
->mFreeContextProps
.load(std::memory_order_acquire
);
607 next
= props
->next
.load(std::memory_order_relaxed
);
608 } while(context
->mFreeContextProps
.compare_exchange_weak(props
, next
,
609 std::memory_order_acq_rel
, std::memory_order_acquire
) == false);
611 /* Copy in current property values. */
612 const auto &listener
= context
->mListener
;
613 props
->Position
= listener
.Position
;
614 props
->Velocity
= listener
.Velocity
;
615 props
->OrientAt
= listener
.OrientAt
;
616 props
->OrientUp
= listener
.OrientUp
;
617 props
->Gain
= listener
.Gain
;
618 props
->MetersPerUnit
= listener
.mMetersPerUnit
;
620 props
->AirAbsorptionGainHF
= context
->mAirAbsorptionGainHF
;
621 props
->DopplerFactor
= context
->mDopplerFactor
;
622 props
->DopplerVelocity
= context
->mDopplerVelocity
;
623 props
->SpeedOfSound
= context
->mSpeedOfSound
;
625 props
->DistanceFactor
= context
->eaxGetDistanceFactor();
628 props
->SourceDistanceModel
= context
->mSourceDistanceModel
;
629 props
->mDistanceModel
= context
->mDistanceModel
;
631 /* Set the new container for updating internal parameters. */
632 props
= context
->mParams
.ContextUpdate
.exchange(props
, std::memory_order_acq_rel
);
635 /* If there was an unused update container, put it back in the
638 AtomicReplaceHead(context
->mFreeContextProps
, props
);