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 alSinc4Resampler
[] = "3rd order Sinc";
54 static const ALchar alBSinc12Resampler
[] = "11th order Sinc";
55 static const ALchar alBSinc24Resampler
[] = "23rd order Sinc";
57 #define DO_UPDATEPROPS() do { \
58 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
59 UpdateContextProps(context); \
61 ATOMIC_FLAG_CLEAR(&context->PropsClean, almemory_order_release); \
65 AL_API ALvoid AL_APIENTRY
alEnable(ALenum capability
)
69 context
= GetContextRef();
72 WriteLock(&context
->PropLock
);
75 case AL_SOURCE_DISTANCE_MODEL
:
76 context
->SourceDistanceModel
= AL_TRUE
;
81 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
85 WriteUnlock(&context
->PropLock
);
86 ALCcontext_DecRef(context
);
89 AL_API ALvoid AL_APIENTRY
alDisable(ALenum capability
)
93 context
= GetContextRef();
96 WriteLock(&context
->PropLock
);
99 case AL_SOURCE_DISTANCE_MODEL
:
100 context
->SourceDistanceModel
= AL_FALSE
;
105 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
109 WriteUnlock(&context
->PropLock
);
110 ALCcontext_DecRef(context
);
113 AL_API ALboolean AL_APIENTRY
alIsEnabled(ALenum capability
)
116 ALboolean value
=AL_FALSE
;
118 context
= GetContextRef();
119 if(!context
) return AL_FALSE
;
123 case AL_SOURCE_DISTANCE_MODEL
:
124 value
= context
->SourceDistanceModel
;
128 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
132 ALCcontext_DecRef(context
);
137 AL_API ALboolean AL_APIENTRY
alGetBoolean(ALenum pname
)
140 ALboolean value
=AL_FALSE
;
142 context
= GetContextRef();
143 if(!context
) return AL_FALSE
;
147 case AL_DOPPLER_FACTOR
:
148 if(context
->DopplerFactor
!= 0.0f
)
152 case AL_DOPPLER_VELOCITY
:
153 if(context
->DopplerVelocity
!= 0.0f
)
157 case AL_DISTANCE_MODEL
:
158 if(context
->DistanceModel
== AL_INVERSE_DISTANCE_CLAMPED
)
162 case AL_SPEED_OF_SOUND
:
163 if(context
->SpeedOfSound
!= 0.0f
)
167 case AL_DEFERRED_UPDATES_SOFT
:
168 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
172 case AL_GAIN_LIMIT_SOFT
:
173 if(GAIN_MIX_MAX
/context
->GainBoost
!= 0.0f
)
177 case AL_NUM_RESAMPLERS_SOFT
:
182 case AL_DEFAULT_RESAMPLER_SOFT
:
183 value
= ResamplerDefault
? AL_TRUE
: AL_FALSE
;
187 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
191 ALCcontext_DecRef(context
);
196 AL_API ALdouble AL_APIENTRY
alGetDouble(ALenum pname
)
199 ALdouble value
= 0.0;
201 context
= GetContextRef();
202 if(!context
) return 0.0;
206 case AL_DOPPLER_FACTOR
:
207 value
= (ALdouble
)context
->DopplerFactor
;
210 case AL_DOPPLER_VELOCITY
:
211 value
= (ALdouble
)context
->DopplerVelocity
;
214 case AL_DISTANCE_MODEL
:
215 value
= (ALdouble
)context
->DistanceModel
;
218 case AL_SPEED_OF_SOUND
:
219 value
= (ALdouble
)context
->SpeedOfSound
;
222 case AL_DEFERRED_UPDATES_SOFT
:
223 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
224 value
= (ALdouble
)AL_TRUE
;
227 case AL_GAIN_LIMIT_SOFT
:
228 value
= (ALdouble
)GAIN_MIX_MAX
/context
->GainBoost
;
231 case AL_NUM_RESAMPLERS_SOFT
:
232 value
= (ALdouble
)(ResamplerMax
+ 1);
235 case AL_DEFAULT_RESAMPLER_SOFT
:
236 value
= (ALdouble
)ResamplerDefault
;
240 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
244 ALCcontext_DecRef(context
);
249 AL_API ALfloat AL_APIENTRY
alGetFloat(ALenum pname
)
252 ALfloat value
= 0.0f
;
254 context
= GetContextRef();
255 if(!context
) return 0.0f
;
259 case AL_DOPPLER_FACTOR
:
260 value
= context
->DopplerFactor
;
263 case AL_DOPPLER_VELOCITY
:
264 value
= context
->DopplerVelocity
;
267 case AL_DISTANCE_MODEL
:
268 value
= (ALfloat
)context
->DistanceModel
;
271 case AL_SPEED_OF_SOUND
:
272 value
= context
->SpeedOfSound
;
275 case AL_DEFERRED_UPDATES_SOFT
:
276 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
277 value
= (ALfloat
)AL_TRUE
;
280 case AL_GAIN_LIMIT_SOFT
:
281 value
= GAIN_MIX_MAX
/context
->GainBoost
;
284 case AL_NUM_RESAMPLERS_SOFT
:
285 value
= (ALfloat
)(ResamplerMax
+ 1);
288 case AL_DEFAULT_RESAMPLER_SOFT
:
289 value
= (ALfloat
)ResamplerDefault
;
293 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
297 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 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
350 ALCcontext_DecRef(context
);
355 AL_API ALint64SOFT AL_APIENTRY
alGetInteger64SOFT(ALenum pname
)
358 ALint64SOFT value
= 0;
360 context
= GetContextRef();
361 if(!context
) return 0;
365 case AL_DOPPLER_FACTOR
:
366 value
= (ALint64SOFT
)context
->DopplerFactor
;
369 case AL_DOPPLER_VELOCITY
:
370 value
= (ALint64SOFT
)context
->DopplerVelocity
;
373 case AL_DISTANCE_MODEL
:
374 value
= (ALint64SOFT
)context
->DistanceModel
;
377 case AL_SPEED_OF_SOUND
:
378 value
= (ALint64SOFT
)context
->SpeedOfSound
;
381 case AL_DEFERRED_UPDATES_SOFT
:
382 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
383 value
= (ALint64SOFT
)AL_TRUE
;
386 case AL_GAIN_LIMIT_SOFT
:
387 value
= (ALint64SOFT
)(GAIN_MIX_MAX
/context
->GainBoost
);
390 case AL_NUM_RESAMPLERS_SOFT
:
391 value
= (ALint64SOFT
)(ResamplerMax
+ 1);
394 case AL_DEFAULT_RESAMPLER_SOFT
:
395 value
= (ALint64SOFT
)ResamplerDefault
;
399 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
403 ALCcontext_DecRef(context
);
408 AL_API ALvoid AL_APIENTRY
alGetBooleanv(ALenum pname
, ALboolean
*values
)
416 case AL_DOPPLER_FACTOR
:
417 case AL_DOPPLER_VELOCITY
:
418 case AL_DISTANCE_MODEL
:
419 case AL_SPEED_OF_SOUND
:
420 case AL_DEFERRED_UPDATES_SOFT
:
421 case AL_GAIN_LIMIT_SOFT
:
422 case AL_NUM_RESAMPLERS_SOFT
:
423 case AL_DEFAULT_RESAMPLER_SOFT
:
424 values
[0] = alGetBoolean(pname
);
429 context
= GetContextRef();
433 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
437 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
441 ALCcontext_DecRef(context
);
444 AL_API ALvoid AL_APIENTRY
alGetDoublev(ALenum pname
, ALdouble
*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] = alGetDouble(pname
);
465 context
= GetContextRef();
469 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
473 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
477 ALCcontext_DecRef(context
);
480 AL_API ALvoid AL_APIENTRY
alGetFloatv(ALenum pname
, ALfloat
*values
)
488 case AL_DOPPLER_FACTOR
:
489 case AL_DOPPLER_VELOCITY
:
490 case AL_DISTANCE_MODEL
:
491 case AL_SPEED_OF_SOUND
:
492 case AL_DEFERRED_UPDATES_SOFT
:
493 case AL_GAIN_LIMIT_SOFT
:
494 case AL_NUM_RESAMPLERS_SOFT
:
495 case AL_DEFAULT_RESAMPLER_SOFT
:
496 values
[0] = alGetFloat(pname
);
501 context
= GetContextRef();
505 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
509 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
513 ALCcontext_DecRef(context
);
516 AL_API ALvoid AL_APIENTRY
alGetIntegerv(ALenum pname
, ALint
*values
)
524 case AL_DOPPLER_FACTOR
:
525 case AL_DOPPLER_VELOCITY
:
526 case AL_DISTANCE_MODEL
:
527 case AL_SPEED_OF_SOUND
:
528 case AL_DEFERRED_UPDATES_SOFT
:
529 case AL_GAIN_LIMIT_SOFT
:
530 case AL_NUM_RESAMPLERS_SOFT
:
531 case AL_DEFAULT_RESAMPLER_SOFT
:
532 values
[0] = alGetInteger(pname
);
537 context
= GetContextRef();
543 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
547 ALCcontext_DecRef(context
);
550 AL_API
void AL_APIENTRY
alGetInteger64vSOFT(ALenum pname
, ALint64SOFT
*values
)
558 case AL_DOPPLER_FACTOR
:
559 case AL_DOPPLER_VELOCITY
:
560 case AL_DISTANCE_MODEL
:
561 case AL_SPEED_OF_SOUND
:
562 case AL_DEFERRED_UPDATES_SOFT
:
563 case AL_GAIN_LIMIT_SOFT
:
564 case AL_NUM_RESAMPLERS_SOFT
:
565 case AL_DEFAULT_RESAMPLER_SOFT
:
566 values
[0] = alGetInteger64SOFT(pname
);
571 context
= GetContextRef();
577 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
581 ALCcontext_DecRef(context
);
584 AL_API
const ALchar
* AL_APIENTRY
alGetString(ALenum pname
)
586 const ALchar
*value
= NULL
;
589 context
= GetContextRef();
590 if(!context
) return NULL
;
607 value
= context
->ExtensionList
;
614 case AL_INVALID_NAME
:
615 value
= alErrInvalidName
;
618 case AL_INVALID_ENUM
:
619 value
= alErrInvalidEnum
;
622 case AL_INVALID_VALUE
:
623 value
= alErrInvalidValue
;
626 case AL_INVALID_OPERATION
:
627 value
= alErrInvalidOp
;
630 case AL_OUT_OF_MEMORY
:
631 value
= alErrOutOfMemory
;
635 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
639 ALCcontext_DecRef(context
);
644 AL_API ALvoid AL_APIENTRY
alDopplerFactor(ALfloat value
)
648 context
= GetContextRef();
651 if(!(value
>= 0.0f
&& isfinite(value
)))
652 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
654 WriteLock(&context
->PropLock
);
655 context
->DopplerFactor
= value
;
657 WriteUnlock(&context
->PropLock
);
660 ALCcontext_DecRef(context
);
663 AL_API ALvoid AL_APIENTRY
alDopplerVelocity(ALfloat value
)
667 context
= GetContextRef();
670 if(!(value
>= 0.0f
&& isfinite(value
)))
671 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
673 WriteLock(&context
->PropLock
);
674 context
->DopplerVelocity
= value
;
676 WriteUnlock(&context
->PropLock
);
679 ALCcontext_DecRef(context
);
682 AL_API ALvoid AL_APIENTRY
alSpeedOfSound(ALfloat value
)
686 context
= GetContextRef();
689 if(!(value
> 0.0f
&& isfinite(value
)))
690 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
692 WriteLock(&context
->PropLock
);
693 context
->SpeedOfSound
= value
;
695 WriteUnlock(&context
->PropLock
);
698 ALCcontext_DecRef(context
);
701 AL_API ALvoid AL_APIENTRY
alDistanceModel(ALenum value
)
705 context
= GetContextRef();
708 if(!(value
== AL_INVERSE_DISTANCE
|| value
== AL_INVERSE_DISTANCE_CLAMPED
||
709 value
== AL_LINEAR_DISTANCE
|| value
== AL_LINEAR_DISTANCE_CLAMPED
||
710 value
== AL_EXPONENT_DISTANCE
|| value
== AL_EXPONENT_DISTANCE_CLAMPED
||
712 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
714 WriteLock(&context
->PropLock
);
715 context
->DistanceModel
= value
;
716 if(!context
->SourceDistanceModel
)
718 WriteUnlock(&context
->PropLock
);
721 ALCcontext_DecRef(context
);
725 AL_API ALvoid AL_APIENTRY
alDeferUpdatesSOFT(void)
729 context
= GetContextRef();
732 ALCcontext_DeferUpdates(context
);
734 ALCcontext_DecRef(context
);
737 AL_API ALvoid AL_APIENTRY
alProcessUpdatesSOFT(void)
741 context
= GetContextRef();
744 ALCcontext_ProcessUpdates(context
);
746 ALCcontext_DecRef(context
);
750 AL_API
const ALchar
* AL_APIENTRY
alGetStringiSOFT(ALenum pname
, ALsizei index
)
752 const char *ResamplerNames
[] = {
753 alPointResampler
, alLinearResampler
,
754 alSinc4Resampler
, alBSinc12Resampler
,
757 const ALchar
*value
= NULL
;
760 static_assert(COUNTOF(ResamplerNames
) == ResamplerMax
+1, "Incorrect ResamplerNames list");
762 context
= GetContextRef();
763 if(!context
) return NULL
;
767 case AL_RESAMPLER_NAME_SOFT
:
768 if(index
< 0 || (size_t)index
>= COUNTOF(ResamplerNames
))
769 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
770 value
= ResamplerNames
[index
];
774 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
778 ALCcontext_DecRef(context
);
784 void UpdateContextProps(ALCcontext
*context
)
786 struct ALcontextProps
*props
;
788 /* Get an unused proprty container, or allocate a new one as needed. */
789 props
= ATOMIC_LOAD(&context
->FreeList
, almemory_order_acquire
);
791 props
= al_calloc(16, sizeof(*props
));
794 struct ALcontextProps
*next
;
796 next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
797 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context
->FreeList
, &props
, next
,
798 almemory_order_seq_cst
, almemory_order_acquire
) == 0);
801 /* Copy in current property values. */
802 props
->MetersPerUnit
= context
->MetersPerUnit
;
804 props
->DopplerFactor
= context
->DopplerFactor
;
805 props
->DopplerVelocity
= context
->DopplerVelocity
;
806 props
->SpeedOfSound
= context
->SpeedOfSound
;
808 props
->SourceDistanceModel
= context
->SourceDistanceModel
;
809 props
->DistanceModel
= context
->DistanceModel
;
811 /* Set the new container for updating internal parameters. */
812 props
= ATOMIC_EXCHANGE_PTR(&context
->Update
, props
, almemory_order_acq_rel
);
815 /* If there was an unused update container, put it back in the
818 ATOMIC_REPLACE_HEAD(struct ALcontextProps
*, &context
->FreeList
, props
);