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 struct ALsource
*LookupSource(ALCcontext
*context
, ALuint id
);
44 extern inline struct ALsource
*RemoveSource(ALCcontext
*context
, ALuint id
);
46 static ALvoid
InitSourceParams(ALsource
*Source
);
47 static ALint64
GetSourceSampleOffset(ALsource
*Source
);
48 static ALdouble
GetSourceSecOffset(ALsource
*Source
);
49 static ALdouble
GetSourceOffset(ALsource
*Source
, ALenum name
);
50 static ALboolean
GetSampleOffset(ALsource
*Source
, ALuint
*offset
, ALuint
*frac
);
52 typedef enum SourceProp
{
55 srcMinGain
= AL_MIN_GAIN
,
56 srcMaxGain
= AL_MAX_GAIN
,
57 srcMaxDistance
= AL_MAX_DISTANCE
,
58 srcRolloffFactor
= AL_ROLLOFF_FACTOR
,
59 srcDopplerFactor
= AL_DOPPLER_FACTOR
,
60 srcConeOuterGain
= AL_CONE_OUTER_GAIN
,
61 srcSecOffset
= AL_SEC_OFFSET
,
62 srcSampleOffset
= AL_SAMPLE_OFFSET
,
63 srcByteOffset
= AL_BYTE_OFFSET
,
64 srcConeInnerAngle
= AL_CONE_INNER_ANGLE
,
65 srcConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
66 srcRefDistance
= AL_REFERENCE_DISTANCE
,
68 srcPosition
= AL_POSITION
,
69 srcVelocity
= AL_VELOCITY
,
70 srcDirection
= AL_DIRECTION
,
72 srcSourceRelative
= AL_SOURCE_RELATIVE
,
73 srcLooping
= AL_LOOPING
,
74 srcBuffer
= AL_BUFFER
,
75 srcSourceState
= AL_SOURCE_STATE
,
76 srcBuffersQueued
= AL_BUFFERS_QUEUED
,
77 srcBuffersProcessed
= AL_BUFFERS_PROCESSED
,
78 srcSourceType
= AL_SOURCE_TYPE
,
81 srcConeOuterGainHF
= AL_CONE_OUTER_GAINHF
,
82 srcAirAbsorptionFactor
= AL_AIR_ABSORPTION_FACTOR
,
83 srcRoomRolloffFactor
= AL_ROOM_ROLLOFF_FACTOR
,
84 srcDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
85 srcAuxSendFilterGainAuto
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
86 srcAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
87 srcDirectFilter
= AL_DIRECT_FILTER
,
88 srcAuxSendFilter
= AL_AUXILIARY_SEND_FILTER
,
90 /* AL_SOFT_direct_channels */
91 srcDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
93 /* AL_EXT_source_distance_model */
94 srcDistanceModel
= AL_DISTANCE_MODEL
,
96 srcByteLengthSOFT
= AL_BYTE_LENGTH_SOFT
,
97 srcSampleLengthSOFT
= AL_SAMPLE_LENGTH_SOFT
,
98 srcSecLengthSOFT
= AL_SEC_LENGTH_SOFT
,
100 /* AL_SOFT_source_latency */
101 srcSampleOffsetLatencySOFT
= AL_SAMPLE_OFFSET_LATENCY_SOFT
,
102 srcSecOffsetLatencySOFT
= AL_SEC_OFFSET_LATENCY_SOFT
,
104 /* AL_EXT_STEREO_ANGLES */
105 srcAngles
= AL_STEREO_ANGLES
,
107 /* AL_EXT_SOURCE_RADIUS */
108 srcRadius
= AL_SOURCE_RADIUS
,
111 srcOrientation
= AL_ORIENTATION
,
114 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALfloat
*values
);
115 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint
*values
);
116 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint64SOFT
*values
);
118 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALdouble
*values
);
119 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint
*values
);
120 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint64
*values
);
122 static ALint
FloatValsByProp(ALenum prop
)
124 if(prop
!= (ALenum
)((SourceProp
)prop
))
126 switch((SourceProp
)prop
)
132 case AL_MAX_DISTANCE
:
133 case AL_ROLLOFF_FACTOR
:
134 case AL_DOPPLER_FACTOR
:
135 case AL_CONE_OUTER_GAIN
:
137 case AL_SAMPLE_OFFSET
:
139 case AL_CONE_INNER_ANGLE
:
140 case AL_CONE_OUTER_ANGLE
:
141 case AL_REFERENCE_DISTANCE
:
142 case AL_CONE_OUTER_GAINHF
:
143 case AL_AIR_ABSORPTION_FACTOR
:
144 case AL_ROOM_ROLLOFF_FACTOR
:
145 case AL_DIRECT_FILTER_GAINHF_AUTO
:
146 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
147 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
148 case AL_DIRECT_CHANNELS_SOFT
:
149 case AL_DISTANCE_MODEL
:
150 case AL_SOURCE_RELATIVE
:
152 case AL_SOURCE_STATE
:
153 case AL_BUFFERS_QUEUED
:
154 case AL_BUFFERS_PROCESSED
:
156 case AL_BYTE_LENGTH_SOFT
:
157 case AL_SAMPLE_LENGTH_SOFT
:
158 case AL_SEC_LENGTH_SOFT
:
159 case AL_SOURCE_RADIUS
:
162 case AL_STEREO_ANGLES
:
173 case AL_SEC_OFFSET_LATENCY_SOFT
:
174 break; /* Double only */
177 case AL_DIRECT_FILTER
:
178 case AL_AUXILIARY_SEND_FILTER
:
179 break; /* i/i64 only */
180 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
181 break; /* i64 only */
185 static ALint
DoubleValsByProp(ALenum prop
)
187 if(prop
!= (ALenum
)((SourceProp
)prop
))
189 switch((SourceProp
)prop
)
195 case AL_MAX_DISTANCE
:
196 case AL_ROLLOFF_FACTOR
:
197 case AL_DOPPLER_FACTOR
:
198 case AL_CONE_OUTER_GAIN
:
200 case AL_SAMPLE_OFFSET
:
202 case AL_CONE_INNER_ANGLE
:
203 case AL_CONE_OUTER_ANGLE
:
204 case AL_REFERENCE_DISTANCE
:
205 case AL_CONE_OUTER_GAINHF
:
206 case AL_AIR_ABSORPTION_FACTOR
:
207 case AL_ROOM_ROLLOFF_FACTOR
:
208 case AL_DIRECT_FILTER_GAINHF_AUTO
:
209 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
210 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
211 case AL_DIRECT_CHANNELS_SOFT
:
212 case AL_DISTANCE_MODEL
:
213 case AL_SOURCE_RELATIVE
:
215 case AL_SOURCE_STATE
:
216 case AL_BUFFERS_QUEUED
:
217 case AL_BUFFERS_PROCESSED
:
219 case AL_BYTE_LENGTH_SOFT
:
220 case AL_SAMPLE_LENGTH_SOFT
:
221 case AL_SEC_LENGTH_SOFT
:
222 case AL_SOURCE_RADIUS
:
225 case AL_SEC_OFFSET_LATENCY_SOFT
:
226 case AL_STEREO_ANGLES
:
238 case AL_DIRECT_FILTER
:
239 case AL_AUXILIARY_SEND_FILTER
:
240 break; /* i/i64 only */
241 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
242 break; /* i64 only */
247 static ALint
IntValsByProp(ALenum prop
)
249 if(prop
!= (ALenum
)((SourceProp
)prop
))
251 switch((SourceProp
)prop
)
257 case AL_MAX_DISTANCE
:
258 case AL_ROLLOFF_FACTOR
:
259 case AL_DOPPLER_FACTOR
:
260 case AL_CONE_OUTER_GAIN
:
262 case AL_SAMPLE_OFFSET
:
264 case AL_CONE_INNER_ANGLE
:
265 case AL_CONE_OUTER_ANGLE
:
266 case AL_REFERENCE_DISTANCE
:
267 case AL_CONE_OUTER_GAINHF
:
268 case AL_AIR_ABSORPTION_FACTOR
:
269 case AL_ROOM_ROLLOFF_FACTOR
:
270 case AL_DIRECT_FILTER_GAINHF_AUTO
:
271 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
272 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
273 case AL_DIRECT_CHANNELS_SOFT
:
274 case AL_DISTANCE_MODEL
:
275 case AL_SOURCE_RELATIVE
:
278 case AL_SOURCE_STATE
:
279 case AL_BUFFERS_QUEUED
:
280 case AL_BUFFERS_PROCESSED
:
282 case AL_DIRECT_FILTER
:
283 case AL_BYTE_LENGTH_SOFT
:
284 case AL_SAMPLE_LENGTH_SOFT
:
285 case AL_SEC_LENGTH_SOFT
:
286 case AL_SOURCE_RADIUS
:
292 case AL_AUXILIARY_SEND_FILTER
:
298 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
299 break; /* i64 only */
300 case AL_SEC_OFFSET_LATENCY_SOFT
:
301 break; /* Double only */
302 case AL_STEREO_ANGLES
:
303 break; /* Float/double only */
307 static ALint
Int64ValsByProp(ALenum prop
)
309 if(prop
!= (ALenum
)((SourceProp
)prop
))
311 switch((SourceProp
)prop
)
317 case AL_MAX_DISTANCE
:
318 case AL_ROLLOFF_FACTOR
:
319 case AL_DOPPLER_FACTOR
:
320 case AL_CONE_OUTER_GAIN
:
322 case AL_SAMPLE_OFFSET
:
324 case AL_CONE_INNER_ANGLE
:
325 case AL_CONE_OUTER_ANGLE
:
326 case AL_REFERENCE_DISTANCE
:
327 case AL_CONE_OUTER_GAINHF
:
328 case AL_AIR_ABSORPTION_FACTOR
:
329 case AL_ROOM_ROLLOFF_FACTOR
:
330 case AL_DIRECT_FILTER_GAINHF_AUTO
:
331 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
332 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
333 case AL_DIRECT_CHANNELS_SOFT
:
334 case AL_DISTANCE_MODEL
:
335 case AL_SOURCE_RELATIVE
:
338 case AL_SOURCE_STATE
:
339 case AL_BUFFERS_QUEUED
:
340 case AL_BUFFERS_PROCESSED
:
342 case AL_DIRECT_FILTER
:
343 case AL_BYTE_LENGTH_SOFT
:
344 case AL_SAMPLE_LENGTH_SOFT
:
345 case AL_SEC_LENGTH_SOFT
:
346 case AL_SOURCE_RADIUS
:
349 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
355 case AL_AUXILIARY_SEND_FILTER
:
361 case AL_SEC_OFFSET_LATENCY_SOFT
:
362 break; /* Double only */
363 case AL_STEREO_ANGLES
:
364 break; /* Float/double only */
370 #define CHECKVAL(x) do { \
372 SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); \
375 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALfloat
*values
)
381 case AL_BYTE_LENGTH_SOFT
:
382 case AL_SAMPLE_LENGTH_SOFT
:
383 case AL_SEC_LENGTH_SOFT
:
384 case AL_SEC_OFFSET_LATENCY_SOFT
:
386 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
389 CHECKVAL(*values
>= 0.0f
);
391 Source
->Pitch
= *values
;
392 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
395 case AL_CONE_INNER_ANGLE
:
396 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
398 Source
->InnerAngle
= *values
;
399 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
402 case AL_CONE_OUTER_ANGLE
:
403 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
405 Source
->OuterAngle
= *values
;
406 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
410 CHECKVAL(*values
>= 0.0f
);
412 Source
->Gain
= *values
;
413 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
416 case AL_MAX_DISTANCE
:
417 CHECKVAL(*values
>= 0.0f
);
419 Source
->MaxDistance
= *values
;
420 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
423 case AL_ROLLOFF_FACTOR
:
424 CHECKVAL(*values
>= 0.0f
);
426 Source
->RollOffFactor
= *values
;
427 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
430 case AL_REFERENCE_DISTANCE
:
431 CHECKVAL(*values
>= 0.0f
);
433 Source
->RefDistance
= *values
;
434 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
438 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
440 Source
->MinGain
= *values
;
441 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
445 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
447 Source
->MaxGain
= *values
;
448 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
451 case AL_CONE_OUTER_GAIN
:
452 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
454 Source
->OuterGain
= *values
;
455 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
458 case AL_CONE_OUTER_GAINHF
:
459 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
461 Source
->OuterGainHF
= *values
;
462 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
465 case AL_AIR_ABSORPTION_FACTOR
:
466 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
468 Source
->AirAbsorptionFactor
= *values
;
469 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
472 case AL_ROOM_ROLLOFF_FACTOR
:
473 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
475 Source
->RoomRolloffFactor
= *values
;
476 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
479 case AL_DOPPLER_FACTOR
:
480 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
482 Source
->DopplerFactor
= *values
;
483 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
487 case AL_SAMPLE_OFFSET
:
489 CHECKVAL(*values
>= 0.0f
);
491 LockContext(Context
);
492 Source
->OffsetType
= prop
;
493 Source
->Offset
= *values
;
495 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
496 !Context
->DeferUpdates
)
498 WriteLock(&Source
->queue_lock
);
499 if(ApplyOffset(Source
) == AL_FALSE
)
501 WriteUnlock(&Source
->queue_lock
);
502 UnlockContext(Context
);
503 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
505 WriteUnlock(&Source
->queue_lock
);
507 UnlockContext(Context
);
510 case AL_SOURCE_RADIUS
:
511 CHECKVAL(*values
>= 0.0f
&& isfinite(*values
));
513 Source
->Radius
= *values
;
514 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
517 case AL_STEREO_ANGLES
:
518 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]));
520 LockContext(Context
);
521 Source
->StereoPan
[0] = values
[0];
522 Source
->StereoPan
[1] = values
[1];
523 UnlockContext(Context
);
524 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
529 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
531 LockContext(Context
);
532 aluVectorSet(&Source
->Position
, values
[0], values
[1], values
[2], 1.0f
);
533 UnlockContext(Context
);
534 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
538 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
540 LockContext(Context
);
541 aluVectorSet(&Source
->Velocity
, values
[0], values
[1], values
[2], 0.0f
);
542 UnlockContext(Context
);
543 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
547 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
549 LockContext(Context
);
550 aluVectorSet(&Source
->Direction
, values
[0], values
[1], values
[2], 0.0f
);
551 UnlockContext(Context
);
552 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
556 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]) &&
557 isfinite(values
[3]) && isfinite(values
[4]) && isfinite(values
[5]));
559 LockContext(Context
);
560 Source
->Orientation
[0][0] = values
[0];
561 Source
->Orientation
[0][1] = values
[1];
562 Source
->Orientation
[0][2] = values
[2];
563 Source
->Orientation
[1][0] = values
[3];
564 Source
->Orientation
[1][1] = values
[4];
565 Source
->Orientation
[1][2] = values
[5];
566 UnlockContext(Context
);
567 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
571 case AL_SOURCE_RELATIVE
:
573 case AL_SOURCE_STATE
:
575 case AL_DISTANCE_MODEL
:
576 case AL_DIRECT_FILTER_GAINHF_AUTO
:
577 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
578 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
579 case AL_DIRECT_CHANNELS_SOFT
:
580 ival
= (ALint
)values
[0];
581 return SetSourceiv(Source
, Context
, prop
, &ival
);
583 case AL_BUFFERS_QUEUED
:
584 case AL_BUFFERS_PROCESSED
:
585 ival
= (ALint
)((ALuint
)values
[0]);
586 return SetSourceiv(Source
, Context
, prop
, &ival
);
589 case AL_DIRECT_FILTER
:
590 case AL_AUXILIARY_SEND_FILTER
:
591 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
595 ERR("Unexpected property: 0x%04x\n", prop
);
596 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
599 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint
*values
)
601 ALCdevice
*device
= Context
->Device
;
602 ALbuffer
*buffer
= NULL
;
603 ALfilter
*filter
= NULL
;
604 ALeffectslot
*slot
= NULL
;
605 ALbufferlistitem
*oldlist
;
606 ALbufferlistitem
*newlist
;
611 case AL_SOURCE_STATE
:
613 case AL_BUFFERS_QUEUED
:
614 case AL_BUFFERS_PROCESSED
:
615 case AL_BYTE_LENGTH_SOFT
:
616 case AL_SAMPLE_LENGTH_SOFT
:
617 case AL_SEC_LENGTH_SOFT
:
619 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
621 case AL_SOURCE_RELATIVE
:
622 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
624 Source
->HeadRelative
= (ALboolean
)*values
;
625 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
629 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
631 Source
->Looping
= (ALboolean
)*values
;
635 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
637 WriteLock(&Source
->queue_lock
);
638 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
640 WriteUnlock(&Source
->queue_lock
);
641 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
646 /* Add the selected buffer to a one-item queue */
647 newlist
= malloc(sizeof(ALbufferlistitem
));
648 newlist
->buffer
= buffer
;
649 newlist
->next
= NULL
;
650 IncrementRef(&buffer
->ref
);
652 /* Source is now Static */
653 Source
->SourceType
= AL_STATIC
;
655 ReadLock(&buffer
->lock
);
656 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
657 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
658 ReadUnlock(&buffer
->lock
);
662 /* Source is now Undetermined */
663 Source
->SourceType
= AL_UNDETERMINED
;
666 oldlist
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &Source
->queue
, newlist
);
667 ATOMIC_STORE(&Source
->current_buffer
, newlist
);
668 WriteUnlock(&Source
->queue_lock
);
670 /* Delete all elements in the previous queue */
671 while(oldlist
!= NULL
)
673 ALbufferlistitem
*temp
= oldlist
;
674 oldlist
= temp
->next
;
677 DecrementRef(&temp
->buffer
->ref
);
683 case AL_SAMPLE_OFFSET
:
685 CHECKVAL(*values
>= 0);
687 LockContext(Context
);
688 Source
->OffsetType
= prop
;
689 Source
->Offset
= *values
;
691 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
692 !Context
->DeferUpdates
)
694 WriteLock(&Source
->queue_lock
);
695 if(ApplyOffset(Source
) == AL_FALSE
)
697 WriteUnlock(&Source
->queue_lock
);
698 UnlockContext(Context
);
699 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
701 WriteUnlock(&Source
->queue_lock
);
703 UnlockContext(Context
);
706 case AL_DIRECT_FILTER
:
707 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
709 LockContext(Context
);
712 Source
->Direct
.Gain
= 1.0f
;
713 Source
->Direct
.GainHF
= 1.0f
;
714 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
715 Source
->Direct
.GainLF
= 1.0f
;
716 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
720 Source
->Direct
.Gain
= filter
->Gain
;
721 Source
->Direct
.GainHF
= filter
->GainHF
;
722 Source
->Direct
.HFReference
= filter
->HFReference
;
723 Source
->Direct
.GainLF
= filter
->GainLF
;
724 Source
->Direct
.LFReference
= filter
->LFReference
;
726 UnlockContext(Context
);
727 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
730 case AL_DIRECT_FILTER_GAINHF_AUTO
:
731 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
733 Source
->DryGainHFAuto
= *values
;
734 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
737 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
738 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
740 Source
->WetGainAuto
= *values
;
741 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
744 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
745 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
747 Source
->WetGainHFAuto
= *values
;
748 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
751 case AL_DIRECT_CHANNELS_SOFT
:
752 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
754 Source
->DirectChannels
= *values
;
755 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
758 case AL_DISTANCE_MODEL
:
759 CHECKVAL(*values
== AL_NONE
||
760 *values
== AL_INVERSE_DISTANCE
||
761 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
762 *values
== AL_LINEAR_DISTANCE
||
763 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
764 *values
== AL_EXPONENT_DISTANCE
||
765 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
767 Source
->DistanceModel
= *values
;
768 if(Context
->SourceDistanceModel
)
769 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
773 case AL_AUXILIARY_SEND_FILTER
:
774 LockContext(Context
);
775 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
776 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
777 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
779 UnlockContext(Context
);
780 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
783 /* Add refcount on the new slot, and release the previous slot */
784 if(slot
) IncrementRef(&slot
->ref
);
785 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
786 if(slot
) DecrementRef(&slot
->ref
);
791 Source
->Send
[values
[1]].Gain
= 1.0f
;
792 Source
->Send
[values
[1]].GainHF
= 1.0f
;
793 Source
->Send
[values
[1]].HFReference
= LOWPASSFREQREF
;
794 Source
->Send
[values
[1]].GainLF
= 1.0f
;
795 Source
->Send
[values
[1]].LFReference
= HIGHPASSFREQREF
;
799 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
800 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
801 Source
->Send
[values
[1]].HFReference
= filter
->HFReference
;
802 Source
->Send
[values
[1]].GainLF
= filter
->GainLF
;
803 Source
->Send
[values
[1]].LFReference
= filter
->LFReference
;
805 UnlockContext(Context
);
806 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
811 case AL_CONE_INNER_ANGLE
:
812 case AL_CONE_OUTER_ANGLE
:
817 case AL_REFERENCE_DISTANCE
:
818 case AL_ROLLOFF_FACTOR
:
819 case AL_CONE_OUTER_GAIN
:
820 case AL_MAX_DISTANCE
:
821 case AL_DOPPLER_FACTOR
:
822 case AL_CONE_OUTER_GAINHF
:
823 case AL_AIR_ABSORPTION_FACTOR
:
824 case AL_ROOM_ROLLOFF_FACTOR
:
825 case AL_SOURCE_RADIUS
:
826 fvals
[0] = (ALfloat
)*values
;
827 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
833 fvals
[0] = (ALfloat
)values
[0];
834 fvals
[1] = (ALfloat
)values
[1];
835 fvals
[2] = (ALfloat
)values
[2];
836 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
840 fvals
[0] = (ALfloat
)values
[0];
841 fvals
[1] = (ALfloat
)values
[1];
842 fvals
[2] = (ALfloat
)values
[2];
843 fvals
[3] = (ALfloat
)values
[3];
844 fvals
[4] = (ALfloat
)values
[4];
845 fvals
[5] = (ALfloat
)values
[5];
846 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
848 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
849 case AL_SEC_OFFSET_LATENCY_SOFT
:
850 case AL_STEREO_ANGLES
:
854 ERR("Unexpected property: 0x%04x\n", prop
);
855 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
858 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint64SOFT
*values
)
866 case AL_BUFFERS_QUEUED
:
867 case AL_BUFFERS_PROCESSED
:
868 case AL_SOURCE_STATE
:
869 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
870 case AL_BYTE_LENGTH_SOFT
:
871 case AL_SAMPLE_LENGTH_SOFT
:
872 case AL_SEC_LENGTH_SOFT
:
874 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
878 case AL_SOURCE_RELATIVE
:
881 case AL_SAMPLE_OFFSET
:
883 case AL_DIRECT_FILTER_GAINHF_AUTO
:
884 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
885 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
886 case AL_DIRECT_CHANNELS_SOFT
:
887 case AL_DISTANCE_MODEL
:
888 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
890 ivals
[0] = (ALint
)*values
;
891 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
895 case AL_DIRECT_FILTER
:
896 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
898 ivals
[0] = (ALuint
)*values
;
899 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
902 case AL_AUXILIARY_SEND_FILTER
:
903 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
904 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
905 values
[2] <= UINT_MAX
&& values
[2] >= 0);
907 ivals
[0] = (ALuint
)values
[0];
908 ivals
[1] = (ALuint
)values
[1];
909 ivals
[2] = (ALuint
)values
[2];
910 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
913 case AL_CONE_INNER_ANGLE
:
914 case AL_CONE_OUTER_ANGLE
:
919 case AL_REFERENCE_DISTANCE
:
920 case AL_ROLLOFF_FACTOR
:
921 case AL_CONE_OUTER_GAIN
:
922 case AL_MAX_DISTANCE
:
923 case AL_DOPPLER_FACTOR
:
924 case AL_CONE_OUTER_GAINHF
:
925 case AL_AIR_ABSORPTION_FACTOR
:
926 case AL_ROOM_ROLLOFF_FACTOR
:
927 case AL_SOURCE_RADIUS
:
928 fvals
[0] = (ALfloat
)*values
;
929 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
935 fvals
[0] = (ALfloat
)values
[0];
936 fvals
[1] = (ALfloat
)values
[1];
937 fvals
[2] = (ALfloat
)values
[2];
938 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
942 fvals
[0] = (ALfloat
)values
[0];
943 fvals
[1] = (ALfloat
)values
[1];
944 fvals
[2] = (ALfloat
)values
[2];
945 fvals
[3] = (ALfloat
)values
[3];
946 fvals
[4] = (ALfloat
)values
[4];
947 fvals
[5] = (ALfloat
)values
[5];
948 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
950 case AL_SEC_OFFSET_LATENCY_SOFT
:
951 case AL_STEREO_ANGLES
:
955 ERR("Unexpected property: 0x%04x\n", prop
);
956 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
962 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALdouble
*values
)
964 ALCdevice
*device
= Context
->Device
;
965 ALbufferlistitem
*BufferList
;
972 *values
= Source
->Gain
;
976 *values
= Source
->Pitch
;
979 case AL_MAX_DISTANCE
:
980 *values
= Source
->MaxDistance
;
983 case AL_ROLLOFF_FACTOR
:
984 *values
= Source
->RollOffFactor
;
987 case AL_REFERENCE_DISTANCE
:
988 *values
= Source
->RefDistance
;
991 case AL_CONE_INNER_ANGLE
:
992 *values
= Source
->InnerAngle
;
995 case AL_CONE_OUTER_ANGLE
:
996 *values
= Source
->OuterAngle
;
1000 *values
= Source
->MinGain
;
1004 *values
= Source
->MaxGain
;
1007 case AL_CONE_OUTER_GAIN
:
1008 *values
= Source
->OuterGain
;
1012 case AL_SAMPLE_OFFSET
:
1013 case AL_BYTE_OFFSET
:
1014 LockContext(Context
);
1015 *values
= GetSourceOffset(Source
, prop
);
1016 UnlockContext(Context
);
1019 case AL_CONE_OUTER_GAINHF
:
1020 *values
= Source
->OuterGainHF
;
1023 case AL_AIR_ABSORPTION_FACTOR
:
1024 *values
= Source
->AirAbsorptionFactor
;
1027 case AL_ROOM_ROLLOFF_FACTOR
:
1028 *values
= Source
->RoomRolloffFactor
;
1031 case AL_DOPPLER_FACTOR
:
1032 *values
= Source
->DopplerFactor
;
1035 case AL_SEC_LENGTH_SOFT
:
1036 ReadLock(&Source
->queue_lock
);
1037 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1044 ALbuffer
*buffer
= BufferList
->buffer
;
1045 if(buffer
&& buffer
->SampleLen
> 0)
1047 freq
= buffer
->Frequency
;
1048 length
+= buffer
->SampleLen
;
1050 } while((BufferList
=BufferList
->next
) != NULL
);
1051 *values
= (ALdouble
)length
/ (ALdouble
)freq
;
1053 ReadUnlock(&Source
->queue_lock
);
1056 case AL_SOURCE_RADIUS
:
1057 *values
= Source
->Radius
;
1060 case AL_STEREO_ANGLES
:
1061 LockContext(Context
);
1062 values
[0] = Source
->StereoPan
[0];
1063 values
[1] = Source
->StereoPan
[1];
1064 UnlockContext(Context
);
1067 case AL_SEC_OFFSET_LATENCY_SOFT
:
1068 LockContext(Context
);
1069 values
[0] = GetSourceSecOffset(Source
);
1070 values
[1] = (ALdouble
)(V0(device
->Backend
,getLatency
)()) /
1072 UnlockContext(Context
);
1076 LockContext(Context
);
1077 values
[0] = Source
->Position
.v
[0];
1078 values
[1] = Source
->Position
.v
[1];
1079 values
[2] = Source
->Position
.v
[2];
1080 UnlockContext(Context
);
1084 LockContext(Context
);
1085 values
[0] = Source
->Velocity
.v
[0];
1086 values
[1] = Source
->Velocity
.v
[1];
1087 values
[2] = Source
->Velocity
.v
[2];
1088 UnlockContext(Context
);
1092 LockContext(Context
);
1093 values
[0] = Source
->Direction
.v
[0];
1094 values
[1] = Source
->Direction
.v
[1];
1095 values
[2] = Source
->Direction
.v
[2];
1096 UnlockContext(Context
);
1099 case AL_ORIENTATION
:
1100 LockContext(Context
);
1101 values
[0] = Source
->Orientation
[0][0];
1102 values
[1] = Source
->Orientation
[0][1];
1103 values
[2] = Source
->Orientation
[0][2];
1104 values
[3] = Source
->Orientation
[1][0];
1105 values
[4] = Source
->Orientation
[1][1];
1106 values
[5] = Source
->Orientation
[1][2];
1107 UnlockContext(Context
);
1111 case AL_SOURCE_RELATIVE
:
1113 case AL_SOURCE_STATE
:
1114 case AL_BUFFERS_QUEUED
:
1115 case AL_BUFFERS_PROCESSED
:
1116 case AL_SOURCE_TYPE
:
1117 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1118 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1119 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1120 case AL_DIRECT_CHANNELS_SOFT
:
1121 case AL_BYTE_LENGTH_SOFT
:
1122 case AL_SAMPLE_LENGTH_SOFT
:
1123 case AL_DISTANCE_MODEL
:
1124 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1125 *values
= (ALdouble
)ivals
[0];
1129 case AL_DIRECT_FILTER
:
1130 case AL_AUXILIARY_SEND_FILTER
:
1131 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1135 ERR("Unexpected property: 0x%04x\n", prop
);
1136 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1139 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint
*values
)
1141 ALbufferlistitem
*BufferList
;
1147 case AL_SOURCE_RELATIVE
:
1148 *values
= Source
->HeadRelative
;
1152 *values
= Source
->Looping
;
1156 ReadLock(&Source
->queue_lock
);
1157 BufferList
= (Source
->SourceType
== AL_STATIC
) ? ATOMIC_LOAD(&Source
->queue
) :
1158 ATOMIC_LOAD(&Source
->current_buffer
);
1159 *values
= (BufferList
&& BufferList
->buffer
) ? BufferList
->buffer
->id
: 0;
1160 ReadUnlock(&Source
->queue_lock
);
1163 case AL_SOURCE_STATE
:
1164 *values
= Source
->state
;
1167 case AL_BYTE_LENGTH_SOFT
:
1168 ReadLock(&Source
->queue_lock
);
1169 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1175 ALbuffer
*buffer
= BufferList
->buffer
;
1176 if(buffer
&& buffer
->SampleLen
> 0)
1178 ALuint byte_align
, sample_align
;
1179 if(buffer
->OriginalType
== UserFmtIMA4
)
1181 ALsizei align
= (buffer
->OriginalAlign
-1)/2 + 4;
1182 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1183 sample_align
= buffer
->OriginalAlign
;
1185 else if(buffer
->OriginalType
== UserFmtMSADPCM
)
1187 ALsizei align
= (buffer
->OriginalAlign
-2)/2 + 7;
1188 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1189 sample_align
= buffer
->OriginalAlign
;
1193 ALsizei align
= buffer
->OriginalAlign
;
1194 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1195 sample_align
= buffer
->OriginalAlign
;
1198 length
+= buffer
->SampleLen
/ sample_align
* byte_align
;
1200 } while((BufferList
=BufferList
->next
) != NULL
);
1203 ReadUnlock(&Source
->queue_lock
);
1206 case AL_SAMPLE_LENGTH_SOFT
:
1207 ReadLock(&Source
->queue_lock
);
1208 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1214 ALbuffer
*buffer
= BufferList
->buffer
;
1215 if(buffer
) length
+= buffer
->SampleLen
;
1216 } while((BufferList
=BufferList
->next
) != NULL
);
1219 ReadUnlock(&Source
->queue_lock
);
1222 case AL_BUFFERS_QUEUED
:
1223 ReadLock(&Source
->queue_lock
);
1224 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1231 } while((BufferList
=BufferList
->next
) != NULL
);
1234 ReadUnlock(&Source
->queue_lock
);
1237 case AL_BUFFERS_PROCESSED
:
1238 ReadLock(&Source
->queue_lock
);
1239 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
1241 /* Buffers on a looping source are in a perpetual state of
1242 * PENDING, so don't report any as PROCESSED */
1247 const ALbufferlistitem
*BufferList
= ATOMIC_LOAD(&Source
->queue
);
1248 const ALbufferlistitem
*Current
= ATOMIC_LOAD(&Source
->current_buffer
);
1250 while(BufferList
&& BufferList
!= Current
)
1253 BufferList
= BufferList
->next
;
1257 ReadUnlock(&Source
->queue_lock
);
1260 case AL_SOURCE_TYPE
:
1261 *values
= Source
->SourceType
;
1264 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1265 *values
= Source
->DryGainHFAuto
;
1268 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1269 *values
= Source
->WetGainAuto
;
1272 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1273 *values
= Source
->WetGainHFAuto
;
1276 case AL_DIRECT_CHANNELS_SOFT
:
1277 *values
= Source
->DirectChannels
;
1280 case AL_DISTANCE_MODEL
:
1281 *values
= Source
->DistanceModel
;
1284 /* 1x float/double */
1285 case AL_CONE_INNER_ANGLE
:
1286 case AL_CONE_OUTER_ANGLE
:
1291 case AL_REFERENCE_DISTANCE
:
1292 case AL_ROLLOFF_FACTOR
:
1293 case AL_CONE_OUTER_GAIN
:
1294 case AL_MAX_DISTANCE
:
1296 case AL_SAMPLE_OFFSET
:
1297 case AL_BYTE_OFFSET
:
1298 case AL_DOPPLER_FACTOR
:
1299 case AL_AIR_ABSORPTION_FACTOR
:
1300 case AL_ROOM_ROLLOFF_FACTOR
:
1301 case AL_CONE_OUTER_GAINHF
:
1302 case AL_SEC_LENGTH_SOFT
:
1303 case AL_SOURCE_RADIUS
:
1304 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1305 *values
= (ALint
)dvals
[0];
1308 /* 3x float/double */
1312 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1314 values
[0] = (ALint
)dvals
[0];
1315 values
[1] = (ALint
)dvals
[1];
1316 values
[2] = (ALint
)dvals
[2];
1320 /* 6x float/double */
1321 case AL_ORIENTATION
:
1322 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1324 values
[0] = (ALint
)dvals
[0];
1325 values
[1] = (ALint
)dvals
[1];
1326 values
[2] = (ALint
)dvals
[2];
1327 values
[3] = (ALint
)dvals
[3];
1328 values
[4] = (ALint
)dvals
[4];
1329 values
[5] = (ALint
)dvals
[5];
1333 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1334 break; /* i64 only */
1335 case AL_SEC_OFFSET_LATENCY_SOFT
:
1336 break; /* Double only */
1337 case AL_STEREO_ANGLES
:
1338 break; /* Float/double only */
1340 case AL_DIRECT_FILTER
:
1341 case AL_AUXILIARY_SEND_FILTER
:
1345 ERR("Unexpected property: 0x%04x\n", prop
);
1346 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1349 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint64
*values
)
1351 ALCdevice
*device
= Context
->Device
;
1358 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1359 LockContext(Context
);
1360 values
[0] = GetSourceSampleOffset(Source
);
1361 values
[1] = V0(device
->Backend
,getLatency
)();
1362 UnlockContext(Context
);
1365 /* 1x float/double */
1366 case AL_CONE_INNER_ANGLE
:
1367 case AL_CONE_OUTER_ANGLE
:
1372 case AL_REFERENCE_DISTANCE
:
1373 case AL_ROLLOFF_FACTOR
:
1374 case AL_CONE_OUTER_GAIN
:
1375 case AL_MAX_DISTANCE
:
1377 case AL_SAMPLE_OFFSET
:
1378 case AL_BYTE_OFFSET
:
1379 case AL_DOPPLER_FACTOR
:
1380 case AL_AIR_ABSORPTION_FACTOR
:
1381 case AL_ROOM_ROLLOFF_FACTOR
:
1382 case AL_CONE_OUTER_GAINHF
:
1383 case AL_SEC_LENGTH_SOFT
:
1384 case AL_SOURCE_RADIUS
:
1385 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1386 *values
= (ALint64
)dvals
[0];
1389 /* 3x float/double */
1393 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1395 values
[0] = (ALint64
)dvals
[0];
1396 values
[1] = (ALint64
)dvals
[1];
1397 values
[2] = (ALint64
)dvals
[2];
1401 /* 6x float/double */
1402 case AL_ORIENTATION
:
1403 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1405 values
[0] = (ALint64
)dvals
[0];
1406 values
[1] = (ALint64
)dvals
[1];
1407 values
[2] = (ALint64
)dvals
[2];
1408 values
[3] = (ALint64
)dvals
[3];
1409 values
[4] = (ALint64
)dvals
[4];
1410 values
[5] = (ALint64
)dvals
[5];
1415 case AL_SOURCE_RELATIVE
:
1417 case AL_SOURCE_STATE
:
1418 case AL_BUFFERS_QUEUED
:
1419 case AL_BUFFERS_PROCESSED
:
1420 case AL_BYTE_LENGTH_SOFT
:
1421 case AL_SAMPLE_LENGTH_SOFT
:
1422 case AL_SOURCE_TYPE
:
1423 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1424 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1425 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1426 case AL_DIRECT_CHANNELS_SOFT
:
1427 case AL_DISTANCE_MODEL
:
1428 if((err
=GetSourceiv(Source
, Context
, prop
, ivals
)) != AL_FALSE
)
1434 case AL_DIRECT_FILTER
:
1435 if((err
=GetSourceiv(Source
, Context
, prop
, ivals
)) != AL_FALSE
)
1436 *values
= (ALuint
)ivals
[0];
1440 case AL_AUXILIARY_SEND_FILTER
:
1441 if((err
=GetSourceiv(Source
, Context
, prop
, ivals
)) != AL_FALSE
)
1443 values
[0] = (ALuint
)ivals
[0];
1444 values
[1] = (ALuint
)ivals
[1];
1445 values
[2] = (ALuint
)ivals
[2];
1449 case AL_SEC_OFFSET_LATENCY_SOFT
:
1450 break; /* Double only */
1451 case AL_STEREO_ANGLES
:
1452 break; /* Float/double only */
1455 ERR("Unexpected property: 0x%04x\n", prop
);
1456 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1460 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
1462 ALCcontext
*context
;
1466 context
= GetContextRef();
1467 if(!context
) return;
1470 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1471 for(cur
= 0;cur
< n
;cur
++)
1473 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
1476 alDeleteSources(cur
, sources
);
1477 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
1479 InitSourceParams(source
);
1481 err
= NewThunkEntry(&source
->id
);
1482 if(err
== AL_NO_ERROR
)
1483 err
= InsertUIntMapEntry(&context
->SourceMap
, source
->id
, source
);
1484 if(err
!= AL_NO_ERROR
)
1486 FreeThunkEntry(source
->id
);
1487 memset(source
, 0, sizeof(ALsource
));
1490 alDeleteSources(cur
, sources
);
1491 SET_ERROR_AND_GOTO(context
, err
, done
);
1494 sources
[cur
] = source
->id
;
1498 ALCcontext_DecRef(context
);
1502 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
1504 ALCcontext
*context
;
1505 ALbufferlistitem
*BufferList
;
1509 context
= GetContextRef();
1510 if(!context
) return;
1513 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1515 /* Check that all Sources are valid */
1516 for(i
= 0;i
< n
;i
++)
1518 if(LookupSource(context
, sources
[i
]) == NULL
)
1519 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
1521 for(i
= 0;i
< n
;i
++)
1523 ALvoice
*voice
, *voice_end
;
1525 if((Source
=RemoveSource(context
, sources
[i
])) == NULL
)
1527 FreeThunkEntry(Source
->id
);
1529 LockContext(context
);
1530 voice
= context
->Voices
;
1531 voice_end
= voice
+ context
->VoiceCount
;
1532 while(voice
!= voice_end
)
1534 ALsource
*old
= Source
;
1535 if(COMPARE_EXCHANGE(&voice
->Source
, &old
, NULL
))
1539 UnlockContext(context
);
1541 BufferList
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &Source
->queue
, NULL
);
1542 while(BufferList
!= NULL
)
1544 ALbufferlistitem
*next
= BufferList
->next
;
1545 if(BufferList
->buffer
!= NULL
)
1546 DecrementRef(&BufferList
->buffer
->ref
);
1551 for(j
= 0;j
< MAX_SENDS
;++j
)
1553 if(Source
->Send
[j
].Slot
)
1554 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
1555 Source
->Send
[j
].Slot
= NULL
;
1558 memset(Source
, 0, sizeof(*Source
));
1563 ALCcontext_DecRef(context
);
1567 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1569 ALCcontext
*context
;
1572 context
= GetContextRef();
1573 if(!context
) return AL_FALSE
;
1575 ret
= (LookupSource(context
, source
) ? AL_TRUE
: AL_FALSE
);
1577 ALCcontext_DecRef(context
);
1583 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1585 ALCcontext
*Context
;
1588 Context
= GetContextRef();
1589 if(!Context
) return;
1591 if((Source
=LookupSource(Context
, source
)) == NULL
)
1592 alSetError(Context
, AL_INVALID_NAME
);
1593 else if(!(FloatValsByProp(param
) == 1))
1594 alSetError(Context
, AL_INVALID_ENUM
);
1596 SetSourcefv(Source
, Context
, param
, &value
);
1598 ALCcontext_DecRef(Context
);
1601 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1603 ALCcontext
*Context
;
1606 Context
= GetContextRef();
1607 if(!Context
) return;
1609 if((Source
=LookupSource(Context
, source
)) == NULL
)
1610 alSetError(Context
, AL_INVALID_NAME
);
1611 else if(!(FloatValsByProp(param
) == 3))
1612 alSetError(Context
, AL_INVALID_ENUM
);
1615 ALfloat fvals
[3] = { value1
, value2
, value3
};
1616 SetSourcefv(Source
, Context
, param
, fvals
);
1619 ALCcontext_DecRef(Context
);
1622 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1624 ALCcontext
*Context
;
1627 Context
= GetContextRef();
1628 if(!Context
) return;
1630 if((Source
=LookupSource(Context
, source
)) == NULL
)
1631 alSetError(Context
, AL_INVALID_NAME
);
1633 alSetError(Context
, AL_INVALID_VALUE
);
1634 else if(!(FloatValsByProp(param
) > 0))
1635 alSetError(Context
, AL_INVALID_ENUM
);
1637 SetSourcefv(Source
, Context
, param
, values
);
1639 ALCcontext_DecRef(Context
);
1643 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1645 ALCcontext
*Context
;
1648 Context
= GetContextRef();
1649 if(!Context
) return;
1651 if((Source
=LookupSource(Context
, source
)) == NULL
)
1652 alSetError(Context
, AL_INVALID_NAME
);
1653 else if(!(DoubleValsByProp(param
) == 1))
1654 alSetError(Context
, AL_INVALID_ENUM
);
1657 ALfloat fval
= (ALfloat
)value
;
1658 SetSourcefv(Source
, Context
, param
, &fval
);
1661 ALCcontext_DecRef(Context
);
1664 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1666 ALCcontext
*Context
;
1669 Context
= GetContextRef();
1670 if(!Context
) return;
1672 if((Source
=LookupSource(Context
, source
)) == NULL
)
1673 alSetError(Context
, AL_INVALID_NAME
);
1674 else if(!(DoubleValsByProp(param
) == 3))
1675 alSetError(Context
, AL_INVALID_ENUM
);
1678 ALfloat fvals
[3] = { (ALfloat
)value1
, (ALfloat
)value2
, (ALfloat
)value3
};
1679 SetSourcefv(Source
, Context
, param
, fvals
);
1682 ALCcontext_DecRef(Context
);
1685 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1687 ALCcontext
*Context
;
1691 Context
= GetContextRef();
1692 if(!Context
) return;
1694 if((Source
=LookupSource(Context
, source
)) == NULL
)
1695 alSetError(Context
, AL_INVALID_NAME
);
1697 alSetError(Context
, AL_INVALID_VALUE
);
1698 else if(!((count
=DoubleValsByProp(param
)) > 0 && count
<= 6))
1699 alSetError(Context
, AL_INVALID_ENUM
);
1705 for(i
= 0;i
< count
;i
++)
1706 fvals
[i
] = (ALfloat
)values
[i
];
1707 SetSourcefv(Source
, Context
, param
, fvals
);
1710 ALCcontext_DecRef(Context
);
1714 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1716 ALCcontext
*Context
;
1719 Context
= GetContextRef();
1720 if(!Context
) return;
1722 if((Source
=LookupSource(Context
, source
)) == NULL
)
1723 alSetError(Context
, AL_INVALID_NAME
);
1724 else if(!(IntValsByProp(param
) == 1))
1725 alSetError(Context
, AL_INVALID_ENUM
);
1727 SetSourceiv(Source
, Context
, param
, &value
);
1729 ALCcontext_DecRef(Context
);
1732 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1734 ALCcontext
*Context
;
1737 Context
= GetContextRef();
1738 if(!Context
) return;
1740 if((Source
=LookupSource(Context
, source
)) == NULL
)
1741 alSetError(Context
, AL_INVALID_NAME
);
1742 else if(!(IntValsByProp(param
) == 3))
1743 alSetError(Context
, AL_INVALID_ENUM
);
1746 ALint ivals
[3] = { value1
, value2
, value3
};
1747 SetSourceiv(Source
, Context
, param
, ivals
);
1750 ALCcontext_DecRef(Context
);
1753 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1755 ALCcontext
*Context
;
1758 Context
= GetContextRef();
1759 if(!Context
) return;
1761 if((Source
=LookupSource(Context
, source
)) == NULL
)
1762 alSetError(Context
, AL_INVALID_NAME
);
1764 alSetError(Context
, AL_INVALID_VALUE
);
1765 else if(!(IntValsByProp(param
) > 0))
1766 alSetError(Context
, AL_INVALID_ENUM
);
1768 SetSourceiv(Source
, Context
, param
, values
);
1770 ALCcontext_DecRef(Context
);
1774 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1776 ALCcontext
*Context
;
1779 Context
= GetContextRef();
1780 if(!Context
) return;
1782 if((Source
=LookupSource(Context
, source
)) == NULL
)
1783 alSetError(Context
, AL_INVALID_NAME
);
1784 else if(!(Int64ValsByProp(param
) == 1))
1785 alSetError(Context
, AL_INVALID_ENUM
);
1787 SetSourcei64v(Source
, Context
, param
, &value
);
1789 ALCcontext_DecRef(Context
);
1792 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1794 ALCcontext
*Context
;
1797 Context
= GetContextRef();
1798 if(!Context
) return;
1800 if((Source
=LookupSource(Context
, source
)) == NULL
)
1801 alSetError(Context
, AL_INVALID_NAME
);
1802 else if(!(Int64ValsByProp(param
) == 3))
1803 alSetError(Context
, AL_INVALID_ENUM
);
1806 ALint64SOFT i64vals
[3] = { value1
, value2
, value3
};
1807 SetSourcei64v(Source
, Context
, param
, i64vals
);
1810 ALCcontext_DecRef(Context
);
1813 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1815 ALCcontext
*Context
;
1818 Context
= GetContextRef();
1819 if(!Context
) return;
1821 if((Source
=LookupSource(Context
, source
)) == NULL
)
1822 alSetError(Context
, AL_INVALID_NAME
);
1824 alSetError(Context
, AL_INVALID_VALUE
);
1825 else if(!(Int64ValsByProp(param
) > 0))
1826 alSetError(Context
, AL_INVALID_ENUM
);
1828 SetSourcei64v(Source
, Context
, param
, values
);
1830 ALCcontext_DecRef(Context
);
1834 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1836 ALCcontext
*Context
;
1839 Context
= GetContextRef();
1840 if(!Context
) return;
1842 if((Source
=LookupSource(Context
, source
)) == NULL
)
1843 alSetError(Context
, AL_INVALID_NAME
);
1845 alSetError(Context
, AL_INVALID_VALUE
);
1846 else if(!(FloatValsByProp(param
) == 1))
1847 alSetError(Context
, AL_INVALID_ENUM
);
1851 if(GetSourcedv(Source
, Context
, param
, &dval
))
1852 *value
= (ALfloat
)dval
;
1855 ALCcontext_DecRef(Context
);
1859 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1861 ALCcontext
*Context
;
1864 Context
= GetContextRef();
1865 if(!Context
) return;
1867 if((Source
=LookupSource(Context
, source
)) == NULL
)
1868 alSetError(Context
, AL_INVALID_NAME
);
1869 else if(!(value1
&& value2
&& value3
))
1870 alSetError(Context
, AL_INVALID_VALUE
);
1871 else if(!(FloatValsByProp(param
) == 3))
1872 alSetError(Context
, AL_INVALID_ENUM
);
1876 if(GetSourcedv(Source
, Context
, param
, dvals
))
1878 *value1
= (ALfloat
)dvals
[0];
1879 *value2
= (ALfloat
)dvals
[1];
1880 *value3
= (ALfloat
)dvals
[2];
1884 ALCcontext_DecRef(Context
);
1888 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1890 ALCcontext
*Context
;
1894 Context
= GetContextRef();
1895 if(!Context
) return;
1897 if((Source
=LookupSource(Context
, source
)) == NULL
)
1898 alSetError(Context
, AL_INVALID_NAME
);
1900 alSetError(Context
, AL_INVALID_VALUE
);
1901 else if(!((count
=FloatValsByProp(param
)) > 0 && count
<= 6))
1902 alSetError(Context
, AL_INVALID_ENUM
);
1906 if(GetSourcedv(Source
, Context
, param
, dvals
))
1909 for(i
= 0;i
< count
;i
++)
1910 values
[i
] = (ALfloat
)dvals
[i
];
1914 ALCcontext_DecRef(Context
);
1918 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1920 ALCcontext
*Context
;
1923 Context
= GetContextRef();
1924 if(!Context
) return;
1926 if((Source
=LookupSource(Context
, source
)) == NULL
)
1927 alSetError(Context
, AL_INVALID_NAME
);
1929 alSetError(Context
, AL_INVALID_VALUE
);
1930 else if(!(DoubleValsByProp(param
) == 1))
1931 alSetError(Context
, AL_INVALID_ENUM
);
1933 GetSourcedv(Source
, Context
, param
, value
);
1935 ALCcontext_DecRef(Context
);
1938 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1940 ALCcontext
*Context
;
1943 Context
= GetContextRef();
1944 if(!Context
) return;
1946 if((Source
=LookupSource(Context
, source
)) == NULL
)
1947 alSetError(Context
, AL_INVALID_NAME
);
1948 else if(!(value1
&& value2
&& value3
))
1949 alSetError(Context
, AL_INVALID_VALUE
);
1950 else if(!(DoubleValsByProp(param
) == 3))
1951 alSetError(Context
, AL_INVALID_ENUM
);
1955 if(GetSourcedv(Source
, Context
, param
, dvals
))
1963 ALCcontext_DecRef(Context
);
1966 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1968 ALCcontext
*Context
;
1971 Context
= GetContextRef();
1972 if(!Context
) return;
1974 if((Source
=LookupSource(Context
, source
)) == NULL
)
1975 alSetError(Context
, AL_INVALID_NAME
);
1977 alSetError(Context
, AL_INVALID_VALUE
);
1978 else if(!(DoubleValsByProp(param
) > 0))
1979 alSetError(Context
, AL_INVALID_ENUM
);
1981 GetSourcedv(Source
, Context
, param
, values
);
1983 ALCcontext_DecRef(Context
);
1987 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1989 ALCcontext
*Context
;
1992 Context
= GetContextRef();
1993 if(!Context
) return;
1995 if((Source
=LookupSource(Context
, source
)) == NULL
)
1996 alSetError(Context
, AL_INVALID_NAME
);
1998 alSetError(Context
, AL_INVALID_VALUE
);
1999 else if(!(IntValsByProp(param
) == 1))
2000 alSetError(Context
, AL_INVALID_ENUM
);
2002 GetSourceiv(Source
, Context
, param
, value
);
2004 ALCcontext_DecRef(Context
);
2008 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
2010 ALCcontext
*Context
;
2013 Context
= GetContextRef();
2014 if(!Context
) return;
2016 if((Source
=LookupSource(Context
, source
)) == NULL
)
2017 alSetError(Context
, AL_INVALID_NAME
);
2018 else if(!(value1
&& value2
&& value3
))
2019 alSetError(Context
, AL_INVALID_VALUE
);
2020 else if(!(IntValsByProp(param
) == 3))
2021 alSetError(Context
, AL_INVALID_ENUM
);
2025 if(GetSourceiv(Source
, Context
, param
, ivals
))
2033 ALCcontext_DecRef(Context
);
2037 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
2039 ALCcontext
*Context
;
2042 Context
= GetContextRef();
2043 if(!Context
) return;
2045 if((Source
=LookupSource(Context
, source
)) == NULL
)
2046 alSetError(Context
, AL_INVALID_NAME
);
2048 alSetError(Context
, AL_INVALID_VALUE
);
2049 else if(!(IntValsByProp(param
) > 0))
2050 alSetError(Context
, AL_INVALID_ENUM
);
2052 GetSourceiv(Source
, Context
, param
, values
);
2054 ALCcontext_DecRef(Context
);
2058 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
2060 ALCcontext
*Context
;
2063 Context
= GetContextRef();
2064 if(!Context
) return;
2066 if((Source
=LookupSource(Context
, source
)) == NULL
)
2067 alSetError(Context
, AL_INVALID_NAME
);
2069 alSetError(Context
, AL_INVALID_VALUE
);
2070 else if(!(Int64ValsByProp(param
) == 1))
2071 alSetError(Context
, AL_INVALID_ENUM
);
2073 GetSourcei64v(Source
, Context
, param
, value
);
2075 ALCcontext_DecRef(Context
);
2078 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
2080 ALCcontext
*Context
;
2083 Context
= GetContextRef();
2084 if(!Context
) return;
2086 if((Source
=LookupSource(Context
, source
)) == NULL
)
2087 alSetError(Context
, AL_INVALID_NAME
);
2088 else if(!(value1
&& value2
&& value3
))
2089 alSetError(Context
, AL_INVALID_VALUE
);
2090 else if(!(Int64ValsByProp(param
) == 3))
2091 alSetError(Context
, AL_INVALID_ENUM
);
2095 if(GetSourcei64v(Source
, Context
, param
, i64vals
))
2097 *value1
= i64vals
[0];
2098 *value2
= i64vals
[1];
2099 *value3
= i64vals
[2];
2103 ALCcontext_DecRef(Context
);
2106 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
2108 ALCcontext
*Context
;
2111 Context
= GetContextRef();
2112 if(!Context
) return;
2114 if((Source
=LookupSource(Context
, source
)) == NULL
)
2115 alSetError(Context
, AL_INVALID_NAME
);
2117 alSetError(Context
, AL_INVALID_VALUE
);
2118 else if(!(Int64ValsByProp(param
) > 0))
2119 alSetError(Context
, AL_INVALID_ENUM
);
2121 GetSourcei64v(Source
, Context
, param
, values
);
2123 ALCcontext_DecRef(Context
);
2127 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
2129 alSourcePlayv(1, &source
);
2131 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2133 ALCcontext
*context
;
2137 context
= GetContextRef();
2138 if(!context
) return;
2141 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2142 for(i
= 0;i
< n
;i
++)
2144 if(!LookupSource(context
, sources
[i
]))
2145 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2148 LockContext(context
);
2149 while(n
> context
->MaxVoices
-context
->VoiceCount
)
2151 ALvoice
*temp
= NULL
;
2154 newcount
= context
->MaxVoices
<< 1;
2156 temp
= realloc(context
->Voices
, newcount
* sizeof(context
->Voices
[0]));
2159 UnlockContext(context
);
2160 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
2162 memset(&temp
[context
->MaxVoices
], 0, (newcount
-context
->MaxVoices
) * sizeof(temp
[0]));
2164 context
->Voices
= temp
;
2165 context
->MaxVoices
= newcount
;
2168 for(i
= 0;i
< n
;i
++)
2170 source
= LookupSource(context
, sources
[i
]);
2171 if(context
->DeferUpdates
) source
->new_state
= AL_PLAYING
;
2172 else SetSourceState(source
, context
, AL_PLAYING
);
2174 UnlockContext(context
);
2177 ALCcontext_DecRef(context
);
2180 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2182 alSourcePausev(1, &source
);
2184 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2186 ALCcontext
*context
;
2190 context
= GetContextRef();
2191 if(!context
) return;
2194 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2195 for(i
= 0;i
< n
;i
++)
2197 if(!LookupSource(context
, sources
[i
]))
2198 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2201 LockContext(context
);
2202 for(i
= 0;i
< n
;i
++)
2204 source
= LookupSource(context
, sources
[i
]);
2205 if(context
->DeferUpdates
) source
->new_state
= AL_PAUSED
;
2206 else SetSourceState(source
, context
, AL_PAUSED
);
2208 UnlockContext(context
);
2211 ALCcontext_DecRef(context
);
2214 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2216 alSourceStopv(1, &source
);
2218 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2220 ALCcontext
*context
;
2224 context
= GetContextRef();
2225 if(!context
) return;
2228 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2229 for(i
= 0;i
< n
;i
++)
2231 if(!LookupSource(context
, sources
[i
]))
2232 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2235 LockContext(context
);
2236 for(i
= 0;i
< n
;i
++)
2238 source
= LookupSource(context
, sources
[i
]);
2239 source
->new_state
= AL_NONE
;
2240 SetSourceState(source
, context
, AL_STOPPED
);
2242 UnlockContext(context
);
2245 ALCcontext_DecRef(context
);
2248 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2250 alSourceRewindv(1, &source
);
2252 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2254 ALCcontext
*context
;
2258 context
= GetContextRef();
2259 if(!context
) return;
2262 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2263 for(i
= 0;i
< n
;i
++)
2265 if(!LookupSource(context
, sources
[i
]))
2266 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2269 LockContext(context
);
2270 for(i
= 0;i
< n
;i
++)
2272 source
= LookupSource(context
, sources
[i
]);
2273 source
->new_state
= AL_NONE
;
2274 SetSourceState(source
, context
, AL_INITIAL
);
2276 UnlockContext(context
);
2279 ALCcontext_DecRef(context
);
2283 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint src
, ALsizei nb
, const ALuint
*buffers
)
2286 ALCcontext
*context
;
2289 ALbufferlistitem
*BufferListStart
;
2290 ALbufferlistitem
*BufferList
;
2291 ALbuffer
*BufferFmt
= NULL
;
2296 context
= GetContextRef();
2297 if(!context
) return;
2299 device
= context
->Device
;
2302 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2303 if((source
=LookupSource(context
, src
)) == NULL
)
2304 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2306 WriteLock(&source
->queue_lock
);
2307 if(source
->SourceType
== AL_STATIC
)
2309 WriteUnlock(&source
->queue_lock
);
2310 /* Can't queue on a Static Source */
2311 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
2314 /* Check for a valid Buffer, for its frequency and format */
2315 BufferList
= ATOMIC_LOAD(&source
->queue
);
2318 if(BufferList
->buffer
)
2320 BufferFmt
= BufferList
->buffer
;
2323 BufferList
= BufferList
->next
;
2326 BufferListStart
= NULL
;
2328 for(i
= 0;i
< nb
;i
++)
2330 ALbuffer
*buffer
= NULL
;
2331 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2333 WriteUnlock(&source
->queue_lock
);
2334 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, buffer_error
);
2337 if(!BufferListStart
)
2339 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2340 BufferList
= BufferListStart
;
2344 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2345 BufferList
= BufferList
->next
;
2347 BufferList
->buffer
= buffer
;
2348 BufferList
->next
= NULL
;
2349 if(!buffer
) continue;
2351 /* Hold a read lock on each buffer being queued while checking all
2352 * provided buffers. This is done so other threads don't see an extra
2353 * reference on some buffers if this operation ends up failing. */
2354 ReadLock(&buffer
->lock
);
2355 IncrementRef(&buffer
->ref
);
2357 if(BufferFmt
== NULL
)
2361 source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2362 source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2364 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2365 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2366 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2368 WriteUnlock(&source
->queue_lock
);
2369 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, buffer_error
);
2372 /* A buffer failed (invalid ID or format), so unlock and release
2373 * each buffer we had. */
2374 while(BufferListStart
)
2376 ALbufferlistitem
*next
= BufferListStart
->next
;
2377 if((buffer
=BufferListStart
->buffer
) != NULL
)
2379 DecrementRef(&buffer
->ref
);
2380 ReadUnlock(&buffer
->lock
);
2382 free(BufferListStart
);
2383 BufferListStart
= next
;
2388 /* All buffers good, unlock them now. */
2389 BufferList
= BufferListStart
;
2390 while(BufferList
!= NULL
)
2392 ALbuffer
*buffer
= BufferList
->buffer
;
2393 if(buffer
) ReadUnlock(&buffer
->lock
);
2394 BufferList
= BufferList
->next
;
2397 /* Source is now streaming */
2398 source
->SourceType
= AL_STREAMING
;
2401 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->queue
, &BufferList
, BufferListStart
))
2403 /* Queue head is not NULL, append to the end of the queue */
2404 while(BufferList
->next
!= NULL
)
2405 BufferList
= BufferList
->next
;
2406 BufferList
->next
= BufferListStart
;
2408 /* If the current buffer was at the end (NULL), put it at the start of the newly queued
2412 ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->current_buffer
, &BufferList
, BufferListStart
);
2413 WriteUnlock(&source
->queue_lock
);
2416 ALCcontext_DecRef(context
);
2419 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint src
, ALsizei nb
, ALuint
*buffers
)
2421 ALCcontext
*context
;
2423 ALbufferlistitem
*OldHead
;
2424 ALbufferlistitem
*OldTail
;
2425 ALbufferlistitem
*Current
;
2431 context
= GetContextRef();
2432 if(!context
) return;
2435 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2437 if((source
=LookupSource(context
, src
)) == NULL
)
2438 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2440 WriteLock(&source
->queue_lock
);
2441 /* Find the new buffer queue head */
2442 OldTail
= ATOMIC_LOAD(&source
->queue
);
2443 Current
= ATOMIC_LOAD(&source
->current_buffer
);
2444 if(OldTail
!= Current
)
2446 for(i
= 1;i
< nb
;i
++)
2448 ALbufferlistitem
*next
= OldTail
->next
;
2449 if(!next
|| next
== Current
) break;
2453 if(source
->Looping
|| source
->SourceType
!= AL_STREAMING
|| i
!= nb
)
2455 WriteUnlock(&source
->queue_lock
);
2456 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2457 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2460 /* Swap it, and cut the new head from the old. */
2461 OldHead
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &source
->queue
, OldTail
->next
);
2464 ALCdevice
*device
= context
->Device
;
2467 /* Once the active mix (if any) is done, it's safe to cut the old tail
2468 * from the new head.
2470 if(((count
=ReadRef(&device
->MixCount
))&1) != 0)
2472 while(count
== ReadRef(&device
->MixCount
))
2475 OldTail
->next
= NULL
;
2477 WriteUnlock(&source
->queue_lock
);
2479 while(OldHead
!= NULL
)
2481 ALbufferlistitem
*next
= OldHead
->next
;
2482 ALbuffer
*buffer
= OldHead
->buffer
;
2488 *(buffers
++) = buffer
->id
;
2489 DecrementRef(&buffer
->ref
);
2497 ALCcontext_DecRef(context
);
2501 static ALvoid
InitSourceParams(ALsource
*Source
)
2505 RWLockInit(&Source
->queue_lock
);
2507 Source
->InnerAngle
= 360.0f
;
2508 Source
->OuterAngle
= 360.0f
;
2509 Source
->Pitch
= 1.0f
;
2510 aluVectorSet(&Source
->Position
, 0.0f
, 0.0f
, 0.0f
, 1.0f
);
2511 aluVectorSet(&Source
->Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2512 aluVectorSet(&Source
->Direction
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2513 Source
->Orientation
[0][0] = 0.0f
;
2514 Source
->Orientation
[0][1] = 0.0f
;
2515 Source
->Orientation
[0][2] = -1.0f
;
2516 Source
->Orientation
[1][0] = 0.0f
;
2517 Source
->Orientation
[1][1] = 1.0f
;
2518 Source
->Orientation
[1][2] = 0.0f
;
2519 Source
->RefDistance
= 1.0f
;
2520 Source
->MaxDistance
= FLT_MAX
;
2521 Source
->RollOffFactor
= 1.0f
;
2522 Source
->Looping
= AL_FALSE
;
2523 Source
->Gain
= 1.0f
;
2524 Source
->MinGain
= 0.0f
;
2525 Source
->MaxGain
= 1.0f
;
2526 Source
->OuterGain
= 0.0f
;
2527 Source
->OuterGainHF
= 1.0f
;
2529 Source
->DryGainHFAuto
= AL_TRUE
;
2530 Source
->WetGainAuto
= AL_TRUE
;
2531 Source
->WetGainHFAuto
= AL_TRUE
;
2532 Source
->AirAbsorptionFactor
= 0.0f
;
2533 Source
->RoomRolloffFactor
= 0.0f
;
2534 Source
->DopplerFactor
= 1.0f
;
2535 Source
->DirectChannels
= AL_FALSE
;
2537 Source
->StereoPan
[0] = DEG2RAD( 30.0f
);
2538 Source
->StereoPan
[1] = DEG2RAD(-30.0f
);
2540 Source
->Radius
= 0.0f
;
2542 Source
->DistanceModel
= DefaultDistanceModel
;
2544 Source
->state
= AL_INITIAL
;
2545 Source
->new_state
= AL_NONE
;
2546 Source
->SourceType
= AL_UNDETERMINED
;
2547 Source
->OffsetType
= AL_NONE
;
2548 Source
->Offset
= 0.0;
2550 ATOMIC_INIT(&Source
->queue
, NULL
);
2551 ATOMIC_INIT(&Source
->current_buffer
, NULL
);
2553 Source
->Direct
.Gain
= 1.0f
;
2554 Source
->Direct
.GainHF
= 1.0f
;
2555 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
2556 Source
->Direct
.GainLF
= 1.0f
;
2557 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
2558 for(i
= 0;i
< MAX_SENDS
;i
++)
2560 Source
->Send
[i
].Gain
= 1.0f
;
2561 Source
->Send
[i
].GainHF
= 1.0f
;
2562 Source
->Send
[i
].HFReference
= LOWPASSFREQREF
;
2563 Source
->Send
[i
].GainLF
= 1.0f
;
2564 Source
->Send
[i
].LFReference
= HIGHPASSFREQREF
;
2567 ATOMIC_INIT(&Source
->NeedsUpdate
, AL_TRUE
);
2573 * Sets the source's new play state given its current state.
2575 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2577 WriteLock(&Source
->queue_lock
);
2578 if(state
== AL_PLAYING
)
2580 ALCdevice
*device
= Context
->Device
;
2581 ALbufferlistitem
*BufferList
;
2582 ALboolean discontinuity
;
2583 ALvoice
*voice
= NULL
;
2586 /* Check that there is a queue containing at least one valid, non zero
2588 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2592 if((buffer
=BufferList
->buffer
) != NULL
&& buffer
->SampleLen
> 0)
2594 BufferList
= BufferList
->next
;
2597 if(Source
->state
!= AL_PAUSED
)
2599 Source
->state
= AL_PLAYING
;
2600 Source
->position
= 0;
2601 Source
->position_fraction
= 0;
2602 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
2603 discontinuity
= AL_TRUE
;
2607 Source
->state
= AL_PLAYING
;
2608 discontinuity
= AL_FALSE
;
2611 // Check if an Offset has been set
2612 if(Source
->OffsetType
!= AL_NONE
)
2614 ApplyOffset(Source
);
2615 /* discontinuity = AL_TRUE;??? */
2618 /* If there's nothing to play, or device is disconnected, go right to
2620 if(!BufferList
|| !device
->Connected
)
2623 /* Make sure this source isn't already active, while looking for an
2624 * unused active source slot to put it in. */
2625 for(i
= 0;i
< Context
->VoiceCount
;i
++)
2627 ALsource
*old
= Source
;
2628 if(COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, NULL
))
2632 voice
= &Context
->Voices
[i
];
2633 voice
->Source
= Source
;
2638 if(voice
== NULL
&& COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, Source
))
2639 voice
= &Context
->Voices
[i
];
2643 voice
= &Context
->Voices
[Context
->VoiceCount
++];
2644 voice
->Source
= Source
;
2647 /* Clear previous samples if playback is discontinuous. */
2649 memset(voice
->PrevSamples
, 0, sizeof(voice
->PrevSamples
));
2651 voice
->Moving
= AL_FALSE
;
2652 for(i
= 0;i
< MAX_INPUT_CHANNELS
;i
++)
2655 for(j
= 0;j
< HRTF_HISTORY_LENGTH
;j
++)
2656 voice
->Direct
.Hrtf
[i
].State
.History
[j
] = 0.0f
;
2657 for(j
= 0;j
< HRIR_LENGTH
;j
++)
2659 voice
->Direct
.Hrtf
[i
].State
.Values
[j
][0] = 0.0f
;
2660 voice
->Direct
.Hrtf
[i
].State
.Values
[j
][1] = 0.0f
;
2664 if(BufferList
->buffer
->FmtChannels
== FmtMono
)
2665 voice
->Update
= CalcSourceParams
;
2667 voice
->Update
= CalcNonAttnSourceParams
;
2669 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
2671 else if(state
== AL_PAUSED
)
2673 if(Source
->state
== AL_PLAYING
)
2674 Source
->state
= AL_PAUSED
;
2676 else if(state
== AL_STOPPED
)
2679 if(Source
->state
!= AL_INITIAL
)
2681 Source
->state
= AL_STOPPED
;
2682 ATOMIC_STORE(&Source
->current_buffer
, NULL
);
2684 Source
->OffsetType
= AL_NONE
;
2685 Source
->Offset
= 0.0;
2687 else if(state
== AL_INITIAL
)
2689 if(Source
->state
!= AL_INITIAL
)
2691 Source
->state
= AL_INITIAL
;
2692 Source
->position
= 0;
2693 Source
->position_fraction
= 0;
2694 ATOMIC_STORE(&Source
->current_buffer
, ATOMIC_LOAD(&Source
->queue
));
2696 Source
->OffsetType
= AL_NONE
;
2697 Source
->Offset
= 0.0;
2699 WriteUnlock(&Source
->queue_lock
);
2702 /* GetSourceSampleOffset
2704 * Gets the current read offset for the given Source, in 32.32 fixed-point
2705 * samples. The offset is relative to the start of the queue (not the start of
2706 * the current buffer).
2708 ALint64
GetSourceSampleOffset(ALsource
*Source
)
2710 const ALbufferlistitem
*BufferList
;
2711 const ALbufferlistitem
*Current
;
2714 ReadLock(&Source
->queue_lock
);
2715 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2717 ReadUnlock(&Source
->queue_lock
);
2721 /* NOTE: This is the offset into the *current* buffer, so add the length of
2722 * any played buffers */
2723 readPos
= (ALuint64
)Source
->position
<< 32;
2724 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2725 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2726 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2727 while(BufferList
&& BufferList
!= Current
)
2729 if(BufferList
->buffer
)
2730 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2731 BufferList
= BufferList
->next
;
2734 ReadUnlock(&Source
->queue_lock
);
2735 return (ALint64
)minu64(readPos
, U64(0x7fffffffffffffff));
2738 /* GetSourceSecOffset
2740 * Gets the current read offset for the given Source, in seconds. The offset is
2741 * relative to the start of the queue (not the start of the current buffer).
2743 static ALdouble
GetSourceSecOffset(ALsource
*Source
)
2745 const ALbufferlistitem
*BufferList
;
2746 const ALbufferlistitem
*Current
;
2747 const ALbuffer
*Buffer
= NULL
;
2750 ReadLock(&Source
->queue_lock
);
2751 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2753 ReadUnlock(&Source
->queue_lock
);
2757 /* NOTE: This is the offset into the *current* buffer, so add the length of
2758 * any played buffers */
2759 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2760 readPos
|= (ALuint64
)Source
->position_fraction
;
2761 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2762 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2763 while(BufferList
&& BufferList
!= Current
)
2765 const ALbuffer
*buffer
= BufferList
->buffer
;
2768 if(!Buffer
) Buffer
= buffer
;
2769 readPos
+= (ALuint64
)buffer
->SampleLen
<< FRACTIONBITS
;
2771 BufferList
= BufferList
->next
;
2774 while(BufferList
&& !Buffer
)
2776 Buffer
= BufferList
->buffer
;
2777 BufferList
= BufferList
->next
;
2779 assert(Buffer
!= NULL
);
2781 ReadUnlock(&Source
->queue_lock
);
2782 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2787 * Gets the current read offset for the given Source, in the appropriate format
2788 * (Bytes, Samples or Seconds). The offset is relative to the start of the
2789 * queue (not the start of the current buffer).
2791 static ALdouble
GetSourceOffset(ALsource
*Source
, ALenum name
)
2793 const ALbufferlistitem
*BufferList
;
2794 const ALbufferlistitem
*Current
;
2795 const ALbuffer
*Buffer
= NULL
;
2796 ALboolean readFin
= AL_FALSE
;
2797 ALuint readPos
, readPosFrac
;
2798 ALuint totalBufferLen
;
2799 ALdouble offset
= 0.0;
2801 ReadLock(&Source
->queue_lock
);
2802 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2804 ReadUnlock(&Source
->queue_lock
);
2808 /* NOTE: This is the offset into the *current* buffer, so add the length of
2809 * any played buffers */
2811 readPos
= Source
->position
;
2812 readPosFrac
= Source
->position_fraction
;
2813 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2814 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2815 while(BufferList
!= NULL
)
2817 const ALbuffer
*buffer
;
2818 readFin
= readFin
|| (BufferList
== Current
);
2819 if((buffer
=BufferList
->buffer
) != NULL
)
2821 if(!Buffer
) Buffer
= buffer
;
2822 totalBufferLen
+= buffer
->SampleLen
;
2823 if(!readFin
) readPos
+= buffer
->SampleLen
;
2825 BufferList
= BufferList
->next
;
2827 assert(Buffer
!= NULL
);
2830 readPos
%= totalBufferLen
;
2833 /* Wrap back to 0 */
2834 if(readPos
>= totalBufferLen
)
2835 readPos
= readPosFrac
= 0;
2841 offset
= (readPos
+ (ALdouble
)readPosFrac
/FRACTIONONE
)/Buffer
->Frequency
;
2844 case AL_SAMPLE_OFFSET
:
2845 offset
= readPos
+ (ALdouble
)readPosFrac
/FRACTIONONE
;
2848 case AL_BYTE_OFFSET
:
2849 if(Buffer
->OriginalType
== UserFmtIMA4
)
2851 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
2852 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2853 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2855 /* Round down to nearest ADPCM block */
2856 offset
= (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2858 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
2860 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
2861 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2862 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2864 /* Round down to nearest ADPCM block */
2865 offset
= (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2869 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2870 offset
= (ALdouble
)(readPos
* FrameSize
);
2875 ReadUnlock(&Source
->queue_lock
);
2882 * Apply the stored playback offset to the Source. This function will update
2883 * the number of buffers "played" given the stored offset.
2885 ALboolean
ApplyOffset(ALsource
*Source
)
2887 ALbufferlistitem
*BufferList
;
2888 const ALbuffer
*Buffer
;
2889 ALuint bufferLen
, totalBufferLen
;
2890 ALuint offset
=0, frac
=0;
2892 /* Get sample frame offset */
2893 if(!GetSampleOffset(Source
, &offset
, &frac
))
2897 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2898 while(BufferList
&& totalBufferLen
<= offset
)
2900 Buffer
= BufferList
->buffer
;
2901 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2903 if(bufferLen
> offset
-totalBufferLen
)
2905 /* Offset is in this buffer */
2906 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
2908 Source
->position
= offset
- totalBufferLen
;
2909 Source
->position_fraction
= frac
;
2913 totalBufferLen
+= bufferLen
;
2915 BufferList
= BufferList
->next
;
2918 /* Offset is out of range of the queue */
2925 * Retrieves the sample offset into the Source's queue (from the Sample, Byte
2926 * or Second offset supplied by the application). This takes into account the
2927 * fact that the buffer format may have been modifed since.
2929 static ALboolean
GetSampleOffset(ALsource
*Source
, ALuint
*offset
, ALuint
*frac
)
2931 const ALbuffer
*Buffer
= NULL
;
2932 const ALbufferlistitem
*BufferList
;
2933 ALdouble dbloff
, dblfrac
;
2935 /* Find the first valid Buffer in the Queue */
2936 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2939 if(BufferList
->buffer
)
2941 Buffer
= BufferList
->buffer
;
2944 BufferList
= BufferList
->next
;
2948 Source
->OffsetType
= AL_NONE
;
2949 Source
->Offset
= 0.0;
2953 switch(Source
->OffsetType
)
2955 case AL_BYTE_OFFSET
:
2956 /* Determine the ByteOffset (and ensure it is block aligned) */
2957 *offset
= (ALuint
)Source
->Offset
;
2958 if(Buffer
->OriginalType
== UserFmtIMA4
)
2960 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
2961 *offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2962 *offset
*= Buffer
->OriginalAlign
;
2964 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
2966 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
2967 *offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2968 *offset
*= Buffer
->OriginalAlign
;
2971 *offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2975 case AL_SAMPLE_OFFSET
:
2976 dblfrac
= modf(Source
->Offset
, &dbloff
);
2977 *offset
= (ALuint
)mind(dbloff
, UINT_MAX
);
2978 *frac
= (ALuint
)mind(dblfrac
*FRACTIONONE
, FRACTIONONE
-1.0);
2982 dblfrac
= modf(Source
->Offset
*Buffer
->Frequency
, &dbloff
);
2983 *offset
= (ALuint
)mind(dbloff
, UINT_MAX
);
2984 *frac
= (ALuint
)mind(dblfrac
*FRACTIONONE
, FRACTIONONE
-1.0);
2987 Source
->OffsetType
= AL_NONE
;
2988 Source
->Offset
= 0.0;
2996 * Destroys all sources in the source map.
2998 ALvoid
ReleaseALSources(ALCcontext
*Context
)
3000 ALbufferlistitem
*item
;
3003 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
3005 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
3006 Context
->SourceMap
.array
[pos
].value
= NULL
;
3008 item
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &temp
->queue
, NULL
);
3011 ALbufferlistitem
*next
= item
->next
;
3012 if(item
->buffer
!= NULL
)
3013 DecrementRef(&item
->buffer
->ref
);
3018 for(j
= 0;j
< MAX_SENDS
;++j
)
3020 if(temp
->Send
[j
].Slot
)
3021 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
3022 temp
->Send
[j
].Slot
= NULL
;
3025 FreeThunkEntry(temp
->id
);
3026 memset(temp
, 0, sizeof(*temp
));