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 WriteLock(&context
->PropLock
);
85 case AL_SOURCE_DISTANCE_MODEL
:
86 context
->SourceDistanceModel
= AL_TRUE
;
91 alSetError(context
, AL_INVALID_VALUE
, 0, "Invalid enable property");
93 WriteUnlock(&context
->PropLock
);
95 ALCcontext_DecRef(context
);
98 AL_API ALvoid AL_APIENTRY
alDisable(ALenum capability
)
102 context
= GetContextRef();
105 WriteLock(&context
->PropLock
);
108 case AL_SOURCE_DISTANCE_MODEL
:
109 context
->SourceDistanceModel
= AL_FALSE
;
114 alSetError(context
, AL_INVALID_VALUE
, 0, "Invalid disable property");
116 WriteUnlock(&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
, 0, "Invalid is enabled property");
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
, 0, "Invalid boolean property");
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
, 0, "Invalid double property");
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
, 0, "Invalid float property");
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
, 0, "Invalid integer property");
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
, 0, "Invalid integer64 property");
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
, 0, "Invalid pointer property");
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
, 0, "NULL pointer");
459 alSetError(context
, AL_INVALID_VALUE
, 0, "Invalid boolean-vector property");
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
, 0, "NULL pointer");
494 alSetError(context
, AL_INVALID_VALUE
, 0, "Invalid double-vector property");
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
, 0, "NULL pointer");
529 alSetError(context
, AL_INVALID_VALUE
, 0, "Invalid float-vector property");
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
, 0, "NULL pointer");
564 alSetError(context
, AL_INVALID_VALUE
, 0, "Invalid integer-vector property");
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
, 0, "NULL pointer");
599 alSetError(context
, AL_INVALID_VALUE
, 0, "Invalid integer64-vector property");
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
, 0, "NULL pointer");
628 alSetError(context
, AL_INVALID_VALUE
, 0, "Invalid pointer-vector property");
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
, 0, "Invalid string property");
688 ALCcontext_DecRef(context
);
692 AL_API ALvoid AL_APIENTRY
alDopplerFactor(ALfloat value
)
696 context
= GetContextRef();
699 if(!(value
>= 0.0f
&& isfinite(value
)))
700 SETERR_GOTO(context
, AL_INVALID_VALUE
, 0, "Doppler factor out of range", done
);
702 WriteLock(&context
->PropLock
);
703 context
->DopplerFactor
= value
;
705 WriteUnlock(&context
->PropLock
);
708 ALCcontext_DecRef(context
);
711 AL_API ALvoid AL_APIENTRY
alDopplerVelocity(ALfloat value
)
715 context
= GetContextRef();
718 if(!(value
>= 0.0f
&& isfinite(value
)))
719 SETERR_GOTO(context
, AL_INVALID_VALUE
, 0, "Doppler velocity out of range", done
);
721 WriteLock(&context
->PropLock
);
722 context
->DopplerVelocity
= value
;
724 WriteUnlock(&context
->PropLock
);
727 ALCcontext_DecRef(context
);
730 AL_API ALvoid AL_APIENTRY
alSpeedOfSound(ALfloat value
)
734 context
= GetContextRef();
737 if(!(value
> 0.0f
&& isfinite(value
)))
738 SETERR_GOTO(context
, AL_INVALID_VALUE
, 0, "Speed of sound out of range", done
);
740 WriteLock(&context
->PropLock
);
741 context
->SpeedOfSound
= value
;
743 WriteUnlock(&context
->PropLock
);
746 ALCcontext_DecRef(context
);
749 AL_API ALvoid AL_APIENTRY
alDistanceModel(ALenum value
)
753 context
= GetContextRef();
756 if(!(value
== AL_INVERSE_DISTANCE
|| value
== AL_INVERSE_DISTANCE_CLAMPED
||
757 value
== AL_LINEAR_DISTANCE
|| value
== AL_LINEAR_DISTANCE_CLAMPED
||
758 value
== AL_EXPONENT_DISTANCE
|| value
== AL_EXPONENT_DISTANCE_CLAMPED
||
760 SETERR_GOTO(context
, AL_INVALID_VALUE
, 0, "Distance model out of range", done
);
762 WriteLock(&context
->PropLock
);
763 context
->DistanceModel
= value
;
764 if(!context
->SourceDistanceModel
)
766 WriteUnlock(&context
->PropLock
);
769 ALCcontext_DecRef(context
);
773 AL_API ALvoid AL_APIENTRY
alDeferUpdatesSOFT(void)
777 context
= GetContextRef();
780 ALCcontext_DeferUpdates(context
);
782 ALCcontext_DecRef(context
);
785 AL_API ALvoid AL_APIENTRY
alProcessUpdatesSOFT(void)
789 context
= GetContextRef();
792 ALCcontext_ProcessUpdates(context
);
794 ALCcontext_DecRef(context
);
798 AL_API
const ALchar
* AL_APIENTRY
alGetStringiSOFT(ALenum pname
, ALsizei index
)
800 const char *ResamplerNames
[] = {
801 alPointResampler
, alLinearResampler
,
802 alCubicResampler
, alBSinc12Resampler
,
805 const ALchar
*value
= NULL
;
808 static_assert(COUNTOF(ResamplerNames
) == ResamplerMax
+1, "Incorrect ResamplerNames list");
810 context
= GetContextRef();
811 if(!context
) return NULL
;
815 case AL_RESAMPLER_NAME_SOFT
:
816 if(index
< 0 || (size_t)index
>= COUNTOF(ResamplerNames
))
817 SETERR_GOTO(context
, AL_INVALID_VALUE
, 0, "Resampler name index out of range", done
);
818 value
= ResamplerNames
[index
];
822 alSetError(context
, AL_INVALID_VALUE
, 0, "Invalid string indexed property");
826 ALCcontext_DecRef(context
);
832 void UpdateContextProps(ALCcontext
*context
)
834 struct ALcontextProps
*props
;
836 /* Get an unused proprty container, or allocate a new one as needed. */
837 props
= ATOMIC_LOAD(&context
->FreeContextProps
, almemory_order_acquire
);
839 props
= al_calloc(16, sizeof(*props
));
842 struct ALcontextProps
*next
;
844 next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
845 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context
->FreeContextProps
, &props
, next
,
846 almemory_order_seq_cst
, almemory_order_acquire
) == 0);
849 /* Copy in current property values. */
850 props
->MetersPerUnit
= context
->MetersPerUnit
;
852 props
->DopplerFactor
= context
->DopplerFactor
;
853 props
->DopplerVelocity
= context
->DopplerVelocity
;
854 props
->SpeedOfSound
= context
->SpeedOfSound
;
856 props
->SourceDistanceModel
= context
->SourceDistanceModel
;
857 props
->DistanceModel
= context
->DistanceModel
;
859 /* Set the new container for updating internal parameters. */
860 props
= ATOMIC_EXCHANGE_PTR(&context
->Update
, props
, almemory_order_acq_rel
);
863 /* If there was an unused update container, put it back in the
866 ATOMIC_REPLACE_HEAD(struct ALcontextProps
*, &context
->FreeContextProps
, props
);