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 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
95 WriteUnlock(&context
->PropLock
);
96 ALCcontext_DecRef(context
);
99 AL_API ALvoid AL_APIENTRY
alDisable(ALenum capability
)
103 context
= GetContextRef();
106 WriteLock(&context
->PropLock
);
109 case AL_SOURCE_DISTANCE_MODEL
:
110 context
->SourceDistanceModel
= AL_FALSE
;
115 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
119 WriteUnlock(&context
->PropLock
);
120 ALCcontext_DecRef(context
);
123 AL_API ALboolean AL_APIENTRY
alIsEnabled(ALenum capability
)
126 ALboolean value
=AL_FALSE
;
128 context
= GetContextRef();
129 if(!context
) return AL_FALSE
;
133 case AL_SOURCE_DISTANCE_MODEL
:
134 value
= context
->SourceDistanceModel
;
138 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
142 ALCcontext_DecRef(context
);
147 AL_API ALboolean AL_APIENTRY
alGetBoolean(ALenum pname
)
150 ALboolean value
=AL_FALSE
;
152 context
= GetContextRef();
153 if(!context
) return AL_FALSE
;
157 case AL_DOPPLER_FACTOR
:
158 if(context
->DopplerFactor
!= 0.0f
)
162 case AL_DOPPLER_VELOCITY
:
163 if(context
->DopplerVelocity
!= 0.0f
)
167 case AL_DISTANCE_MODEL
:
168 if(context
->DistanceModel
== AL_INVERSE_DISTANCE_CLAMPED
)
172 case AL_SPEED_OF_SOUND
:
173 if(context
->SpeedOfSound
!= 0.0f
)
177 case AL_DEFERRED_UPDATES_SOFT
:
178 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
182 case AL_GAIN_LIMIT_SOFT
:
183 if(GAIN_MIX_MAX
/context
->GainBoost
!= 0.0f
)
187 case AL_NUM_RESAMPLERS_SOFT
:
192 case AL_DEFAULT_RESAMPLER_SOFT
:
193 value
= ResamplerDefault
? AL_TRUE
: AL_FALSE
;
197 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
201 ALCcontext_DecRef(context
);
206 AL_API ALdouble AL_APIENTRY
alGetDouble(ALenum pname
)
209 ALdouble value
= 0.0;
211 context
= GetContextRef();
212 if(!context
) return 0.0;
216 case AL_DOPPLER_FACTOR
:
217 value
= (ALdouble
)context
->DopplerFactor
;
220 case AL_DOPPLER_VELOCITY
:
221 value
= (ALdouble
)context
->DopplerVelocity
;
224 case AL_DISTANCE_MODEL
:
225 value
= (ALdouble
)context
->DistanceModel
;
228 case AL_SPEED_OF_SOUND
:
229 value
= (ALdouble
)context
->SpeedOfSound
;
232 case AL_DEFERRED_UPDATES_SOFT
:
233 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
234 value
= (ALdouble
)AL_TRUE
;
237 case AL_GAIN_LIMIT_SOFT
:
238 value
= (ALdouble
)GAIN_MIX_MAX
/context
->GainBoost
;
241 case AL_NUM_RESAMPLERS_SOFT
:
242 value
= (ALdouble
)(ResamplerMax
+ 1);
245 case AL_DEFAULT_RESAMPLER_SOFT
:
246 value
= (ALdouble
)ResamplerDefault
;
250 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
254 ALCcontext_DecRef(context
);
259 AL_API ALfloat AL_APIENTRY
alGetFloat(ALenum pname
)
262 ALfloat value
= 0.0f
;
264 context
= GetContextRef();
265 if(!context
) return 0.0f
;
269 case AL_DOPPLER_FACTOR
:
270 value
= context
->DopplerFactor
;
273 case AL_DOPPLER_VELOCITY
:
274 value
= context
->DopplerVelocity
;
277 case AL_DISTANCE_MODEL
:
278 value
= (ALfloat
)context
->DistanceModel
;
281 case AL_SPEED_OF_SOUND
:
282 value
= context
->SpeedOfSound
;
285 case AL_DEFERRED_UPDATES_SOFT
:
286 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
287 value
= (ALfloat
)AL_TRUE
;
290 case AL_GAIN_LIMIT_SOFT
:
291 value
= GAIN_MIX_MAX
/context
->GainBoost
;
294 case AL_NUM_RESAMPLERS_SOFT
:
295 value
= (ALfloat
)(ResamplerMax
+ 1);
298 case AL_DEFAULT_RESAMPLER_SOFT
:
299 value
= (ALfloat
)ResamplerDefault
;
303 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
307 ALCcontext_DecRef(context
);
312 AL_API ALint AL_APIENTRY
alGetInteger(ALenum pname
)
317 context
= GetContextRef();
318 if(!context
) return 0;
322 case AL_DOPPLER_FACTOR
:
323 value
= (ALint
)context
->DopplerFactor
;
326 case AL_DOPPLER_VELOCITY
:
327 value
= (ALint
)context
->DopplerVelocity
;
330 case AL_DISTANCE_MODEL
:
331 value
= (ALint
)context
->DistanceModel
;
334 case AL_SPEED_OF_SOUND
:
335 value
= (ALint
)context
->SpeedOfSound
;
338 case AL_DEFERRED_UPDATES_SOFT
:
339 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
340 value
= (ALint
)AL_TRUE
;
343 case AL_GAIN_LIMIT_SOFT
:
344 value
= (ALint
)(GAIN_MIX_MAX
/context
->GainBoost
);
347 case AL_NUM_RESAMPLERS_SOFT
:
348 value
= ResamplerMax
+ 1;
351 case AL_DEFAULT_RESAMPLER_SOFT
:
352 value
= ResamplerDefault
;
356 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
360 ALCcontext_DecRef(context
);
365 AL_API ALint64SOFT AL_APIENTRY
alGetInteger64SOFT(ALenum pname
)
368 ALint64SOFT value
= 0;
370 context
= GetContextRef();
371 if(!context
) return 0;
375 case AL_DOPPLER_FACTOR
:
376 value
= (ALint64SOFT
)context
->DopplerFactor
;
379 case AL_DOPPLER_VELOCITY
:
380 value
= (ALint64SOFT
)context
->DopplerVelocity
;
383 case AL_DISTANCE_MODEL
:
384 value
= (ALint64SOFT
)context
->DistanceModel
;
387 case AL_SPEED_OF_SOUND
:
388 value
= (ALint64SOFT
)context
->SpeedOfSound
;
391 case AL_DEFERRED_UPDATES_SOFT
:
392 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
393 value
= (ALint64SOFT
)AL_TRUE
;
396 case AL_GAIN_LIMIT_SOFT
:
397 value
= (ALint64SOFT
)(GAIN_MIX_MAX
/context
->GainBoost
);
400 case AL_NUM_RESAMPLERS_SOFT
:
401 value
= (ALint64SOFT
)(ResamplerMax
+ 1);
404 case AL_DEFAULT_RESAMPLER_SOFT
:
405 value
= (ALint64SOFT
)ResamplerDefault
;
409 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
413 ALCcontext_DecRef(context
);
418 AL_API ALvoid AL_APIENTRY
alGetBooleanv(ALenum pname
, ALboolean
*values
)
426 case AL_DOPPLER_FACTOR
:
427 case AL_DOPPLER_VELOCITY
:
428 case AL_DISTANCE_MODEL
:
429 case AL_SPEED_OF_SOUND
:
430 case AL_DEFERRED_UPDATES_SOFT
:
431 case AL_GAIN_LIMIT_SOFT
:
432 case AL_NUM_RESAMPLERS_SOFT
:
433 case AL_DEFAULT_RESAMPLER_SOFT
:
434 values
[0] = alGetBoolean(pname
);
439 context
= GetContextRef();
443 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
447 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
451 ALCcontext_DecRef(context
);
454 AL_API ALvoid AL_APIENTRY
alGetDoublev(ALenum pname
, ALdouble
*values
)
462 case AL_DOPPLER_FACTOR
:
463 case AL_DOPPLER_VELOCITY
:
464 case AL_DISTANCE_MODEL
:
465 case AL_SPEED_OF_SOUND
:
466 case AL_DEFERRED_UPDATES_SOFT
:
467 case AL_GAIN_LIMIT_SOFT
:
468 case AL_NUM_RESAMPLERS_SOFT
:
469 case AL_DEFAULT_RESAMPLER_SOFT
:
470 values
[0] = alGetDouble(pname
);
475 context
= GetContextRef();
479 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
483 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
487 ALCcontext_DecRef(context
);
490 AL_API ALvoid AL_APIENTRY
alGetFloatv(ALenum pname
, ALfloat
*values
)
498 case AL_DOPPLER_FACTOR
:
499 case AL_DOPPLER_VELOCITY
:
500 case AL_DISTANCE_MODEL
:
501 case AL_SPEED_OF_SOUND
:
502 case AL_DEFERRED_UPDATES_SOFT
:
503 case AL_GAIN_LIMIT_SOFT
:
504 case AL_NUM_RESAMPLERS_SOFT
:
505 case AL_DEFAULT_RESAMPLER_SOFT
:
506 values
[0] = alGetFloat(pname
);
511 context
= GetContextRef();
515 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
519 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
523 ALCcontext_DecRef(context
);
526 AL_API ALvoid AL_APIENTRY
alGetIntegerv(ALenum pname
, ALint
*values
)
534 case AL_DOPPLER_FACTOR
:
535 case AL_DOPPLER_VELOCITY
:
536 case AL_DISTANCE_MODEL
:
537 case AL_SPEED_OF_SOUND
:
538 case AL_DEFERRED_UPDATES_SOFT
:
539 case AL_GAIN_LIMIT_SOFT
:
540 case AL_NUM_RESAMPLERS_SOFT
:
541 case AL_DEFAULT_RESAMPLER_SOFT
:
542 values
[0] = alGetInteger(pname
);
547 context
= GetContextRef();
553 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
557 ALCcontext_DecRef(context
);
560 AL_API
void AL_APIENTRY
alGetInteger64vSOFT(ALenum pname
, ALint64SOFT
*values
)
568 case AL_DOPPLER_FACTOR
:
569 case AL_DOPPLER_VELOCITY
:
570 case AL_DISTANCE_MODEL
:
571 case AL_SPEED_OF_SOUND
:
572 case AL_DEFERRED_UPDATES_SOFT
:
573 case AL_GAIN_LIMIT_SOFT
:
574 case AL_NUM_RESAMPLERS_SOFT
:
575 case AL_DEFAULT_RESAMPLER_SOFT
:
576 values
[0] = alGetInteger64SOFT(pname
);
581 context
= GetContextRef();
587 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
591 ALCcontext_DecRef(context
);
594 AL_API
const ALchar
* AL_APIENTRY
alGetString(ALenum pname
)
596 const ALchar
*value
= NULL
;
599 context
= GetContextRef();
600 if(!context
) return NULL
;
617 value
= context
->ExtensionList
;
624 case AL_INVALID_NAME
:
625 value
= alErrInvalidName
;
628 case AL_INVALID_ENUM
:
629 value
= alErrInvalidEnum
;
632 case AL_INVALID_VALUE
:
633 value
= alErrInvalidValue
;
636 case AL_INVALID_OPERATION
:
637 value
= alErrInvalidOp
;
640 case AL_OUT_OF_MEMORY
:
641 value
= alErrOutOfMemory
;
645 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
649 ALCcontext_DecRef(context
);
654 AL_API ALvoid AL_APIENTRY
alDopplerFactor(ALfloat value
)
658 context
= GetContextRef();
661 if(!(value
>= 0.0f
&& isfinite(value
)))
662 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
664 WriteLock(&context
->PropLock
);
665 context
->DopplerFactor
= value
;
667 WriteUnlock(&context
->PropLock
);
670 ALCcontext_DecRef(context
);
673 AL_API ALvoid AL_APIENTRY
alDopplerVelocity(ALfloat value
)
677 context
= GetContextRef();
680 if(!(value
>= 0.0f
&& isfinite(value
)))
681 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
683 WriteLock(&context
->PropLock
);
684 context
->DopplerVelocity
= value
;
686 WriteUnlock(&context
->PropLock
);
689 ALCcontext_DecRef(context
);
692 AL_API ALvoid AL_APIENTRY
alSpeedOfSound(ALfloat value
)
696 context
= GetContextRef();
699 if(!(value
> 0.0f
&& isfinite(value
)))
700 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
702 WriteLock(&context
->PropLock
);
703 context
->SpeedOfSound
= value
;
705 WriteUnlock(&context
->PropLock
);
708 ALCcontext_DecRef(context
);
711 AL_API ALvoid AL_APIENTRY
alDistanceModel(ALenum value
)
715 context
= GetContextRef();
718 if(!(value
== AL_INVERSE_DISTANCE
|| value
== AL_INVERSE_DISTANCE_CLAMPED
||
719 value
== AL_LINEAR_DISTANCE
|| value
== AL_LINEAR_DISTANCE_CLAMPED
||
720 value
== AL_EXPONENT_DISTANCE
|| value
== AL_EXPONENT_DISTANCE_CLAMPED
||
722 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
724 WriteLock(&context
->PropLock
);
725 context
->DistanceModel
= value
;
726 if(!context
->SourceDistanceModel
)
728 WriteUnlock(&context
->PropLock
);
731 ALCcontext_DecRef(context
);
735 AL_API ALvoid AL_APIENTRY
alDeferUpdatesSOFT(void)
739 context
= GetContextRef();
742 ALCcontext_DeferUpdates(context
);
744 ALCcontext_DecRef(context
);
747 AL_API ALvoid AL_APIENTRY
alProcessUpdatesSOFT(void)
751 context
= GetContextRef();
754 ALCcontext_ProcessUpdates(context
);
756 ALCcontext_DecRef(context
);
760 AL_API
const ALchar
* AL_APIENTRY
alGetStringiSOFT(ALenum pname
, ALsizei index
)
762 const char *ResamplerNames
[] = {
763 alPointResampler
, alLinearResampler
,
764 alCubicResampler
, alBSinc12Resampler
,
767 const ALchar
*value
= NULL
;
770 static_assert(COUNTOF(ResamplerNames
) == ResamplerMax
+1, "Incorrect ResamplerNames list");
772 context
= GetContextRef();
773 if(!context
) return NULL
;
777 case AL_RESAMPLER_NAME_SOFT
:
778 if(index
< 0 || (size_t)index
>= COUNTOF(ResamplerNames
))
779 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
780 value
= ResamplerNames
[index
];
784 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
788 ALCcontext_DecRef(context
);
794 void UpdateContextProps(ALCcontext
*context
)
796 struct ALcontextProps
*props
;
798 /* Get an unused proprty container, or allocate a new one as needed. */
799 props
= ATOMIC_LOAD(&context
->FreeContextProps
, almemory_order_acquire
);
801 props
= al_calloc(16, sizeof(*props
));
804 struct ALcontextProps
*next
;
806 next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
807 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context
->FreeContextProps
, &props
, next
,
808 almemory_order_seq_cst
, almemory_order_acquire
) == 0);
811 /* Copy in current property values. */
812 props
->MetersPerUnit
= context
->MetersPerUnit
;
814 props
->DopplerFactor
= context
->DopplerFactor
;
815 props
->DopplerVelocity
= context
->DopplerVelocity
;
816 props
->SpeedOfSound
= context
->SpeedOfSound
;
818 props
->SourceDistanceModel
= context
->SourceDistanceModel
;
819 props
->DistanceModel
= context
->DistanceModel
;
821 /* Set the new container for updating internal parameters. */
822 props
= ATOMIC_EXCHANGE_PTR(&context
->Update
, props
, almemory_order_acq_rel
);
825 /* If there was an unused update container, put it back in the
828 ATOMIC_REPLACE_HEAD(struct ALcontextProps
*, &context
->FreeContextProps
, props
);