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 ALvoid
GetSourceOffsets(ALsource
*Source
, ALenum name
, ALdouble
*offsets
, ALdouble updateLen
);
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_buffer_sub_data / AL_SOFT_buffer_samples */
101 srcSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
102 srcByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
104 /* AL_SOFT_source_latency */
105 srcSampleOffsetLatencySOFT
= AL_SAMPLE_OFFSET_LATENCY_SOFT
,
106 srcSecOffsetLatencySOFT
= AL_SEC_OFFSET_LATENCY_SOFT
,
108 /* AL_EXT_STEREO_ANGLES */
109 srcAngles
= AL_STEREO_ANGLES
,
112 srcOrientation
= AL_ORIENTATION
,
115 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALfloat
*values
);
116 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint
*values
);
117 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint64SOFT
*values
);
119 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALdouble
*values
);
120 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint
*values
);
121 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint64
*values
);
123 static ALint
FloatValsByProp(ALenum prop
)
125 if(prop
!= (ALenum
)((SourceProp
)prop
))
127 switch((SourceProp
)prop
)
133 case AL_MAX_DISTANCE
:
134 case AL_ROLLOFF_FACTOR
:
135 case AL_DOPPLER_FACTOR
:
136 case AL_CONE_OUTER_GAIN
:
138 case AL_SAMPLE_OFFSET
:
140 case AL_CONE_INNER_ANGLE
:
141 case AL_CONE_OUTER_ANGLE
:
142 case AL_REFERENCE_DISTANCE
:
143 case AL_CONE_OUTER_GAINHF
:
144 case AL_AIR_ABSORPTION_FACTOR
:
145 case AL_ROOM_ROLLOFF_FACTOR
:
146 case AL_DIRECT_FILTER_GAINHF_AUTO
:
147 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
148 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
149 case AL_DIRECT_CHANNELS_SOFT
:
150 case AL_DISTANCE_MODEL
:
151 case AL_SOURCE_RELATIVE
:
153 case AL_SOURCE_STATE
:
154 case AL_BUFFERS_QUEUED
:
155 case AL_BUFFERS_PROCESSED
:
157 case AL_BYTE_LENGTH_SOFT
:
158 case AL_SAMPLE_LENGTH_SOFT
:
159 case AL_SEC_LENGTH_SOFT
:
162 case AL_SAMPLE_RW_OFFSETS_SOFT
:
163 case AL_BYTE_RW_OFFSETS_SOFT
:
164 case AL_STEREO_ANGLES
:
175 case AL_SEC_OFFSET_LATENCY_SOFT
:
176 break; /* Double only */
179 case AL_DIRECT_FILTER
:
180 case AL_AUXILIARY_SEND_FILTER
:
181 break; /* i/i64 only */
182 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
183 break; /* i64 only */
187 static ALint
DoubleValsByProp(ALenum prop
)
189 if(prop
!= (ALenum
)((SourceProp
)prop
))
191 switch((SourceProp
)prop
)
197 case AL_MAX_DISTANCE
:
198 case AL_ROLLOFF_FACTOR
:
199 case AL_DOPPLER_FACTOR
:
200 case AL_CONE_OUTER_GAIN
:
202 case AL_SAMPLE_OFFSET
:
204 case AL_CONE_INNER_ANGLE
:
205 case AL_CONE_OUTER_ANGLE
:
206 case AL_REFERENCE_DISTANCE
:
207 case AL_CONE_OUTER_GAINHF
:
208 case AL_AIR_ABSORPTION_FACTOR
:
209 case AL_ROOM_ROLLOFF_FACTOR
:
210 case AL_DIRECT_FILTER_GAINHF_AUTO
:
211 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
212 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
213 case AL_DIRECT_CHANNELS_SOFT
:
214 case AL_DISTANCE_MODEL
:
215 case AL_SOURCE_RELATIVE
:
217 case AL_SOURCE_STATE
:
218 case AL_BUFFERS_QUEUED
:
219 case AL_BUFFERS_PROCESSED
:
221 case AL_BYTE_LENGTH_SOFT
:
222 case AL_SAMPLE_LENGTH_SOFT
:
223 case AL_SEC_LENGTH_SOFT
:
226 case AL_SAMPLE_RW_OFFSETS_SOFT
:
227 case AL_BYTE_RW_OFFSETS_SOFT
:
228 case AL_SEC_OFFSET_LATENCY_SOFT
:
229 case AL_STEREO_ANGLES
:
241 case AL_DIRECT_FILTER
:
242 case AL_AUXILIARY_SEND_FILTER
:
243 break; /* i/i64 only */
244 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
245 break; /* i64 only */
250 static ALint
IntValsByProp(ALenum prop
)
252 if(prop
!= (ALenum
)((SourceProp
)prop
))
254 switch((SourceProp
)prop
)
260 case AL_MAX_DISTANCE
:
261 case AL_ROLLOFF_FACTOR
:
262 case AL_DOPPLER_FACTOR
:
263 case AL_CONE_OUTER_GAIN
:
265 case AL_SAMPLE_OFFSET
:
267 case AL_CONE_INNER_ANGLE
:
268 case AL_CONE_OUTER_ANGLE
:
269 case AL_REFERENCE_DISTANCE
:
270 case AL_CONE_OUTER_GAINHF
:
271 case AL_AIR_ABSORPTION_FACTOR
:
272 case AL_ROOM_ROLLOFF_FACTOR
:
273 case AL_DIRECT_FILTER_GAINHF_AUTO
:
274 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
275 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
276 case AL_DIRECT_CHANNELS_SOFT
:
277 case AL_DISTANCE_MODEL
:
278 case AL_SOURCE_RELATIVE
:
281 case AL_SOURCE_STATE
:
282 case AL_BUFFERS_QUEUED
:
283 case AL_BUFFERS_PROCESSED
:
285 case AL_DIRECT_FILTER
:
286 case AL_BYTE_LENGTH_SOFT
:
287 case AL_SAMPLE_LENGTH_SOFT
:
288 case AL_SEC_LENGTH_SOFT
:
291 case AL_SAMPLE_RW_OFFSETS_SOFT
:
292 case AL_BYTE_RW_OFFSETS_SOFT
:
298 case AL_AUXILIARY_SEND_FILTER
:
304 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
305 break; /* i64 only */
306 case AL_SEC_OFFSET_LATENCY_SOFT
:
307 break; /* Double only */
308 case AL_STEREO_ANGLES
:
309 break; /* Float/double only */
313 static ALint
Int64ValsByProp(ALenum prop
)
315 if(prop
!= (ALenum
)((SourceProp
)prop
))
317 switch((SourceProp
)prop
)
323 case AL_MAX_DISTANCE
:
324 case AL_ROLLOFF_FACTOR
:
325 case AL_DOPPLER_FACTOR
:
326 case AL_CONE_OUTER_GAIN
:
328 case AL_SAMPLE_OFFSET
:
330 case AL_CONE_INNER_ANGLE
:
331 case AL_CONE_OUTER_ANGLE
:
332 case AL_REFERENCE_DISTANCE
:
333 case AL_CONE_OUTER_GAINHF
:
334 case AL_AIR_ABSORPTION_FACTOR
:
335 case AL_ROOM_ROLLOFF_FACTOR
:
336 case AL_DIRECT_FILTER_GAINHF_AUTO
:
337 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
338 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
339 case AL_DIRECT_CHANNELS_SOFT
:
340 case AL_DISTANCE_MODEL
:
341 case AL_SOURCE_RELATIVE
:
344 case AL_SOURCE_STATE
:
345 case AL_BUFFERS_QUEUED
:
346 case AL_BUFFERS_PROCESSED
:
348 case AL_DIRECT_FILTER
:
349 case AL_BYTE_LENGTH_SOFT
:
350 case AL_SAMPLE_LENGTH_SOFT
:
351 case AL_SEC_LENGTH_SOFT
:
354 case AL_SAMPLE_RW_OFFSETS_SOFT
:
355 case AL_BYTE_RW_OFFSETS_SOFT
:
356 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
362 case AL_AUXILIARY_SEND_FILTER
:
368 case AL_SEC_OFFSET_LATENCY_SOFT
:
369 break; /* Double only */
370 case AL_STEREO_ANGLES
:
371 break; /* Float/double only */
377 #define CHECKVAL(x) do { \
379 SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); \
382 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALfloat
*values
)
388 case AL_BYTE_RW_OFFSETS_SOFT
:
389 case AL_SAMPLE_RW_OFFSETS_SOFT
:
390 case AL_BYTE_LENGTH_SOFT
:
391 case AL_SAMPLE_LENGTH_SOFT
:
392 case AL_SEC_LENGTH_SOFT
:
393 case AL_SEC_OFFSET_LATENCY_SOFT
:
395 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
398 CHECKVAL(*values
>= 0.0f
);
400 Source
->Pitch
= *values
;
401 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
404 case AL_CONE_INNER_ANGLE
:
405 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
407 Source
->InnerAngle
= *values
;
408 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
411 case AL_CONE_OUTER_ANGLE
:
412 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
414 Source
->OuterAngle
= *values
;
415 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
419 CHECKVAL(*values
>= 0.0f
);
421 Source
->Gain
= *values
;
422 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
425 case AL_MAX_DISTANCE
:
426 CHECKVAL(*values
>= 0.0f
);
428 Source
->MaxDistance
= *values
;
429 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
432 case AL_ROLLOFF_FACTOR
:
433 CHECKVAL(*values
>= 0.0f
);
435 Source
->RollOffFactor
= *values
;
436 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
439 case AL_REFERENCE_DISTANCE
:
440 CHECKVAL(*values
>= 0.0f
);
442 Source
->RefDistance
= *values
;
443 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
447 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
449 Source
->MinGain
= *values
;
450 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
454 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
456 Source
->MaxGain
= *values
;
457 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
460 case AL_CONE_OUTER_GAIN
:
461 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
463 Source
->OuterGain
= *values
;
464 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
467 case AL_CONE_OUTER_GAINHF
:
468 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
470 Source
->OuterGainHF
= *values
;
471 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
474 case AL_AIR_ABSORPTION_FACTOR
:
475 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
477 Source
->AirAbsorptionFactor
= *values
;
478 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
481 case AL_ROOM_ROLLOFF_FACTOR
:
482 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
484 Source
->RoomRolloffFactor
= *values
;
485 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
488 case AL_DOPPLER_FACTOR
:
489 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
491 Source
->DopplerFactor
= *values
;
492 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
496 case AL_SAMPLE_OFFSET
:
498 CHECKVAL(*values
>= 0.0f
);
500 LockContext(Context
);
501 Source
->OffsetType
= prop
;
502 Source
->Offset
= *values
;
504 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
505 !Context
->DeferUpdates
)
507 WriteLock(&Source
->queue_lock
);
508 if(ApplyOffset(Source
) == AL_FALSE
)
510 WriteUnlock(&Source
->queue_lock
);
511 UnlockContext(Context
);
512 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
514 WriteUnlock(&Source
->queue_lock
);
516 UnlockContext(Context
);
520 case AL_STEREO_ANGLES
:
521 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]));
523 LockContext(Context
);
524 Source
->StereoPan
[0] = values
[0];
525 Source
->StereoPan
[1] = values
[1];
526 UnlockContext(Context
);
527 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
532 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
534 LockContext(Context
);
535 aluVectorSet(&Source
->Position
, values
[0], values
[1], values
[2], 1.0f
);
536 UnlockContext(Context
);
537 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
541 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
543 LockContext(Context
);
544 aluVectorSet(&Source
->Velocity
, values
[0], values
[1], values
[2], 0.0f
);
545 UnlockContext(Context
);
546 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
550 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
552 LockContext(Context
);
553 aluVectorSet(&Source
->Direction
, values
[0], values
[1], values
[2], 0.0f
);
554 UnlockContext(Context
);
555 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
559 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]) &&
560 isfinite(values
[3]) && isfinite(values
[4]) && isfinite(values
[5]));
562 LockContext(Context
);
563 Source
->Orientation
[0][0] = values
[0];
564 Source
->Orientation
[0][1] = values
[1];
565 Source
->Orientation
[0][2] = values
[2];
566 Source
->Orientation
[1][0] = values
[3];
567 Source
->Orientation
[1][1] = values
[4];
568 Source
->Orientation
[1][2] = values
[5];
569 UnlockContext(Context
);
570 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
574 case AL_SOURCE_RELATIVE
:
576 case AL_SOURCE_STATE
:
578 case AL_DISTANCE_MODEL
:
579 case AL_DIRECT_FILTER_GAINHF_AUTO
:
580 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
581 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
582 case AL_DIRECT_CHANNELS_SOFT
:
583 ival
= (ALint
)values
[0];
584 return SetSourceiv(Source
, Context
, prop
, &ival
);
586 case AL_BUFFERS_QUEUED
:
587 case AL_BUFFERS_PROCESSED
:
588 ival
= (ALint
)((ALuint
)values
[0]);
589 return SetSourceiv(Source
, Context
, prop
, &ival
);
592 case AL_DIRECT_FILTER
:
593 case AL_AUXILIARY_SEND_FILTER
:
594 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
598 ERR("Unexpected property: 0x%04x\n", prop
);
599 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
602 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint
*values
)
604 ALCdevice
*device
= Context
->Device
;
605 ALbuffer
*buffer
= NULL
;
606 ALfilter
*filter
= NULL
;
607 ALeffectslot
*slot
= NULL
;
608 ALbufferlistitem
*oldlist
;
609 ALbufferlistitem
*newlist
;
614 case AL_SOURCE_STATE
:
616 case AL_BUFFERS_QUEUED
:
617 case AL_BUFFERS_PROCESSED
:
618 case AL_SAMPLE_RW_OFFSETS_SOFT
:
619 case AL_BYTE_RW_OFFSETS_SOFT
:
620 case AL_BYTE_LENGTH_SOFT
:
621 case AL_SAMPLE_LENGTH_SOFT
:
622 case AL_SEC_LENGTH_SOFT
:
624 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
626 case AL_SOURCE_RELATIVE
:
627 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
629 Source
->HeadRelative
= (ALboolean
)*values
;
630 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
634 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
636 Source
->Looping
= (ALboolean
)*values
;
640 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
642 WriteLock(&Source
->queue_lock
);
643 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
645 WriteUnlock(&Source
->queue_lock
);
646 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
651 /* Add the selected buffer to a one-item queue */
652 newlist
= malloc(sizeof(ALbufferlistitem
));
653 newlist
->buffer
= buffer
;
654 newlist
->next
= NULL
;
655 IncrementRef(&buffer
->ref
);
657 /* Source is now Static */
658 Source
->SourceType
= AL_STATIC
;
660 ReadLock(&buffer
->lock
);
661 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
662 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
663 ReadUnlock(&buffer
->lock
);
667 /* Source is now Undetermined */
668 Source
->SourceType
= AL_UNDETERMINED
;
671 oldlist
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &Source
->queue
, newlist
);
672 ATOMIC_STORE(&Source
->current_buffer
, newlist
);
673 WriteUnlock(&Source
->queue_lock
);
675 /* Delete all elements in the previous queue */
676 while(oldlist
!= NULL
)
678 ALbufferlistitem
*temp
= oldlist
;
679 oldlist
= temp
->next
;
682 DecrementRef(&temp
->buffer
->ref
);
688 case AL_SAMPLE_OFFSET
:
690 CHECKVAL(*values
>= 0);
692 LockContext(Context
);
693 Source
->OffsetType
= prop
;
694 Source
->Offset
= *values
;
696 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
697 !Context
->DeferUpdates
)
699 WriteLock(&Source
->queue_lock
);
700 if(ApplyOffset(Source
) == AL_FALSE
)
702 WriteUnlock(&Source
->queue_lock
);
703 UnlockContext(Context
);
704 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
706 WriteUnlock(&Source
->queue_lock
);
708 UnlockContext(Context
);
711 case AL_DIRECT_FILTER
:
712 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
714 LockContext(Context
);
717 Source
->Direct
.Gain
= 1.0f
;
718 Source
->Direct
.GainHF
= 1.0f
;
719 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
720 Source
->Direct
.GainLF
= 1.0f
;
721 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
725 Source
->Direct
.Gain
= filter
->Gain
;
726 Source
->Direct
.GainHF
= filter
->GainHF
;
727 Source
->Direct
.HFReference
= filter
->HFReference
;
728 Source
->Direct
.GainLF
= filter
->GainLF
;
729 Source
->Direct
.LFReference
= filter
->LFReference
;
731 UnlockContext(Context
);
732 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
735 case AL_DIRECT_FILTER_GAINHF_AUTO
:
736 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
738 Source
->DryGainHFAuto
= *values
;
739 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
742 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
743 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
745 Source
->WetGainAuto
= *values
;
746 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
749 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
750 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
752 Source
->WetGainHFAuto
= *values
;
753 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
756 case AL_DIRECT_CHANNELS_SOFT
:
757 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
759 Source
->DirectChannels
= *values
;
760 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
763 case AL_DISTANCE_MODEL
:
764 CHECKVAL(*values
== AL_NONE
||
765 *values
== AL_INVERSE_DISTANCE
||
766 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
767 *values
== AL_LINEAR_DISTANCE
||
768 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
769 *values
== AL_EXPONENT_DISTANCE
||
770 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
772 Source
->DistanceModel
= *values
;
773 if(Context
->SourceDistanceModel
)
774 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
778 case AL_AUXILIARY_SEND_FILTER
:
779 LockContext(Context
);
780 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
781 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
782 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
784 UnlockContext(Context
);
785 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
788 /* Add refcount on the new slot, and release the previous slot */
789 if(slot
) IncrementRef(&slot
->ref
);
790 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
791 if(slot
) DecrementRef(&slot
->ref
);
796 Source
->Send
[values
[1]].Gain
= 1.0f
;
797 Source
->Send
[values
[1]].GainHF
= 1.0f
;
798 Source
->Send
[values
[1]].HFReference
= LOWPASSFREQREF
;
799 Source
->Send
[values
[1]].GainLF
= 1.0f
;
800 Source
->Send
[values
[1]].LFReference
= HIGHPASSFREQREF
;
804 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
805 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
806 Source
->Send
[values
[1]].HFReference
= filter
->HFReference
;
807 Source
->Send
[values
[1]].GainLF
= filter
->GainLF
;
808 Source
->Send
[values
[1]].LFReference
= filter
->LFReference
;
810 UnlockContext(Context
);
811 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
816 case AL_CONE_INNER_ANGLE
:
817 case AL_CONE_OUTER_ANGLE
:
822 case AL_REFERENCE_DISTANCE
:
823 case AL_ROLLOFF_FACTOR
:
824 case AL_CONE_OUTER_GAIN
:
825 case AL_MAX_DISTANCE
:
826 case AL_DOPPLER_FACTOR
:
827 case AL_CONE_OUTER_GAINHF
:
828 case AL_AIR_ABSORPTION_FACTOR
:
829 case AL_ROOM_ROLLOFF_FACTOR
:
830 fvals
[0] = (ALfloat
)*values
;
831 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
837 fvals
[0] = (ALfloat
)values
[0];
838 fvals
[1] = (ALfloat
)values
[1];
839 fvals
[2] = (ALfloat
)values
[2];
840 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
844 fvals
[0] = (ALfloat
)values
[0];
845 fvals
[1] = (ALfloat
)values
[1];
846 fvals
[2] = (ALfloat
)values
[2];
847 fvals
[3] = (ALfloat
)values
[3];
848 fvals
[4] = (ALfloat
)values
[4];
849 fvals
[5] = (ALfloat
)values
[5];
850 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
852 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
853 case AL_SEC_OFFSET_LATENCY_SOFT
:
854 case AL_STEREO_ANGLES
:
858 ERR("Unexpected property: 0x%04x\n", prop
);
859 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
862 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint64SOFT
*values
)
870 case AL_BUFFERS_QUEUED
:
871 case AL_BUFFERS_PROCESSED
:
872 case AL_SOURCE_STATE
:
873 case AL_SAMPLE_RW_OFFSETS_SOFT
:
874 case AL_BYTE_RW_OFFSETS_SOFT
:
875 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
876 case AL_BYTE_LENGTH_SOFT
:
877 case AL_SAMPLE_LENGTH_SOFT
:
878 case AL_SEC_LENGTH_SOFT
:
880 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
884 case AL_SOURCE_RELATIVE
:
887 case AL_SAMPLE_OFFSET
:
889 case AL_DIRECT_FILTER_GAINHF_AUTO
:
890 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
891 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
892 case AL_DIRECT_CHANNELS_SOFT
:
893 case AL_DISTANCE_MODEL
:
894 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
896 ivals
[0] = (ALint
)*values
;
897 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
901 case AL_DIRECT_FILTER
:
902 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
904 ivals
[0] = (ALuint
)*values
;
905 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
908 case AL_AUXILIARY_SEND_FILTER
:
909 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
910 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
911 values
[2] <= UINT_MAX
&& values
[2] >= 0);
913 ivals
[0] = (ALuint
)values
[0];
914 ivals
[1] = (ALuint
)values
[1];
915 ivals
[2] = (ALuint
)values
[2];
916 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
919 case AL_CONE_INNER_ANGLE
:
920 case AL_CONE_OUTER_ANGLE
:
925 case AL_REFERENCE_DISTANCE
:
926 case AL_ROLLOFF_FACTOR
:
927 case AL_CONE_OUTER_GAIN
:
928 case AL_MAX_DISTANCE
:
929 case AL_DOPPLER_FACTOR
:
930 case AL_CONE_OUTER_GAINHF
:
931 case AL_AIR_ABSORPTION_FACTOR
:
932 case AL_ROOM_ROLLOFF_FACTOR
:
933 fvals
[0] = (ALfloat
)*values
;
934 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
940 fvals
[0] = (ALfloat
)values
[0];
941 fvals
[1] = (ALfloat
)values
[1];
942 fvals
[2] = (ALfloat
)values
[2];
943 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
947 fvals
[0] = (ALfloat
)values
[0];
948 fvals
[1] = (ALfloat
)values
[1];
949 fvals
[2] = (ALfloat
)values
[2];
950 fvals
[3] = (ALfloat
)values
[3];
951 fvals
[4] = (ALfloat
)values
[4];
952 fvals
[5] = (ALfloat
)values
[5];
953 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
955 case AL_SEC_OFFSET_LATENCY_SOFT
:
956 case AL_STEREO_ANGLES
:
960 ERR("Unexpected property: 0x%04x\n", prop
);
961 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
967 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALdouble
*values
)
969 ALCdevice
*device
= Context
->Device
;
970 ALbufferlistitem
*BufferList
;
979 *values
= Source
->Gain
;
983 *values
= Source
->Pitch
;
986 case AL_MAX_DISTANCE
:
987 *values
= Source
->MaxDistance
;
990 case AL_ROLLOFF_FACTOR
:
991 *values
= Source
->RollOffFactor
;
994 case AL_REFERENCE_DISTANCE
:
995 *values
= Source
->RefDistance
;
998 case AL_CONE_INNER_ANGLE
:
999 *values
= Source
->InnerAngle
;
1002 case AL_CONE_OUTER_ANGLE
:
1003 *values
= Source
->OuterAngle
;
1007 *values
= Source
->MinGain
;
1011 *values
= Source
->MaxGain
;
1014 case AL_CONE_OUTER_GAIN
:
1015 *values
= Source
->OuterGain
;
1019 case AL_SAMPLE_OFFSET
:
1020 case AL_BYTE_OFFSET
:
1021 LockContext(Context
);
1022 GetSourceOffsets(Source
, prop
, offsets
, 0.0);
1023 UnlockContext(Context
);
1024 *values
= offsets
[0];
1027 case AL_CONE_OUTER_GAINHF
:
1028 *values
= Source
->OuterGainHF
;
1031 case AL_AIR_ABSORPTION_FACTOR
:
1032 *values
= Source
->AirAbsorptionFactor
;
1035 case AL_ROOM_ROLLOFF_FACTOR
:
1036 *values
= Source
->RoomRolloffFactor
;
1039 case AL_DOPPLER_FACTOR
:
1040 *values
= Source
->DopplerFactor
;
1043 case AL_SEC_LENGTH_SOFT
:
1044 ReadLock(&Source
->queue_lock
);
1045 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1052 ALbuffer
*buffer
= BufferList
->buffer
;
1053 if(buffer
&& buffer
->SampleLen
> 0)
1055 freq
= buffer
->Frequency
;
1056 length
+= buffer
->SampleLen
;
1058 } while((BufferList
=BufferList
->next
) != NULL
);
1059 *values
= (ALdouble
)length
/ (ALdouble
)freq
;
1061 ReadUnlock(&Source
->queue_lock
);
1064 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1065 case AL_BYTE_RW_OFFSETS_SOFT
:
1066 LockContext(Context
);
1067 updateLen
= (ALdouble
)device
->UpdateSize
/ device
->Frequency
;
1068 GetSourceOffsets(Source
, prop
, values
, updateLen
);
1069 UnlockContext(Context
);
1072 case AL_SEC_OFFSET_LATENCY_SOFT
:
1073 LockContext(Context
);
1074 values
[0] = GetSourceSecOffset(Source
);
1075 values
[1] = (ALdouble
)(V0(device
->Backend
,getLatency
)()) /
1077 UnlockContext(Context
);
1080 case AL_STEREO_ANGLES
:
1081 LockContext(Context
);
1082 values
[0] = Source
->StereoPan
[0];
1083 values
[1] = Source
->StereoPan
[1];
1084 UnlockContext(Context
);
1088 LockContext(Context
);
1089 values
[0] = Source
->Position
.v
[0];
1090 values
[1] = Source
->Position
.v
[1];
1091 values
[2] = Source
->Position
.v
[2];
1092 UnlockContext(Context
);
1096 LockContext(Context
);
1097 values
[0] = Source
->Velocity
.v
[0];
1098 values
[1] = Source
->Velocity
.v
[1];
1099 values
[2] = Source
->Velocity
.v
[2];
1100 UnlockContext(Context
);
1104 LockContext(Context
);
1105 values
[0] = Source
->Direction
.v
[0];
1106 values
[1] = Source
->Direction
.v
[1];
1107 values
[2] = Source
->Direction
.v
[2];
1108 UnlockContext(Context
);
1111 case AL_ORIENTATION
:
1112 LockContext(Context
);
1113 values
[0] = Source
->Orientation
[0][0];
1114 values
[1] = Source
->Orientation
[0][1];
1115 values
[2] = Source
->Orientation
[0][2];
1116 values
[3] = Source
->Orientation
[1][0];
1117 values
[4] = Source
->Orientation
[1][1];
1118 values
[5] = Source
->Orientation
[1][2];
1119 UnlockContext(Context
);
1123 case AL_SOURCE_RELATIVE
:
1125 case AL_SOURCE_STATE
:
1126 case AL_BUFFERS_QUEUED
:
1127 case AL_BUFFERS_PROCESSED
:
1128 case AL_SOURCE_TYPE
:
1129 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1130 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1131 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1132 case AL_DIRECT_CHANNELS_SOFT
:
1133 case AL_BYTE_LENGTH_SOFT
:
1134 case AL_SAMPLE_LENGTH_SOFT
:
1135 case AL_DISTANCE_MODEL
:
1136 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1137 *values
= (ALdouble
)ivals
[0];
1141 case AL_DIRECT_FILTER
:
1142 case AL_AUXILIARY_SEND_FILTER
:
1143 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1147 ERR("Unexpected property: 0x%04x\n", prop
);
1148 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1151 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint
*values
)
1153 ALbufferlistitem
*BufferList
;
1159 case AL_SOURCE_RELATIVE
:
1160 *values
= Source
->HeadRelative
;
1164 *values
= Source
->Looping
;
1168 ReadLock(&Source
->queue_lock
);
1169 BufferList
= (Source
->SourceType
== AL_STATIC
) ? ATOMIC_LOAD(&Source
->queue
) :
1170 ATOMIC_LOAD(&Source
->current_buffer
);
1171 *values
= (BufferList
&& BufferList
->buffer
) ? BufferList
->buffer
->id
: 0;
1172 ReadUnlock(&Source
->queue_lock
);
1175 case AL_SOURCE_STATE
:
1176 *values
= Source
->state
;
1179 case AL_BYTE_LENGTH_SOFT
:
1180 ReadLock(&Source
->queue_lock
);
1181 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1187 ALbuffer
*buffer
= BufferList
->buffer
;
1188 if(buffer
&& buffer
->SampleLen
> 0)
1190 ALuint byte_align
, sample_align
;
1191 if(buffer
->OriginalType
== UserFmtIMA4
)
1193 ALsizei align
= (buffer
->OriginalAlign
-1)/2 + 4;
1194 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1195 sample_align
= buffer
->OriginalAlign
;
1197 else if(buffer
->OriginalType
== UserFmtMSADPCM
)
1199 ALsizei align
= (buffer
->OriginalAlign
-2)/2 + 7;
1200 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1201 sample_align
= buffer
->OriginalAlign
;
1205 ALsizei align
= buffer
->OriginalAlign
;
1206 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1207 sample_align
= buffer
->OriginalAlign
;
1210 length
+= buffer
->SampleLen
/ sample_align
* byte_align
;
1212 } while((BufferList
=BufferList
->next
) != NULL
);
1215 ReadUnlock(&Source
->queue_lock
);
1218 case AL_SAMPLE_LENGTH_SOFT
:
1219 ReadLock(&Source
->queue_lock
);
1220 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1226 ALbuffer
*buffer
= BufferList
->buffer
;
1227 if(buffer
) length
+= buffer
->SampleLen
;
1228 } while((BufferList
=BufferList
->next
) != NULL
);
1231 ReadUnlock(&Source
->queue_lock
);
1234 case AL_BUFFERS_QUEUED
:
1235 ReadLock(&Source
->queue_lock
);
1236 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1243 } while((BufferList
=BufferList
->next
) != NULL
);
1246 ReadUnlock(&Source
->queue_lock
);
1249 case AL_BUFFERS_PROCESSED
:
1250 ReadLock(&Source
->queue_lock
);
1251 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
1253 /* Buffers on a looping source are in a perpetual state of
1254 * PENDING, so don't report any as PROCESSED */
1259 const ALbufferlistitem
*BufferList
= ATOMIC_LOAD(&Source
->queue
);
1260 const ALbufferlistitem
*Current
= ATOMIC_LOAD(&Source
->current_buffer
);
1262 while(BufferList
&& BufferList
!= Current
)
1265 BufferList
= BufferList
->next
;
1269 ReadUnlock(&Source
->queue_lock
);
1272 case AL_SOURCE_TYPE
:
1273 *values
= Source
->SourceType
;
1276 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1277 *values
= Source
->DryGainHFAuto
;
1280 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1281 *values
= Source
->WetGainAuto
;
1284 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1285 *values
= Source
->WetGainHFAuto
;
1288 case AL_DIRECT_CHANNELS_SOFT
:
1289 *values
= Source
->DirectChannels
;
1292 case AL_DISTANCE_MODEL
:
1293 *values
= Source
->DistanceModel
;
1296 /* 1x float/double */
1297 case AL_CONE_INNER_ANGLE
:
1298 case AL_CONE_OUTER_ANGLE
:
1303 case AL_REFERENCE_DISTANCE
:
1304 case AL_ROLLOFF_FACTOR
:
1305 case AL_CONE_OUTER_GAIN
:
1306 case AL_MAX_DISTANCE
:
1308 case AL_SAMPLE_OFFSET
:
1309 case AL_BYTE_OFFSET
:
1310 case AL_DOPPLER_FACTOR
:
1311 case AL_AIR_ABSORPTION_FACTOR
:
1312 case AL_ROOM_ROLLOFF_FACTOR
:
1313 case AL_CONE_OUTER_GAINHF
:
1314 case AL_SEC_LENGTH_SOFT
:
1315 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1316 *values
= (ALint
)dvals
[0];
1319 /* 2x float/double */
1320 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1321 case AL_BYTE_RW_OFFSETS_SOFT
:
1322 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1324 values
[0] = (ALint
)dvals
[0];
1325 values
[1] = (ALint
)dvals
[1];
1329 /* 3x float/double */
1333 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1335 values
[0] = (ALint
)dvals
[0];
1336 values
[1] = (ALint
)dvals
[1];
1337 values
[2] = (ALint
)dvals
[2];
1341 /* 6x float/double */
1342 case AL_ORIENTATION
:
1343 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1345 values
[0] = (ALint
)dvals
[0];
1346 values
[1] = (ALint
)dvals
[1];
1347 values
[2] = (ALint
)dvals
[2];
1348 values
[3] = (ALint
)dvals
[3];
1349 values
[4] = (ALint
)dvals
[4];
1350 values
[5] = (ALint
)dvals
[5];
1354 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1355 break; /* i64 only */
1356 case AL_SEC_OFFSET_LATENCY_SOFT
:
1357 break; /* Double only */
1358 case AL_STEREO_ANGLES
:
1359 break; /* Float/double only */
1361 case AL_DIRECT_FILTER
:
1362 case AL_AUXILIARY_SEND_FILTER
:
1366 ERR("Unexpected property: 0x%04x\n", prop
);
1367 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1370 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint64
*values
)
1372 ALCdevice
*device
= Context
->Device
;
1379 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1380 LockContext(Context
);
1381 values
[0] = GetSourceSampleOffset(Source
);
1382 values
[1] = V0(device
->Backend
,getLatency
)();
1383 UnlockContext(Context
);
1386 /* 1x float/double */
1387 case AL_CONE_INNER_ANGLE
:
1388 case AL_CONE_OUTER_ANGLE
:
1393 case AL_REFERENCE_DISTANCE
:
1394 case AL_ROLLOFF_FACTOR
:
1395 case AL_CONE_OUTER_GAIN
:
1396 case AL_MAX_DISTANCE
:
1398 case AL_SAMPLE_OFFSET
:
1399 case AL_BYTE_OFFSET
:
1400 case AL_DOPPLER_FACTOR
:
1401 case AL_AIR_ABSORPTION_FACTOR
:
1402 case AL_ROOM_ROLLOFF_FACTOR
:
1403 case AL_CONE_OUTER_GAINHF
:
1404 case AL_SEC_LENGTH_SOFT
:
1405 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1406 *values
= (ALint64
)dvals
[0];
1409 /* 2x float/double */
1410 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1411 case AL_BYTE_RW_OFFSETS_SOFT
:
1412 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1414 values
[0] = (ALint64
)dvals
[0];
1415 values
[1] = (ALint64
)dvals
[1];
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
;
1535 ALbufferlistitem
*BufferList
;
1539 context
= GetContextRef();
1540 if(!context
) return;
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 BufferList
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &Source
->queue
, NULL
);
1572 while(BufferList
!= NULL
)
1574 ALbufferlistitem
*next
= BufferList
->next
;
1575 if(BufferList
->buffer
!= NULL
)
1576 DecrementRef(&BufferList
->buffer
->ref
);
1581 for(j
= 0;j
< MAX_SENDS
;++j
)
1583 if(Source
->Send
[j
].Slot
)
1584 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
1585 Source
->Send
[j
].Slot
= NULL
;
1588 memset(Source
, 0, sizeof(*Source
));
1593 ALCcontext_DecRef(context
);
1597 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1599 ALCcontext
*context
;
1602 context
= GetContextRef();
1603 if(!context
) return AL_FALSE
;
1605 ret
= (LookupSource(context
, source
) ? AL_TRUE
: AL_FALSE
);
1607 ALCcontext_DecRef(context
);
1613 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1615 ALCcontext
*Context
;
1618 Context
= GetContextRef();
1619 if(!Context
) return;
1621 if((Source
=LookupSource(Context
, source
)) == NULL
)
1622 alSetError(Context
, AL_INVALID_NAME
);
1623 else if(!(FloatValsByProp(param
) == 1))
1624 alSetError(Context
, AL_INVALID_ENUM
);
1626 SetSourcefv(Source
, Context
, param
, &value
);
1628 ALCcontext_DecRef(Context
);
1631 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1633 ALCcontext
*Context
;
1636 Context
= GetContextRef();
1637 if(!Context
) return;
1639 if((Source
=LookupSource(Context
, source
)) == NULL
)
1640 alSetError(Context
, AL_INVALID_NAME
);
1641 else if(!(FloatValsByProp(param
) == 3))
1642 alSetError(Context
, AL_INVALID_ENUM
);
1645 ALfloat fvals
[3] = { value1
, value2
, value3
};
1646 SetSourcefv(Source
, Context
, param
, fvals
);
1649 ALCcontext_DecRef(Context
);
1652 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1654 ALCcontext
*Context
;
1657 Context
= GetContextRef();
1658 if(!Context
) return;
1660 if((Source
=LookupSource(Context
, source
)) == NULL
)
1661 alSetError(Context
, AL_INVALID_NAME
);
1663 alSetError(Context
, AL_INVALID_VALUE
);
1664 else if(!(FloatValsByProp(param
) > 0))
1665 alSetError(Context
, AL_INVALID_ENUM
);
1667 SetSourcefv(Source
, Context
, param
, values
);
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 if((Source
=LookupSource(Context
, source
)) == NULL
)
1682 alSetError(Context
, AL_INVALID_NAME
);
1683 else if(!(DoubleValsByProp(param
) == 1))
1684 alSetError(Context
, AL_INVALID_ENUM
);
1687 ALfloat fval
= (ALfloat
)value
;
1688 SetSourcefv(Source
, Context
, param
, &fval
);
1691 ALCcontext_DecRef(Context
);
1694 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1696 ALCcontext
*Context
;
1699 Context
= GetContextRef();
1700 if(!Context
) return;
1702 if((Source
=LookupSource(Context
, source
)) == NULL
)
1703 alSetError(Context
, AL_INVALID_NAME
);
1704 else if(!(DoubleValsByProp(param
) == 3))
1705 alSetError(Context
, AL_INVALID_ENUM
);
1708 ALfloat fvals
[3] = { (ALfloat
)value1
, (ALfloat
)value2
, (ALfloat
)value3
};
1709 SetSourcefv(Source
, Context
, param
, fvals
);
1712 ALCcontext_DecRef(Context
);
1715 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1717 ALCcontext
*Context
;
1721 Context
= GetContextRef();
1722 if(!Context
) return;
1724 if((Source
=LookupSource(Context
, source
)) == NULL
)
1725 alSetError(Context
, AL_INVALID_NAME
);
1727 alSetError(Context
, AL_INVALID_VALUE
);
1728 else if(!((count
=DoubleValsByProp(param
)) > 0 && count
<= 6))
1729 alSetError(Context
, AL_INVALID_ENUM
);
1735 for(i
= 0;i
< count
;i
++)
1736 fvals
[i
] = (ALfloat
)values
[i
];
1737 SetSourcefv(Source
, Context
, param
, fvals
);
1740 ALCcontext_DecRef(Context
);
1744 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1746 ALCcontext
*Context
;
1749 Context
= GetContextRef();
1750 if(!Context
) return;
1752 if((Source
=LookupSource(Context
, source
)) == NULL
)
1753 alSetError(Context
, AL_INVALID_NAME
);
1754 else if(!(IntValsByProp(param
) == 1))
1755 alSetError(Context
, AL_INVALID_ENUM
);
1757 SetSourceiv(Source
, Context
, param
, &value
);
1759 ALCcontext_DecRef(Context
);
1762 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1764 ALCcontext
*Context
;
1767 Context
= GetContextRef();
1768 if(!Context
) return;
1770 if((Source
=LookupSource(Context
, source
)) == NULL
)
1771 alSetError(Context
, AL_INVALID_NAME
);
1772 else if(!(IntValsByProp(param
) == 3))
1773 alSetError(Context
, AL_INVALID_ENUM
);
1776 ALint ivals
[3] = { value1
, value2
, value3
};
1777 SetSourceiv(Source
, Context
, param
, ivals
);
1780 ALCcontext_DecRef(Context
);
1783 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1785 ALCcontext
*Context
;
1788 Context
= GetContextRef();
1789 if(!Context
) return;
1791 if((Source
=LookupSource(Context
, source
)) == NULL
)
1792 alSetError(Context
, AL_INVALID_NAME
);
1794 alSetError(Context
, AL_INVALID_VALUE
);
1795 else if(!(IntValsByProp(param
) > 0))
1796 alSetError(Context
, AL_INVALID_ENUM
);
1798 SetSourceiv(Source
, Context
, param
, values
);
1800 ALCcontext_DecRef(Context
);
1804 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1806 ALCcontext
*Context
;
1809 Context
= GetContextRef();
1810 if(!Context
) return;
1812 if((Source
=LookupSource(Context
, source
)) == NULL
)
1813 alSetError(Context
, AL_INVALID_NAME
);
1814 else if(!(Int64ValsByProp(param
) == 1))
1815 alSetError(Context
, AL_INVALID_ENUM
);
1817 SetSourcei64v(Source
, Context
, param
, &value
);
1819 ALCcontext_DecRef(Context
);
1822 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1824 ALCcontext
*Context
;
1827 Context
= GetContextRef();
1828 if(!Context
) return;
1830 if((Source
=LookupSource(Context
, source
)) == NULL
)
1831 alSetError(Context
, AL_INVALID_NAME
);
1832 else if(!(Int64ValsByProp(param
) == 3))
1833 alSetError(Context
, AL_INVALID_ENUM
);
1836 ALint64SOFT i64vals
[3] = { value1
, value2
, value3
};
1837 SetSourcei64v(Source
, Context
, param
, i64vals
);
1840 ALCcontext_DecRef(Context
);
1843 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1845 ALCcontext
*Context
;
1848 Context
= GetContextRef();
1849 if(!Context
) return;
1851 if((Source
=LookupSource(Context
, source
)) == NULL
)
1852 alSetError(Context
, AL_INVALID_NAME
);
1854 alSetError(Context
, AL_INVALID_VALUE
);
1855 else if(!(Int64ValsByProp(param
) > 0))
1856 alSetError(Context
, AL_INVALID_ENUM
);
1858 SetSourcei64v(Source
, Context
, param
, values
);
1860 ALCcontext_DecRef(Context
);
1864 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1866 ALCcontext
*Context
;
1869 Context
= GetContextRef();
1870 if(!Context
) return;
1872 if((Source
=LookupSource(Context
, source
)) == NULL
)
1873 alSetError(Context
, AL_INVALID_NAME
);
1875 alSetError(Context
, AL_INVALID_VALUE
);
1876 else if(!(FloatValsByProp(param
) == 1))
1877 alSetError(Context
, AL_INVALID_ENUM
);
1881 if(GetSourcedv(Source
, Context
, param
, &dval
))
1882 *value
= (ALfloat
)dval
;
1885 ALCcontext_DecRef(Context
);
1889 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1891 ALCcontext
*Context
;
1894 Context
= GetContextRef();
1895 if(!Context
) return;
1897 if((Source
=LookupSource(Context
, source
)) == NULL
)
1898 alSetError(Context
, AL_INVALID_NAME
);
1899 else if(!(value1
&& value2
&& value3
))
1900 alSetError(Context
, AL_INVALID_VALUE
);
1901 else if(!(FloatValsByProp(param
) == 3))
1902 alSetError(Context
, AL_INVALID_ENUM
);
1906 if(GetSourcedv(Source
, Context
, param
, dvals
))
1908 *value1
= (ALfloat
)dvals
[0];
1909 *value2
= (ALfloat
)dvals
[1];
1910 *value3
= (ALfloat
)dvals
[2];
1914 ALCcontext_DecRef(Context
);
1918 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1920 ALCcontext
*Context
;
1924 Context
= GetContextRef();
1925 if(!Context
) return;
1927 if((Source
=LookupSource(Context
, source
)) == NULL
)
1928 alSetError(Context
, AL_INVALID_NAME
);
1930 alSetError(Context
, AL_INVALID_VALUE
);
1931 else if(!((count
=FloatValsByProp(param
)) > 0 && count
<= 6))
1932 alSetError(Context
, AL_INVALID_ENUM
);
1936 if(GetSourcedv(Source
, Context
, param
, dvals
))
1939 for(i
= 0;i
< count
;i
++)
1940 values
[i
] = (ALfloat
)dvals
[i
];
1944 ALCcontext_DecRef(Context
);
1948 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1950 ALCcontext
*Context
;
1953 Context
= GetContextRef();
1954 if(!Context
) return;
1956 if((Source
=LookupSource(Context
, source
)) == NULL
)
1957 alSetError(Context
, AL_INVALID_NAME
);
1959 alSetError(Context
, AL_INVALID_VALUE
);
1960 else if(!(DoubleValsByProp(param
) == 1))
1961 alSetError(Context
, AL_INVALID_ENUM
);
1963 GetSourcedv(Source
, Context
, param
, value
);
1965 ALCcontext_DecRef(Context
);
1968 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1970 ALCcontext
*Context
;
1973 Context
= GetContextRef();
1974 if(!Context
) return;
1976 if((Source
=LookupSource(Context
, source
)) == NULL
)
1977 alSetError(Context
, AL_INVALID_NAME
);
1978 else if(!(value1
&& value2
&& value3
))
1979 alSetError(Context
, AL_INVALID_VALUE
);
1980 else if(!(DoubleValsByProp(param
) == 3))
1981 alSetError(Context
, AL_INVALID_ENUM
);
1985 if(GetSourcedv(Source
, Context
, param
, dvals
))
1993 ALCcontext_DecRef(Context
);
1996 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1998 ALCcontext
*Context
;
2001 Context
= GetContextRef();
2002 if(!Context
) return;
2004 if((Source
=LookupSource(Context
, source
)) == NULL
)
2005 alSetError(Context
, AL_INVALID_NAME
);
2007 alSetError(Context
, AL_INVALID_VALUE
);
2008 else if(!(DoubleValsByProp(param
) > 0))
2009 alSetError(Context
, AL_INVALID_ENUM
);
2011 GetSourcedv(Source
, Context
, param
, values
);
2013 ALCcontext_DecRef(Context
);
2017 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
2019 ALCcontext
*Context
;
2022 Context
= GetContextRef();
2023 if(!Context
) return;
2025 if((Source
=LookupSource(Context
, source
)) == NULL
)
2026 alSetError(Context
, AL_INVALID_NAME
);
2028 alSetError(Context
, AL_INVALID_VALUE
);
2029 else if(!(IntValsByProp(param
) == 1))
2030 alSetError(Context
, AL_INVALID_ENUM
);
2032 GetSourceiv(Source
, Context
, param
, value
);
2034 ALCcontext_DecRef(Context
);
2038 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
2040 ALCcontext
*Context
;
2043 Context
= GetContextRef();
2044 if(!Context
) return;
2046 if((Source
=LookupSource(Context
, source
)) == NULL
)
2047 alSetError(Context
, AL_INVALID_NAME
);
2048 else if(!(value1
&& value2
&& value3
))
2049 alSetError(Context
, AL_INVALID_VALUE
);
2050 else if(!(IntValsByProp(param
) == 3))
2051 alSetError(Context
, AL_INVALID_ENUM
);
2055 if(GetSourceiv(Source
, Context
, param
, ivals
))
2063 ALCcontext_DecRef(Context
);
2067 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
2069 ALCcontext
*Context
;
2072 Context
= GetContextRef();
2073 if(!Context
) return;
2075 if((Source
=LookupSource(Context
, source
)) == NULL
)
2076 alSetError(Context
, AL_INVALID_NAME
);
2078 alSetError(Context
, AL_INVALID_VALUE
);
2079 else if(!(IntValsByProp(param
) > 0))
2080 alSetError(Context
, AL_INVALID_ENUM
);
2082 GetSourceiv(Source
, Context
, param
, values
);
2084 ALCcontext_DecRef(Context
);
2088 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
2090 ALCcontext
*Context
;
2093 Context
= GetContextRef();
2094 if(!Context
) return;
2096 if((Source
=LookupSource(Context
, source
)) == NULL
)
2097 alSetError(Context
, AL_INVALID_NAME
);
2099 alSetError(Context
, AL_INVALID_VALUE
);
2100 else if(!(Int64ValsByProp(param
) == 1))
2101 alSetError(Context
, AL_INVALID_ENUM
);
2103 GetSourcei64v(Source
, Context
, param
, value
);
2105 ALCcontext_DecRef(Context
);
2108 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
2110 ALCcontext
*Context
;
2113 Context
= GetContextRef();
2114 if(!Context
) return;
2116 if((Source
=LookupSource(Context
, source
)) == NULL
)
2117 alSetError(Context
, AL_INVALID_NAME
);
2118 else if(!(value1
&& value2
&& value3
))
2119 alSetError(Context
, AL_INVALID_VALUE
);
2120 else if(!(Int64ValsByProp(param
) == 3))
2121 alSetError(Context
, AL_INVALID_ENUM
);
2125 if(GetSourcei64v(Source
, Context
, param
, i64vals
))
2127 *value1
= i64vals
[0];
2128 *value2
= i64vals
[1];
2129 *value3
= i64vals
[2];
2133 ALCcontext_DecRef(Context
);
2136 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
2138 ALCcontext
*Context
;
2141 Context
= GetContextRef();
2142 if(!Context
) return;
2144 if((Source
=LookupSource(Context
, source
)) == NULL
)
2145 alSetError(Context
, AL_INVALID_NAME
);
2147 alSetError(Context
, AL_INVALID_VALUE
);
2148 else if(!(Int64ValsByProp(param
) > 0))
2149 alSetError(Context
, AL_INVALID_ENUM
);
2151 GetSourcei64v(Source
, Context
, param
, values
);
2153 ALCcontext_DecRef(Context
);
2157 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
2159 alSourcePlayv(1, &source
);
2161 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2163 ALCcontext
*context
;
2167 context
= GetContextRef();
2168 if(!context
) return;
2171 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2172 for(i
= 0;i
< n
;i
++)
2174 if(!LookupSource(context
, sources
[i
]))
2175 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2178 LockContext(context
);
2179 while(n
> context
->MaxVoices
-context
->VoiceCount
)
2181 ALvoice
*temp
= NULL
;
2184 newcount
= context
->MaxVoices
<< 1;
2186 temp
= realloc(context
->Voices
, newcount
* sizeof(context
->Voices
[0]));
2189 UnlockContext(context
);
2190 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
2192 memset(&temp
[context
->MaxVoices
], 0, (newcount
-context
->MaxVoices
) * sizeof(temp
[0]));
2194 context
->Voices
= temp
;
2195 context
->MaxVoices
= newcount
;
2198 for(i
= 0;i
< n
;i
++)
2200 source
= LookupSource(context
, sources
[i
]);
2201 if(context
->DeferUpdates
) source
->new_state
= AL_PLAYING
;
2202 else SetSourceState(source
, context
, AL_PLAYING
);
2204 UnlockContext(context
);
2207 ALCcontext_DecRef(context
);
2210 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2212 alSourcePausev(1, &source
);
2214 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2216 ALCcontext
*context
;
2220 context
= GetContextRef();
2221 if(!context
) return;
2224 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2225 for(i
= 0;i
< n
;i
++)
2227 if(!LookupSource(context
, sources
[i
]))
2228 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2231 LockContext(context
);
2232 for(i
= 0;i
< n
;i
++)
2234 source
= LookupSource(context
, sources
[i
]);
2235 if(context
->DeferUpdates
) source
->new_state
= AL_PAUSED
;
2236 else SetSourceState(source
, context
, AL_PAUSED
);
2238 UnlockContext(context
);
2241 ALCcontext_DecRef(context
);
2244 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2246 alSourceStopv(1, &source
);
2248 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2250 ALCcontext
*context
;
2254 context
= GetContextRef();
2255 if(!context
) return;
2258 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2259 for(i
= 0;i
< n
;i
++)
2261 if(!LookupSource(context
, sources
[i
]))
2262 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2265 LockContext(context
);
2266 for(i
= 0;i
< n
;i
++)
2268 source
= LookupSource(context
, sources
[i
]);
2269 source
->new_state
= AL_NONE
;
2270 SetSourceState(source
, context
, AL_STOPPED
);
2272 UnlockContext(context
);
2275 ALCcontext_DecRef(context
);
2278 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2280 alSourceRewindv(1, &source
);
2282 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2284 ALCcontext
*context
;
2288 context
= GetContextRef();
2289 if(!context
) return;
2292 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2293 for(i
= 0;i
< n
;i
++)
2295 if(!LookupSource(context
, sources
[i
]))
2296 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2299 LockContext(context
);
2300 for(i
= 0;i
< n
;i
++)
2302 source
= LookupSource(context
, sources
[i
]);
2303 source
->new_state
= AL_NONE
;
2304 SetSourceState(source
, context
, AL_INITIAL
);
2306 UnlockContext(context
);
2309 ALCcontext_DecRef(context
);
2313 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint src
, ALsizei nb
, const ALuint
*buffers
)
2316 ALCcontext
*context
;
2319 ALbufferlistitem
*BufferListStart
;
2320 ALbufferlistitem
*BufferList
;
2321 ALbuffer
*BufferFmt
= NULL
;
2326 context
= GetContextRef();
2327 if(!context
) return;
2329 device
= context
->Device
;
2332 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2333 if((source
=LookupSource(context
, src
)) == NULL
)
2334 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2336 WriteLock(&source
->queue_lock
);
2337 if(source
->SourceType
== AL_STATIC
)
2339 WriteUnlock(&source
->queue_lock
);
2340 /* Can't queue on a Static Source */
2341 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
2344 /* Check for a valid Buffer, for its frequency and format */
2345 BufferList
= ATOMIC_LOAD(&source
->queue
);
2348 if(BufferList
->buffer
)
2350 BufferFmt
= BufferList
->buffer
;
2353 BufferList
= BufferList
->next
;
2356 BufferListStart
= NULL
;
2358 for(i
= 0;i
< nb
;i
++)
2360 ALbuffer
*buffer
= NULL
;
2361 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2363 WriteUnlock(&source
->queue_lock
);
2364 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, buffer_error
);
2367 if(!BufferListStart
)
2369 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2370 BufferList
= BufferListStart
;
2374 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2375 BufferList
= BufferList
->next
;
2377 BufferList
->buffer
= buffer
;
2378 BufferList
->next
= NULL
;
2379 if(!buffer
) continue;
2381 /* Hold a read lock on each buffer being queued while checking all
2382 * provided buffers. This is done so other threads don't see an extra
2383 * reference on some buffers if this operation ends up failing. */
2384 ReadLock(&buffer
->lock
);
2385 IncrementRef(&buffer
->ref
);
2387 if(BufferFmt
== NULL
)
2391 source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2392 source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2394 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2395 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2396 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2398 WriteUnlock(&source
->queue_lock
);
2399 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, buffer_error
);
2402 /* A buffer failed (invalid ID or format), so unlock and release
2403 * each buffer we had. */
2404 while(BufferListStart
)
2406 ALbufferlistitem
*next
= BufferListStart
->next
;
2407 if((buffer
=BufferListStart
->buffer
) != NULL
)
2409 DecrementRef(&buffer
->ref
);
2410 ReadUnlock(&buffer
->lock
);
2412 free(BufferListStart
);
2413 BufferListStart
= next
;
2418 /* All buffers good, unlock them now. */
2419 BufferList
= BufferListStart
;
2420 while(BufferList
!= NULL
)
2422 ALbuffer
*buffer
= BufferList
->buffer
;
2423 if(buffer
) ReadUnlock(&buffer
->lock
);
2424 BufferList
= BufferList
->next
;
2427 /* Source is now streaming */
2428 source
->SourceType
= AL_STREAMING
;
2431 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->queue
, &BufferList
, BufferListStart
))
2433 /* Queue head is not NULL, append to the end of the queue */
2434 while(BufferList
->next
!= NULL
)
2435 BufferList
= BufferList
->next
;
2436 BufferList
->next
= BufferListStart
;
2438 /* If the current buffer was at the end (NULL), put it at the start of the newly queued
2442 ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->current_buffer
, &BufferList
, BufferListStart
);
2443 WriteUnlock(&source
->queue_lock
);
2446 ALCcontext_DecRef(context
);
2449 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint src
, ALsizei nb
, ALuint
*buffers
)
2451 ALCcontext
*context
;
2453 ALbufferlistitem
*OldHead
;
2454 ALbufferlistitem
*OldTail
;
2455 ALbufferlistitem
*Current
;
2461 context
= GetContextRef();
2462 if(!context
) return;
2465 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2467 if((source
=LookupSource(context
, src
)) == NULL
)
2468 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2470 WriteLock(&source
->queue_lock
);
2471 /* Find the new buffer queue head */
2472 OldTail
= ATOMIC_LOAD(&source
->queue
);
2473 Current
= ATOMIC_LOAD(&source
->current_buffer
);
2474 if(OldTail
!= Current
)
2476 for(i
= 1;i
< nb
;i
++)
2478 ALbufferlistitem
*next
= OldTail
->next
;
2479 if(!next
|| next
== Current
) break;
2483 if(source
->Looping
|| source
->SourceType
!= AL_STREAMING
|| i
!= nb
)
2485 WriteUnlock(&source
->queue_lock
);
2486 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2487 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2490 /* Swap it, and cut the new head from the old. */
2491 OldHead
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &source
->queue
, OldTail
->next
);
2494 ALCdevice
*device
= context
->Device
;
2497 /* Once the active mix (if any) is done, it's safe to cut the old tail
2498 * from the new head.
2500 if(((count
=ReadRef(&device
->MixCount
))&1) != 0)
2502 while(count
== ReadRef(&device
->MixCount
))
2505 OldTail
->next
= NULL
;
2507 WriteUnlock(&source
->queue_lock
);
2509 while(OldHead
!= NULL
)
2511 ALbufferlistitem
*next
= OldHead
->next
;
2512 ALbuffer
*buffer
= OldHead
->buffer
;
2518 *(buffers
++) = buffer
->id
;
2519 DecrementRef(&buffer
->ref
);
2527 ALCcontext_DecRef(context
);
2531 static ALvoid
InitSourceParams(ALsource
*Source
)
2535 RWLockInit(&Source
->queue_lock
);
2537 Source
->InnerAngle
= 360.0f
;
2538 Source
->OuterAngle
= 360.0f
;
2539 Source
->Pitch
= 1.0f
;
2540 aluVectorSet(&Source
->Position
, 0.0f
, 0.0f
, 0.0f
, 1.0f
);
2541 aluVectorSet(&Source
->Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2542 aluVectorSet(&Source
->Direction
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2543 Source
->Orientation
[0][0] = 0.0f
;
2544 Source
->Orientation
[0][1] = 0.0f
;
2545 Source
->Orientation
[0][2] = -1.0f
;
2546 Source
->Orientation
[1][0] = 0.0f
;
2547 Source
->Orientation
[1][1] = 1.0f
;
2548 Source
->Orientation
[1][2] = 0.0f
;
2549 Source
->RefDistance
= 1.0f
;
2550 Source
->MaxDistance
= FLT_MAX
;
2551 Source
->RollOffFactor
= 1.0f
;
2552 Source
->Looping
= AL_FALSE
;
2553 Source
->Gain
= 1.0f
;
2554 Source
->MinGain
= 0.0f
;
2555 Source
->MaxGain
= 1.0f
;
2556 Source
->OuterGain
= 0.0f
;
2557 Source
->OuterGainHF
= 1.0f
;
2559 Source
->DryGainHFAuto
= AL_TRUE
;
2560 Source
->WetGainAuto
= AL_TRUE
;
2561 Source
->WetGainHFAuto
= AL_TRUE
;
2562 Source
->AirAbsorptionFactor
= 0.0f
;
2563 Source
->RoomRolloffFactor
= 0.0f
;
2564 Source
->DopplerFactor
= 1.0f
;
2565 Source
->DirectChannels
= AL_FALSE
;
2567 Source
->StereoPan
[0] = DEG2RAD( 30.0f
);
2568 Source
->StereoPan
[1] = DEG2RAD(-30.0f
);
2570 Source
->Radius
= 0.0f
;
2572 Source
->DistanceModel
= DefaultDistanceModel
;
2574 Source
->state
= AL_INITIAL
;
2575 Source
->new_state
= AL_NONE
;
2576 Source
->SourceType
= AL_UNDETERMINED
;
2577 Source
->Offset
= -1.0;
2579 ATOMIC_INIT(&Source
->queue
, NULL
);
2580 ATOMIC_INIT(&Source
->current_buffer
, NULL
);
2582 Source
->Direct
.Gain
= 1.0f
;
2583 Source
->Direct
.GainHF
= 1.0f
;
2584 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
2585 Source
->Direct
.GainLF
= 1.0f
;
2586 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
2587 for(i
= 0;i
< MAX_SENDS
;i
++)
2589 Source
->Send
[i
].Gain
= 1.0f
;
2590 Source
->Send
[i
].GainHF
= 1.0f
;
2591 Source
->Send
[i
].HFReference
= LOWPASSFREQREF
;
2592 Source
->Send
[i
].GainLF
= 1.0f
;
2593 Source
->Send
[i
].LFReference
= HIGHPASSFREQREF
;
2596 ATOMIC_INIT(&Source
->NeedsUpdate
, AL_TRUE
);
2602 * Sets the source's new play state given its current state.
2604 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2606 WriteLock(&Source
->queue_lock
);
2607 if(state
== AL_PLAYING
)
2609 ALCdevice
*device
= Context
->Device
;
2610 ALbufferlistitem
*BufferList
;
2611 ALboolean discontinuity
;
2612 ALvoice
*voice
= NULL
;
2615 /* Check that there is a queue containing at least one valid, non zero
2617 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2621 if((buffer
=BufferList
->buffer
) != NULL
&& buffer
->SampleLen
> 0)
2623 BufferList
= BufferList
->next
;
2626 if(Source
->state
!= AL_PAUSED
)
2628 Source
->state
= AL_PLAYING
;
2629 Source
->position
= 0;
2630 Source
->position_fraction
= 0;
2631 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
2632 discontinuity
= AL_TRUE
;
2636 Source
->state
= AL_PLAYING
;
2637 discontinuity
= AL_FALSE
;
2640 // Check if an Offset has been set
2641 if(Source
->Offset
>= 0.0)
2643 ApplyOffset(Source
);
2644 /* discontinuity = AL_TRUE;??? */
2647 /* If there's nothing to play, or device is disconnected, go right to
2649 if(!BufferList
|| !device
->Connected
)
2652 /* Make sure this source isn't already active, while looking for an
2653 * unused active source slot to put it in. */
2654 for(i
= 0;i
< Context
->VoiceCount
;i
++)
2656 ALsource
*old
= Source
;
2657 if(COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, NULL
))
2661 voice
= &Context
->Voices
[i
];
2662 voice
->Source
= Source
;
2667 if(voice
== NULL
&& COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, Source
))
2668 voice
= &Context
->Voices
[i
];
2672 voice
= &Context
->Voices
[Context
->VoiceCount
++];
2673 voice
->Source
= Source
;
2676 /* Clear previous samples if playback is discontinuous. */
2678 memset(voice
->PrevSamples
, 0, sizeof(voice
->PrevSamples
));
2680 voice
->Moving
= AL_FALSE
;
2681 for(i
= 0;i
< MAX_INPUT_CHANNELS
;i
++)
2684 for(j
= 0;j
< HRTF_HISTORY_LENGTH
;j
++)
2685 voice
->Direct
.Hrtf
[i
].State
.History
[j
] = 0.0f
;
2686 for(j
= 0;j
< HRIR_LENGTH
;j
++)
2688 voice
->Direct
.Hrtf
[i
].State
.Values
[j
][0] = 0.0f
;
2689 voice
->Direct
.Hrtf
[i
].State
.Values
[j
][1] = 0.0f
;
2693 if(BufferList
->buffer
->FmtChannels
== FmtMono
)
2694 voice
->Update
= CalcSourceParams
;
2696 voice
->Update
= CalcNonAttnSourceParams
;
2698 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
2700 else if(state
== AL_PAUSED
)
2702 if(Source
->state
== AL_PLAYING
)
2703 Source
->state
= AL_PAUSED
;
2705 else if(state
== AL_STOPPED
)
2708 if(Source
->state
!= AL_INITIAL
)
2710 Source
->state
= AL_STOPPED
;
2711 ATOMIC_STORE(&Source
->current_buffer
, NULL
);
2713 Source
->Offset
= -1.0;
2715 else if(state
== AL_INITIAL
)
2717 if(Source
->state
!= AL_INITIAL
)
2719 Source
->state
= AL_INITIAL
;
2720 Source
->position
= 0;
2721 Source
->position_fraction
= 0;
2722 ATOMIC_STORE(&Source
->current_buffer
, ATOMIC_LOAD(&Source
->queue
));
2724 Source
->Offset
= -1.0;
2726 WriteUnlock(&Source
->queue_lock
);
2729 /* GetSourceSampleOffset
2731 * Gets the current read offset for the given Source, in 32.32 fixed-point
2732 * samples. The offset is relative to the start of the queue (not the start of
2733 * the current buffer).
2735 ALint64
GetSourceSampleOffset(ALsource
*Source
)
2737 const ALbufferlistitem
*BufferList
;
2738 const ALbufferlistitem
*Current
;
2741 ReadLock(&Source
->queue_lock
);
2742 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2744 ReadUnlock(&Source
->queue_lock
);
2748 /* NOTE: This is the offset into the *current* buffer, so add the length of
2749 * any played buffers */
2750 readPos
= (ALuint64
)Source
->position
<< 32;
2751 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2752 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2753 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2754 while(BufferList
&& BufferList
!= Current
)
2756 if(BufferList
->buffer
)
2757 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2758 BufferList
= BufferList
->next
;
2761 ReadUnlock(&Source
->queue_lock
);
2762 return (ALint64
)minu64(readPos
, U64(0x7fffffffffffffff));
2765 /* GetSourceSecOffset
2767 * Gets the current read offset for the given Source, in seconds. The offset is
2768 * relative to the start of the queue (not the start of the current buffer).
2770 static ALdouble
GetSourceSecOffset(ALsource
*Source
)
2772 const ALbufferlistitem
*BufferList
;
2773 const ALbufferlistitem
*Current
;
2774 const ALbuffer
*Buffer
= NULL
;
2777 ReadLock(&Source
->queue_lock
);
2778 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2780 ReadUnlock(&Source
->queue_lock
);
2784 /* NOTE: This is the offset into the *current* buffer, so add the length of
2785 * any played buffers */
2786 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2787 readPos
|= (ALuint64
)Source
->position_fraction
;
2788 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2789 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2790 while(BufferList
&& BufferList
!= Current
)
2792 const ALbuffer
*buffer
= BufferList
->buffer
;
2795 if(!Buffer
) Buffer
= buffer
;
2796 readPos
+= (ALuint64
)buffer
->SampleLen
<< FRACTIONBITS
;
2798 BufferList
= BufferList
->next
;
2801 while(BufferList
&& !Buffer
)
2803 Buffer
= BufferList
->buffer
;
2804 BufferList
= BufferList
->next
;
2806 assert(Buffer
!= NULL
);
2808 ReadUnlock(&Source
->queue_lock
);
2809 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2814 * Gets the current read and write offsets for the given Source, in the
2815 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2816 * the start of the queue (not the start of the current buffer).
2818 static ALvoid
GetSourceOffsets(ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2820 const ALbufferlistitem
*BufferList
;
2821 const ALbufferlistitem
*Current
;
2822 const ALbuffer
*Buffer
= NULL
;
2823 ALboolean readFin
= AL_FALSE
;
2824 ALuint readPos
, readPosFrac
, writePos
;
2825 ALuint totalBufferLen
;
2827 ReadLock(&Source
->queue_lock
);
2828 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2832 ReadUnlock(&Source
->queue_lock
);
2836 if(updateLen
> 0.0 && updateLen
< 0.015)
2839 /* NOTE: This is the offset into the *current* buffer, so add the length of
2840 * any played buffers */
2842 readPos
= Source
->position
;
2843 readPosFrac
= Source
->position_fraction
;
2844 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2845 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2846 while(BufferList
!= NULL
)
2848 const ALbuffer
*buffer
;
2849 readFin
= readFin
|| (BufferList
== Current
);
2850 if((buffer
=BufferList
->buffer
) != NULL
)
2852 if(!Buffer
) Buffer
= buffer
;
2853 totalBufferLen
+= buffer
->SampleLen
;
2854 if(!readFin
) readPos
+= buffer
->SampleLen
;
2856 BufferList
= BufferList
->next
;
2858 assert(Buffer
!= NULL
);
2860 if(Source
->state
== AL_PLAYING
)
2861 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
+ 0.5f
);
2867 readPos
%= totalBufferLen
;
2868 writePos
%= totalBufferLen
;
2872 /* Wrap positions back to 0 */
2873 if(readPos
>= totalBufferLen
)
2874 readPos
= readPosFrac
= 0;
2875 if(writePos
>= totalBufferLen
)
2882 offset
[0] = (readPos
+ (ALdouble
)readPosFrac
/FRACTIONONE
)/Buffer
->Frequency
;
2883 offset
[1] = (ALdouble
)writePos
/Buffer
->Frequency
;
2886 case AL_SAMPLE_OFFSET
:
2887 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2888 offset
[0] = readPos
+ (ALdouble
)readPosFrac
/FRACTIONONE
;
2889 offset
[1] = (ALdouble
)writePos
;
2892 case AL_BYTE_OFFSET
:
2893 case AL_BYTE_RW_OFFSETS_SOFT
:
2894 if(Buffer
->OriginalType
== UserFmtIMA4
)
2896 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
2897 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2898 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2900 /* Round down to nearest ADPCM block */
2901 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2902 if(Source
->state
!= AL_PLAYING
)
2903 offset
[1] = offset
[0];
2906 /* Round up to nearest ADPCM block */
2907 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2908 FrameBlockSize
* BlockSize
);
2911 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
2913 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
2914 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2915 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2917 /* Round down to nearest ADPCM block */
2918 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2919 if(Source
->state
!= AL_PLAYING
)
2920 offset
[1] = offset
[0];
2923 /* Round up to nearest ADPCM block */
2924 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2925 FrameBlockSize
* BlockSize
);
2930 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2931 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2932 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2937 ReadUnlock(&Source
->queue_lock
);
2943 * Apply the stored playback offset to the Source. This function will update
2944 * the number of buffers "played" given the stored offset.
2946 ALboolean
ApplyOffset(ALsource
*Source
)
2948 ALbufferlistitem
*BufferList
;
2949 const ALbuffer
*Buffer
;
2950 ALuint bufferLen
, totalBufferLen
;
2951 ALuint offset
=0, frac
=0;
2953 /* Get sample frame offset */
2954 if(!GetSampleOffset(Source
, &offset
, &frac
))
2958 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2959 while(BufferList
&& totalBufferLen
<= offset
)
2961 Buffer
= BufferList
->buffer
;
2962 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2964 if(bufferLen
> offset
-totalBufferLen
)
2966 /* Offset is in this buffer */
2967 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
2969 Source
->position
= offset
- totalBufferLen
;
2970 Source
->position_fraction
= frac
;
2974 totalBufferLen
+= bufferLen
;
2976 BufferList
= BufferList
->next
;
2979 /* Offset is out of range of the queue */
2986 * Retrieves the sample offset into the Source's queue (from the Sample, Byte
2987 * or Second offset supplied by the application). This takes into account the
2988 * fact that the buffer format may have been modifed since.
2990 static ALboolean
GetSampleOffset(ALsource
*Source
, ALuint
*offset
, ALuint
*frac
)
2992 const ALbuffer
*Buffer
= NULL
;
2993 const ALbufferlistitem
*BufferList
;
2994 ALdouble dbloff
, dblfrac
;
2996 /* Find the first valid Buffer in the Queue */
2997 BufferList
= ATOMIC_LOAD(&Source
->queue
);
3000 if(BufferList
->buffer
)
3002 Buffer
= BufferList
->buffer
;
3005 BufferList
= BufferList
->next
;
3009 Source
->Offset
= -1.0;
3013 switch(Source
->OffsetType
)
3015 case AL_BYTE_OFFSET
:
3016 /* Determine the ByteOffset (and ensure it is block aligned) */
3017 *offset
= (ALuint
)Source
->Offset
;
3018 if(Buffer
->OriginalType
== UserFmtIMA4
)
3020 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
3021 *offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
3022 *offset
*= Buffer
->OriginalAlign
;
3024 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
3026 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
3027 *offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
3028 *offset
*= Buffer
->OriginalAlign
;
3031 *offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
3035 case AL_SAMPLE_OFFSET
:
3036 dblfrac
= modf(Source
->Offset
, &dbloff
);
3037 *offset
= (ALuint
)mind(dbloff
, UINT_MAX
);
3038 *frac
= (ALuint
)mind(dblfrac
*FRACTIONONE
, FRACTIONONE
-1.0);
3042 dblfrac
= modf(Source
->Offset
*Buffer
->Frequency
, &dbloff
);
3043 *offset
= (ALuint
)mind(dbloff
, UINT_MAX
);
3044 *frac
= (ALuint
)mind(dblfrac
*FRACTIONONE
, FRACTIONONE
-1.0);
3047 Source
->Offset
= -1.0;
3055 * Destroys all sources in the source map.
3057 ALvoid
ReleaseALSources(ALCcontext
*Context
)
3059 ALbufferlistitem
*item
;
3062 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
3064 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
3065 Context
->SourceMap
.array
[pos
].value
= NULL
;
3067 item
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &temp
->queue
, NULL
);
3070 ALbufferlistitem
*next
= item
->next
;
3071 if(item
->buffer
!= NULL
)
3072 DecrementRef(&item
->buffer
->ref
);
3077 for(j
= 0;j
< MAX_SENDS
;++j
)
3079 if(temp
->Send
[j
].Slot
)
3080 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
3081 temp
->Send
[j
].Slot
= NULL
;
3084 FreeThunkEntry(temp
->id
);
3085 memset(temp
, 0, sizeof(*temp
));