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
;
131 case AL_SOURCE_DISTANCE_MODEL
:
132 value
= context
->SourceDistanceModel
;
136 alSetError(context
, AL_INVALID_VALUE
, "Invalid is enabled property 0x%04x", capability
);
139 ALCcontext_DecRef(context
);
143 AL_API ALboolean AL_APIENTRY
alGetBoolean(ALenum pname
)
146 ALboolean value
=AL_FALSE
;
148 context
= GetContextRef();
149 if(!context
) return AL_FALSE
;
153 case AL_DOPPLER_FACTOR
:
154 if(context
->DopplerFactor
!= 0.0f
)
158 case AL_DOPPLER_VELOCITY
:
159 if(context
->DopplerVelocity
!= 0.0f
)
163 case AL_DISTANCE_MODEL
:
164 if(context
->DistanceModel
== AL_INVERSE_DISTANCE_CLAMPED
)
168 case AL_SPEED_OF_SOUND
:
169 if(context
->SpeedOfSound
!= 0.0f
)
173 case AL_DEFERRED_UPDATES_SOFT
:
174 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
178 case AL_GAIN_LIMIT_SOFT
:
179 if(GAIN_MIX_MAX
/context
->GainBoost
!= 0.0f
)
183 case AL_NUM_RESAMPLERS_SOFT
:
188 case AL_DEFAULT_RESAMPLER_SOFT
:
189 value
= ResamplerDefault
? AL_TRUE
: AL_FALSE
;
193 alSetError(context
, AL_INVALID_VALUE
, "Invalid boolean property 0x%04x", pname
);
196 ALCcontext_DecRef(context
);
200 AL_API ALdouble AL_APIENTRY
alGetDouble(ALenum pname
)
203 ALdouble value
= 0.0;
205 context
= GetContextRef();
206 if(!context
) return 0.0;
210 case AL_DOPPLER_FACTOR
:
211 value
= (ALdouble
)context
->DopplerFactor
;
214 case AL_DOPPLER_VELOCITY
:
215 value
= (ALdouble
)context
->DopplerVelocity
;
218 case AL_DISTANCE_MODEL
:
219 value
= (ALdouble
)context
->DistanceModel
;
222 case AL_SPEED_OF_SOUND
:
223 value
= (ALdouble
)context
->SpeedOfSound
;
226 case AL_DEFERRED_UPDATES_SOFT
:
227 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
228 value
= (ALdouble
)AL_TRUE
;
231 case AL_GAIN_LIMIT_SOFT
:
232 value
= (ALdouble
)GAIN_MIX_MAX
/context
->GainBoost
;
235 case AL_NUM_RESAMPLERS_SOFT
:
236 value
= (ALdouble
)(ResamplerMax
+ 1);
239 case AL_DEFAULT_RESAMPLER_SOFT
:
240 value
= (ALdouble
)ResamplerDefault
;
244 alSetError(context
, AL_INVALID_VALUE
, "Invalid double property 0x%04x", pname
);
247 ALCcontext_DecRef(context
);
251 AL_API ALfloat AL_APIENTRY
alGetFloat(ALenum pname
)
254 ALfloat value
= 0.0f
;
256 context
= GetContextRef();
257 if(!context
) return 0.0f
;
261 case AL_DOPPLER_FACTOR
:
262 value
= context
->DopplerFactor
;
265 case AL_DOPPLER_VELOCITY
:
266 value
= context
->DopplerVelocity
;
269 case AL_DISTANCE_MODEL
:
270 value
= (ALfloat
)context
->DistanceModel
;
273 case AL_SPEED_OF_SOUND
:
274 value
= context
->SpeedOfSound
;
277 case AL_DEFERRED_UPDATES_SOFT
:
278 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
279 value
= (ALfloat
)AL_TRUE
;
282 case AL_GAIN_LIMIT_SOFT
:
283 value
= GAIN_MIX_MAX
/context
->GainBoost
;
286 case AL_NUM_RESAMPLERS_SOFT
:
287 value
= (ALfloat
)(ResamplerMax
+ 1);
290 case AL_DEFAULT_RESAMPLER_SOFT
:
291 value
= (ALfloat
)ResamplerDefault
;
295 alSetError(context
, AL_INVALID_VALUE
, "Invalid float property 0x%04x", pname
);
298 ALCcontext_DecRef(context
);
302 AL_API ALint AL_APIENTRY
alGetInteger(ALenum pname
)
307 context
= GetContextRef();
308 if(!context
) return 0;
312 case AL_DOPPLER_FACTOR
:
313 value
= (ALint
)context
->DopplerFactor
;
316 case AL_DOPPLER_VELOCITY
:
317 value
= (ALint
)context
->DopplerVelocity
;
320 case AL_DISTANCE_MODEL
:
321 value
= (ALint
)context
->DistanceModel
;
324 case AL_SPEED_OF_SOUND
:
325 value
= (ALint
)context
->SpeedOfSound
;
328 case AL_DEFERRED_UPDATES_SOFT
:
329 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
330 value
= (ALint
)AL_TRUE
;
333 case AL_GAIN_LIMIT_SOFT
:
334 value
= (ALint
)(GAIN_MIX_MAX
/context
->GainBoost
);
337 case AL_NUM_RESAMPLERS_SOFT
:
338 value
= ResamplerMax
+ 1;
341 case AL_DEFAULT_RESAMPLER_SOFT
:
342 value
= ResamplerDefault
;
346 alSetError(context
, AL_INVALID_VALUE
, "Invalid integer property 0x%04x", pname
);
349 ALCcontext_DecRef(context
);
353 AL_API ALint64SOFT AL_APIENTRY
alGetInteger64SOFT(ALenum pname
)
356 ALint64SOFT value
= 0;
358 context
= GetContextRef();
359 if(!context
) return 0;
363 case AL_DOPPLER_FACTOR
:
364 value
= (ALint64SOFT
)context
->DopplerFactor
;
367 case AL_DOPPLER_VELOCITY
:
368 value
= (ALint64SOFT
)context
->DopplerVelocity
;
371 case AL_DISTANCE_MODEL
:
372 value
= (ALint64SOFT
)context
->DistanceModel
;
375 case AL_SPEED_OF_SOUND
:
376 value
= (ALint64SOFT
)context
->SpeedOfSound
;
379 case AL_DEFERRED_UPDATES_SOFT
:
380 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
381 value
= (ALint64SOFT
)AL_TRUE
;
384 case AL_GAIN_LIMIT_SOFT
:
385 value
= (ALint64SOFT
)(GAIN_MIX_MAX
/context
->GainBoost
);
388 case AL_NUM_RESAMPLERS_SOFT
:
389 value
= (ALint64SOFT
)(ResamplerMax
+ 1);
392 case AL_DEFAULT_RESAMPLER_SOFT
:
393 value
= (ALint64SOFT
)ResamplerDefault
;
397 alSetError(context
, AL_INVALID_VALUE
, "Invalid integer64 property 0x%04x", pname
);
400 ALCcontext_DecRef(context
);
404 AL_API
void* AL_APIENTRY
alGetPointerSOFT(ALenum pname
)
409 context
= GetContextRef();
410 if(!context
) return NULL
;
414 case AL_EVENT_CALLBACK_FUNCTION_SOFT
:
415 value
= context
->EventCb
;
418 case AL_EVENT_CALLBACK_USER_PARAM_SOFT
:
419 value
= context
->EventParam
;
423 alSetError(context
, AL_INVALID_VALUE
, "Invalid pointer property 0x%04x", pname
);
426 ALCcontext_DecRef(context
);
430 AL_API ALvoid AL_APIENTRY
alGetBooleanv(ALenum pname
, ALboolean
*values
)
438 case AL_DOPPLER_FACTOR
:
439 case AL_DOPPLER_VELOCITY
:
440 case AL_DISTANCE_MODEL
:
441 case AL_SPEED_OF_SOUND
:
442 case AL_DEFERRED_UPDATES_SOFT
:
443 case AL_GAIN_LIMIT_SOFT
:
444 case AL_NUM_RESAMPLERS_SOFT
:
445 case AL_DEFAULT_RESAMPLER_SOFT
:
446 values
[0] = alGetBoolean(pname
);
451 context
= GetContextRef();
455 alSetError(context
, AL_INVALID_VALUE
, "NULL pointer");
459 alSetError(context
, AL_INVALID_VALUE
, "Invalid boolean-vector property 0x%04x", pname
);
462 ALCcontext_DecRef(context
);
465 AL_API ALvoid AL_APIENTRY
alGetDoublev(ALenum pname
, ALdouble
*values
)
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] = alGetDouble(pname
);
486 context
= GetContextRef();
490 alSetError(context
, AL_INVALID_VALUE
, "NULL pointer");
494 alSetError(context
, AL_INVALID_VALUE
, "Invalid double-vector property 0x%04x", pname
);
497 ALCcontext_DecRef(context
);
500 AL_API ALvoid AL_APIENTRY
alGetFloatv(ALenum pname
, ALfloat
*values
)
508 case AL_DOPPLER_FACTOR
:
509 case AL_DOPPLER_VELOCITY
:
510 case AL_DISTANCE_MODEL
:
511 case AL_SPEED_OF_SOUND
:
512 case AL_DEFERRED_UPDATES_SOFT
:
513 case AL_GAIN_LIMIT_SOFT
:
514 case AL_NUM_RESAMPLERS_SOFT
:
515 case AL_DEFAULT_RESAMPLER_SOFT
:
516 values
[0] = alGetFloat(pname
);
521 context
= GetContextRef();
525 alSetError(context
, AL_INVALID_VALUE
, "NULL pointer");
529 alSetError(context
, AL_INVALID_VALUE
, "Invalid float-vector property 0x%04x", pname
);
532 ALCcontext_DecRef(context
);
535 AL_API ALvoid AL_APIENTRY
alGetIntegerv(ALenum pname
, ALint
*values
)
543 case AL_DOPPLER_FACTOR
:
544 case AL_DOPPLER_VELOCITY
:
545 case AL_DISTANCE_MODEL
:
546 case AL_SPEED_OF_SOUND
:
547 case AL_DEFERRED_UPDATES_SOFT
:
548 case AL_GAIN_LIMIT_SOFT
:
549 case AL_NUM_RESAMPLERS_SOFT
:
550 case AL_DEFAULT_RESAMPLER_SOFT
:
551 values
[0] = alGetInteger(pname
);
556 context
= GetContextRef();
560 alSetError(context
, AL_INVALID_VALUE
, "NULL pointer");
564 alSetError(context
, AL_INVALID_VALUE
, "Invalid integer-vector property 0x%04x", pname
);
567 ALCcontext_DecRef(context
);
570 AL_API
void AL_APIENTRY
alGetInteger64vSOFT(ALenum pname
, ALint64SOFT
*values
)
578 case AL_DOPPLER_FACTOR
:
579 case AL_DOPPLER_VELOCITY
:
580 case AL_DISTANCE_MODEL
:
581 case AL_SPEED_OF_SOUND
:
582 case AL_DEFERRED_UPDATES_SOFT
:
583 case AL_GAIN_LIMIT_SOFT
:
584 case AL_NUM_RESAMPLERS_SOFT
:
585 case AL_DEFAULT_RESAMPLER_SOFT
:
586 values
[0] = alGetInteger64SOFT(pname
);
591 context
= GetContextRef();
595 alSetError(context
, AL_INVALID_VALUE
, "NULL pointer");
599 alSetError(context
, AL_INVALID_VALUE
, "Invalid integer64-vector property 0x%04x", pname
);
602 ALCcontext_DecRef(context
);
605 AL_API
void AL_APIENTRY
alGetPointervSOFT(ALenum pname
, void **values
)
613 case AL_EVENT_CALLBACK_FUNCTION_SOFT
:
614 case AL_EVENT_CALLBACK_USER_PARAM_SOFT
:
615 values
[0] = alGetPointerSOFT(pname
);
620 context
= GetContextRef();
624 alSetError(context
, AL_INVALID_VALUE
, "NULL pointer");
628 alSetError(context
, AL_INVALID_VALUE
, "Invalid pointer-vector property 0x%04x", pname
);
631 ALCcontext_DecRef(context
);
634 AL_API
const ALchar
* AL_APIENTRY
alGetString(ALenum pname
)
636 const ALchar
*value
= NULL
;
639 context
= GetContextRef();
640 if(!context
) return NULL
;
657 value
= context
->ExtensionList
;
664 case AL_INVALID_NAME
:
665 value
= alErrInvalidName
;
668 case AL_INVALID_ENUM
:
669 value
= alErrInvalidEnum
;
672 case AL_INVALID_VALUE
:
673 value
= alErrInvalidValue
;
676 case AL_INVALID_OPERATION
:
677 value
= alErrInvalidOp
;
680 case AL_OUT_OF_MEMORY
:
681 value
= alErrOutOfMemory
;
685 alSetError(context
, AL_INVALID_VALUE
, "Invalid string property 0x%04x", pname
);
688 ALCcontext_DecRef(context
);
692 AL_API ALvoid AL_APIENTRY
alDopplerFactor(ALfloat value
)
696 context
= GetContextRef();
699 if(!(value
>= 0.0f
&& isfinite(value
)))
700 alSetError(context
, AL_INVALID_VALUE
, "Doppler factor %f out of range", value
);
703 almtx_lock(&context
->PropLock
);
704 context
->DopplerFactor
= value
;
706 almtx_unlock(&context
->PropLock
);
709 ALCcontext_DecRef(context
);
712 AL_API ALvoid AL_APIENTRY
alDopplerVelocity(ALfloat value
)
716 context
= GetContextRef();
719 if((ATOMIC_LOAD(&context
->EnabledEvts
, almemory_order_relaxed
)&EventType_Deprecated
))
721 static const ALCchar msg
[] =
722 "alDopplerVelocity is deprecated in AL1.1, use alSpeedOfSound";
723 const ALsizei msglen
= (ALsizei
)strlen(msg
);
724 ALbitfieldSOFT enabledevts
;
725 almtx_lock(&context
->EventCbLock
);
726 enabledevts
= ATOMIC_LOAD(&context
->EnabledEvts
, almemory_order_relaxed
);
727 if((enabledevts
&EventType_Deprecated
) && context
->EventCb
)
728 (*context
->EventCb
)(AL_EVENT_TYPE_DEPRECATED_SOFT
, 0, 0, msglen
, msg
,
729 context
->EventParam
);
730 almtx_unlock(&context
->EventCbLock
);
733 if(!(value
>= 0.0f
&& isfinite(value
)))
734 alSetError(context
, AL_INVALID_VALUE
, "Doppler velocity %f out of range", value
);
737 almtx_lock(&context
->PropLock
);
738 context
->DopplerVelocity
= value
;
740 almtx_unlock(&context
->PropLock
);
743 ALCcontext_DecRef(context
);
746 AL_API ALvoid AL_APIENTRY
alSpeedOfSound(ALfloat value
)
750 context
= GetContextRef();
753 if(!(value
> 0.0f
&& isfinite(value
)))
754 alSetError(context
, AL_INVALID_VALUE
, "Speed of sound %f out of range", value
);
757 almtx_lock(&context
->PropLock
);
758 context
->SpeedOfSound
= value
;
760 almtx_unlock(&context
->PropLock
);
763 ALCcontext_DecRef(context
);
766 AL_API ALvoid AL_APIENTRY
alDistanceModel(ALenum value
)
770 context
= GetContextRef();
773 if(!(value
== AL_INVERSE_DISTANCE
|| value
== AL_INVERSE_DISTANCE_CLAMPED
||
774 value
== AL_LINEAR_DISTANCE
|| value
== AL_LINEAR_DISTANCE_CLAMPED
||
775 value
== AL_EXPONENT_DISTANCE
|| value
== AL_EXPONENT_DISTANCE_CLAMPED
||
777 alSetError(context
, AL_INVALID_VALUE
, "Distance model 0x%04x out of range", value
);
780 almtx_lock(&context
->PropLock
);
781 context
->DistanceModel
= value
;
782 if(!context
->SourceDistanceModel
)
784 almtx_unlock(&context
->PropLock
);
787 ALCcontext_DecRef(context
);
791 AL_API ALvoid AL_APIENTRY
alDeferUpdatesSOFT(void)
795 context
= GetContextRef();
798 ALCcontext_DeferUpdates(context
);
800 ALCcontext_DecRef(context
);
803 AL_API ALvoid AL_APIENTRY
alProcessUpdatesSOFT(void)
807 context
= GetContextRef();
810 ALCcontext_ProcessUpdates(context
);
812 ALCcontext_DecRef(context
);
816 AL_API
const ALchar
* AL_APIENTRY
alGetStringiSOFT(ALenum pname
, ALsizei index
)
818 const char *ResamplerNames
[] = {
819 alPointResampler
, alLinearResampler
,
820 alCubicResampler
, alBSinc12Resampler
,
823 const ALchar
*value
= NULL
;
826 static_assert(COUNTOF(ResamplerNames
) == ResamplerMax
+1, "Incorrect ResamplerNames list");
828 context
= GetContextRef();
829 if(!context
) return NULL
;
833 case AL_RESAMPLER_NAME_SOFT
:
834 if(index
< 0 || (size_t)index
>= COUNTOF(ResamplerNames
))
835 SETERR_GOTO(context
, AL_INVALID_VALUE
, done
, "Resampler name index %d out of range",
837 value
= ResamplerNames
[index
];
841 alSetError(context
, AL_INVALID_VALUE
, "Invalid string indexed property");
845 ALCcontext_DecRef(context
);
850 void UpdateContextProps(ALCcontext
*context
)
852 struct ALcontextProps
*props
;
854 /* Get an unused proprty container, or allocate a new one as needed. */
855 props
= ATOMIC_LOAD(&context
->FreeContextProps
, almemory_order_acquire
);
857 props
= al_calloc(16, sizeof(*props
));
860 struct ALcontextProps
*next
;
862 next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
863 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context
->FreeContextProps
, &props
, next
,
864 almemory_order_seq_cst
, almemory_order_acquire
) == 0);
867 /* Copy in current property values. */
868 props
->MetersPerUnit
= context
->MetersPerUnit
;
870 props
->DopplerFactor
= context
->DopplerFactor
;
871 props
->DopplerVelocity
= context
->DopplerVelocity
;
872 props
->SpeedOfSound
= context
->SpeedOfSound
;
874 props
->SourceDistanceModel
= context
->SourceDistanceModel
;
875 props
->DistanceModel
= context
->DistanceModel
;
877 /* Set the new container for updating internal parameters. */
878 props
= ATOMIC_EXCHANGE_PTR(&context
->Update
, props
, almemory_order_acq_rel
);
881 /* If there was an unused update container, put it back in the
884 ATOMIC_REPLACE_HEAD(struct ALcontextProps
*, &context
->FreeContextProps
, props
);