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 AL_API ALvoid AL_APIENTRY
alEnable(ALenum capability
)
61 context
= GetContextRef();
64 WriteLock(&context
->PropLock
);
67 case AL_SOURCE_DISTANCE_MODEL
:
68 context
->SourceDistanceModel
= AL_TRUE
;
72 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
74 if(!ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
75 UpdateContextProps(context
);
78 WriteUnlock(&context
->PropLock
);
79 ALCcontext_DecRef(context
);
82 AL_API ALvoid AL_APIENTRY
alDisable(ALenum capability
)
86 context
= GetContextRef();
89 WriteLock(&context
->PropLock
);
92 case AL_SOURCE_DISTANCE_MODEL
:
93 context
->SourceDistanceModel
= AL_FALSE
;
97 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
99 if(!ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
100 UpdateContextProps(context
);
103 WriteUnlock(&context
->PropLock
);
104 ALCcontext_DecRef(context
);
107 AL_API ALboolean AL_APIENTRY
alIsEnabled(ALenum capability
)
110 ALboolean value
=AL_FALSE
;
112 context
= GetContextRef();
113 if(!context
) return AL_FALSE
;
117 case AL_SOURCE_DISTANCE_MODEL
:
118 value
= context
->SourceDistanceModel
;
122 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
126 ALCcontext_DecRef(context
);
131 AL_API ALboolean AL_APIENTRY
alGetBoolean(ALenum pname
)
134 ALboolean value
=AL_FALSE
;
136 context
= GetContextRef();
137 if(!context
) return AL_FALSE
;
141 case AL_DOPPLER_FACTOR
:
142 if(context
->DopplerFactor
!= 0.0f
)
146 case AL_DOPPLER_VELOCITY
:
147 if(context
->DopplerVelocity
!= 0.0f
)
151 case AL_DISTANCE_MODEL
:
152 if(context
->DistanceModel
== AL_INVERSE_DISTANCE_CLAMPED
)
156 case AL_SPEED_OF_SOUND
:
157 if(context
->SpeedOfSound
!= 0.0f
)
161 case AL_DEFERRED_UPDATES_SOFT
:
162 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
166 case AL_GAIN_LIMIT_SOFT
:
167 if(GAIN_MIX_MAX
/context
->GainBoost
!= 0.0f
)
171 case AL_NUM_RESAMPLERS_SOFT
:
176 case AL_DEFAULT_RESAMPLER_SOFT
:
177 value
= ResamplerDefault
? AL_TRUE
: AL_FALSE
;
181 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
185 ALCcontext_DecRef(context
);
190 AL_API ALdouble AL_APIENTRY
alGetDouble(ALenum pname
)
193 ALdouble value
= 0.0;
195 context
= GetContextRef();
196 if(!context
) return 0.0;
200 case AL_DOPPLER_FACTOR
:
201 value
= (ALdouble
)context
->DopplerFactor
;
204 case AL_DOPPLER_VELOCITY
:
205 value
= (ALdouble
)context
->DopplerVelocity
;
208 case AL_DISTANCE_MODEL
:
209 value
= (ALdouble
)context
->DistanceModel
;
212 case AL_SPEED_OF_SOUND
:
213 value
= (ALdouble
)context
->SpeedOfSound
;
216 case AL_DEFERRED_UPDATES_SOFT
:
217 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
218 value
= (ALdouble
)AL_TRUE
;
221 case AL_GAIN_LIMIT_SOFT
:
222 value
= (ALdouble
)GAIN_MIX_MAX
/context
->GainBoost
;
225 case AL_NUM_RESAMPLERS_SOFT
:
226 value
= (ALdouble
)(ResamplerMax
+ 1);
229 case AL_DEFAULT_RESAMPLER_SOFT
:
230 value
= (ALdouble
)ResamplerDefault
;
234 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
238 ALCcontext_DecRef(context
);
243 AL_API ALfloat AL_APIENTRY
alGetFloat(ALenum pname
)
246 ALfloat value
= 0.0f
;
248 context
= GetContextRef();
249 if(!context
) return 0.0f
;
253 case AL_DOPPLER_FACTOR
:
254 value
= context
->DopplerFactor
;
257 case AL_DOPPLER_VELOCITY
:
258 value
= context
->DopplerVelocity
;
261 case AL_DISTANCE_MODEL
:
262 value
= (ALfloat
)context
->DistanceModel
;
265 case AL_SPEED_OF_SOUND
:
266 value
= context
->SpeedOfSound
;
269 case AL_DEFERRED_UPDATES_SOFT
:
270 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
271 value
= (ALfloat
)AL_TRUE
;
274 case AL_GAIN_LIMIT_SOFT
:
275 value
= GAIN_MIX_MAX
/context
->GainBoost
;
278 case AL_NUM_RESAMPLERS_SOFT
:
279 value
= (ALfloat
)(ResamplerMax
+ 1);
282 case AL_DEFAULT_RESAMPLER_SOFT
:
283 value
= (ALfloat
)ResamplerDefault
;
287 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
291 ALCcontext_DecRef(context
);
296 AL_API ALint AL_APIENTRY
alGetInteger(ALenum pname
)
301 context
= GetContextRef();
302 if(!context
) return 0;
306 case AL_DOPPLER_FACTOR
:
307 value
= (ALint
)context
->DopplerFactor
;
310 case AL_DOPPLER_VELOCITY
:
311 value
= (ALint
)context
->DopplerVelocity
;
314 case AL_DISTANCE_MODEL
:
315 value
= (ALint
)context
->DistanceModel
;
318 case AL_SPEED_OF_SOUND
:
319 value
= (ALint
)context
->SpeedOfSound
;
322 case AL_DEFERRED_UPDATES_SOFT
:
323 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
324 value
= (ALint
)AL_TRUE
;
327 case AL_GAIN_LIMIT_SOFT
:
328 value
= (ALint
)(GAIN_MIX_MAX
/context
->GainBoost
);
331 case AL_NUM_RESAMPLERS_SOFT
:
332 value
= ResamplerMax
+ 1;
335 case AL_DEFAULT_RESAMPLER_SOFT
:
336 value
= ResamplerDefault
;
340 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
344 ALCcontext_DecRef(context
);
349 AL_API ALint64SOFT AL_APIENTRY
alGetInteger64SOFT(ALenum pname
)
352 ALint64SOFT value
= 0;
354 context
= GetContextRef();
355 if(!context
) return 0;
359 case AL_DOPPLER_FACTOR
:
360 value
= (ALint64SOFT
)context
->DopplerFactor
;
363 case AL_DOPPLER_VELOCITY
:
364 value
= (ALint64SOFT
)context
->DopplerVelocity
;
367 case AL_DISTANCE_MODEL
:
368 value
= (ALint64SOFT
)context
->DistanceModel
;
371 case AL_SPEED_OF_SOUND
:
372 value
= (ALint64SOFT
)context
->SpeedOfSound
;
375 case AL_DEFERRED_UPDATES_SOFT
:
376 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
377 value
= (ALint64SOFT
)AL_TRUE
;
380 case AL_GAIN_LIMIT_SOFT
:
381 value
= (ALint64SOFT
)(GAIN_MIX_MAX
/context
->GainBoost
);
384 case AL_NUM_RESAMPLERS_SOFT
:
385 value
= (ALint64SOFT
)(ResamplerMax
+ 1);
388 case AL_DEFAULT_RESAMPLER_SOFT
:
389 value
= (ALint64SOFT
)ResamplerDefault
;
393 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
397 ALCcontext_DecRef(context
);
402 AL_API ALvoid AL_APIENTRY
alGetBooleanv(ALenum pname
, ALboolean
*values
)
410 case AL_DOPPLER_FACTOR
:
411 case AL_DOPPLER_VELOCITY
:
412 case AL_DISTANCE_MODEL
:
413 case AL_SPEED_OF_SOUND
:
414 case AL_DEFERRED_UPDATES_SOFT
:
415 case AL_GAIN_LIMIT_SOFT
:
416 case AL_NUM_RESAMPLERS_SOFT
:
417 case AL_DEFAULT_RESAMPLER_SOFT
:
418 values
[0] = alGetBoolean(pname
);
423 context
= GetContextRef();
427 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
431 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
435 ALCcontext_DecRef(context
);
438 AL_API ALvoid AL_APIENTRY
alGetDoublev(ALenum pname
, ALdouble
*values
)
446 case AL_DOPPLER_FACTOR
:
447 case AL_DOPPLER_VELOCITY
:
448 case AL_DISTANCE_MODEL
:
449 case AL_SPEED_OF_SOUND
:
450 case AL_DEFERRED_UPDATES_SOFT
:
451 case AL_GAIN_LIMIT_SOFT
:
452 case AL_NUM_RESAMPLERS_SOFT
:
453 case AL_DEFAULT_RESAMPLER_SOFT
:
454 values
[0] = alGetDouble(pname
);
459 context
= GetContextRef();
463 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
467 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
471 ALCcontext_DecRef(context
);
474 AL_API ALvoid AL_APIENTRY
alGetFloatv(ALenum pname
, ALfloat
*values
)
482 case AL_DOPPLER_FACTOR
:
483 case AL_DOPPLER_VELOCITY
:
484 case AL_DISTANCE_MODEL
:
485 case AL_SPEED_OF_SOUND
:
486 case AL_DEFERRED_UPDATES_SOFT
:
487 case AL_GAIN_LIMIT_SOFT
:
488 case AL_NUM_RESAMPLERS_SOFT
:
489 case AL_DEFAULT_RESAMPLER_SOFT
:
490 values
[0] = alGetFloat(pname
);
495 context
= GetContextRef();
499 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
503 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
507 ALCcontext_DecRef(context
);
510 AL_API ALvoid AL_APIENTRY
alGetIntegerv(ALenum pname
, ALint
*values
)
518 case AL_DOPPLER_FACTOR
:
519 case AL_DOPPLER_VELOCITY
:
520 case AL_DISTANCE_MODEL
:
521 case AL_SPEED_OF_SOUND
:
522 case AL_DEFERRED_UPDATES_SOFT
:
523 case AL_GAIN_LIMIT_SOFT
:
524 case AL_NUM_RESAMPLERS_SOFT
:
525 case AL_DEFAULT_RESAMPLER_SOFT
:
526 values
[0] = alGetInteger(pname
);
531 context
= GetContextRef();
537 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
541 ALCcontext_DecRef(context
);
544 AL_API
void AL_APIENTRY
alGetInteger64vSOFT(ALenum pname
, ALint64SOFT
*values
)
552 case AL_DOPPLER_FACTOR
:
553 case AL_DOPPLER_VELOCITY
:
554 case AL_DISTANCE_MODEL
:
555 case AL_SPEED_OF_SOUND
:
556 case AL_DEFERRED_UPDATES_SOFT
:
557 case AL_GAIN_LIMIT_SOFT
:
558 case AL_NUM_RESAMPLERS_SOFT
:
559 case AL_DEFAULT_RESAMPLER_SOFT
:
560 values
[0] = alGetInteger64SOFT(pname
);
565 context
= GetContextRef();
571 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
575 ALCcontext_DecRef(context
);
578 AL_API
const ALchar
* AL_APIENTRY
alGetString(ALenum pname
)
580 const ALchar
*value
= NULL
;
583 context
= GetContextRef();
584 if(!context
) return NULL
;
601 value
= context
->ExtensionList
;
608 case AL_INVALID_NAME
:
609 value
= alErrInvalidName
;
612 case AL_INVALID_ENUM
:
613 value
= alErrInvalidEnum
;
616 case AL_INVALID_VALUE
:
617 value
= alErrInvalidValue
;
620 case AL_INVALID_OPERATION
:
621 value
= alErrInvalidOp
;
624 case AL_OUT_OF_MEMORY
:
625 value
= alErrOutOfMemory
;
629 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
633 ALCcontext_DecRef(context
);
638 AL_API ALvoid AL_APIENTRY
alDopplerFactor(ALfloat value
)
642 context
= GetContextRef();
645 if(!(value
>= 0.0f
&& isfinite(value
)))
646 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
648 WriteLock(&context
->PropLock
);
649 context
->DopplerFactor
= value
;
650 if(!ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
651 UpdateContextProps(context
);
652 WriteUnlock(&context
->PropLock
);
655 ALCcontext_DecRef(context
);
658 AL_API ALvoid AL_APIENTRY
alDopplerVelocity(ALfloat value
)
662 context
= GetContextRef();
665 if(!(value
>= 0.0f
&& isfinite(value
)))
666 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
668 WriteLock(&context
->PropLock
);
669 context
->DopplerVelocity
= value
;
670 if(!ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
671 UpdateContextProps(context
);
672 WriteUnlock(&context
->PropLock
);
675 ALCcontext_DecRef(context
);
678 AL_API ALvoid AL_APIENTRY
alSpeedOfSound(ALfloat value
)
682 context
= GetContextRef();
685 if(!(value
> 0.0f
&& isfinite(value
)))
686 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
688 WriteLock(&context
->PropLock
);
689 context
->SpeedOfSound
= value
;
690 if(!ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
691 UpdateContextProps(context
);
692 WriteUnlock(&context
->PropLock
);
695 ALCcontext_DecRef(context
);
698 AL_API ALvoid AL_APIENTRY
alDistanceModel(ALenum value
)
702 context
= GetContextRef();
705 if(!(value
== AL_INVERSE_DISTANCE
|| value
== AL_INVERSE_DISTANCE_CLAMPED
||
706 value
== AL_LINEAR_DISTANCE
|| value
== AL_LINEAR_DISTANCE_CLAMPED
||
707 value
== AL_EXPONENT_DISTANCE
|| value
== AL_EXPONENT_DISTANCE_CLAMPED
||
709 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
711 WriteLock(&context
->PropLock
);
712 context
->DistanceModel
= value
;
713 if(!context
->SourceDistanceModel
)
715 if(!ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
716 UpdateContextProps(context
);
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
);