2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 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
35 #include "alAuxEffectSlot.h"
37 #include "backends/base.h"
43 extern inline void LockSourcesRead(ALCcontext
*context
);
44 extern inline void UnlockSourcesRead(ALCcontext
*context
);
45 extern inline void LockSourcesWrite(ALCcontext
*context
);
46 extern inline void UnlockSourcesWrite(ALCcontext
*context
);
47 extern inline struct ALsource
*LookupSource(ALCcontext
*context
, ALuint id
);
48 extern inline struct ALsource
*RemoveSource(ALCcontext
*context
, ALuint id
);
50 static ALvoid
InitSourceParams(ALsource
*Source
);
51 static ALvoid
DeinitSource(ALsource
*source
);
52 static ALint64
GetSourceSampleOffset(ALsource
*Source
);
53 static ALdouble
GetSourceSecOffset(ALsource
*Source
);
54 static ALdouble
GetSourceOffset(ALsource
*Source
, ALenum name
);
55 static ALboolean
GetSampleOffset(ALsource
*Source
, ALuint
*offset
, ALuint
*frac
);
57 typedef enum SourceProp
{
60 srcMinGain
= AL_MIN_GAIN
,
61 srcMaxGain
= AL_MAX_GAIN
,
62 srcMaxDistance
= AL_MAX_DISTANCE
,
63 srcRolloffFactor
= AL_ROLLOFF_FACTOR
,
64 srcDopplerFactor
= AL_DOPPLER_FACTOR
,
65 srcConeOuterGain
= AL_CONE_OUTER_GAIN
,
66 srcSecOffset
= AL_SEC_OFFSET
,
67 srcSampleOffset
= AL_SAMPLE_OFFSET
,
68 srcByteOffset
= AL_BYTE_OFFSET
,
69 srcConeInnerAngle
= AL_CONE_INNER_ANGLE
,
70 srcConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
71 srcRefDistance
= AL_REFERENCE_DISTANCE
,
73 srcPosition
= AL_POSITION
,
74 srcVelocity
= AL_VELOCITY
,
75 srcDirection
= AL_DIRECTION
,
77 srcSourceRelative
= AL_SOURCE_RELATIVE
,
78 srcLooping
= AL_LOOPING
,
79 srcBuffer
= AL_BUFFER
,
80 srcSourceState
= AL_SOURCE_STATE
,
81 srcBuffersQueued
= AL_BUFFERS_QUEUED
,
82 srcBuffersProcessed
= AL_BUFFERS_PROCESSED
,
83 srcSourceType
= AL_SOURCE_TYPE
,
86 srcConeOuterGainHF
= AL_CONE_OUTER_GAINHF
,
87 srcAirAbsorptionFactor
= AL_AIR_ABSORPTION_FACTOR
,
88 srcRoomRolloffFactor
= AL_ROOM_ROLLOFF_FACTOR
,
89 srcDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
90 srcAuxSendFilterGainAuto
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
91 srcAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
92 srcDirectFilter
= AL_DIRECT_FILTER
,
93 srcAuxSendFilter
= AL_AUXILIARY_SEND_FILTER
,
95 /* AL_SOFT_direct_channels */
96 srcDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
98 /* AL_EXT_source_distance_model */
99 srcDistanceModel
= AL_DISTANCE_MODEL
,
101 srcByteLengthSOFT
= AL_BYTE_LENGTH_SOFT
,
102 srcSampleLengthSOFT
= AL_SAMPLE_LENGTH_SOFT
,
103 srcSecLengthSOFT
= AL_SEC_LENGTH_SOFT
,
105 /* AL_SOFT_source_latency */
106 srcSampleOffsetLatencySOFT
= AL_SAMPLE_OFFSET_LATENCY_SOFT
,
107 srcSecOffsetLatencySOFT
= AL_SEC_OFFSET_LATENCY_SOFT
,
109 /* AL_EXT_STEREO_ANGLES */
110 srcAngles
= AL_STEREO_ANGLES
,
112 /* AL_EXT_SOURCE_RADIUS */
113 srcRadius
= AL_SOURCE_RADIUS
,
116 srcOrientation
= AL_ORIENTATION
,
119 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALfloat
*values
);
120 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint
*values
);
121 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint64SOFT
*values
);
123 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALdouble
*values
);
124 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint
*values
);
125 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint64
*values
);
127 static inline bool SourceShouldUpdate(const ALsource
*source
, const ALCcontext
*context
)
129 return (source
->state
== AL_PLAYING
|| source
->state
== AL_PAUSED
) &&
130 !ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
);
133 static ALint
FloatValsByProp(ALenum prop
)
135 if(prop
!= (ALenum
)((SourceProp
)prop
))
137 switch((SourceProp
)prop
)
143 case AL_MAX_DISTANCE
:
144 case AL_ROLLOFF_FACTOR
:
145 case AL_DOPPLER_FACTOR
:
146 case AL_CONE_OUTER_GAIN
:
148 case AL_SAMPLE_OFFSET
:
150 case AL_CONE_INNER_ANGLE
:
151 case AL_CONE_OUTER_ANGLE
:
152 case AL_REFERENCE_DISTANCE
:
153 case AL_CONE_OUTER_GAINHF
:
154 case AL_AIR_ABSORPTION_FACTOR
:
155 case AL_ROOM_ROLLOFF_FACTOR
:
156 case AL_DIRECT_FILTER_GAINHF_AUTO
:
157 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
158 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
159 case AL_DIRECT_CHANNELS_SOFT
:
160 case AL_DISTANCE_MODEL
:
161 case AL_SOURCE_RELATIVE
:
163 case AL_SOURCE_STATE
:
164 case AL_BUFFERS_QUEUED
:
165 case AL_BUFFERS_PROCESSED
:
167 case AL_BYTE_LENGTH_SOFT
:
168 case AL_SAMPLE_LENGTH_SOFT
:
169 case AL_SEC_LENGTH_SOFT
:
170 case AL_SOURCE_RADIUS
:
173 case AL_STEREO_ANGLES
:
184 case AL_SEC_OFFSET_LATENCY_SOFT
:
185 break; /* Double only */
188 case AL_DIRECT_FILTER
:
189 case AL_AUXILIARY_SEND_FILTER
:
190 break; /* i/i64 only */
191 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
192 break; /* i64 only */
196 static ALint
DoubleValsByProp(ALenum prop
)
198 if(prop
!= (ALenum
)((SourceProp
)prop
))
200 switch((SourceProp
)prop
)
206 case AL_MAX_DISTANCE
:
207 case AL_ROLLOFF_FACTOR
:
208 case AL_DOPPLER_FACTOR
:
209 case AL_CONE_OUTER_GAIN
:
211 case AL_SAMPLE_OFFSET
:
213 case AL_CONE_INNER_ANGLE
:
214 case AL_CONE_OUTER_ANGLE
:
215 case AL_REFERENCE_DISTANCE
:
216 case AL_CONE_OUTER_GAINHF
:
217 case AL_AIR_ABSORPTION_FACTOR
:
218 case AL_ROOM_ROLLOFF_FACTOR
:
219 case AL_DIRECT_FILTER_GAINHF_AUTO
:
220 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
221 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
222 case AL_DIRECT_CHANNELS_SOFT
:
223 case AL_DISTANCE_MODEL
:
224 case AL_SOURCE_RELATIVE
:
226 case AL_SOURCE_STATE
:
227 case AL_BUFFERS_QUEUED
:
228 case AL_BUFFERS_PROCESSED
:
230 case AL_BYTE_LENGTH_SOFT
:
231 case AL_SAMPLE_LENGTH_SOFT
:
232 case AL_SEC_LENGTH_SOFT
:
233 case AL_SOURCE_RADIUS
:
236 case AL_SEC_OFFSET_LATENCY_SOFT
:
237 case AL_STEREO_ANGLES
:
249 case AL_DIRECT_FILTER
:
250 case AL_AUXILIARY_SEND_FILTER
:
251 break; /* i/i64 only */
252 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
253 break; /* i64 only */
258 static ALint
IntValsByProp(ALenum prop
)
260 if(prop
!= (ALenum
)((SourceProp
)prop
))
262 switch((SourceProp
)prop
)
268 case AL_MAX_DISTANCE
:
269 case AL_ROLLOFF_FACTOR
:
270 case AL_DOPPLER_FACTOR
:
271 case AL_CONE_OUTER_GAIN
:
273 case AL_SAMPLE_OFFSET
:
275 case AL_CONE_INNER_ANGLE
:
276 case AL_CONE_OUTER_ANGLE
:
277 case AL_REFERENCE_DISTANCE
:
278 case AL_CONE_OUTER_GAINHF
:
279 case AL_AIR_ABSORPTION_FACTOR
:
280 case AL_ROOM_ROLLOFF_FACTOR
:
281 case AL_DIRECT_FILTER_GAINHF_AUTO
:
282 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
283 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
284 case AL_DIRECT_CHANNELS_SOFT
:
285 case AL_DISTANCE_MODEL
:
286 case AL_SOURCE_RELATIVE
:
289 case AL_SOURCE_STATE
:
290 case AL_BUFFERS_QUEUED
:
291 case AL_BUFFERS_PROCESSED
:
293 case AL_DIRECT_FILTER
:
294 case AL_BYTE_LENGTH_SOFT
:
295 case AL_SAMPLE_LENGTH_SOFT
:
296 case AL_SEC_LENGTH_SOFT
:
297 case AL_SOURCE_RADIUS
:
303 case AL_AUXILIARY_SEND_FILTER
:
309 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
310 break; /* i64 only */
311 case AL_SEC_OFFSET_LATENCY_SOFT
:
312 break; /* Double only */
313 case AL_STEREO_ANGLES
:
314 break; /* Float/double only */
318 static ALint
Int64ValsByProp(ALenum prop
)
320 if(prop
!= (ALenum
)((SourceProp
)prop
))
322 switch((SourceProp
)prop
)
328 case AL_MAX_DISTANCE
:
329 case AL_ROLLOFF_FACTOR
:
330 case AL_DOPPLER_FACTOR
:
331 case AL_CONE_OUTER_GAIN
:
333 case AL_SAMPLE_OFFSET
:
335 case AL_CONE_INNER_ANGLE
:
336 case AL_CONE_OUTER_ANGLE
:
337 case AL_REFERENCE_DISTANCE
:
338 case AL_CONE_OUTER_GAINHF
:
339 case AL_AIR_ABSORPTION_FACTOR
:
340 case AL_ROOM_ROLLOFF_FACTOR
:
341 case AL_DIRECT_FILTER_GAINHF_AUTO
:
342 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
343 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
344 case AL_DIRECT_CHANNELS_SOFT
:
345 case AL_DISTANCE_MODEL
:
346 case AL_SOURCE_RELATIVE
:
349 case AL_SOURCE_STATE
:
350 case AL_BUFFERS_QUEUED
:
351 case AL_BUFFERS_PROCESSED
:
353 case AL_DIRECT_FILTER
:
354 case AL_BYTE_LENGTH_SOFT
:
355 case AL_SAMPLE_LENGTH_SOFT
:
356 case AL_SEC_LENGTH_SOFT
:
357 case AL_SOURCE_RADIUS
:
360 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
366 case AL_AUXILIARY_SEND_FILTER
:
372 case AL_SEC_OFFSET_LATENCY_SOFT
:
373 break; /* Double only */
374 case AL_STEREO_ANGLES
:
375 break; /* Float/double only */
381 #define CHECKVAL(x) do { \
383 SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); \
386 #define DO_UPDATEPROPS() do { \
387 if(SourceShouldUpdate(Source, Context)) \
388 UpdateSourceProps(Source, device->NumAuxSends); \
391 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALfloat
*values
)
393 ALCdevice
*device
= Context
->Device
;
398 case AL_BYTE_LENGTH_SOFT
:
399 case AL_SAMPLE_LENGTH_SOFT
:
400 case AL_SEC_LENGTH_SOFT
:
401 case AL_SEC_OFFSET_LATENCY_SOFT
:
403 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
406 CHECKVAL(*values
>= 0.0f
);
408 Source
->Pitch
= *values
;
412 case AL_CONE_INNER_ANGLE
:
413 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
415 Source
->InnerAngle
= *values
;
419 case AL_CONE_OUTER_ANGLE
:
420 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
422 Source
->OuterAngle
= *values
;
427 CHECKVAL(*values
>= 0.0f
);
429 Source
->Gain
= *values
;
433 case AL_MAX_DISTANCE
:
434 CHECKVAL(*values
>= 0.0f
);
436 Source
->MaxDistance
= *values
;
440 case AL_ROLLOFF_FACTOR
:
441 CHECKVAL(*values
>= 0.0f
);
443 Source
->RollOffFactor
= *values
;
447 case AL_REFERENCE_DISTANCE
:
448 CHECKVAL(*values
>= 0.0f
);
450 Source
->RefDistance
= *values
;
455 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
457 Source
->MinGain
= *values
;
462 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
464 Source
->MaxGain
= *values
;
468 case AL_CONE_OUTER_GAIN
:
469 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
471 Source
->OuterGain
= *values
;
475 case AL_CONE_OUTER_GAINHF
:
476 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
478 Source
->OuterGainHF
= *values
;
482 case AL_AIR_ABSORPTION_FACTOR
:
483 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
485 Source
->AirAbsorptionFactor
= *values
;
489 case AL_ROOM_ROLLOFF_FACTOR
:
490 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
492 Source
->RoomRolloffFactor
= *values
;
496 case AL_DOPPLER_FACTOR
:
497 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
499 Source
->DopplerFactor
= *values
;
504 case AL_SAMPLE_OFFSET
:
506 CHECKVAL(*values
>= 0.0f
);
508 Source
->OffsetType
= prop
;
509 Source
->Offset
= *values
;
511 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
512 !ATOMIC_LOAD(&Context
->DeferUpdates
, almemory_order_acquire
))
514 LockContext(Context
);
515 WriteLock(&Source
->queue_lock
);
516 if(ApplyOffset(Source
) == AL_FALSE
)
518 WriteUnlock(&Source
->queue_lock
);
519 UnlockContext(Context
);
520 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
522 WriteUnlock(&Source
->queue_lock
);
523 UnlockContext(Context
);
527 case AL_SOURCE_RADIUS
:
528 CHECKVAL(*values
>= 0.0f
&& isfinite(*values
));
530 Source
->Radius
= *values
;
534 case AL_STEREO_ANGLES
:
535 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]));
537 Source
->StereoPan
[0] = values
[0];
538 Source
->StereoPan
[1] = values
[1];
544 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
546 Source
->Position
[0] = values
[0];
547 Source
->Position
[1] = values
[1];
548 Source
->Position
[2] = values
[2];
553 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
555 Source
->Velocity
[0] = values
[0];
556 Source
->Velocity
[1] = values
[1];
557 Source
->Velocity
[2] = values
[2];
562 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
564 Source
->Direction
[0] = values
[0];
565 Source
->Direction
[1] = values
[1];
566 Source
->Direction
[2] = values
[2];
571 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]) &&
572 isfinite(values
[3]) && isfinite(values
[4]) && isfinite(values
[5]));
574 Source
->Orientation
[0][0] = values
[0];
575 Source
->Orientation
[0][1] = values
[1];
576 Source
->Orientation
[0][2] = values
[2];
577 Source
->Orientation
[1][0] = values
[3];
578 Source
->Orientation
[1][1] = values
[4];
579 Source
->Orientation
[1][2] = values
[5];
584 case AL_SOURCE_RELATIVE
:
586 case AL_SOURCE_STATE
:
588 case AL_DISTANCE_MODEL
:
589 case AL_DIRECT_FILTER_GAINHF_AUTO
:
590 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
591 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
592 case AL_DIRECT_CHANNELS_SOFT
:
593 ival
= (ALint
)values
[0];
594 return SetSourceiv(Source
, Context
, prop
, &ival
);
596 case AL_BUFFERS_QUEUED
:
597 case AL_BUFFERS_PROCESSED
:
598 ival
= (ALint
)((ALuint
)values
[0]);
599 return SetSourceiv(Source
, Context
, prop
, &ival
);
602 case AL_DIRECT_FILTER
:
603 case AL_AUXILIARY_SEND_FILTER
:
604 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
608 ERR("Unexpected property: 0x%04x\n", prop
);
609 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
612 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint
*values
)
614 ALCdevice
*device
= Context
->Device
;
615 ALbuffer
*buffer
= NULL
;
616 ALfilter
*filter
= NULL
;
617 ALeffectslot
*slot
= NULL
;
618 ALbufferlistitem
*oldlist
;
619 ALbufferlistitem
*newlist
;
624 case AL_SOURCE_STATE
:
626 case AL_BUFFERS_QUEUED
:
627 case AL_BUFFERS_PROCESSED
:
628 case AL_BYTE_LENGTH_SOFT
:
629 case AL_SAMPLE_LENGTH_SOFT
:
630 case AL_SEC_LENGTH_SOFT
:
632 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
634 case AL_SOURCE_RELATIVE
:
635 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
637 Source
->HeadRelative
= (ALboolean
)*values
;
642 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
644 Source
->Looping
= (ALboolean
)*values
;
649 LockBuffersRead(device
);
650 if(!(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
))
652 UnlockBuffersRead(device
);
653 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
656 WriteLock(&Source
->queue_lock
);
657 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
659 WriteUnlock(&Source
->queue_lock
);
660 UnlockBuffersRead(device
);
661 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
666 /* Add the selected buffer to a one-item queue */
667 newlist
= malloc(sizeof(ALbufferlistitem
));
668 newlist
->buffer
= buffer
;
669 newlist
->next
= NULL
;
670 IncrementRef(&buffer
->ref
);
672 /* Source is now Static */
673 Source
->SourceType
= AL_STATIC
;
675 ReadLock(&buffer
->lock
);
676 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
677 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
678 ReadUnlock(&buffer
->lock
);
682 /* Source is now Undetermined */
683 Source
->SourceType
= AL_UNDETERMINED
;
686 oldlist
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &Source
->queue
, newlist
);
687 ATOMIC_STORE(&Source
->current_buffer
, newlist
);
688 WriteUnlock(&Source
->queue_lock
);
689 UnlockBuffersRead(device
);
691 /* Delete all elements in the previous queue */
692 while(oldlist
!= NULL
)
694 ALbufferlistitem
*temp
= oldlist
;
695 oldlist
= temp
->next
;
698 DecrementRef(&temp
->buffer
->ref
);
704 case AL_SAMPLE_OFFSET
:
706 CHECKVAL(*values
>= 0);
708 Source
->OffsetType
= prop
;
709 Source
->Offset
= *values
;
711 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
712 !ATOMIC_LOAD(&Context
->DeferUpdates
, almemory_order_acquire
))
714 LockContext(Context
);
715 WriteLock(&Source
->queue_lock
);
716 if(ApplyOffset(Source
) == AL_FALSE
)
718 WriteUnlock(&Source
->queue_lock
);
719 UnlockContext(Context
);
720 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
722 WriteUnlock(&Source
->queue_lock
);
723 UnlockContext(Context
);
727 case AL_DIRECT_FILTER
:
728 LockFiltersRead(device
);
729 if(!(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
))
731 UnlockFiltersRead(device
);
732 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
737 Source
->Direct
.Gain
= 1.0f
;
738 Source
->Direct
.GainHF
= 1.0f
;
739 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
740 Source
->Direct
.GainLF
= 1.0f
;
741 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
745 Source
->Direct
.Gain
= filter
->Gain
;
746 Source
->Direct
.GainHF
= filter
->GainHF
;
747 Source
->Direct
.HFReference
= filter
->HFReference
;
748 Source
->Direct
.GainLF
= filter
->GainLF
;
749 Source
->Direct
.LFReference
= filter
->LFReference
;
751 UnlockFiltersRead(device
);
755 case AL_DIRECT_FILTER_GAINHF_AUTO
:
756 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
758 Source
->DryGainHFAuto
= *values
;
762 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
763 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
765 Source
->WetGainAuto
= *values
;
769 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
770 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
772 Source
->WetGainHFAuto
= *values
;
776 case AL_DIRECT_CHANNELS_SOFT
:
777 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
779 Source
->DirectChannels
= *values
;
783 case AL_DISTANCE_MODEL
:
784 CHECKVAL(*values
== AL_NONE
||
785 *values
== AL_INVERSE_DISTANCE
||
786 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
787 *values
== AL_LINEAR_DISTANCE
||
788 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
789 *values
== AL_EXPONENT_DISTANCE
||
790 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
792 Source
->DistanceModel
= *values
;
793 if(Context
->SourceDistanceModel
)
798 case AL_AUXILIARY_SEND_FILTER
:
799 LockFiltersRead(device
);
800 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
801 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
802 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
804 UnlockFiltersRead(device
);
805 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
811 Source
->Send
[values
[1]].Gain
= 1.0f
;
812 Source
->Send
[values
[1]].GainHF
= 1.0f
;
813 Source
->Send
[values
[1]].HFReference
= LOWPASSFREQREF
;
814 Source
->Send
[values
[1]].GainLF
= 1.0f
;
815 Source
->Send
[values
[1]].LFReference
= HIGHPASSFREQREF
;
819 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
820 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
821 Source
->Send
[values
[1]].HFReference
= filter
->HFReference
;
822 Source
->Send
[values
[1]].GainLF
= filter
->GainLF
;
823 Source
->Send
[values
[1]].LFReference
= filter
->LFReference
;
825 UnlockFiltersRead(device
);
827 if(slot
!= Source
->Send
[values
[1]].Slot
&&
828 (Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
))
830 /* Add refcount on the new slot, and release the previous slot */
831 if(slot
) IncrementRef(&slot
->ref
);
832 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
833 if(slot
) DecrementRef(&slot
->ref
);
834 /* We must force an update if the auxiliary slot changed on a
835 * playing source, in case the slot is about to be deleted.
837 UpdateSourceProps(Source
, device
->NumAuxSends
);
841 if(slot
) IncrementRef(&slot
->ref
);
842 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
843 if(slot
) DecrementRef(&slot
->ref
);
851 case AL_CONE_INNER_ANGLE
:
852 case AL_CONE_OUTER_ANGLE
:
857 case AL_REFERENCE_DISTANCE
:
858 case AL_ROLLOFF_FACTOR
:
859 case AL_CONE_OUTER_GAIN
:
860 case AL_MAX_DISTANCE
:
861 case AL_DOPPLER_FACTOR
:
862 case AL_CONE_OUTER_GAINHF
:
863 case AL_AIR_ABSORPTION_FACTOR
:
864 case AL_ROOM_ROLLOFF_FACTOR
:
865 case AL_SOURCE_RADIUS
:
866 fvals
[0] = (ALfloat
)*values
;
867 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
873 fvals
[0] = (ALfloat
)values
[0];
874 fvals
[1] = (ALfloat
)values
[1];
875 fvals
[2] = (ALfloat
)values
[2];
876 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
880 fvals
[0] = (ALfloat
)values
[0];
881 fvals
[1] = (ALfloat
)values
[1];
882 fvals
[2] = (ALfloat
)values
[2];
883 fvals
[3] = (ALfloat
)values
[3];
884 fvals
[4] = (ALfloat
)values
[4];
885 fvals
[5] = (ALfloat
)values
[5];
886 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
888 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
889 case AL_SEC_OFFSET_LATENCY_SOFT
:
890 case AL_STEREO_ANGLES
:
894 ERR("Unexpected property: 0x%04x\n", prop
);
895 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
898 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint64SOFT
*values
)
906 case AL_BUFFERS_QUEUED
:
907 case AL_BUFFERS_PROCESSED
:
908 case AL_SOURCE_STATE
:
909 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
910 case AL_BYTE_LENGTH_SOFT
:
911 case AL_SAMPLE_LENGTH_SOFT
:
912 case AL_SEC_LENGTH_SOFT
:
914 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
918 case AL_SOURCE_RELATIVE
:
921 case AL_SAMPLE_OFFSET
:
923 case AL_DIRECT_FILTER_GAINHF_AUTO
:
924 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
925 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
926 case AL_DIRECT_CHANNELS_SOFT
:
927 case AL_DISTANCE_MODEL
:
928 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
930 ivals
[0] = (ALint
)*values
;
931 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
935 case AL_DIRECT_FILTER
:
936 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
938 ivals
[0] = (ALuint
)*values
;
939 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
942 case AL_AUXILIARY_SEND_FILTER
:
943 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
944 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
945 values
[2] <= UINT_MAX
&& values
[2] >= 0);
947 ivals
[0] = (ALuint
)values
[0];
948 ivals
[1] = (ALuint
)values
[1];
949 ivals
[2] = (ALuint
)values
[2];
950 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
953 case AL_CONE_INNER_ANGLE
:
954 case AL_CONE_OUTER_ANGLE
:
959 case AL_REFERENCE_DISTANCE
:
960 case AL_ROLLOFF_FACTOR
:
961 case AL_CONE_OUTER_GAIN
:
962 case AL_MAX_DISTANCE
:
963 case AL_DOPPLER_FACTOR
:
964 case AL_CONE_OUTER_GAINHF
:
965 case AL_AIR_ABSORPTION_FACTOR
:
966 case AL_ROOM_ROLLOFF_FACTOR
:
967 case AL_SOURCE_RADIUS
:
968 fvals
[0] = (ALfloat
)*values
;
969 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
975 fvals
[0] = (ALfloat
)values
[0];
976 fvals
[1] = (ALfloat
)values
[1];
977 fvals
[2] = (ALfloat
)values
[2];
978 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
982 fvals
[0] = (ALfloat
)values
[0];
983 fvals
[1] = (ALfloat
)values
[1];
984 fvals
[2] = (ALfloat
)values
[2];
985 fvals
[3] = (ALfloat
)values
[3];
986 fvals
[4] = (ALfloat
)values
[4];
987 fvals
[5] = (ALfloat
)values
[5];
988 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
990 case AL_SEC_OFFSET_LATENCY_SOFT
:
991 case AL_STEREO_ANGLES
:
995 ERR("Unexpected property: 0x%04x\n", prop
);
996 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1002 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALdouble
*values
)
1004 ALCdevice
*device
= Context
->Device
;
1005 ALbufferlistitem
*BufferList
;
1012 *values
= Source
->Gain
;
1016 *values
= Source
->Pitch
;
1019 case AL_MAX_DISTANCE
:
1020 *values
= Source
->MaxDistance
;
1023 case AL_ROLLOFF_FACTOR
:
1024 *values
= Source
->RollOffFactor
;
1027 case AL_REFERENCE_DISTANCE
:
1028 *values
= Source
->RefDistance
;
1031 case AL_CONE_INNER_ANGLE
:
1032 *values
= Source
->InnerAngle
;
1035 case AL_CONE_OUTER_ANGLE
:
1036 *values
= Source
->OuterAngle
;
1040 *values
= Source
->MinGain
;
1044 *values
= Source
->MaxGain
;
1047 case AL_CONE_OUTER_GAIN
:
1048 *values
= Source
->OuterGain
;
1052 case AL_SAMPLE_OFFSET
:
1053 case AL_BYTE_OFFSET
:
1054 LockContext(Context
);
1055 *values
= GetSourceOffset(Source
, prop
);
1056 UnlockContext(Context
);
1059 case AL_CONE_OUTER_GAINHF
:
1060 *values
= Source
->OuterGainHF
;
1063 case AL_AIR_ABSORPTION_FACTOR
:
1064 *values
= Source
->AirAbsorptionFactor
;
1067 case AL_ROOM_ROLLOFF_FACTOR
:
1068 *values
= Source
->RoomRolloffFactor
;
1071 case AL_DOPPLER_FACTOR
:
1072 *values
= Source
->DopplerFactor
;
1075 case AL_SEC_LENGTH_SOFT
:
1076 ReadLock(&Source
->queue_lock
);
1077 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1084 ALbuffer
*buffer
= BufferList
->buffer
;
1085 if(buffer
&& buffer
->SampleLen
> 0)
1087 freq
= buffer
->Frequency
;
1088 length
+= buffer
->SampleLen
;
1090 } while((BufferList
=BufferList
->next
) != NULL
);
1091 *values
= (ALdouble
)length
/ (ALdouble
)freq
;
1093 ReadUnlock(&Source
->queue_lock
);
1096 case AL_SOURCE_RADIUS
:
1097 *values
= Source
->Radius
;
1100 case AL_STEREO_ANGLES
:
1101 values
[0] = Source
->StereoPan
[0];
1102 values
[1] = Source
->StereoPan
[1];
1105 case AL_SEC_OFFSET_LATENCY_SOFT
:
1106 LockContext(Context
);
1107 values
[0] = GetSourceSecOffset(Source
);
1108 values
[1] = (ALdouble
)(V0(device
->Backend
,getLatency
)()) /
1110 UnlockContext(Context
);
1114 values
[0] = Source
->Position
[0];
1115 values
[1] = Source
->Position
[1];
1116 values
[2] = Source
->Position
[2];
1120 values
[0] = Source
->Velocity
[0];
1121 values
[1] = Source
->Velocity
[1];
1122 values
[2] = Source
->Velocity
[2];
1126 values
[0] = Source
->Direction
[0];
1127 values
[1] = Source
->Direction
[1];
1128 values
[2] = Source
->Direction
[2];
1131 case AL_ORIENTATION
:
1132 values
[0] = Source
->Orientation
[0][0];
1133 values
[1] = Source
->Orientation
[0][1];
1134 values
[2] = Source
->Orientation
[0][2];
1135 values
[3] = Source
->Orientation
[1][0];
1136 values
[4] = Source
->Orientation
[1][1];
1137 values
[5] = Source
->Orientation
[1][2];
1141 case AL_SOURCE_RELATIVE
:
1143 case AL_SOURCE_STATE
:
1144 case AL_BUFFERS_QUEUED
:
1145 case AL_BUFFERS_PROCESSED
:
1146 case AL_SOURCE_TYPE
:
1147 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1148 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1149 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1150 case AL_DIRECT_CHANNELS_SOFT
:
1151 case AL_BYTE_LENGTH_SOFT
:
1152 case AL_SAMPLE_LENGTH_SOFT
:
1153 case AL_DISTANCE_MODEL
:
1154 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1155 *values
= (ALdouble
)ivals
[0];
1159 case AL_DIRECT_FILTER
:
1160 case AL_AUXILIARY_SEND_FILTER
:
1161 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1165 ERR("Unexpected property: 0x%04x\n", prop
);
1166 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1169 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint
*values
)
1171 ALbufferlistitem
*BufferList
;
1177 case AL_SOURCE_RELATIVE
:
1178 *values
= Source
->HeadRelative
;
1182 *values
= Source
->Looping
;
1186 ReadLock(&Source
->queue_lock
);
1187 BufferList
= (Source
->SourceType
== AL_STATIC
) ? ATOMIC_LOAD(&Source
->queue
) :
1188 ATOMIC_LOAD(&Source
->current_buffer
);
1189 *values
= (BufferList
&& BufferList
->buffer
) ? BufferList
->buffer
->id
: 0;
1190 ReadUnlock(&Source
->queue_lock
);
1193 case AL_SOURCE_STATE
:
1194 *values
= Source
->state
;
1197 case AL_BYTE_LENGTH_SOFT
:
1198 ReadLock(&Source
->queue_lock
);
1199 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1205 ALbuffer
*buffer
= BufferList
->buffer
;
1206 if(buffer
&& buffer
->SampleLen
> 0)
1208 ALuint byte_align
, sample_align
;
1209 if(buffer
->OriginalType
== UserFmtIMA4
)
1211 ALsizei align
= (buffer
->OriginalAlign
-1)/2 + 4;
1212 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1213 sample_align
= buffer
->OriginalAlign
;
1215 else if(buffer
->OriginalType
== UserFmtMSADPCM
)
1217 ALsizei align
= (buffer
->OriginalAlign
-2)/2 + 7;
1218 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1219 sample_align
= buffer
->OriginalAlign
;
1223 ALsizei align
= buffer
->OriginalAlign
;
1224 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1225 sample_align
= buffer
->OriginalAlign
;
1228 length
+= buffer
->SampleLen
/ sample_align
* byte_align
;
1230 } while((BufferList
=BufferList
->next
) != NULL
);
1233 ReadUnlock(&Source
->queue_lock
);
1236 case AL_SAMPLE_LENGTH_SOFT
:
1237 ReadLock(&Source
->queue_lock
);
1238 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1244 ALbuffer
*buffer
= BufferList
->buffer
;
1245 if(buffer
) length
+= buffer
->SampleLen
;
1246 } while((BufferList
=BufferList
->next
) != NULL
);
1249 ReadUnlock(&Source
->queue_lock
);
1252 case AL_BUFFERS_QUEUED
:
1253 ReadLock(&Source
->queue_lock
);
1254 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1261 } while((BufferList
=BufferList
->next
) != NULL
);
1264 ReadUnlock(&Source
->queue_lock
);
1267 case AL_BUFFERS_PROCESSED
:
1268 ReadLock(&Source
->queue_lock
);
1269 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
1271 /* Buffers on a looping source are in a perpetual state of
1272 * PENDING, so don't report any as PROCESSED */
1277 const ALbufferlistitem
*BufferList
= ATOMIC_LOAD(&Source
->queue
);
1278 const ALbufferlistitem
*Current
= ATOMIC_LOAD(&Source
->current_buffer
);
1280 while(BufferList
&& BufferList
!= Current
)
1283 BufferList
= BufferList
->next
;
1287 ReadUnlock(&Source
->queue_lock
);
1290 case AL_SOURCE_TYPE
:
1291 *values
= Source
->SourceType
;
1294 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1295 *values
= Source
->DryGainHFAuto
;
1298 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1299 *values
= Source
->WetGainAuto
;
1302 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1303 *values
= Source
->WetGainHFAuto
;
1306 case AL_DIRECT_CHANNELS_SOFT
:
1307 *values
= Source
->DirectChannels
;
1310 case AL_DISTANCE_MODEL
:
1311 *values
= Source
->DistanceModel
;
1314 /* 1x float/double */
1315 case AL_CONE_INNER_ANGLE
:
1316 case AL_CONE_OUTER_ANGLE
:
1321 case AL_REFERENCE_DISTANCE
:
1322 case AL_ROLLOFF_FACTOR
:
1323 case AL_CONE_OUTER_GAIN
:
1324 case AL_MAX_DISTANCE
:
1326 case AL_SAMPLE_OFFSET
:
1327 case AL_BYTE_OFFSET
:
1328 case AL_DOPPLER_FACTOR
:
1329 case AL_AIR_ABSORPTION_FACTOR
:
1330 case AL_ROOM_ROLLOFF_FACTOR
:
1331 case AL_CONE_OUTER_GAINHF
:
1332 case AL_SEC_LENGTH_SOFT
:
1333 case AL_SOURCE_RADIUS
:
1334 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1335 *values
= (ALint
)dvals
[0];
1338 /* 3x float/double */
1342 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1344 values
[0] = (ALint
)dvals
[0];
1345 values
[1] = (ALint
)dvals
[1];
1346 values
[2] = (ALint
)dvals
[2];
1350 /* 6x float/double */
1351 case AL_ORIENTATION
:
1352 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1354 values
[0] = (ALint
)dvals
[0];
1355 values
[1] = (ALint
)dvals
[1];
1356 values
[2] = (ALint
)dvals
[2];
1357 values
[3] = (ALint
)dvals
[3];
1358 values
[4] = (ALint
)dvals
[4];
1359 values
[5] = (ALint
)dvals
[5];
1363 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1364 break; /* i64 only */
1365 case AL_SEC_OFFSET_LATENCY_SOFT
:
1366 break; /* Double only */
1367 case AL_STEREO_ANGLES
:
1368 break; /* Float/double only */
1370 case AL_DIRECT_FILTER
:
1371 case AL_AUXILIARY_SEND_FILTER
:
1375 ERR("Unexpected property: 0x%04x\n", prop
);
1376 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1379 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint64
*values
)
1381 ALCdevice
*device
= Context
->Device
;
1388 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1389 LockContext(Context
);
1390 values
[0] = GetSourceSampleOffset(Source
);
1391 values
[1] = V0(device
->Backend
,getLatency
)();
1392 UnlockContext(Context
);
1395 /* 1x float/double */
1396 case AL_CONE_INNER_ANGLE
:
1397 case AL_CONE_OUTER_ANGLE
:
1402 case AL_REFERENCE_DISTANCE
:
1403 case AL_ROLLOFF_FACTOR
:
1404 case AL_CONE_OUTER_GAIN
:
1405 case AL_MAX_DISTANCE
:
1407 case AL_SAMPLE_OFFSET
:
1408 case AL_BYTE_OFFSET
:
1409 case AL_DOPPLER_FACTOR
:
1410 case AL_AIR_ABSORPTION_FACTOR
:
1411 case AL_ROOM_ROLLOFF_FACTOR
:
1412 case AL_CONE_OUTER_GAINHF
:
1413 case AL_SEC_LENGTH_SOFT
:
1414 case AL_SOURCE_RADIUS
:
1415 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1416 *values
= (ALint64
)dvals
[0];
1419 /* 3x float/double */
1423 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1425 values
[0] = (ALint64
)dvals
[0];
1426 values
[1] = (ALint64
)dvals
[1];
1427 values
[2] = (ALint64
)dvals
[2];
1431 /* 6x float/double */
1432 case AL_ORIENTATION
:
1433 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1435 values
[0] = (ALint64
)dvals
[0];
1436 values
[1] = (ALint64
)dvals
[1];
1437 values
[2] = (ALint64
)dvals
[2];
1438 values
[3] = (ALint64
)dvals
[3];
1439 values
[4] = (ALint64
)dvals
[4];
1440 values
[5] = (ALint64
)dvals
[5];
1445 case AL_SOURCE_RELATIVE
:
1447 case AL_SOURCE_STATE
:
1448 case AL_BUFFERS_QUEUED
:
1449 case AL_BUFFERS_PROCESSED
:
1450 case AL_BYTE_LENGTH_SOFT
:
1451 case AL_SAMPLE_LENGTH_SOFT
:
1452 case AL_SOURCE_TYPE
:
1453 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1454 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1455 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1456 case AL_DIRECT_CHANNELS_SOFT
:
1457 case AL_DISTANCE_MODEL
:
1458 if((err
=GetSourceiv(Source
, Context
, prop
, ivals
)) != AL_FALSE
)
1464 case AL_DIRECT_FILTER
:
1465 if((err
=GetSourceiv(Source
, Context
, prop
, ivals
)) != AL_FALSE
)
1466 *values
= (ALuint
)ivals
[0];
1470 case AL_AUXILIARY_SEND_FILTER
:
1471 if((err
=GetSourceiv(Source
, Context
, prop
, ivals
)) != AL_FALSE
)
1473 values
[0] = (ALuint
)ivals
[0];
1474 values
[1] = (ALuint
)ivals
[1];
1475 values
[2] = (ALuint
)ivals
[2];
1479 case AL_SEC_OFFSET_LATENCY_SOFT
:
1480 break; /* Double only */
1481 case AL_STEREO_ANGLES
:
1482 break; /* Float/double only */
1485 ERR("Unexpected property: 0x%04x\n", prop
);
1486 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1490 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
1492 ALCcontext
*context
;
1496 context
= GetContextRef();
1497 if(!context
) return;
1500 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1501 for(cur
= 0;cur
< n
;cur
++)
1503 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
1506 alDeleteSources(cur
, sources
);
1507 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
1509 InitSourceParams(source
);
1511 err
= NewThunkEntry(&source
->id
);
1512 if(err
== AL_NO_ERROR
)
1513 err
= InsertUIntMapEntry(&context
->SourceMap
, source
->id
, source
);
1514 if(err
!= AL_NO_ERROR
)
1516 FreeThunkEntry(source
->id
);
1517 memset(source
, 0, sizeof(ALsource
));
1520 alDeleteSources(cur
, sources
);
1521 SET_ERROR_AND_GOTO(context
, err
, done
);
1524 sources
[cur
] = source
->id
;
1528 ALCcontext_DecRef(context
);
1532 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
1534 ALCcontext
*context
;
1538 context
= GetContextRef();
1539 if(!context
) return;
1541 LockSourcesWrite(context
);
1543 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1545 /* Check that all Sources are valid */
1546 for(i
= 0;i
< n
;i
++)
1548 if(LookupSource(context
, sources
[i
]) == NULL
)
1549 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
1551 for(i
= 0;i
< n
;i
++)
1553 ALvoice
*voice
, *voice_end
;
1555 if((Source
=RemoveSource(context
, sources
[i
])) == NULL
)
1557 FreeThunkEntry(Source
->id
);
1559 LockContext(context
);
1560 voice
= context
->Voices
;
1561 voice_end
= voice
+ context
->VoiceCount
;
1562 while(voice
!= voice_end
)
1564 ALsource
*old
= Source
;
1565 if(COMPARE_EXCHANGE(&voice
->Source
, &old
, NULL
))
1569 UnlockContext(context
);
1571 DeinitSource(Source
);
1573 memset(Source
, 0, sizeof(*Source
));
1578 UnlockSourcesWrite(context
);
1579 ALCcontext_DecRef(context
);
1583 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1585 ALCcontext
*context
;
1588 context
= GetContextRef();
1589 if(!context
) return AL_FALSE
;
1591 LockSourcesRead(context
);
1592 ret
= (LookupSource(context
, source
) ? AL_TRUE
: AL_FALSE
);
1593 UnlockSourcesRead(context
);
1595 ALCcontext_DecRef(context
);
1601 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1603 ALCcontext
*Context
;
1606 Context
= GetContextRef();
1607 if(!Context
) return;
1609 WriteLock(&Context
->PropLock
);
1610 LockSourcesRead(Context
);
1611 if((Source
=LookupSource(Context
, source
)) == NULL
)
1612 alSetError(Context
, AL_INVALID_NAME
);
1613 else if(!(FloatValsByProp(param
) == 1))
1614 alSetError(Context
, AL_INVALID_ENUM
);
1616 SetSourcefv(Source
, Context
, param
, &value
);
1617 UnlockSourcesRead(Context
);
1618 WriteUnlock(&Context
->PropLock
);
1620 ALCcontext_DecRef(Context
);
1623 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1625 ALCcontext
*Context
;
1628 Context
= GetContextRef();
1629 if(!Context
) return;
1631 WriteLock(&Context
->PropLock
);
1632 LockSourcesRead(Context
);
1633 if((Source
=LookupSource(Context
, source
)) == NULL
)
1634 alSetError(Context
, AL_INVALID_NAME
);
1635 else if(!(FloatValsByProp(param
) == 3))
1636 alSetError(Context
, AL_INVALID_ENUM
);
1639 ALfloat fvals
[3] = { value1
, value2
, value3
};
1640 SetSourcefv(Source
, Context
, param
, fvals
);
1642 UnlockSourcesRead(Context
);
1643 WriteUnlock(&Context
->PropLock
);
1645 ALCcontext_DecRef(Context
);
1648 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1650 ALCcontext
*Context
;
1653 Context
= GetContextRef();
1654 if(!Context
) return;
1656 WriteLock(&Context
->PropLock
);
1657 LockSourcesRead(Context
);
1658 if((Source
=LookupSource(Context
, source
)) == NULL
)
1659 alSetError(Context
, AL_INVALID_NAME
);
1661 alSetError(Context
, AL_INVALID_VALUE
);
1662 else if(!(FloatValsByProp(param
) > 0))
1663 alSetError(Context
, AL_INVALID_ENUM
);
1665 SetSourcefv(Source
, Context
, param
, values
);
1666 UnlockSourcesRead(Context
);
1667 WriteUnlock(&Context
->PropLock
);
1669 ALCcontext_DecRef(Context
);
1673 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1675 ALCcontext
*Context
;
1678 Context
= GetContextRef();
1679 if(!Context
) return;
1681 WriteLock(&Context
->PropLock
);
1682 LockSourcesRead(Context
);
1683 if((Source
=LookupSource(Context
, source
)) == NULL
)
1684 alSetError(Context
, AL_INVALID_NAME
);
1685 else if(!(DoubleValsByProp(param
) == 1))
1686 alSetError(Context
, AL_INVALID_ENUM
);
1689 ALfloat fval
= (ALfloat
)value
;
1690 SetSourcefv(Source
, Context
, param
, &fval
);
1692 UnlockSourcesRead(Context
);
1693 WriteUnlock(&Context
->PropLock
);
1695 ALCcontext_DecRef(Context
);
1698 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1700 ALCcontext
*Context
;
1703 Context
= GetContextRef();
1704 if(!Context
) return;
1706 WriteLock(&Context
->PropLock
);
1707 LockSourcesRead(Context
);
1708 if((Source
=LookupSource(Context
, source
)) == NULL
)
1709 alSetError(Context
, AL_INVALID_NAME
);
1710 else if(!(DoubleValsByProp(param
) == 3))
1711 alSetError(Context
, AL_INVALID_ENUM
);
1714 ALfloat fvals
[3] = { (ALfloat
)value1
, (ALfloat
)value2
, (ALfloat
)value3
};
1715 SetSourcefv(Source
, Context
, param
, fvals
);
1717 UnlockSourcesRead(Context
);
1718 WriteUnlock(&Context
->PropLock
);
1720 ALCcontext_DecRef(Context
);
1723 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1725 ALCcontext
*Context
;
1729 Context
= GetContextRef();
1730 if(!Context
) return;
1732 WriteLock(&Context
->PropLock
);
1733 LockSourcesRead(Context
);
1734 if((Source
=LookupSource(Context
, source
)) == NULL
)
1735 alSetError(Context
, AL_INVALID_NAME
);
1737 alSetError(Context
, AL_INVALID_VALUE
);
1738 else if(!((count
=DoubleValsByProp(param
)) > 0 && count
<= 6))
1739 alSetError(Context
, AL_INVALID_ENUM
);
1745 for(i
= 0;i
< count
;i
++)
1746 fvals
[i
] = (ALfloat
)values
[i
];
1747 SetSourcefv(Source
, Context
, param
, fvals
);
1749 UnlockSourcesRead(Context
);
1750 WriteUnlock(&Context
->PropLock
);
1752 ALCcontext_DecRef(Context
);
1756 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1758 ALCcontext
*Context
;
1761 Context
= GetContextRef();
1762 if(!Context
) return;
1764 WriteLock(&Context
->PropLock
);
1765 LockSourcesRead(Context
);
1766 if((Source
=LookupSource(Context
, source
)) == NULL
)
1767 alSetError(Context
, AL_INVALID_NAME
);
1768 else if(!(IntValsByProp(param
) == 1))
1769 alSetError(Context
, AL_INVALID_ENUM
);
1771 SetSourceiv(Source
, Context
, param
, &value
);
1772 UnlockSourcesRead(Context
);
1773 WriteUnlock(&Context
->PropLock
);
1775 ALCcontext_DecRef(Context
);
1778 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1780 ALCcontext
*Context
;
1783 Context
= GetContextRef();
1784 if(!Context
) return;
1786 WriteLock(&Context
->PropLock
);
1787 LockSourcesRead(Context
);
1788 if((Source
=LookupSource(Context
, source
)) == NULL
)
1789 alSetError(Context
, AL_INVALID_NAME
);
1790 else if(!(IntValsByProp(param
) == 3))
1791 alSetError(Context
, AL_INVALID_ENUM
);
1794 ALint ivals
[3] = { value1
, value2
, value3
};
1795 SetSourceiv(Source
, Context
, param
, ivals
);
1797 UnlockSourcesRead(Context
);
1798 WriteUnlock(&Context
->PropLock
);
1800 ALCcontext_DecRef(Context
);
1803 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1805 ALCcontext
*Context
;
1808 Context
= GetContextRef();
1809 if(!Context
) return;
1811 WriteLock(&Context
->PropLock
);
1812 LockSourcesRead(Context
);
1813 if((Source
=LookupSource(Context
, source
)) == NULL
)
1814 alSetError(Context
, AL_INVALID_NAME
);
1816 alSetError(Context
, AL_INVALID_VALUE
);
1817 else if(!(IntValsByProp(param
) > 0))
1818 alSetError(Context
, AL_INVALID_ENUM
);
1820 SetSourceiv(Source
, Context
, param
, values
);
1821 UnlockSourcesRead(Context
);
1822 WriteUnlock(&Context
->PropLock
);
1824 ALCcontext_DecRef(Context
);
1828 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1830 ALCcontext
*Context
;
1833 Context
= GetContextRef();
1834 if(!Context
) return;
1836 WriteLock(&Context
->PropLock
);
1837 LockSourcesRead(Context
);
1838 if((Source
=LookupSource(Context
, source
)) == NULL
)
1839 alSetError(Context
, AL_INVALID_NAME
);
1840 else if(!(Int64ValsByProp(param
) == 1))
1841 alSetError(Context
, AL_INVALID_ENUM
);
1843 SetSourcei64v(Source
, Context
, param
, &value
);
1844 UnlockSourcesRead(Context
);
1845 WriteUnlock(&Context
->PropLock
);
1847 ALCcontext_DecRef(Context
);
1850 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1852 ALCcontext
*Context
;
1855 Context
= GetContextRef();
1856 if(!Context
) return;
1858 WriteLock(&Context
->PropLock
);
1859 LockSourcesRead(Context
);
1860 if((Source
=LookupSource(Context
, source
)) == NULL
)
1861 alSetError(Context
, AL_INVALID_NAME
);
1862 else if(!(Int64ValsByProp(param
) == 3))
1863 alSetError(Context
, AL_INVALID_ENUM
);
1866 ALint64SOFT i64vals
[3] = { value1
, value2
, value3
};
1867 SetSourcei64v(Source
, Context
, param
, i64vals
);
1869 UnlockSourcesRead(Context
);
1870 WriteUnlock(&Context
->PropLock
);
1872 ALCcontext_DecRef(Context
);
1875 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1877 ALCcontext
*Context
;
1880 Context
= GetContextRef();
1881 if(!Context
) return;
1883 WriteLock(&Context
->PropLock
);
1884 LockSourcesRead(Context
);
1885 if((Source
=LookupSource(Context
, source
)) == NULL
)
1886 alSetError(Context
, AL_INVALID_NAME
);
1888 alSetError(Context
, AL_INVALID_VALUE
);
1889 else if(!(Int64ValsByProp(param
) > 0))
1890 alSetError(Context
, AL_INVALID_ENUM
);
1892 SetSourcei64v(Source
, Context
, param
, values
);
1893 UnlockSourcesRead(Context
);
1894 WriteUnlock(&Context
->PropLock
);
1896 ALCcontext_DecRef(Context
);
1900 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1902 ALCcontext
*Context
;
1905 Context
= GetContextRef();
1906 if(!Context
) return;
1908 ReadLock(&Context
->PropLock
);
1909 LockSourcesRead(Context
);
1910 if((Source
=LookupSource(Context
, source
)) == NULL
)
1911 alSetError(Context
, AL_INVALID_NAME
);
1913 alSetError(Context
, AL_INVALID_VALUE
);
1914 else if(!(FloatValsByProp(param
) == 1))
1915 alSetError(Context
, AL_INVALID_ENUM
);
1919 if(GetSourcedv(Source
, Context
, param
, &dval
))
1920 *value
= (ALfloat
)dval
;
1922 UnlockSourcesRead(Context
);
1923 ReadUnlock(&Context
->PropLock
);
1925 ALCcontext_DecRef(Context
);
1929 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1931 ALCcontext
*Context
;
1934 Context
= GetContextRef();
1935 if(!Context
) return;
1937 ReadLock(&Context
->PropLock
);
1938 LockSourcesRead(Context
);
1939 if((Source
=LookupSource(Context
, source
)) == NULL
)
1940 alSetError(Context
, AL_INVALID_NAME
);
1941 else if(!(value1
&& value2
&& value3
))
1942 alSetError(Context
, AL_INVALID_VALUE
);
1943 else if(!(FloatValsByProp(param
) == 3))
1944 alSetError(Context
, AL_INVALID_ENUM
);
1948 if(GetSourcedv(Source
, Context
, param
, dvals
))
1950 *value1
= (ALfloat
)dvals
[0];
1951 *value2
= (ALfloat
)dvals
[1];
1952 *value3
= (ALfloat
)dvals
[2];
1955 UnlockSourcesRead(Context
);
1956 ReadUnlock(&Context
->PropLock
);
1958 ALCcontext_DecRef(Context
);
1962 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1964 ALCcontext
*Context
;
1968 Context
= GetContextRef();
1969 if(!Context
) return;
1971 ReadLock(&Context
->PropLock
);
1972 LockSourcesRead(Context
);
1973 if((Source
=LookupSource(Context
, source
)) == NULL
)
1974 alSetError(Context
, AL_INVALID_NAME
);
1976 alSetError(Context
, AL_INVALID_VALUE
);
1977 else if(!((count
=FloatValsByProp(param
)) > 0 && count
<= 6))
1978 alSetError(Context
, AL_INVALID_ENUM
);
1982 if(GetSourcedv(Source
, Context
, param
, dvals
))
1985 for(i
= 0;i
< count
;i
++)
1986 values
[i
] = (ALfloat
)dvals
[i
];
1989 UnlockSourcesRead(Context
);
1990 ReadUnlock(&Context
->PropLock
);
1992 ALCcontext_DecRef(Context
);
1996 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1998 ALCcontext
*Context
;
2001 Context
= GetContextRef();
2002 if(!Context
) return;
2004 ReadLock(&Context
->PropLock
);
2005 LockSourcesRead(Context
);
2006 if((Source
=LookupSource(Context
, source
)) == NULL
)
2007 alSetError(Context
, AL_INVALID_NAME
);
2009 alSetError(Context
, AL_INVALID_VALUE
);
2010 else if(!(DoubleValsByProp(param
) == 1))
2011 alSetError(Context
, AL_INVALID_ENUM
);
2013 GetSourcedv(Source
, Context
, param
, value
);
2014 UnlockSourcesRead(Context
);
2015 ReadUnlock(&Context
->PropLock
);
2017 ALCcontext_DecRef(Context
);
2020 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
2022 ALCcontext
*Context
;
2025 Context
= GetContextRef();
2026 if(!Context
) return;
2028 ReadLock(&Context
->PropLock
);
2029 LockSourcesRead(Context
);
2030 if((Source
=LookupSource(Context
, source
)) == NULL
)
2031 alSetError(Context
, AL_INVALID_NAME
);
2032 else if(!(value1
&& value2
&& value3
))
2033 alSetError(Context
, AL_INVALID_VALUE
);
2034 else if(!(DoubleValsByProp(param
) == 3))
2035 alSetError(Context
, AL_INVALID_ENUM
);
2039 if(GetSourcedv(Source
, Context
, param
, dvals
))
2046 UnlockSourcesRead(Context
);
2047 ReadUnlock(&Context
->PropLock
);
2049 ALCcontext_DecRef(Context
);
2052 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
2054 ALCcontext
*Context
;
2057 Context
= GetContextRef();
2058 if(!Context
) return;
2060 ReadLock(&Context
->PropLock
);
2061 LockSourcesRead(Context
);
2062 if((Source
=LookupSource(Context
, source
)) == NULL
)
2063 alSetError(Context
, AL_INVALID_NAME
);
2065 alSetError(Context
, AL_INVALID_VALUE
);
2066 else if(!(DoubleValsByProp(param
) > 0))
2067 alSetError(Context
, AL_INVALID_ENUM
);
2069 GetSourcedv(Source
, Context
, param
, values
);
2070 UnlockSourcesRead(Context
);
2071 ReadUnlock(&Context
->PropLock
);
2073 ALCcontext_DecRef(Context
);
2077 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
2079 ALCcontext
*Context
;
2082 Context
= GetContextRef();
2083 if(!Context
) return;
2085 ReadLock(&Context
->PropLock
);
2086 LockSourcesRead(Context
);
2087 if((Source
=LookupSource(Context
, source
)) == NULL
)
2088 alSetError(Context
, AL_INVALID_NAME
);
2090 alSetError(Context
, AL_INVALID_VALUE
);
2091 else if(!(IntValsByProp(param
) == 1))
2092 alSetError(Context
, AL_INVALID_ENUM
);
2094 GetSourceiv(Source
, Context
, param
, value
);
2095 UnlockSourcesRead(Context
);
2096 ReadUnlock(&Context
->PropLock
);
2098 ALCcontext_DecRef(Context
);
2102 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
2104 ALCcontext
*Context
;
2107 Context
= GetContextRef();
2108 if(!Context
) return;
2110 ReadLock(&Context
->PropLock
);
2111 LockSourcesRead(Context
);
2112 if((Source
=LookupSource(Context
, source
)) == NULL
)
2113 alSetError(Context
, AL_INVALID_NAME
);
2114 else if(!(value1
&& value2
&& value3
))
2115 alSetError(Context
, AL_INVALID_VALUE
);
2116 else if(!(IntValsByProp(param
) == 3))
2117 alSetError(Context
, AL_INVALID_ENUM
);
2121 if(GetSourceiv(Source
, Context
, param
, ivals
))
2128 UnlockSourcesRead(Context
);
2129 ReadUnlock(&Context
->PropLock
);
2131 ALCcontext_DecRef(Context
);
2135 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
2137 ALCcontext
*Context
;
2140 Context
= GetContextRef();
2141 if(!Context
) return;
2143 ReadLock(&Context
->PropLock
);
2144 LockSourcesRead(Context
);
2145 if((Source
=LookupSource(Context
, source
)) == NULL
)
2146 alSetError(Context
, AL_INVALID_NAME
);
2148 alSetError(Context
, AL_INVALID_VALUE
);
2149 else if(!(IntValsByProp(param
) > 0))
2150 alSetError(Context
, AL_INVALID_ENUM
);
2152 GetSourceiv(Source
, Context
, param
, values
);
2153 UnlockSourcesRead(Context
);
2154 ReadUnlock(&Context
->PropLock
);
2156 ALCcontext_DecRef(Context
);
2160 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
2162 ALCcontext
*Context
;
2165 Context
= GetContextRef();
2166 if(!Context
) return;
2168 ReadLock(&Context
->PropLock
);
2169 LockSourcesRead(Context
);
2170 if((Source
=LookupSource(Context
, source
)) == NULL
)
2171 alSetError(Context
, AL_INVALID_NAME
);
2173 alSetError(Context
, AL_INVALID_VALUE
);
2174 else if(!(Int64ValsByProp(param
) == 1))
2175 alSetError(Context
, AL_INVALID_ENUM
);
2177 GetSourcei64v(Source
, Context
, param
, value
);
2178 UnlockSourcesRead(Context
);
2179 ReadUnlock(&Context
->PropLock
);
2181 ALCcontext_DecRef(Context
);
2184 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
2186 ALCcontext
*Context
;
2189 Context
= GetContextRef();
2190 if(!Context
) return;
2192 ReadLock(&Context
->PropLock
);
2193 LockSourcesRead(Context
);
2194 if((Source
=LookupSource(Context
, source
)) == NULL
)
2195 alSetError(Context
, AL_INVALID_NAME
);
2196 else if(!(value1
&& value2
&& value3
))
2197 alSetError(Context
, AL_INVALID_VALUE
);
2198 else if(!(Int64ValsByProp(param
) == 3))
2199 alSetError(Context
, AL_INVALID_ENUM
);
2203 if(GetSourcei64v(Source
, Context
, param
, i64vals
))
2205 *value1
= i64vals
[0];
2206 *value2
= i64vals
[1];
2207 *value3
= i64vals
[2];
2210 UnlockSourcesRead(Context
);
2211 ReadUnlock(&Context
->PropLock
);
2213 ALCcontext_DecRef(Context
);
2216 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
2218 ALCcontext
*Context
;
2221 Context
= GetContextRef();
2222 if(!Context
) return;
2224 ReadLock(&Context
->PropLock
);
2225 LockSourcesRead(Context
);
2226 if((Source
=LookupSource(Context
, source
)) == NULL
)
2227 alSetError(Context
, AL_INVALID_NAME
);
2229 alSetError(Context
, AL_INVALID_VALUE
);
2230 else if(!(Int64ValsByProp(param
) > 0))
2231 alSetError(Context
, AL_INVALID_ENUM
);
2233 GetSourcei64v(Source
, Context
, param
, values
);
2234 UnlockSourcesRead(Context
);
2235 ReadUnlock(&Context
->PropLock
);
2237 ALCcontext_DecRef(Context
);
2241 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
2243 alSourcePlayv(1, &source
);
2245 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2247 ALCcontext
*context
;
2251 context
= GetContextRef();
2252 if(!context
) return;
2254 LockSourcesRead(context
);
2256 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2257 for(i
= 0;i
< n
;i
++)
2259 if(!LookupSource(context
, sources
[i
]))
2260 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2263 LockContext(context
);
2264 while(n
> context
->MaxVoices
-context
->VoiceCount
)
2266 ALvoice
*temp
= NULL
;
2269 newcount
= context
->MaxVoices
<< 1;
2271 temp
= realloc(context
->Voices
, newcount
* sizeof(context
->Voices
[0]));
2274 UnlockContext(context
);
2275 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
2277 memset(&temp
[context
->MaxVoices
], 0, (newcount
-context
->MaxVoices
) * sizeof(temp
[0]));
2279 context
->Voices
= temp
;
2280 context
->MaxVoices
= newcount
;
2283 for(i
= 0;i
< n
;i
++)
2285 source
= LookupSource(context
, sources
[i
]);
2286 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
2287 source
->new_state
= AL_PLAYING
;
2289 SetSourceState(source
, context
, AL_PLAYING
);
2291 UnlockContext(context
);
2294 UnlockSourcesRead(context
);
2295 ALCcontext_DecRef(context
);
2298 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2300 alSourcePausev(1, &source
);
2302 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2304 ALCcontext
*context
;
2308 context
= GetContextRef();
2309 if(!context
) return;
2311 LockSourcesRead(context
);
2313 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2314 for(i
= 0;i
< n
;i
++)
2316 if(!LookupSource(context
, sources
[i
]))
2317 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2320 LockContext(context
);
2321 for(i
= 0;i
< n
;i
++)
2323 source
= LookupSource(context
, sources
[i
]);
2324 if(ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
2325 source
->new_state
= AL_PAUSED
;
2327 SetSourceState(source
, context
, AL_PAUSED
);
2329 UnlockContext(context
);
2332 UnlockSourcesRead(context
);
2333 ALCcontext_DecRef(context
);
2336 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2338 alSourceStopv(1, &source
);
2340 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2342 ALCcontext
*context
;
2346 context
= GetContextRef();
2347 if(!context
) return;
2349 LockSourcesRead(context
);
2351 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2352 for(i
= 0;i
< n
;i
++)
2354 if(!LookupSource(context
, sources
[i
]))
2355 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2358 LockContext(context
);
2359 for(i
= 0;i
< n
;i
++)
2361 source
= LookupSource(context
, sources
[i
]);
2362 source
->new_state
= AL_NONE
;
2363 SetSourceState(source
, context
, AL_STOPPED
);
2365 UnlockContext(context
);
2368 UnlockSourcesRead(context
);
2369 ALCcontext_DecRef(context
);
2372 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2374 alSourceRewindv(1, &source
);
2376 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2378 ALCcontext
*context
;
2382 context
= GetContextRef();
2383 if(!context
) return;
2385 LockSourcesRead(context
);
2387 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2388 for(i
= 0;i
< n
;i
++)
2390 if(!LookupSource(context
, sources
[i
]))
2391 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2394 LockContext(context
);
2395 for(i
= 0;i
< n
;i
++)
2397 source
= LookupSource(context
, sources
[i
]);
2398 source
->new_state
= AL_NONE
;
2399 SetSourceState(source
, context
, AL_INITIAL
);
2401 UnlockContext(context
);
2404 UnlockSourcesRead(context
);
2405 ALCcontext_DecRef(context
);
2409 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint src
, ALsizei nb
, const ALuint
*buffers
)
2412 ALCcontext
*context
;
2415 ALbufferlistitem
*BufferListStart
;
2416 ALbufferlistitem
*BufferList
;
2417 ALbuffer
*BufferFmt
= NULL
;
2422 context
= GetContextRef();
2423 if(!context
) return;
2425 device
= context
->Device
;
2427 LockSourcesRead(context
);
2429 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2430 if((source
=LookupSource(context
, src
)) == NULL
)
2431 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2433 WriteLock(&source
->queue_lock
);
2434 if(source
->SourceType
== AL_STATIC
)
2436 WriteUnlock(&source
->queue_lock
);
2437 /* Can't queue on a Static Source */
2438 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
2441 /* Check for a valid Buffer, for its frequency and format */
2442 BufferList
= ATOMIC_LOAD(&source
->queue
);
2445 if(BufferList
->buffer
)
2447 BufferFmt
= BufferList
->buffer
;
2450 BufferList
= BufferList
->next
;
2453 LockBuffersRead(device
);
2454 BufferListStart
= NULL
;
2456 for(i
= 0;i
< nb
;i
++)
2458 ALbuffer
*buffer
= NULL
;
2459 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2461 WriteUnlock(&source
->queue_lock
);
2462 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, buffer_error
);
2465 if(!BufferListStart
)
2467 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2468 BufferList
= BufferListStart
;
2472 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2473 BufferList
= BufferList
->next
;
2475 BufferList
->buffer
= buffer
;
2476 BufferList
->next
= NULL
;
2477 if(!buffer
) continue;
2479 /* Hold a read lock on each buffer being queued while checking all
2480 * provided buffers. This is done so other threads don't see an extra
2481 * reference on some buffers if this operation ends up failing. */
2482 ReadLock(&buffer
->lock
);
2483 IncrementRef(&buffer
->ref
);
2485 if(BufferFmt
== NULL
)
2489 source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2490 source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2492 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2493 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2494 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2496 WriteUnlock(&source
->queue_lock
);
2497 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, buffer_error
);
2500 /* A buffer failed (invalid ID or format), so unlock and release
2501 * each buffer we had. */
2502 while(BufferListStart
)
2504 ALbufferlistitem
*next
= BufferListStart
->next
;
2505 if((buffer
=BufferListStart
->buffer
) != NULL
)
2507 DecrementRef(&buffer
->ref
);
2508 ReadUnlock(&buffer
->lock
);
2510 free(BufferListStart
);
2511 BufferListStart
= next
;
2513 UnlockBuffersRead(device
);
2517 /* All buffers good, unlock them now. */
2518 BufferList
= BufferListStart
;
2519 while(BufferList
!= NULL
)
2521 ALbuffer
*buffer
= BufferList
->buffer
;
2522 if(buffer
) ReadUnlock(&buffer
->lock
);
2523 BufferList
= BufferList
->next
;
2525 UnlockBuffersRead(device
);
2527 /* Source is now streaming */
2528 source
->SourceType
= AL_STREAMING
;
2531 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->queue
, &BufferList
, BufferListStart
))
2533 /* Queue head is not NULL, append to the end of the queue */
2534 while(BufferList
->next
!= NULL
)
2535 BufferList
= BufferList
->next
;
2536 BufferList
->next
= BufferListStart
;
2538 /* If the current buffer was at the end (NULL), put it at the start of the newly queued
2542 ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->current_buffer
, &BufferList
, BufferListStart
);
2543 WriteUnlock(&source
->queue_lock
);
2546 UnlockSourcesRead(context
);
2547 ALCcontext_DecRef(context
);
2550 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint src
, ALsizei nb
, ALuint
*buffers
)
2552 ALCcontext
*context
;
2554 ALbufferlistitem
*OldHead
;
2555 ALbufferlistitem
*OldTail
;
2556 ALbufferlistitem
*Current
;
2562 context
= GetContextRef();
2563 if(!context
) return;
2565 LockSourcesRead(context
);
2567 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2569 if((source
=LookupSource(context
, src
)) == NULL
)
2570 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2572 WriteLock(&source
->queue_lock
);
2573 /* Find the new buffer queue head */
2574 OldTail
= ATOMIC_LOAD(&source
->queue
);
2575 Current
= ATOMIC_LOAD(&source
->current_buffer
);
2576 if(OldTail
!= Current
)
2578 for(i
= 1;i
< nb
;i
++)
2580 ALbufferlistitem
*next
= OldTail
->next
;
2581 if(!next
|| next
== Current
) break;
2585 if(source
->Looping
|| source
->SourceType
!= AL_STREAMING
|| i
!= nb
)
2587 WriteUnlock(&source
->queue_lock
);
2588 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2589 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2592 /* Swap it, and cut the new head from the old. */
2593 OldHead
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &source
->queue
, OldTail
->next
);
2596 ALCdevice
*device
= context
->Device
;
2599 /* Once the active mix (if any) is done, it's safe to cut the old tail
2600 * from the new head.
2602 if(((count
=ReadRef(&device
->MixCount
))&1) != 0)
2604 while(count
== ReadRef(&device
->MixCount
))
2607 OldTail
->next
= NULL
;
2609 WriteUnlock(&source
->queue_lock
);
2611 while(OldHead
!= NULL
)
2613 ALbufferlistitem
*next
= OldHead
->next
;
2614 ALbuffer
*buffer
= OldHead
->buffer
;
2620 *(buffers
++) = buffer
->id
;
2621 DecrementRef(&buffer
->ref
);
2629 UnlockSourcesRead(context
);
2630 ALCcontext_DecRef(context
);
2634 static ALvoid
InitSourceParams(ALsource
*Source
)
2638 RWLockInit(&Source
->queue_lock
);
2640 Source
->InnerAngle
= 360.0f
;
2641 Source
->OuterAngle
= 360.0f
;
2642 Source
->Pitch
= 1.0f
;
2643 Source
->Position
[0] = 0.0f
;
2644 Source
->Position
[1] = 0.0f
;
2645 Source
->Position
[2] = 0.0f
;
2646 Source
->Velocity
[0] = 0.0f
;
2647 Source
->Velocity
[1] = 0.0f
;
2648 Source
->Velocity
[2] = 0.0f
;
2649 Source
->Direction
[0] = 0.0f
;
2650 Source
->Direction
[1] = 0.0f
;
2651 Source
->Direction
[2] = 0.0f
;
2652 Source
->Orientation
[0][0] = 0.0f
;
2653 Source
->Orientation
[0][1] = 0.0f
;
2654 Source
->Orientation
[0][2] = -1.0f
;
2655 Source
->Orientation
[1][0] = 0.0f
;
2656 Source
->Orientation
[1][1] = 1.0f
;
2657 Source
->Orientation
[1][2] = 0.0f
;
2658 Source
->RefDistance
= 1.0f
;
2659 Source
->MaxDistance
= FLT_MAX
;
2660 Source
->RollOffFactor
= 1.0f
;
2661 Source
->Looping
= AL_FALSE
;
2662 Source
->Gain
= 1.0f
;
2663 Source
->MinGain
= 0.0f
;
2664 Source
->MaxGain
= 1.0f
;
2665 Source
->OuterGain
= 0.0f
;
2666 Source
->OuterGainHF
= 1.0f
;
2668 Source
->DryGainHFAuto
= AL_TRUE
;
2669 Source
->WetGainAuto
= AL_TRUE
;
2670 Source
->WetGainHFAuto
= AL_TRUE
;
2671 Source
->AirAbsorptionFactor
= 0.0f
;
2672 Source
->RoomRolloffFactor
= 0.0f
;
2673 Source
->DopplerFactor
= 1.0f
;
2674 Source
->DirectChannels
= AL_FALSE
;
2676 Source
->StereoPan
[0] = DEG2RAD( 30.0f
);
2677 Source
->StereoPan
[1] = DEG2RAD(-30.0f
);
2679 Source
->Radius
= 0.0f
;
2681 Source
->DistanceModel
= DefaultDistanceModel
;
2683 Source
->Direct
.Gain
= 1.0f
;
2684 Source
->Direct
.GainHF
= 1.0f
;
2685 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
2686 Source
->Direct
.GainLF
= 1.0f
;
2687 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
2688 for(i
= 0;i
< MAX_SENDS
;i
++)
2690 Source
->Send
[i
].Gain
= 1.0f
;
2691 Source
->Send
[i
].GainHF
= 1.0f
;
2692 Source
->Send
[i
].HFReference
= LOWPASSFREQREF
;
2693 Source
->Send
[i
].GainLF
= 1.0f
;
2694 Source
->Send
[i
].LFReference
= HIGHPASSFREQREF
;
2697 Source
->state
= AL_INITIAL
;
2698 Source
->new_state
= AL_NONE
;
2699 Source
->SourceType
= AL_UNDETERMINED
;
2700 Source
->OffsetType
= AL_NONE
;
2701 Source
->Offset
= 0.0;
2703 ATOMIC_INIT(&Source
->queue
, NULL
);
2704 ATOMIC_INIT(&Source
->current_buffer
, NULL
);
2706 ATOMIC_INIT(&Source
->Update
, NULL
);
2707 ATOMIC_INIT(&Source
->FreeList
, NULL
);
2710 static ALvoid
DeinitSource(ALsource
*source
)
2712 ALbufferlistitem
*BufferList
;
2713 struct ALsourceProps
*props
;
2717 props
= ATOMIC_LOAD(&source
->Update
);
2718 if(props
) al_free(props
);
2720 props
= ATOMIC_LOAD(&source
->FreeList
, almemory_order_relaxed
);
2723 struct ALsourceProps
*next
;
2724 next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
2729 /* This is excessively spammy if it traces every source destruction, so
2730 * just warn if it was unexpectedly large.
2733 WARN("Freed "SZFMT
" Source property objects\n", count
);
2735 BufferList
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &source
->queue
, NULL
);
2736 while(BufferList
!= NULL
)
2738 ALbufferlistitem
*next
= BufferList
->next
;
2739 if(BufferList
->buffer
!= NULL
)
2740 DecrementRef(&BufferList
->buffer
->ref
);
2745 for(i
= 0;i
< MAX_SENDS
;++i
)
2747 if(source
->Send
[i
].Slot
)
2748 DecrementRef(&source
->Send
[i
].Slot
->ref
);
2749 source
->Send
[i
].Slot
= NULL
;
2753 void UpdateSourceProps(ALsource
*source
, ALuint num_sends
)
2755 struct ALsourceProps
*props
;
2758 /* Get an unused property container, or allocate a new one as needed. */
2759 props
= ATOMIC_LOAD(&source
->FreeList
, almemory_order_acquire
);
2761 props
= al_calloc(16, sizeof(*props
));
2764 struct ALsourceProps
*next
;
2766 next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
2767 } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALsourceProps
*,
2768 &source
->FreeList
, &props
, next
, almemory_order_seq_cst
,
2769 almemory_order_consume
) == 0);
2772 /* Copy in current property values. */
2773 ATOMIC_STORE(&props
->Pitch
, source
->Pitch
, almemory_order_relaxed
);
2774 ATOMIC_STORE(&props
->Gain
, source
->Gain
, almemory_order_relaxed
);
2775 ATOMIC_STORE(&props
->OuterGain
, source
->OuterGain
, almemory_order_relaxed
);
2776 ATOMIC_STORE(&props
->MinGain
, source
->MinGain
, almemory_order_relaxed
);
2777 ATOMIC_STORE(&props
->MaxGain
, source
->MaxGain
, almemory_order_relaxed
);
2778 ATOMIC_STORE(&props
->InnerAngle
, source
->InnerAngle
, almemory_order_relaxed
);
2779 ATOMIC_STORE(&props
->OuterAngle
, source
->OuterAngle
, almemory_order_relaxed
);
2780 ATOMIC_STORE(&props
->RefDistance
, source
->RefDistance
, almemory_order_relaxed
);
2781 ATOMIC_STORE(&props
->MaxDistance
, source
->MaxDistance
, almemory_order_relaxed
);
2782 ATOMIC_STORE(&props
->RollOffFactor
, source
->RollOffFactor
, almemory_order_relaxed
);
2783 for(i
= 0;i
< 3;i
++)
2784 ATOMIC_STORE(&props
->Position
[i
], source
->Position
[i
], almemory_order_relaxed
);
2785 for(i
= 0;i
< 3;i
++)
2786 ATOMIC_STORE(&props
->Velocity
[i
], source
->Velocity
[i
], almemory_order_relaxed
);
2787 for(i
= 0;i
< 3;i
++)
2788 ATOMIC_STORE(&props
->Direction
[i
], source
->Direction
[i
], almemory_order_relaxed
);
2789 for(i
= 0;i
< 2;i
++)
2792 for(j
= 0;j
< 3;j
++)
2793 ATOMIC_STORE(&props
->Orientation
[i
][j
], source
->Orientation
[i
][j
],
2794 almemory_order_relaxed
);
2796 ATOMIC_STORE(&props
->HeadRelative
, source
->HeadRelative
, almemory_order_relaxed
);
2797 ATOMIC_STORE(&props
->Looping
, source
->Looping
, almemory_order_relaxed
);
2798 ATOMIC_STORE(&props
->DistanceModel
, source
->DistanceModel
, almemory_order_relaxed
);
2799 ATOMIC_STORE(&props
->DirectChannels
, source
->DirectChannels
, almemory_order_relaxed
);
2801 ATOMIC_STORE(&props
->DryGainHFAuto
, source
->DryGainHFAuto
, almemory_order_relaxed
);
2802 ATOMIC_STORE(&props
->WetGainAuto
, source
->WetGainAuto
, almemory_order_relaxed
);
2803 ATOMIC_STORE(&props
->WetGainHFAuto
, source
->WetGainHFAuto
, almemory_order_relaxed
);
2804 ATOMIC_STORE(&props
->OuterGainHF
, source
->OuterGainHF
, almemory_order_relaxed
);
2806 ATOMIC_STORE(&props
->AirAbsorptionFactor
, source
->AirAbsorptionFactor
, almemory_order_relaxed
);
2807 ATOMIC_STORE(&props
->RoomRolloffFactor
, source
->RoomRolloffFactor
, almemory_order_relaxed
);
2808 ATOMIC_STORE(&props
->DopplerFactor
, source
->DopplerFactor
, almemory_order_relaxed
);
2810 ATOMIC_STORE(&props
->StereoPan
[0], source
->StereoPan
[0], almemory_order_relaxed
);
2811 ATOMIC_STORE(&props
->StereoPan
[1], source
->StereoPan
[1], almemory_order_relaxed
);
2813 ATOMIC_STORE(&props
->Radius
, source
->Radius
, almemory_order_relaxed
);
2815 ATOMIC_STORE(&props
->Direct
.Gain
, source
->Direct
.Gain
, almemory_order_relaxed
);
2816 ATOMIC_STORE(&props
->Direct
.GainHF
, source
->Direct
.GainHF
, almemory_order_relaxed
);
2817 ATOMIC_STORE(&props
->Direct
.HFReference
, source
->Direct
.HFReference
, almemory_order_relaxed
);
2818 ATOMIC_STORE(&props
->Direct
.GainLF
, source
->Direct
.GainLF
, almemory_order_relaxed
);
2819 ATOMIC_STORE(&props
->Direct
.LFReference
, source
->Direct
.LFReference
, almemory_order_relaxed
);
2821 for(i
= 0;i
< num_sends
;i
++)
2823 ATOMIC_STORE(&props
->Send
[i
].Slot
, source
->Send
[i
].Slot
, almemory_order_relaxed
);
2824 ATOMIC_STORE(&props
->Send
[i
].Gain
, source
->Send
[i
].Gain
, almemory_order_relaxed
);
2825 ATOMIC_STORE(&props
->Send
[i
].GainHF
, source
->Send
[i
].GainHF
, almemory_order_relaxed
);
2826 ATOMIC_STORE(&props
->Send
[i
].HFReference
, source
->Send
[i
].HFReference
,
2827 almemory_order_relaxed
);
2828 ATOMIC_STORE(&props
->Send
[i
].GainLF
, source
->Send
[i
].GainLF
, almemory_order_relaxed
);
2829 ATOMIC_STORE(&props
->Send
[i
].LFReference
, source
->Send
[i
].LFReference
,
2830 almemory_order_relaxed
);
2833 /* Set the new container for updating internal parameters. */
2834 props
= ATOMIC_EXCHANGE(struct ALsourceProps
*, &source
->Update
, props
, almemory_order_acq_rel
);
2837 /* If there was an unused update container, put it back in the
2840 struct ALsourceProps
*first
= ATOMIC_LOAD(&source
->FreeList
);
2842 ATOMIC_STORE(&props
->next
, first
, almemory_order_relaxed
);
2843 } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALsourceProps
*,
2844 &source
->FreeList
, &first
, props
) == 0);
2848 void UpdateAllSourceProps(ALCcontext
*context
)
2850 ALuint num_sends
= context
->Device
->NumAuxSends
;
2854 /* Tell the mixer to stop applying updates, then wait for any active
2855 * updating to finish, before providing source updates.
2857 ATOMIC_STORE(&context
->HoldUpdates
, AL_TRUE
);
2858 while(((updates
=ReadRef(&context
->UpdateCount
))&1) != 0)
2860 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2862 ALvoice
*voice
= &context
->Voices
[pos
];
2863 ALsource
*source
= voice
->Source
;
2864 if(source
!= NULL
&& (source
->state
== AL_PLAYING
||
2865 source
->state
== AL_PAUSED
))
2866 UpdateSourceProps(source
, num_sends
);
2868 /* Now with all updates declared, let the mixer continue applying them so
2869 * they all happen at once.
2871 ATOMIC_STORE(&context
->HoldUpdates
, AL_FALSE
);
2877 * Sets the source's new play state given its current state.
2879 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2881 WriteLock(&Source
->queue_lock
);
2882 if(state
== AL_PLAYING
)
2884 ALCdevice
*device
= Context
->Device
;
2885 ALbufferlistitem
*BufferList
;
2886 ALboolean discontinuity
;
2887 ALvoice
*voice
= NULL
;
2890 /* Check that there is a queue containing at least one valid, non zero
2892 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2896 if((buffer
=BufferList
->buffer
) != NULL
&& buffer
->SampleLen
> 0)
2898 BufferList
= BufferList
->next
;
2901 if(Source
->state
!= AL_PAUSED
)
2903 Source
->state
= AL_PLAYING
;
2904 Source
->position
= 0;
2905 Source
->position_fraction
= 0;
2906 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
2907 discontinuity
= AL_TRUE
;
2911 Source
->state
= AL_PLAYING
;
2912 discontinuity
= AL_FALSE
;
2915 // Check if an Offset has been set
2916 if(Source
->OffsetType
!= AL_NONE
)
2918 ApplyOffset(Source
);
2919 /* discontinuity = AL_TRUE;??? */
2922 /* If there's nothing to play, or device is disconnected, go right to
2924 if(!BufferList
|| !device
->Connected
)
2927 /* Make sure this source isn't already active, while looking for an
2928 * unused active source slot to put it in. */
2929 for(i
= 0;i
< Context
->VoiceCount
;i
++)
2931 ALsource
*old
= Source
;
2932 if(COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, NULL
))
2936 voice
= &Context
->Voices
[i
];
2937 voice
->Source
= Source
;
2942 if(voice
== NULL
&& COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, Source
))
2943 voice
= &Context
->Voices
[i
];
2947 voice
= &Context
->Voices
[Context
->VoiceCount
++];
2948 voice
->Source
= Source
;
2951 /* Clear previous samples if playback is discontinuous. */
2953 memset(voice
->PrevSamples
, 0, sizeof(voice
->PrevSamples
));
2955 voice
->Moving
= AL_FALSE
;
2956 for(i
= 0;i
< MAX_INPUT_CHANNELS
;i
++)
2959 for(j
= 0;j
< HRTF_HISTORY_LENGTH
;j
++)
2960 voice
->Direct
.Hrtf
[i
].State
.History
[j
] = 0.0f
;
2961 for(j
= 0;j
< HRIR_LENGTH
;j
++)
2963 voice
->Direct
.Hrtf
[i
].State
.Values
[j
][0] = 0.0f
;
2964 voice
->Direct
.Hrtf
[i
].State
.Values
[j
][1] = 0.0f
;
2968 UpdateSourceProps(Source
, device
->NumAuxSends
);
2970 else if(state
== AL_PAUSED
)
2972 if(Source
->state
== AL_PLAYING
)
2973 Source
->state
= AL_PAUSED
;
2975 else if(state
== AL_STOPPED
)
2978 if(Source
->state
!= AL_INITIAL
)
2980 Source
->state
= AL_STOPPED
;
2981 ATOMIC_STORE(&Source
->current_buffer
, NULL
);
2983 Source
->OffsetType
= AL_NONE
;
2984 Source
->Offset
= 0.0;
2986 else if(state
== AL_INITIAL
)
2988 if(Source
->state
!= AL_INITIAL
)
2990 Source
->state
= AL_INITIAL
;
2991 Source
->position
= 0;
2992 Source
->position_fraction
= 0;
2993 ATOMIC_STORE(&Source
->current_buffer
, ATOMIC_LOAD(&Source
->queue
));
2995 Source
->OffsetType
= AL_NONE
;
2996 Source
->Offset
= 0.0;
2998 WriteUnlock(&Source
->queue_lock
);
3001 /* GetSourceSampleOffset
3003 * Gets the current read offset for the given Source, in 32.32 fixed-point
3004 * samples. The offset is relative to the start of the queue (not the start of
3005 * the current buffer).
3007 ALint64
GetSourceSampleOffset(ALsource
*Source
)
3009 const ALbufferlistitem
*BufferList
;
3010 const ALbufferlistitem
*Current
;
3013 ReadLock(&Source
->queue_lock
);
3014 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
3016 ReadUnlock(&Source
->queue_lock
);
3020 /* NOTE: This is the offset into the *current* buffer, so add the length of
3021 * any played buffers */
3022 readPos
= (ALuint64
)Source
->position
<< 32;
3023 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
3024 BufferList
= ATOMIC_LOAD(&Source
->queue
);
3025 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
3026 while(BufferList
&& BufferList
!= Current
)
3028 if(BufferList
->buffer
)
3029 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
3030 BufferList
= BufferList
->next
;
3033 ReadUnlock(&Source
->queue_lock
);
3034 return (ALint64
)minu64(readPos
, U64(0x7fffffffffffffff));
3037 /* GetSourceSecOffset
3039 * Gets the current read offset for the given Source, in seconds. The offset is
3040 * relative to the start of the queue (not the start of the current buffer).
3042 static ALdouble
GetSourceSecOffset(ALsource
*Source
)
3044 const ALbufferlistitem
*BufferList
;
3045 const ALbufferlistitem
*Current
;
3046 const ALbuffer
*Buffer
= NULL
;
3049 ReadLock(&Source
->queue_lock
);
3050 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
3052 ReadUnlock(&Source
->queue_lock
);
3056 /* NOTE: This is the offset into the *current* buffer, so add the length of
3057 * any played buffers */
3058 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
3059 readPos
|= (ALuint64
)Source
->position_fraction
;
3060 BufferList
= ATOMIC_LOAD(&Source
->queue
);
3061 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
3062 while(BufferList
&& BufferList
!= Current
)
3064 const ALbuffer
*buffer
= BufferList
->buffer
;
3067 if(!Buffer
) Buffer
= buffer
;
3068 readPos
+= (ALuint64
)buffer
->SampleLen
<< FRACTIONBITS
;
3070 BufferList
= BufferList
->next
;
3073 while(BufferList
&& !Buffer
)
3075 Buffer
= BufferList
->buffer
;
3076 BufferList
= BufferList
->next
;
3078 assert(Buffer
!= NULL
);
3080 ReadUnlock(&Source
->queue_lock
);
3081 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
3086 * Gets the current read offset for the given Source, in the appropriate format
3087 * (Bytes, Samples or Seconds). The offset is relative to the start of the
3088 * queue (not the start of the current buffer).
3090 static ALdouble
GetSourceOffset(ALsource
*Source
, ALenum name
)
3092 const ALbufferlistitem
*BufferList
;
3093 const ALbufferlistitem
*Current
;
3094 const ALbuffer
*Buffer
= NULL
;
3095 ALboolean readFin
= AL_FALSE
;
3096 ALuint readPos
, readPosFrac
;
3097 ALuint totalBufferLen
;
3098 ALdouble offset
= 0.0;
3100 ReadLock(&Source
->queue_lock
);
3101 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
3103 ReadUnlock(&Source
->queue_lock
);
3107 /* NOTE: This is the offset into the *current* buffer, so add the length of
3108 * any played buffers */
3110 readPos
= Source
->position
;
3111 readPosFrac
= Source
->position_fraction
;
3112 BufferList
= ATOMIC_LOAD(&Source
->queue
);
3113 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
3114 while(BufferList
!= NULL
)
3116 const ALbuffer
*buffer
;
3117 readFin
= readFin
|| (BufferList
== Current
);
3118 if((buffer
=BufferList
->buffer
) != NULL
)
3120 if(!Buffer
) Buffer
= buffer
;
3121 totalBufferLen
+= buffer
->SampleLen
;
3122 if(!readFin
) readPos
+= buffer
->SampleLen
;
3124 BufferList
= BufferList
->next
;
3126 assert(Buffer
!= NULL
);
3129 readPos
%= totalBufferLen
;
3132 /* Wrap back to 0 */
3133 if(readPos
>= totalBufferLen
)
3134 readPos
= readPosFrac
= 0;
3140 offset
= (readPos
+ (ALdouble
)readPosFrac
/FRACTIONONE
)/Buffer
->Frequency
;
3143 case AL_SAMPLE_OFFSET
:
3144 offset
= readPos
+ (ALdouble
)readPosFrac
/FRACTIONONE
;
3147 case AL_BYTE_OFFSET
:
3148 if(Buffer
->OriginalType
== UserFmtIMA4
)
3150 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
3151 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
3152 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
3154 /* Round down to nearest ADPCM block */
3155 offset
= (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
3157 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
3159 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
3160 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
3161 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
3163 /* Round down to nearest ADPCM block */
3164 offset
= (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
3168 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
3169 offset
= (ALdouble
)(readPos
* FrameSize
);
3174 ReadUnlock(&Source
->queue_lock
);
3181 * Apply the stored playback offset to the Source. This function will update
3182 * the number of buffers "played" given the stored offset.
3184 ALboolean
ApplyOffset(ALsource
*Source
)
3186 ALbufferlistitem
*BufferList
;
3187 const ALbuffer
*Buffer
;
3188 ALuint bufferLen
, totalBufferLen
;
3189 ALuint offset
=0, frac
=0;
3191 /* Get sample frame offset */
3192 if(!GetSampleOffset(Source
, &offset
, &frac
))
3196 BufferList
= ATOMIC_LOAD(&Source
->queue
);
3197 while(BufferList
&& totalBufferLen
<= offset
)
3199 Buffer
= BufferList
->buffer
;
3200 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
3202 if(bufferLen
> offset
-totalBufferLen
)
3204 /* Offset is in this buffer */
3205 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
3207 Source
->position
= offset
- totalBufferLen
;
3208 Source
->position_fraction
= frac
;
3212 totalBufferLen
+= bufferLen
;
3214 BufferList
= BufferList
->next
;
3217 /* Offset is out of range of the queue */
3224 * Retrieves the sample offset into the Source's queue (from the Sample, Byte
3225 * or Second offset supplied by the application). This takes into account the
3226 * fact that the buffer format may have been modifed since.
3228 static ALboolean
GetSampleOffset(ALsource
*Source
, ALuint
*offset
, ALuint
*frac
)
3230 const ALbuffer
*Buffer
= NULL
;
3231 const ALbufferlistitem
*BufferList
;
3232 ALdouble dbloff
, dblfrac
;
3234 /* Find the first valid Buffer in the Queue */
3235 BufferList
= ATOMIC_LOAD(&Source
->queue
);
3238 if(BufferList
->buffer
)
3240 Buffer
= BufferList
->buffer
;
3243 BufferList
= BufferList
->next
;
3247 Source
->OffsetType
= AL_NONE
;
3248 Source
->Offset
= 0.0;
3252 switch(Source
->OffsetType
)
3254 case AL_BYTE_OFFSET
:
3255 /* Determine the ByteOffset (and ensure it is block aligned) */
3256 *offset
= (ALuint
)Source
->Offset
;
3257 if(Buffer
->OriginalType
== UserFmtIMA4
)
3259 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
3260 *offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
3261 *offset
*= Buffer
->OriginalAlign
;
3263 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
3265 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
3266 *offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
3267 *offset
*= Buffer
->OriginalAlign
;
3270 *offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
3274 case AL_SAMPLE_OFFSET
:
3275 dblfrac
= modf(Source
->Offset
, &dbloff
);
3276 *offset
= (ALuint
)mind(dbloff
, UINT_MAX
);
3277 *frac
= (ALuint
)mind(dblfrac
*FRACTIONONE
, FRACTIONONE
-1.0);
3281 dblfrac
= modf(Source
->Offset
*Buffer
->Frequency
, &dbloff
);
3282 *offset
= (ALuint
)mind(dbloff
, UINT_MAX
);
3283 *frac
= (ALuint
)mind(dblfrac
*FRACTIONONE
, FRACTIONONE
-1.0);
3286 Source
->OffsetType
= AL_NONE
;
3287 Source
->Offset
= 0.0;
3295 * Destroys all sources in the source map.
3297 ALvoid
ReleaseALSources(ALCcontext
*Context
)
3300 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
3302 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
3303 Context
->SourceMap
.array
[pos
].value
= NULL
;
3307 FreeThunkEntry(temp
->id
);
3308 memset(temp
, 0, sizeof(*temp
));