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
31 #include "alListener.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";
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
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); \
71 ATOMIC_FLAG_CLEAR(&context->PropsClean, almemory_order_release); \
75 AL_API ALvoid AL_APIENTRY
alEnable(ALenum capability
)
79 context
= GetContextRef();
82 almtx_lock(&context
->PropLock
);
85 case AL_SOURCE_DISTANCE_MODEL
:
86 context
->SourceDistanceModel
= AL_TRUE
;
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
)
102 context
= GetContextRef();
105 almtx_lock(&context
->PropLock
);
108 case AL_SOURCE_DISTANCE_MODEL
:
109 context
->SourceDistanceModel
= AL_FALSE
;
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
)
124 ALboolean value
=AL_FALSE
;
126 context
= GetContextRef();
127 if(!context
) return AL_FALSE
;
129 almtx_lock(&context
->PropLock
);
132 case AL_SOURCE_DISTANCE_MODEL
:
133 value
= context
->SourceDistanceModel
;
137 alSetError(context
, AL_INVALID_VALUE
, "Invalid is enabled property 0x%04x", capability
);
139 almtx_unlock(&context
->PropLock
);
141 ALCcontext_DecRef(context
);
145 AL_API ALboolean AL_APIENTRY
alGetBoolean(ALenum pname
)
148 ALboolean value
=AL_FALSE
;
150 context
= GetContextRef();
151 if(!context
) return AL_FALSE
;
153 almtx_lock(&context
->PropLock
);
156 case AL_DOPPLER_FACTOR
:
157 if(context
->DopplerFactor
!= 0.0f
)
161 case AL_DOPPLER_VELOCITY
:
162 if(context
->DopplerVelocity
!= 0.0f
)
166 case AL_DISTANCE_MODEL
:
167 if(context
->DistanceModel
== AL_INVERSE_DISTANCE_CLAMPED
)
171 case AL_SPEED_OF_SOUND
:
172 if(context
->SpeedOfSound
!= 0.0f
)
176 case AL_DEFERRED_UPDATES_SOFT
:
177 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
181 case AL_GAIN_LIMIT_SOFT
:
182 if(GAIN_MIX_MAX
/context
->GainBoost
!= 0.0f
)
186 case AL_NUM_RESAMPLERS_SOFT
:
191 case AL_DEFAULT_RESAMPLER_SOFT
:
192 value
= ResamplerDefault
? AL_TRUE
: AL_FALSE
;
196 alSetError(context
, AL_INVALID_VALUE
, "Invalid boolean property 0x%04x", pname
);
198 almtx_unlock(&context
->PropLock
);
200 ALCcontext_DecRef(context
);
204 AL_API ALdouble AL_APIENTRY
alGetDouble(ALenum pname
)
207 ALdouble value
= 0.0;
209 context
= GetContextRef();
210 if(!context
) return 0.0;
212 almtx_lock(&context
->PropLock
);
215 case AL_DOPPLER_FACTOR
:
216 value
= (ALdouble
)context
->DopplerFactor
;
219 case AL_DOPPLER_VELOCITY
:
220 value
= (ALdouble
)context
->DopplerVelocity
;
223 case AL_DISTANCE_MODEL
:
224 value
= (ALdouble
)context
->DistanceModel
;
227 case AL_SPEED_OF_SOUND
:
228 value
= (ALdouble
)context
->SpeedOfSound
;
231 case AL_DEFERRED_UPDATES_SOFT
:
232 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
233 value
= (ALdouble
)AL_TRUE
;
236 case AL_GAIN_LIMIT_SOFT
:
237 value
= (ALdouble
)GAIN_MIX_MAX
/context
->GainBoost
;
240 case AL_NUM_RESAMPLERS_SOFT
:
241 value
= (ALdouble
)(ResamplerMax
+ 1);
244 case AL_DEFAULT_RESAMPLER_SOFT
:
245 value
= (ALdouble
)ResamplerDefault
;
249 alSetError(context
, AL_INVALID_VALUE
, "Invalid double property 0x%04x", pname
);
251 almtx_unlock(&context
->PropLock
);
253 ALCcontext_DecRef(context
);
257 AL_API ALfloat AL_APIENTRY
alGetFloat(ALenum pname
)
260 ALfloat value
= 0.0f
;
262 context
= GetContextRef();
263 if(!context
) return 0.0f
;
265 almtx_lock(&context
->PropLock
);
268 case AL_DOPPLER_FACTOR
:
269 value
= context
->DopplerFactor
;
272 case AL_DOPPLER_VELOCITY
:
273 value
= context
->DopplerVelocity
;
276 case AL_DISTANCE_MODEL
:
277 value
= (ALfloat
)context
->DistanceModel
;
280 case AL_SPEED_OF_SOUND
:
281 value
= context
->SpeedOfSound
;
284 case AL_DEFERRED_UPDATES_SOFT
:
285 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
286 value
= (ALfloat
)AL_TRUE
;
289 case AL_GAIN_LIMIT_SOFT
:
290 value
= GAIN_MIX_MAX
/context
->GainBoost
;
293 case AL_NUM_RESAMPLERS_SOFT
:
294 value
= (ALfloat
)(ResamplerMax
+ 1);
297 case AL_DEFAULT_RESAMPLER_SOFT
:
298 value
= (ALfloat
)ResamplerDefault
;
302 alSetError(context
, AL_INVALID_VALUE
, "Invalid float property 0x%04x", pname
);
304 almtx_unlock(&context
->PropLock
);
306 ALCcontext_DecRef(context
);
310 AL_API ALint AL_APIENTRY
alGetInteger(ALenum pname
)
315 context
= GetContextRef();
316 if(!context
) return 0;
318 almtx_lock(&context
->PropLock
);
321 case AL_DOPPLER_FACTOR
:
322 value
= (ALint
)context
->DopplerFactor
;
325 case AL_DOPPLER_VELOCITY
:
326 value
= (ALint
)context
->DopplerVelocity
;
329 case AL_DISTANCE_MODEL
:
330 value
= (ALint
)context
->DistanceModel
;
333 case AL_SPEED_OF_SOUND
:
334 value
= (ALint
)context
->SpeedOfSound
;
337 case AL_DEFERRED_UPDATES_SOFT
:
338 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
339 value
= (ALint
)AL_TRUE
;
342 case AL_GAIN_LIMIT_SOFT
:
343 value
= (ALint
)(GAIN_MIX_MAX
/context
->GainBoost
);
346 case AL_NUM_RESAMPLERS_SOFT
:
347 value
= ResamplerMax
+ 1;
350 case AL_DEFAULT_RESAMPLER_SOFT
:
351 value
= ResamplerDefault
;
355 alSetError(context
, AL_INVALID_VALUE
, "Invalid integer property 0x%04x", pname
);
357 almtx_unlock(&context
->PropLock
);
359 ALCcontext_DecRef(context
);
363 AL_API ALint64SOFT AL_APIENTRY
alGetInteger64SOFT(ALenum pname
)
366 ALint64SOFT value
= 0;
368 context
= GetContextRef();
369 if(!context
) return 0;
371 almtx_lock(&context
->PropLock
);
374 case AL_DOPPLER_FACTOR
:
375 value
= (ALint64SOFT
)context
->DopplerFactor
;
378 case AL_DOPPLER_VELOCITY
:
379 value
= (ALint64SOFT
)context
->DopplerVelocity
;
382 case AL_DISTANCE_MODEL
:
383 value
= (ALint64SOFT
)context
->DistanceModel
;
386 case AL_SPEED_OF_SOUND
:
387 value
= (ALint64SOFT
)context
->SpeedOfSound
;
390 case AL_DEFERRED_UPDATES_SOFT
:
391 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
392 value
= (ALint64SOFT
)AL_TRUE
;
395 case AL_GAIN_LIMIT_SOFT
:
396 value
= (ALint64SOFT
)(GAIN_MIX_MAX
/context
->GainBoost
);
399 case AL_NUM_RESAMPLERS_SOFT
:
400 value
= (ALint64SOFT
)(ResamplerMax
+ 1);
403 case AL_DEFAULT_RESAMPLER_SOFT
:
404 value
= (ALint64SOFT
)ResamplerDefault
;
408 alSetError(context
, AL_INVALID_VALUE
, "Invalid integer64 property 0x%04x", pname
);
410 almtx_unlock(&context
->PropLock
);
412 ALCcontext_DecRef(context
);
416 AL_API
void* AL_APIENTRY
alGetPointerSOFT(ALenum pname
)
421 context
= GetContextRef();
422 if(!context
) return NULL
;
424 almtx_lock(&context
->PropLock
);
427 case AL_EVENT_CALLBACK_FUNCTION_SOFT
:
428 value
= context
->EventCb
;
431 case AL_EVENT_CALLBACK_USER_PARAM_SOFT
:
432 value
= context
->EventParam
;
436 alSetError(context
, AL_INVALID_VALUE
, "Invalid pointer property 0x%04x", pname
);
438 almtx_unlock(&context
->PropLock
);
440 ALCcontext_DecRef(context
);
444 AL_API ALvoid AL_APIENTRY
alGetBooleanv(ALenum pname
, ALboolean
*values
)
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
);
465 context
= GetContextRef();
469 alSetError(context
, AL_INVALID_VALUE
, "NULL pointer");
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
)
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
);
500 context
= GetContextRef();
504 alSetError(context
, AL_INVALID_VALUE
, "NULL pointer");
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
)
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
);
535 context
= GetContextRef();
539 alSetError(context
, AL_INVALID_VALUE
, "NULL pointer");
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
)
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
);
570 context
= GetContextRef();
574 alSetError(context
, AL_INVALID_VALUE
, "NULL pointer");
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
)
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
);
605 context
= GetContextRef();
609 alSetError(context
, AL_INVALID_VALUE
, "NULL pointer");
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
)
627 case AL_EVENT_CALLBACK_FUNCTION_SOFT
:
628 case AL_EVENT_CALLBACK_USER_PARAM_SOFT
:
629 values
[0] = alGetPointerSOFT(pname
);
634 context
= GetContextRef();
638 alSetError(context
, AL_INVALID_VALUE
, "NULL pointer");
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
;
653 context
= GetContextRef();
654 if(!context
) return NULL
;
671 value
= context
->ExtensionList
;
678 case AL_INVALID_NAME
:
679 value
= alErrInvalidName
;
682 case AL_INVALID_ENUM
:
683 value
= alErrInvalidEnum
;
686 case AL_INVALID_VALUE
:
687 value
= alErrInvalidValue
;
690 case AL_INVALID_OPERATION
:
691 value
= alErrInvalidOp
;
694 case AL_OUT_OF_MEMORY
:
695 value
= alErrOutOfMemory
;
699 alSetError(context
, AL_INVALID_VALUE
, "Invalid string property 0x%04x", pname
);
702 ALCcontext_DecRef(context
);
706 AL_API ALvoid AL_APIENTRY
alDopplerFactor(ALfloat value
)
710 context
= GetContextRef();
713 if(!(value
>= 0.0f
&& isfinite(value
)))
714 alSetError(context
, AL_INVALID_VALUE
, "Doppler factor %f out of range", value
);
717 almtx_lock(&context
->PropLock
);
718 context
->DopplerFactor
= value
;
720 almtx_unlock(&context
->PropLock
);
723 ALCcontext_DecRef(context
);
726 AL_API ALvoid AL_APIENTRY
alDopplerVelocity(ALfloat value
)
730 context
= GetContextRef();
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
);
751 almtx_lock(&context
->PropLock
);
752 context
->DopplerVelocity
= value
;
754 almtx_unlock(&context
->PropLock
);
757 ALCcontext_DecRef(context
);
760 AL_API ALvoid AL_APIENTRY
alSpeedOfSound(ALfloat value
)
764 context
= GetContextRef();
767 if(!(value
> 0.0f
&& isfinite(value
)))
768 alSetError(context
, AL_INVALID_VALUE
, "Speed of sound %f out of range", value
);
771 almtx_lock(&context
->PropLock
);
772 context
->SpeedOfSound
= value
;
774 almtx_unlock(&context
->PropLock
);
777 ALCcontext_DecRef(context
);
780 AL_API ALvoid AL_APIENTRY
alDistanceModel(ALenum value
)
784 context
= GetContextRef();
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
||
791 alSetError(context
, AL_INVALID_VALUE
, "Distance model 0x%04x out of range", value
);
794 almtx_lock(&context
->PropLock
);
795 context
->DistanceModel
= value
;
796 if(!context
->SourceDistanceModel
)
798 almtx_unlock(&context
->PropLock
);
801 ALCcontext_DecRef(context
);
805 AL_API ALvoid AL_APIENTRY
alDeferUpdatesSOFT(void)
809 context
= GetContextRef();
812 ALCcontext_DeferUpdates(context
);
814 ALCcontext_DecRef(context
);
817 AL_API ALvoid AL_APIENTRY
alProcessUpdatesSOFT(void)
821 context
= GetContextRef();
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
,
837 const ALchar
*value
= NULL
;
840 static_assert(COUNTOF(ResamplerNames
) == ResamplerMax
+1, "Incorrect ResamplerNames list");
842 context
= GetContextRef();
843 if(!context
) return NULL
;
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",
851 value
= ResamplerNames
[index
];
855 alSetError(context
, AL_INVALID_VALUE
, "Invalid string indexed property");
859 ALCcontext_DecRef(context
);
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
);
871 props
= al_calloc(16, sizeof(*props
));
874 struct ALcontextProps
*next
;
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
);
895 /* If there was an unused update container, put it back in the
898 ATOMIC_REPLACE_HEAD(struct ALcontextProps
*, &context
->FreeContextProps
, props
);