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"
42 extern inline struct ALsource
*LookupSource(ALCcontext
*context
, ALuint id
);
43 extern inline struct ALsource
*RemoveSource(ALCcontext
*context
, ALuint id
);
45 static ALvoid
InitSourceParams(ALsource
*Source
);
46 static ALint64
GetSourceSampleOffset(ALsource
*Source
);
47 static ALdouble
GetSourceSecOffset(ALsource
*Source
);
48 static ALvoid
GetSourceOffsets(ALsource
*Source
, ALenum name
, ALdouble
*offsets
, ALdouble updateLen
);
49 static ALboolean
GetSampleOffset(ALsource
*Source
, ALuint
*offset
, ALuint
*frac
);
51 typedef enum SourceProp
{
54 srcMinGain
= AL_MIN_GAIN
,
55 srcMaxGain
= AL_MAX_GAIN
,
56 srcMaxDistance
= AL_MAX_DISTANCE
,
57 srcRolloffFactor
= AL_ROLLOFF_FACTOR
,
58 srcDopplerFactor
= AL_DOPPLER_FACTOR
,
59 srcConeOuterGain
= AL_CONE_OUTER_GAIN
,
60 srcSecOffset
= AL_SEC_OFFSET
,
61 srcSampleOffset
= AL_SAMPLE_OFFSET
,
62 srcByteOffset
= AL_BYTE_OFFSET
,
63 srcConeInnerAngle
= AL_CONE_INNER_ANGLE
,
64 srcConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
65 srcRefDistance
= AL_REFERENCE_DISTANCE
,
67 srcPosition
= AL_POSITION
,
68 srcVelocity
= AL_VELOCITY
,
69 srcDirection
= AL_DIRECTION
,
71 srcSourceRelative
= AL_SOURCE_RELATIVE
,
72 srcLooping
= AL_LOOPING
,
73 srcBuffer
= AL_BUFFER
,
74 srcSourceState
= AL_SOURCE_STATE
,
75 srcBuffersQueued
= AL_BUFFERS_QUEUED
,
76 srcBuffersProcessed
= AL_BUFFERS_PROCESSED
,
77 srcSourceType
= AL_SOURCE_TYPE
,
80 srcConeOuterGainHF
= AL_CONE_OUTER_GAINHF
,
81 srcAirAbsorptionFactor
= AL_AIR_ABSORPTION_FACTOR
,
82 srcRoomRolloffFactor
= AL_ROOM_ROLLOFF_FACTOR
,
83 srcDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
84 srcAuxSendFilterGainAuto
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
85 srcAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
86 srcDirectFilter
= AL_DIRECT_FILTER
,
87 srcAuxSendFilter
= AL_AUXILIARY_SEND_FILTER
,
89 /* AL_SOFT_direct_channels */
90 srcDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
92 /* AL_EXT_source_distance_model */
93 srcDistanceModel
= AL_DISTANCE_MODEL
,
95 srcByteLengthSOFT
= AL_BYTE_LENGTH_SOFT
,
96 srcSampleLengthSOFT
= AL_SAMPLE_LENGTH_SOFT
,
97 srcSecLengthSOFT
= AL_SEC_LENGTH_SOFT
,
99 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
100 srcSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
101 srcByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
103 /* AL_SOFT_source_latency */
104 srcSampleOffsetLatencySOFT
= AL_SAMPLE_OFFSET_LATENCY_SOFT
,
105 srcSecOffsetLatencySOFT
= AL_SEC_OFFSET_LATENCY_SOFT
,
108 srcOrientation
= AL_ORIENTATION
,
111 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALfloat
*values
);
112 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint
*values
);
113 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint64SOFT
*values
);
115 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALdouble
*values
);
116 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint
*values
);
117 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint64
*values
);
119 static ALint
FloatValsByProp(ALenum prop
)
121 if(prop
!= (ALenum
)((SourceProp
)prop
))
123 switch((SourceProp
)prop
)
129 case AL_MAX_DISTANCE
:
130 case AL_ROLLOFF_FACTOR
:
131 case AL_DOPPLER_FACTOR
:
132 case AL_CONE_OUTER_GAIN
:
134 case AL_SAMPLE_OFFSET
:
136 case AL_CONE_INNER_ANGLE
:
137 case AL_CONE_OUTER_ANGLE
:
138 case AL_REFERENCE_DISTANCE
:
139 case AL_CONE_OUTER_GAINHF
:
140 case AL_AIR_ABSORPTION_FACTOR
:
141 case AL_ROOM_ROLLOFF_FACTOR
:
142 case AL_DIRECT_FILTER_GAINHF_AUTO
:
143 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
144 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
145 case AL_DIRECT_CHANNELS_SOFT
:
146 case AL_DISTANCE_MODEL
:
147 case AL_SOURCE_RELATIVE
:
149 case AL_SOURCE_STATE
:
150 case AL_BUFFERS_QUEUED
:
151 case AL_BUFFERS_PROCESSED
:
153 case AL_BYTE_LENGTH_SOFT
:
154 case AL_SAMPLE_LENGTH_SOFT
:
155 case AL_SEC_LENGTH_SOFT
:
158 case AL_SAMPLE_RW_OFFSETS_SOFT
:
159 case AL_BYTE_RW_OFFSETS_SOFT
:
170 case AL_SEC_OFFSET_LATENCY_SOFT
:
171 break; /* Double only */
174 case AL_DIRECT_FILTER
:
175 case AL_AUXILIARY_SEND_FILTER
:
176 break; /* i/i64 only */
177 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
178 break; /* i64 only */
182 static ALint
DoubleValsByProp(ALenum prop
)
184 if(prop
!= (ALenum
)((SourceProp
)prop
))
186 switch((SourceProp
)prop
)
192 case AL_MAX_DISTANCE
:
193 case AL_ROLLOFF_FACTOR
:
194 case AL_DOPPLER_FACTOR
:
195 case AL_CONE_OUTER_GAIN
:
197 case AL_SAMPLE_OFFSET
:
199 case AL_CONE_INNER_ANGLE
:
200 case AL_CONE_OUTER_ANGLE
:
201 case AL_REFERENCE_DISTANCE
:
202 case AL_CONE_OUTER_GAINHF
:
203 case AL_AIR_ABSORPTION_FACTOR
:
204 case AL_ROOM_ROLLOFF_FACTOR
:
205 case AL_DIRECT_FILTER_GAINHF_AUTO
:
206 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
207 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
208 case AL_DIRECT_CHANNELS_SOFT
:
209 case AL_DISTANCE_MODEL
:
210 case AL_SOURCE_RELATIVE
:
212 case AL_SOURCE_STATE
:
213 case AL_BUFFERS_QUEUED
:
214 case AL_BUFFERS_PROCESSED
:
216 case AL_BYTE_LENGTH_SOFT
:
217 case AL_SAMPLE_LENGTH_SOFT
:
218 case AL_SEC_LENGTH_SOFT
:
221 case AL_SAMPLE_RW_OFFSETS_SOFT
:
222 case AL_BYTE_RW_OFFSETS_SOFT
:
223 case AL_SEC_OFFSET_LATENCY_SOFT
:
235 case AL_DIRECT_FILTER
:
236 case AL_AUXILIARY_SEND_FILTER
:
237 break; /* i/i64 only */
238 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
239 break; /* i64 only */
244 static ALint
IntValsByProp(ALenum prop
)
246 if(prop
!= (ALenum
)((SourceProp
)prop
))
248 switch((SourceProp
)prop
)
254 case AL_MAX_DISTANCE
:
255 case AL_ROLLOFF_FACTOR
:
256 case AL_DOPPLER_FACTOR
:
257 case AL_CONE_OUTER_GAIN
:
259 case AL_SAMPLE_OFFSET
:
261 case AL_CONE_INNER_ANGLE
:
262 case AL_CONE_OUTER_ANGLE
:
263 case AL_REFERENCE_DISTANCE
:
264 case AL_CONE_OUTER_GAINHF
:
265 case AL_AIR_ABSORPTION_FACTOR
:
266 case AL_ROOM_ROLLOFF_FACTOR
:
267 case AL_DIRECT_FILTER_GAINHF_AUTO
:
268 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
269 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
270 case AL_DIRECT_CHANNELS_SOFT
:
271 case AL_DISTANCE_MODEL
:
272 case AL_SOURCE_RELATIVE
:
275 case AL_SOURCE_STATE
:
276 case AL_BUFFERS_QUEUED
:
277 case AL_BUFFERS_PROCESSED
:
279 case AL_DIRECT_FILTER
:
280 case AL_BYTE_LENGTH_SOFT
:
281 case AL_SAMPLE_LENGTH_SOFT
:
282 case AL_SEC_LENGTH_SOFT
:
285 case AL_SAMPLE_RW_OFFSETS_SOFT
:
286 case AL_BYTE_RW_OFFSETS_SOFT
:
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 */
305 static ALint
Int64ValsByProp(ALenum prop
)
307 if(prop
!= (ALenum
)((SourceProp
)prop
))
309 switch((SourceProp
)prop
)
315 case AL_MAX_DISTANCE
:
316 case AL_ROLLOFF_FACTOR
:
317 case AL_DOPPLER_FACTOR
:
318 case AL_CONE_OUTER_GAIN
:
320 case AL_SAMPLE_OFFSET
:
322 case AL_CONE_INNER_ANGLE
:
323 case AL_CONE_OUTER_ANGLE
:
324 case AL_REFERENCE_DISTANCE
:
325 case AL_CONE_OUTER_GAINHF
:
326 case AL_AIR_ABSORPTION_FACTOR
:
327 case AL_ROOM_ROLLOFF_FACTOR
:
328 case AL_DIRECT_FILTER_GAINHF_AUTO
:
329 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
330 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
331 case AL_DIRECT_CHANNELS_SOFT
:
332 case AL_DISTANCE_MODEL
:
333 case AL_SOURCE_RELATIVE
:
336 case AL_SOURCE_STATE
:
337 case AL_BUFFERS_QUEUED
:
338 case AL_BUFFERS_PROCESSED
:
340 case AL_DIRECT_FILTER
:
341 case AL_BYTE_LENGTH_SOFT
:
342 case AL_SAMPLE_LENGTH_SOFT
:
343 case AL_SEC_LENGTH_SOFT
:
346 case AL_SAMPLE_RW_OFFSETS_SOFT
:
347 case AL_BYTE_RW_OFFSETS_SOFT
:
348 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
354 case AL_AUXILIARY_SEND_FILTER
:
360 case AL_SEC_OFFSET_LATENCY_SOFT
:
361 break; /* Double only */
367 #define CHECKVAL(x) do { \
369 SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); \
372 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALfloat
*values
)
378 case AL_BYTE_RW_OFFSETS_SOFT
:
379 case AL_SAMPLE_RW_OFFSETS_SOFT
:
380 case AL_BYTE_LENGTH_SOFT
:
381 case AL_SAMPLE_LENGTH_SOFT
:
382 case AL_SEC_LENGTH_SOFT
:
383 case AL_SEC_OFFSET_LATENCY_SOFT
:
385 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
388 CHECKVAL(*values
>= 0.0f
);
390 Source
->Pitch
= *values
;
391 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
394 case AL_CONE_INNER_ANGLE
:
395 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
397 Source
->InnerAngle
= *values
;
398 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
401 case AL_CONE_OUTER_ANGLE
:
402 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
404 Source
->OuterAngle
= *values
;
405 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
409 CHECKVAL(*values
>= 0.0f
);
411 Source
->Gain
= *values
;
412 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
415 case AL_MAX_DISTANCE
:
416 CHECKVAL(*values
>= 0.0f
);
418 Source
->MaxDistance
= *values
;
419 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
422 case AL_ROLLOFF_FACTOR
:
423 CHECKVAL(*values
>= 0.0f
);
425 Source
->RollOffFactor
= *values
;
426 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
429 case AL_REFERENCE_DISTANCE
:
430 CHECKVAL(*values
>= 0.0f
);
432 Source
->RefDistance
= *values
;
433 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
437 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
439 Source
->MinGain
= *values
;
440 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
444 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
446 Source
->MaxGain
= *values
;
447 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
450 case AL_CONE_OUTER_GAIN
:
451 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
453 Source
->OuterGain
= *values
;
454 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
457 case AL_CONE_OUTER_GAINHF
:
458 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
460 Source
->OuterGainHF
= *values
;
461 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
464 case AL_AIR_ABSORPTION_FACTOR
:
465 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
467 Source
->AirAbsorptionFactor
= *values
;
468 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
471 case AL_ROOM_ROLLOFF_FACTOR
:
472 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
474 Source
->RoomRolloffFactor
= *values
;
475 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
478 case AL_DOPPLER_FACTOR
:
479 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
481 Source
->DopplerFactor
= *values
;
482 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
486 case AL_SAMPLE_OFFSET
:
488 CHECKVAL(*values
>= 0.0f
);
490 LockContext(Context
);
491 Source
->OffsetType
= prop
;
492 Source
->Offset
= *values
;
494 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
495 !Context
->DeferUpdates
)
497 WriteLock(&Source
->queue_lock
);
498 if(ApplyOffset(Source
) == AL_FALSE
)
500 WriteUnlock(&Source
->queue_lock
);
501 UnlockContext(Context
);
502 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
504 WriteUnlock(&Source
->queue_lock
);
506 UnlockContext(Context
);
511 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
513 LockContext(Context
);
514 aluVectorSet(&Source
->Position
, values
[0], values
[1], values
[2], 1.0f
);
515 UnlockContext(Context
);
516 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
520 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
522 LockContext(Context
);
523 aluVectorSet(&Source
->Velocity
, values
[0], values
[1], values
[2], 0.0f
);
524 UnlockContext(Context
);
525 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
529 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
531 LockContext(Context
);
532 aluVectorSet(&Source
->Direction
, values
[0], values
[1], values
[2], 0.0f
);
533 UnlockContext(Context
);
534 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
538 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]) &&
539 isfinite(values
[3]) && isfinite(values
[4]) && isfinite(values
[5]));
541 LockContext(Context
);
542 Source
->Orientation
[0][0] = values
[0];
543 Source
->Orientation
[0][1] = values
[1];
544 Source
->Orientation
[0][2] = values
[2];
545 Source
->Orientation
[1][0] = values
[3];
546 Source
->Orientation
[1][1] = values
[4];
547 Source
->Orientation
[1][2] = values
[5];
548 UnlockContext(Context
);
549 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
553 case AL_SOURCE_RELATIVE
:
555 case AL_SOURCE_STATE
:
557 case AL_DISTANCE_MODEL
:
558 case AL_DIRECT_FILTER_GAINHF_AUTO
:
559 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
560 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
561 case AL_DIRECT_CHANNELS_SOFT
:
562 ival
= (ALint
)values
[0];
563 return SetSourceiv(Source
, Context
, prop
, &ival
);
565 case AL_BUFFERS_QUEUED
:
566 case AL_BUFFERS_PROCESSED
:
567 ival
= (ALint
)((ALuint
)values
[0]);
568 return SetSourceiv(Source
, Context
, prop
, &ival
);
571 case AL_DIRECT_FILTER
:
572 case AL_AUXILIARY_SEND_FILTER
:
573 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
577 ERR("Unexpected property: 0x%04x\n", prop
);
578 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
581 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint
*values
)
583 ALCdevice
*device
= Context
->Device
;
584 ALbuffer
*buffer
= NULL
;
585 ALfilter
*filter
= NULL
;
586 ALeffectslot
*slot
= NULL
;
587 ALbufferlistitem
*oldlist
;
588 ALbufferlistitem
*newlist
;
593 case AL_SOURCE_STATE
:
595 case AL_BUFFERS_QUEUED
:
596 case AL_BUFFERS_PROCESSED
:
597 case AL_SAMPLE_RW_OFFSETS_SOFT
:
598 case AL_BYTE_RW_OFFSETS_SOFT
:
599 case AL_BYTE_LENGTH_SOFT
:
600 case AL_SAMPLE_LENGTH_SOFT
:
601 case AL_SEC_LENGTH_SOFT
:
603 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
605 case AL_SOURCE_RELATIVE
:
606 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
608 Source
->HeadRelative
= (ALboolean
)*values
;
609 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
613 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
615 Source
->Looping
= (ALboolean
)*values
;
619 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
621 WriteLock(&Source
->queue_lock
);
622 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
624 WriteUnlock(&Source
->queue_lock
);
625 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
630 /* Add the selected buffer to a one-item queue */
631 newlist
= malloc(sizeof(ALbufferlistitem
));
632 newlist
->buffer
= buffer
;
633 newlist
->next
= NULL
;
634 IncrementRef(&buffer
->ref
);
636 /* Source is now Static */
637 Source
->SourceType
= AL_STATIC
;
639 ReadLock(&buffer
->lock
);
640 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
641 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
642 ReadUnlock(&buffer
->lock
);
646 /* Source is now Undetermined */
647 Source
->SourceType
= AL_UNDETERMINED
;
650 oldlist
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &Source
->queue
, newlist
);
651 ATOMIC_STORE(&Source
->current_buffer
, newlist
);
652 WriteUnlock(&Source
->queue_lock
);
654 /* Delete all elements in the previous queue */
655 while(oldlist
!= NULL
)
657 ALbufferlistitem
*temp
= oldlist
;
658 oldlist
= temp
->next
;
661 DecrementRef(&temp
->buffer
->ref
);
667 case AL_SAMPLE_OFFSET
:
669 CHECKVAL(*values
>= 0);
671 LockContext(Context
);
672 Source
->OffsetType
= prop
;
673 Source
->Offset
= *values
;
675 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
676 !Context
->DeferUpdates
)
678 WriteLock(&Source
->queue_lock
);
679 if(ApplyOffset(Source
) == AL_FALSE
)
681 WriteUnlock(&Source
->queue_lock
);
682 UnlockContext(Context
);
683 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
685 WriteUnlock(&Source
->queue_lock
);
687 UnlockContext(Context
);
690 case AL_DIRECT_FILTER
:
691 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
693 LockContext(Context
);
696 Source
->Direct
.Gain
= 1.0f
;
697 Source
->Direct
.GainHF
= 1.0f
;
698 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
699 Source
->Direct
.GainLF
= 1.0f
;
700 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
704 Source
->Direct
.Gain
= filter
->Gain
;
705 Source
->Direct
.GainHF
= filter
->GainHF
;
706 Source
->Direct
.HFReference
= filter
->HFReference
;
707 Source
->Direct
.GainLF
= filter
->GainLF
;
708 Source
->Direct
.LFReference
= filter
->LFReference
;
710 UnlockContext(Context
);
711 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
714 case AL_DIRECT_FILTER_GAINHF_AUTO
:
715 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
717 Source
->DryGainHFAuto
= *values
;
718 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
721 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
722 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
724 Source
->WetGainAuto
= *values
;
725 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
728 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
729 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
731 Source
->WetGainHFAuto
= *values
;
732 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
735 case AL_DIRECT_CHANNELS_SOFT
:
736 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
738 Source
->DirectChannels
= *values
;
739 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
742 case AL_DISTANCE_MODEL
:
743 CHECKVAL(*values
== AL_NONE
||
744 *values
== AL_INVERSE_DISTANCE
||
745 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
746 *values
== AL_LINEAR_DISTANCE
||
747 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
748 *values
== AL_EXPONENT_DISTANCE
||
749 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
751 Source
->DistanceModel
= *values
;
752 if(Context
->SourceDistanceModel
)
753 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
757 case AL_AUXILIARY_SEND_FILTER
:
758 LockContext(Context
);
759 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
760 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
761 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
763 UnlockContext(Context
);
764 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
767 /* Add refcount on the new slot, and release the previous slot */
768 if(slot
) IncrementRef(&slot
->ref
);
769 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
770 if(slot
) DecrementRef(&slot
->ref
);
775 Source
->Send
[values
[1]].Gain
= 1.0f
;
776 Source
->Send
[values
[1]].GainHF
= 1.0f
;
777 Source
->Send
[values
[1]].HFReference
= LOWPASSFREQREF
;
778 Source
->Send
[values
[1]].GainLF
= 1.0f
;
779 Source
->Send
[values
[1]].LFReference
= HIGHPASSFREQREF
;
783 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
784 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
785 Source
->Send
[values
[1]].HFReference
= filter
->HFReference
;
786 Source
->Send
[values
[1]].GainLF
= filter
->GainLF
;
787 Source
->Send
[values
[1]].LFReference
= filter
->LFReference
;
789 UnlockContext(Context
);
790 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
795 case AL_CONE_INNER_ANGLE
:
796 case AL_CONE_OUTER_ANGLE
:
801 case AL_REFERENCE_DISTANCE
:
802 case AL_ROLLOFF_FACTOR
:
803 case AL_CONE_OUTER_GAIN
:
804 case AL_MAX_DISTANCE
:
805 case AL_DOPPLER_FACTOR
:
806 case AL_CONE_OUTER_GAINHF
:
807 case AL_AIR_ABSORPTION_FACTOR
:
808 case AL_ROOM_ROLLOFF_FACTOR
:
809 fvals
[0] = (ALfloat
)*values
;
810 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
816 fvals
[0] = (ALfloat
)values
[0];
817 fvals
[1] = (ALfloat
)values
[1];
818 fvals
[2] = (ALfloat
)values
[2];
819 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
823 fvals
[0] = (ALfloat
)values
[0];
824 fvals
[1] = (ALfloat
)values
[1];
825 fvals
[2] = (ALfloat
)values
[2];
826 fvals
[3] = (ALfloat
)values
[3];
827 fvals
[4] = (ALfloat
)values
[4];
828 fvals
[5] = (ALfloat
)values
[5];
829 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
831 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
832 case AL_SEC_OFFSET_LATENCY_SOFT
:
836 ERR("Unexpected property: 0x%04x\n", prop
);
837 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
840 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, const ALint64SOFT
*values
)
848 case AL_BUFFERS_QUEUED
:
849 case AL_BUFFERS_PROCESSED
:
850 case AL_SOURCE_STATE
:
851 case AL_SAMPLE_RW_OFFSETS_SOFT
:
852 case AL_BYTE_RW_OFFSETS_SOFT
:
853 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
854 case AL_BYTE_LENGTH_SOFT
:
855 case AL_SAMPLE_LENGTH_SOFT
:
856 case AL_SEC_LENGTH_SOFT
:
858 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
862 case AL_SOURCE_RELATIVE
:
865 case AL_SAMPLE_OFFSET
:
867 case AL_DIRECT_FILTER_GAINHF_AUTO
:
868 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
869 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
870 case AL_DIRECT_CHANNELS_SOFT
:
871 case AL_DISTANCE_MODEL
:
872 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
874 ivals
[0] = (ALint
)*values
;
875 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
879 case AL_DIRECT_FILTER
:
880 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
882 ivals
[0] = (ALuint
)*values
;
883 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
886 case AL_AUXILIARY_SEND_FILTER
:
887 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
888 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
889 values
[2] <= UINT_MAX
&& values
[2] >= 0);
891 ivals
[0] = (ALuint
)values
[0];
892 ivals
[1] = (ALuint
)values
[1];
893 ivals
[2] = (ALuint
)values
[2];
894 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
897 case AL_CONE_INNER_ANGLE
:
898 case AL_CONE_OUTER_ANGLE
:
903 case AL_REFERENCE_DISTANCE
:
904 case AL_ROLLOFF_FACTOR
:
905 case AL_CONE_OUTER_GAIN
:
906 case AL_MAX_DISTANCE
:
907 case AL_DOPPLER_FACTOR
:
908 case AL_CONE_OUTER_GAINHF
:
909 case AL_AIR_ABSORPTION_FACTOR
:
910 case AL_ROOM_ROLLOFF_FACTOR
:
911 fvals
[0] = (ALfloat
)*values
;
912 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
918 fvals
[0] = (ALfloat
)values
[0];
919 fvals
[1] = (ALfloat
)values
[1];
920 fvals
[2] = (ALfloat
)values
[2];
921 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
925 fvals
[0] = (ALfloat
)values
[0];
926 fvals
[1] = (ALfloat
)values
[1];
927 fvals
[2] = (ALfloat
)values
[2];
928 fvals
[3] = (ALfloat
)values
[3];
929 fvals
[4] = (ALfloat
)values
[4];
930 fvals
[5] = (ALfloat
)values
[5];
931 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
933 case AL_SEC_OFFSET_LATENCY_SOFT
:
937 ERR("Unexpected property: 0x%04x\n", prop
);
938 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
944 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALdouble
*values
)
946 ALCdevice
*device
= Context
->Device
;
947 ALbufferlistitem
*BufferList
;
956 *values
= Source
->Gain
;
960 *values
= Source
->Pitch
;
963 case AL_MAX_DISTANCE
:
964 *values
= Source
->MaxDistance
;
967 case AL_ROLLOFF_FACTOR
:
968 *values
= Source
->RollOffFactor
;
971 case AL_REFERENCE_DISTANCE
:
972 *values
= Source
->RefDistance
;
975 case AL_CONE_INNER_ANGLE
:
976 *values
= Source
->InnerAngle
;
979 case AL_CONE_OUTER_ANGLE
:
980 *values
= Source
->OuterAngle
;
984 *values
= Source
->MinGain
;
988 *values
= Source
->MaxGain
;
991 case AL_CONE_OUTER_GAIN
:
992 *values
= Source
->OuterGain
;
996 case AL_SAMPLE_OFFSET
:
998 LockContext(Context
);
999 GetSourceOffsets(Source
, prop
, offsets
, 0.0);
1000 UnlockContext(Context
);
1001 *values
= offsets
[0];
1004 case AL_CONE_OUTER_GAINHF
:
1005 *values
= Source
->OuterGainHF
;
1008 case AL_AIR_ABSORPTION_FACTOR
:
1009 *values
= Source
->AirAbsorptionFactor
;
1012 case AL_ROOM_ROLLOFF_FACTOR
:
1013 *values
= Source
->RoomRolloffFactor
;
1016 case AL_DOPPLER_FACTOR
:
1017 *values
= Source
->DopplerFactor
;
1020 case AL_SEC_LENGTH_SOFT
:
1021 ReadLock(&Source
->queue_lock
);
1022 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1029 ALbuffer
*buffer
= BufferList
->buffer
;
1030 if(buffer
&& buffer
->SampleLen
> 0)
1032 freq
= buffer
->Frequency
;
1033 length
+= buffer
->SampleLen
;
1035 } while((BufferList
=BufferList
->next
) != NULL
);
1036 *values
= (ALdouble
)length
/ (ALdouble
)freq
;
1038 ReadUnlock(&Source
->queue_lock
);
1041 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1042 case AL_BYTE_RW_OFFSETS_SOFT
:
1043 LockContext(Context
);
1044 updateLen
= (ALdouble
)device
->UpdateSize
/ device
->Frequency
;
1045 GetSourceOffsets(Source
, prop
, values
, updateLen
);
1046 UnlockContext(Context
);
1049 case AL_SEC_OFFSET_LATENCY_SOFT
:
1050 LockContext(Context
);
1051 values
[0] = GetSourceSecOffset(Source
);
1052 values
[1] = (ALdouble
)(V0(device
->Backend
,getLatency
)()) /
1054 UnlockContext(Context
);
1058 LockContext(Context
);
1059 values
[0] = Source
->Position
.v
[0];
1060 values
[1] = Source
->Position
.v
[1];
1061 values
[2] = Source
->Position
.v
[2];
1062 UnlockContext(Context
);
1066 LockContext(Context
);
1067 values
[0] = Source
->Velocity
.v
[0];
1068 values
[1] = Source
->Velocity
.v
[1];
1069 values
[2] = Source
->Velocity
.v
[2];
1070 UnlockContext(Context
);
1074 LockContext(Context
);
1075 values
[0] = Source
->Direction
.v
[0];
1076 values
[1] = Source
->Direction
.v
[1];
1077 values
[2] = Source
->Direction
.v
[2];
1078 UnlockContext(Context
);
1081 case AL_ORIENTATION
:
1082 LockContext(Context
);
1083 values
[0] = Source
->Orientation
[0][0];
1084 values
[1] = Source
->Orientation
[0][1];
1085 values
[2] = Source
->Orientation
[0][2];
1086 values
[3] = Source
->Orientation
[1][0];
1087 values
[4] = Source
->Orientation
[1][1];
1088 values
[5] = Source
->Orientation
[1][2];
1089 UnlockContext(Context
);
1093 case AL_SOURCE_RELATIVE
:
1095 case AL_SOURCE_STATE
:
1096 case AL_BUFFERS_QUEUED
:
1097 case AL_BUFFERS_PROCESSED
:
1098 case AL_SOURCE_TYPE
:
1099 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1100 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1101 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1102 case AL_DIRECT_CHANNELS_SOFT
:
1103 case AL_BYTE_LENGTH_SOFT
:
1104 case AL_SAMPLE_LENGTH_SOFT
:
1105 case AL_DISTANCE_MODEL
:
1106 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1107 *values
= (ALdouble
)ivals
[0];
1111 case AL_DIRECT_FILTER
:
1112 case AL_AUXILIARY_SEND_FILTER
:
1113 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1117 ERR("Unexpected property: 0x%04x\n", prop
);
1118 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1121 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint
*values
)
1123 ALbufferlistitem
*BufferList
;
1129 case AL_SOURCE_RELATIVE
:
1130 *values
= Source
->HeadRelative
;
1134 *values
= Source
->Looping
;
1138 ReadLock(&Source
->queue_lock
);
1139 BufferList
= (Source
->SourceType
== AL_STATIC
) ? ATOMIC_LOAD(&Source
->queue
) :
1140 ATOMIC_LOAD(&Source
->current_buffer
);
1141 *values
= (BufferList
&& BufferList
->buffer
) ? BufferList
->buffer
->id
: 0;
1142 ReadUnlock(&Source
->queue_lock
);
1145 case AL_SOURCE_STATE
:
1146 *values
= Source
->state
;
1149 case AL_BYTE_LENGTH_SOFT
:
1150 ReadLock(&Source
->queue_lock
);
1151 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1157 ALbuffer
*buffer
= BufferList
->buffer
;
1158 if(buffer
&& buffer
->SampleLen
> 0)
1160 ALuint byte_align
, sample_align
;
1161 if(buffer
->OriginalType
== UserFmtIMA4
)
1163 ALsizei align
= (buffer
->OriginalAlign
-1)/2 + 4;
1164 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1165 sample_align
= buffer
->OriginalAlign
;
1167 else if(buffer
->OriginalType
== UserFmtMSADPCM
)
1169 ALsizei align
= (buffer
->OriginalAlign
-2)/2 + 7;
1170 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1171 sample_align
= buffer
->OriginalAlign
;
1175 ALsizei align
= buffer
->OriginalAlign
;
1176 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1177 sample_align
= buffer
->OriginalAlign
;
1180 length
+= buffer
->SampleLen
/ sample_align
* byte_align
;
1182 } while((BufferList
=BufferList
->next
) != NULL
);
1185 ReadUnlock(&Source
->queue_lock
);
1188 case AL_SAMPLE_LENGTH_SOFT
:
1189 ReadLock(&Source
->queue_lock
);
1190 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1196 ALbuffer
*buffer
= BufferList
->buffer
;
1197 if(buffer
) length
+= buffer
->SampleLen
;
1198 } while((BufferList
=BufferList
->next
) != NULL
);
1201 ReadUnlock(&Source
->queue_lock
);
1204 case AL_BUFFERS_QUEUED
:
1205 ReadLock(&Source
->queue_lock
);
1206 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1213 } while((BufferList
=BufferList
->next
) != NULL
);
1216 ReadUnlock(&Source
->queue_lock
);
1219 case AL_BUFFERS_PROCESSED
:
1220 ReadLock(&Source
->queue_lock
);
1221 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
1223 /* Buffers on a looping source are in a perpetual state of
1224 * PENDING, so don't report any as PROCESSED */
1229 const ALbufferlistitem
*BufferList
= ATOMIC_LOAD(&Source
->queue
);
1230 const ALbufferlistitem
*Current
= ATOMIC_LOAD(&Source
->current_buffer
);
1232 while(BufferList
&& BufferList
!= Current
)
1235 BufferList
= BufferList
->next
;
1239 ReadUnlock(&Source
->queue_lock
);
1242 case AL_SOURCE_TYPE
:
1243 *values
= Source
->SourceType
;
1246 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1247 *values
= Source
->DryGainHFAuto
;
1250 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1251 *values
= Source
->WetGainAuto
;
1254 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1255 *values
= Source
->WetGainHFAuto
;
1258 case AL_DIRECT_CHANNELS_SOFT
:
1259 *values
= Source
->DirectChannels
;
1262 case AL_DISTANCE_MODEL
:
1263 *values
= Source
->DistanceModel
;
1266 /* 1x float/double */
1267 case AL_CONE_INNER_ANGLE
:
1268 case AL_CONE_OUTER_ANGLE
:
1273 case AL_REFERENCE_DISTANCE
:
1274 case AL_ROLLOFF_FACTOR
:
1275 case AL_CONE_OUTER_GAIN
:
1276 case AL_MAX_DISTANCE
:
1278 case AL_SAMPLE_OFFSET
:
1279 case AL_BYTE_OFFSET
:
1280 case AL_DOPPLER_FACTOR
:
1281 case AL_AIR_ABSORPTION_FACTOR
:
1282 case AL_ROOM_ROLLOFF_FACTOR
:
1283 case AL_CONE_OUTER_GAINHF
:
1284 case AL_SEC_LENGTH_SOFT
:
1285 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1286 *values
= (ALint
)dvals
[0];
1289 /* 2x float/double */
1290 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1291 case AL_BYTE_RW_OFFSETS_SOFT
:
1292 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1294 values
[0] = (ALint
)dvals
[0];
1295 values
[1] = (ALint
)dvals
[1];
1299 /* 3x float/double */
1303 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1305 values
[0] = (ALint
)dvals
[0];
1306 values
[1] = (ALint
)dvals
[1];
1307 values
[2] = (ALint
)dvals
[2];
1311 /* 6x float/double */
1312 case AL_ORIENTATION
:
1313 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1315 values
[0] = (ALint
)dvals
[0];
1316 values
[1] = (ALint
)dvals
[1];
1317 values
[2] = (ALint
)dvals
[2];
1318 values
[3] = (ALint
)dvals
[3];
1319 values
[4] = (ALint
)dvals
[4];
1320 values
[5] = (ALint
)dvals
[5];
1324 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1325 break; /* i64 only */
1326 case AL_SEC_OFFSET_LATENCY_SOFT
:
1327 break; /* Double only */
1329 case AL_DIRECT_FILTER
:
1330 case AL_AUXILIARY_SEND_FILTER
:
1334 ERR("Unexpected property: 0x%04x\n", prop
);
1335 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1338 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SourceProp prop
, ALint64
*values
)
1340 ALCdevice
*device
= Context
->Device
;
1347 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1348 LockContext(Context
);
1349 values
[0] = GetSourceSampleOffset(Source
);
1350 values
[1] = V0(device
->Backend
,getLatency
)();
1351 UnlockContext(Context
);
1354 /* 1x float/double */
1355 case AL_CONE_INNER_ANGLE
:
1356 case AL_CONE_OUTER_ANGLE
:
1361 case AL_REFERENCE_DISTANCE
:
1362 case AL_ROLLOFF_FACTOR
:
1363 case AL_CONE_OUTER_GAIN
:
1364 case AL_MAX_DISTANCE
:
1366 case AL_SAMPLE_OFFSET
:
1367 case AL_BYTE_OFFSET
:
1368 case AL_DOPPLER_FACTOR
:
1369 case AL_AIR_ABSORPTION_FACTOR
:
1370 case AL_ROOM_ROLLOFF_FACTOR
:
1371 case AL_CONE_OUTER_GAINHF
:
1372 case AL_SEC_LENGTH_SOFT
:
1373 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1374 *values
= (ALint64
)dvals
[0];
1377 /* 2x float/double */
1378 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1379 case AL_BYTE_RW_OFFSETS_SOFT
:
1380 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1382 values
[0] = (ALint64
)dvals
[0];
1383 values
[1] = (ALint64
)dvals
[1];
1387 /* 3x float/double */
1391 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1393 values
[0] = (ALint64
)dvals
[0];
1394 values
[1] = (ALint64
)dvals
[1];
1395 values
[2] = (ALint64
)dvals
[2];
1399 /* 6x float/double */
1400 case AL_ORIENTATION
:
1401 if((err
=GetSourcedv(Source
, Context
, prop
, dvals
)) != AL_FALSE
)
1403 values
[0] = (ALint64
)dvals
[0];
1404 values
[1] = (ALint64
)dvals
[1];
1405 values
[2] = (ALint64
)dvals
[2];
1406 values
[3] = (ALint64
)dvals
[3];
1407 values
[4] = (ALint64
)dvals
[4];
1408 values
[5] = (ALint64
)dvals
[5];
1413 case AL_SOURCE_RELATIVE
:
1415 case AL_SOURCE_STATE
:
1416 case AL_BUFFERS_QUEUED
:
1417 case AL_BUFFERS_PROCESSED
:
1418 case AL_BYTE_LENGTH_SOFT
:
1419 case AL_SAMPLE_LENGTH_SOFT
:
1420 case AL_SOURCE_TYPE
:
1421 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1422 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1423 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1424 case AL_DIRECT_CHANNELS_SOFT
:
1425 case AL_DISTANCE_MODEL
:
1426 if((err
=GetSourceiv(Source
, Context
, prop
, ivals
)) != AL_FALSE
)
1432 case AL_DIRECT_FILTER
:
1433 if((err
=GetSourceiv(Source
, Context
, prop
, ivals
)) != AL_FALSE
)
1434 *values
= (ALuint
)ivals
[0];
1438 case AL_AUXILIARY_SEND_FILTER
:
1439 if((err
=GetSourceiv(Source
, Context
, prop
, ivals
)) != AL_FALSE
)
1441 values
[0] = (ALuint
)ivals
[0];
1442 values
[1] = (ALuint
)ivals
[1];
1443 values
[2] = (ALuint
)ivals
[2];
1447 case AL_SEC_OFFSET_LATENCY_SOFT
:
1448 break; /* Double only */
1451 ERR("Unexpected property: 0x%04x\n", prop
);
1452 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1456 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
1458 ALCcontext
*context
;
1462 context
= GetContextRef();
1463 if(!context
) return;
1466 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1467 for(cur
= 0;cur
< n
;cur
++)
1469 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
1472 alDeleteSources(cur
, sources
);
1473 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
1475 InitSourceParams(source
);
1477 err
= NewThunkEntry(&source
->id
);
1478 if(err
== AL_NO_ERROR
)
1479 err
= InsertUIntMapEntry(&context
->SourceMap
, source
->id
, source
);
1480 if(err
!= AL_NO_ERROR
)
1482 FreeThunkEntry(source
->id
);
1483 memset(source
, 0, sizeof(ALsource
));
1486 alDeleteSources(cur
, sources
);
1487 SET_ERROR_AND_GOTO(context
, err
, done
);
1490 sources
[cur
] = source
->id
;
1494 ALCcontext_DecRef(context
);
1498 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
1500 ALCcontext
*context
;
1501 ALbufferlistitem
*BufferList
;
1505 context
= GetContextRef();
1506 if(!context
) return;
1509 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1511 /* Check that all Sources are valid */
1512 for(i
= 0;i
< n
;i
++)
1514 if(LookupSource(context
, sources
[i
]) == NULL
)
1515 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
1517 for(i
= 0;i
< n
;i
++)
1519 ALvoice
*voice
, *voice_end
;
1521 if((Source
=RemoveSource(context
, sources
[i
])) == NULL
)
1523 FreeThunkEntry(Source
->id
);
1525 LockContext(context
);
1526 voice
= context
->Voices
;
1527 voice_end
= voice
+ context
->VoiceCount
;
1528 while(voice
!= voice_end
)
1530 ALsource
*old
= Source
;
1531 if(COMPARE_EXCHANGE(&voice
->Source
, &old
, NULL
))
1535 UnlockContext(context
);
1537 BufferList
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &Source
->queue
, NULL
);
1538 while(BufferList
!= NULL
)
1540 ALbufferlistitem
*next
= BufferList
->next
;
1541 if(BufferList
->buffer
!= NULL
)
1542 DecrementRef(&BufferList
->buffer
->ref
);
1547 for(j
= 0;j
< MAX_SENDS
;++j
)
1549 if(Source
->Send
[j
].Slot
)
1550 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
1551 Source
->Send
[j
].Slot
= NULL
;
1554 memset(Source
, 0, sizeof(*Source
));
1559 ALCcontext_DecRef(context
);
1563 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1565 ALCcontext
*context
;
1568 context
= GetContextRef();
1569 if(!context
) return AL_FALSE
;
1571 ret
= (LookupSource(context
, source
) ? AL_TRUE
: AL_FALSE
);
1573 ALCcontext_DecRef(context
);
1579 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1581 ALCcontext
*Context
;
1584 Context
= GetContextRef();
1585 if(!Context
) return;
1587 if((Source
=LookupSource(Context
, source
)) == NULL
)
1588 alSetError(Context
, AL_INVALID_NAME
);
1589 else if(!(FloatValsByProp(param
) == 1))
1590 alSetError(Context
, AL_INVALID_ENUM
);
1592 SetSourcefv(Source
, Context
, param
, &value
);
1594 ALCcontext_DecRef(Context
);
1597 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1599 ALCcontext
*Context
;
1602 Context
= GetContextRef();
1603 if(!Context
) return;
1605 if((Source
=LookupSource(Context
, source
)) == NULL
)
1606 alSetError(Context
, AL_INVALID_NAME
);
1607 else if(!(FloatValsByProp(param
) == 3))
1608 alSetError(Context
, AL_INVALID_ENUM
);
1611 ALfloat fvals
[3] = { value1
, value2
, value3
};
1612 SetSourcefv(Source
, Context
, param
, fvals
);
1615 ALCcontext_DecRef(Context
);
1618 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1620 ALCcontext
*Context
;
1623 Context
= GetContextRef();
1624 if(!Context
) return;
1626 if((Source
=LookupSource(Context
, source
)) == NULL
)
1627 alSetError(Context
, AL_INVALID_NAME
);
1629 alSetError(Context
, AL_INVALID_VALUE
);
1630 else if(!(FloatValsByProp(param
) > 0))
1631 alSetError(Context
, AL_INVALID_ENUM
);
1633 SetSourcefv(Source
, Context
, param
, values
);
1635 ALCcontext_DecRef(Context
);
1639 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1641 ALCcontext
*Context
;
1644 Context
= GetContextRef();
1645 if(!Context
) return;
1647 if((Source
=LookupSource(Context
, source
)) == NULL
)
1648 alSetError(Context
, AL_INVALID_NAME
);
1649 else if(!(DoubleValsByProp(param
) == 1))
1650 alSetError(Context
, AL_INVALID_ENUM
);
1653 ALfloat fval
= (ALfloat
)value
;
1654 SetSourcefv(Source
, Context
, param
, &fval
);
1657 ALCcontext_DecRef(Context
);
1660 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1662 ALCcontext
*Context
;
1665 Context
= GetContextRef();
1666 if(!Context
) return;
1668 if((Source
=LookupSource(Context
, source
)) == NULL
)
1669 alSetError(Context
, AL_INVALID_NAME
);
1670 else if(!(DoubleValsByProp(param
) == 3))
1671 alSetError(Context
, AL_INVALID_ENUM
);
1674 ALfloat fvals
[3] = { (ALfloat
)value1
, (ALfloat
)value2
, (ALfloat
)value3
};
1675 SetSourcefv(Source
, Context
, param
, fvals
);
1678 ALCcontext_DecRef(Context
);
1681 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1683 ALCcontext
*Context
;
1687 Context
= GetContextRef();
1688 if(!Context
) return;
1690 if((Source
=LookupSource(Context
, source
)) == NULL
)
1691 alSetError(Context
, AL_INVALID_NAME
);
1693 alSetError(Context
, AL_INVALID_VALUE
);
1694 else if(!((count
=DoubleValsByProp(param
)) > 0 && count
<= 6))
1695 alSetError(Context
, AL_INVALID_ENUM
);
1701 for(i
= 0;i
< count
;i
++)
1702 fvals
[i
] = (ALfloat
)values
[i
];
1703 SetSourcefv(Source
, Context
, param
, fvals
);
1706 ALCcontext_DecRef(Context
);
1710 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1712 ALCcontext
*Context
;
1715 Context
= GetContextRef();
1716 if(!Context
) return;
1718 if((Source
=LookupSource(Context
, source
)) == NULL
)
1719 alSetError(Context
, AL_INVALID_NAME
);
1720 else if(!(IntValsByProp(param
) == 1))
1721 alSetError(Context
, AL_INVALID_ENUM
);
1723 SetSourceiv(Source
, Context
, param
, &value
);
1725 ALCcontext_DecRef(Context
);
1728 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1730 ALCcontext
*Context
;
1733 Context
= GetContextRef();
1734 if(!Context
) return;
1736 if((Source
=LookupSource(Context
, source
)) == NULL
)
1737 alSetError(Context
, AL_INVALID_NAME
);
1738 else if(!(IntValsByProp(param
) == 3))
1739 alSetError(Context
, AL_INVALID_ENUM
);
1742 ALint ivals
[3] = { value1
, value2
, value3
};
1743 SetSourceiv(Source
, Context
, param
, ivals
);
1746 ALCcontext_DecRef(Context
);
1749 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1751 ALCcontext
*Context
;
1754 Context
= GetContextRef();
1755 if(!Context
) return;
1757 if((Source
=LookupSource(Context
, source
)) == NULL
)
1758 alSetError(Context
, AL_INVALID_NAME
);
1760 alSetError(Context
, AL_INVALID_VALUE
);
1761 else if(!(IntValsByProp(param
) > 0))
1762 alSetError(Context
, AL_INVALID_ENUM
);
1764 SetSourceiv(Source
, Context
, param
, values
);
1766 ALCcontext_DecRef(Context
);
1770 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1772 ALCcontext
*Context
;
1775 Context
= GetContextRef();
1776 if(!Context
) return;
1778 if((Source
=LookupSource(Context
, source
)) == NULL
)
1779 alSetError(Context
, AL_INVALID_NAME
);
1780 else if(!(Int64ValsByProp(param
) == 1))
1781 alSetError(Context
, AL_INVALID_ENUM
);
1783 SetSourcei64v(Source
, Context
, param
, &value
);
1785 ALCcontext_DecRef(Context
);
1788 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1790 ALCcontext
*Context
;
1793 Context
= GetContextRef();
1794 if(!Context
) return;
1796 if((Source
=LookupSource(Context
, source
)) == NULL
)
1797 alSetError(Context
, AL_INVALID_NAME
);
1798 else if(!(Int64ValsByProp(param
) == 3))
1799 alSetError(Context
, AL_INVALID_ENUM
);
1802 ALint64SOFT i64vals
[3] = { value1
, value2
, value3
};
1803 SetSourcei64v(Source
, Context
, param
, i64vals
);
1806 ALCcontext_DecRef(Context
);
1809 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1811 ALCcontext
*Context
;
1814 Context
= GetContextRef();
1815 if(!Context
) return;
1817 if((Source
=LookupSource(Context
, source
)) == NULL
)
1818 alSetError(Context
, AL_INVALID_NAME
);
1820 alSetError(Context
, AL_INVALID_VALUE
);
1821 else if(!(Int64ValsByProp(param
) > 0))
1822 alSetError(Context
, AL_INVALID_ENUM
);
1824 SetSourcei64v(Source
, Context
, param
, values
);
1826 ALCcontext_DecRef(Context
);
1830 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1832 ALCcontext
*Context
;
1835 Context
= GetContextRef();
1836 if(!Context
) return;
1838 if((Source
=LookupSource(Context
, source
)) == NULL
)
1839 alSetError(Context
, AL_INVALID_NAME
);
1841 alSetError(Context
, AL_INVALID_VALUE
);
1842 else if(!(FloatValsByProp(param
) == 1))
1843 alSetError(Context
, AL_INVALID_ENUM
);
1847 if(GetSourcedv(Source
, Context
, param
, &dval
))
1848 *value
= (ALfloat
)dval
;
1851 ALCcontext_DecRef(Context
);
1855 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1857 ALCcontext
*Context
;
1860 Context
= GetContextRef();
1861 if(!Context
) return;
1863 if((Source
=LookupSource(Context
, source
)) == NULL
)
1864 alSetError(Context
, AL_INVALID_NAME
);
1865 else if(!(value1
&& value2
&& value3
))
1866 alSetError(Context
, AL_INVALID_VALUE
);
1867 else if(!(FloatValsByProp(param
) == 3))
1868 alSetError(Context
, AL_INVALID_ENUM
);
1872 if(GetSourcedv(Source
, Context
, param
, dvals
))
1874 *value1
= (ALfloat
)dvals
[0];
1875 *value2
= (ALfloat
)dvals
[1];
1876 *value3
= (ALfloat
)dvals
[2];
1880 ALCcontext_DecRef(Context
);
1884 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1886 ALCcontext
*Context
;
1890 Context
= GetContextRef();
1891 if(!Context
) return;
1893 if((Source
=LookupSource(Context
, source
)) == NULL
)
1894 alSetError(Context
, AL_INVALID_NAME
);
1896 alSetError(Context
, AL_INVALID_VALUE
);
1897 else if(!((count
=FloatValsByProp(param
)) > 0 && count
<= 6))
1898 alSetError(Context
, AL_INVALID_ENUM
);
1902 if(GetSourcedv(Source
, Context
, param
, dvals
))
1905 for(i
= 0;i
< count
;i
++)
1906 values
[i
] = (ALfloat
)dvals
[i
];
1910 ALCcontext_DecRef(Context
);
1914 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1916 ALCcontext
*Context
;
1919 Context
= GetContextRef();
1920 if(!Context
) return;
1922 if((Source
=LookupSource(Context
, source
)) == NULL
)
1923 alSetError(Context
, AL_INVALID_NAME
);
1925 alSetError(Context
, AL_INVALID_VALUE
);
1926 else if(!(DoubleValsByProp(param
) == 1))
1927 alSetError(Context
, AL_INVALID_ENUM
);
1929 GetSourcedv(Source
, Context
, param
, value
);
1931 ALCcontext_DecRef(Context
);
1934 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1936 ALCcontext
*Context
;
1939 Context
= GetContextRef();
1940 if(!Context
) return;
1942 if((Source
=LookupSource(Context
, source
)) == NULL
)
1943 alSetError(Context
, AL_INVALID_NAME
);
1944 else if(!(value1
&& value2
&& value3
))
1945 alSetError(Context
, AL_INVALID_VALUE
);
1946 else if(!(DoubleValsByProp(param
) == 3))
1947 alSetError(Context
, AL_INVALID_ENUM
);
1951 if(GetSourcedv(Source
, Context
, param
, dvals
))
1959 ALCcontext_DecRef(Context
);
1962 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1964 ALCcontext
*Context
;
1967 Context
= GetContextRef();
1968 if(!Context
) return;
1970 if((Source
=LookupSource(Context
, source
)) == NULL
)
1971 alSetError(Context
, AL_INVALID_NAME
);
1973 alSetError(Context
, AL_INVALID_VALUE
);
1974 else if(!(DoubleValsByProp(param
) > 0))
1975 alSetError(Context
, AL_INVALID_ENUM
);
1977 GetSourcedv(Source
, Context
, param
, values
);
1979 ALCcontext_DecRef(Context
);
1983 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1985 ALCcontext
*Context
;
1988 Context
= GetContextRef();
1989 if(!Context
) return;
1991 if((Source
=LookupSource(Context
, source
)) == NULL
)
1992 alSetError(Context
, AL_INVALID_NAME
);
1994 alSetError(Context
, AL_INVALID_VALUE
);
1995 else if(!(IntValsByProp(param
) == 1))
1996 alSetError(Context
, AL_INVALID_ENUM
);
1998 GetSourceiv(Source
, Context
, param
, value
);
2000 ALCcontext_DecRef(Context
);
2004 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
2006 ALCcontext
*Context
;
2009 Context
= GetContextRef();
2010 if(!Context
) return;
2012 if((Source
=LookupSource(Context
, source
)) == NULL
)
2013 alSetError(Context
, AL_INVALID_NAME
);
2014 else if(!(value1
&& value2
&& value3
))
2015 alSetError(Context
, AL_INVALID_VALUE
);
2016 else if(!(IntValsByProp(param
) == 3))
2017 alSetError(Context
, AL_INVALID_ENUM
);
2021 if(GetSourceiv(Source
, Context
, param
, ivals
))
2029 ALCcontext_DecRef(Context
);
2033 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
2035 ALCcontext
*Context
;
2038 Context
= GetContextRef();
2039 if(!Context
) return;
2041 if((Source
=LookupSource(Context
, source
)) == NULL
)
2042 alSetError(Context
, AL_INVALID_NAME
);
2044 alSetError(Context
, AL_INVALID_VALUE
);
2045 else if(!(IntValsByProp(param
) > 0))
2046 alSetError(Context
, AL_INVALID_ENUM
);
2048 GetSourceiv(Source
, Context
, param
, values
);
2050 ALCcontext_DecRef(Context
);
2054 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
2056 ALCcontext
*Context
;
2059 Context
= GetContextRef();
2060 if(!Context
) return;
2062 if((Source
=LookupSource(Context
, source
)) == NULL
)
2063 alSetError(Context
, AL_INVALID_NAME
);
2065 alSetError(Context
, AL_INVALID_VALUE
);
2066 else if(!(Int64ValsByProp(param
) == 1))
2067 alSetError(Context
, AL_INVALID_ENUM
);
2069 GetSourcei64v(Source
, Context
, param
, value
);
2071 ALCcontext_DecRef(Context
);
2074 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
2076 ALCcontext
*Context
;
2079 Context
= GetContextRef();
2080 if(!Context
) return;
2082 if((Source
=LookupSource(Context
, source
)) == NULL
)
2083 alSetError(Context
, AL_INVALID_NAME
);
2084 else if(!(value1
&& value2
&& value3
))
2085 alSetError(Context
, AL_INVALID_VALUE
);
2086 else if(!(Int64ValsByProp(param
) == 3))
2087 alSetError(Context
, AL_INVALID_ENUM
);
2091 if(GetSourcei64v(Source
, Context
, param
, i64vals
))
2093 *value1
= i64vals
[0];
2094 *value2
= i64vals
[1];
2095 *value3
= i64vals
[2];
2099 ALCcontext_DecRef(Context
);
2102 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
2104 ALCcontext
*Context
;
2107 Context
= GetContextRef();
2108 if(!Context
) return;
2110 if((Source
=LookupSource(Context
, source
)) == NULL
)
2111 alSetError(Context
, AL_INVALID_NAME
);
2113 alSetError(Context
, AL_INVALID_VALUE
);
2114 else if(!(Int64ValsByProp(param
) > 0))
2115 alSetError(Context
, AL_INVALID_ENUM
);
2117 GetSourcei64v(Source
, Context
, param
, values
);
2119 ALCcontext_DecRef(Context
);
2123 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
2125 alSourcePlayv(1, &source
);
2127 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2129 ALCcontext
*context
;
2133 context
= GetContextRef();
2134 if(!context
) return;
2137 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2138 for(i
= 0;i
< n
;i
++)
2140 if(!LookupSource(context
, sources
[i
]))
2141 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2144 LockContext(context
);
2145 while(n
> context
->MaxVoices
-context
->VoiceCount
)
2147 ALvoice
*temp
= NULL
;
2150 newcount
= context
->MaxVoices
<< 1;
2152 temp
= realloc(context
->Voices
, newcount
* sizeof(context
->Voices
[0]));
2155 UnlockContext(context
);
2156 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
2158 memset(&temp
[context
->MaxVoices
], 0, (newcount
-context
->MaxVoices
) * sizeof(temp
[0]));
2160 context
->Voices
= temp
;
2161 context
->MaxVoices
= newcount
;
2164 for(i
= 0;i
< n
;i
++)
2166 source
= LookupSource(context
, sources
[i
]);
2167 if(context
->DeferUpdates
) source
->new_state
= AL_PLAYING
;
2168 else SetSourceState(source
, context
, AL_PLAYING
);
2170 UnlockContext(context
);
2173 ALCcontext_DecRef(context
);
2176 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2178 alSourcePausev(1, &source
);
2180 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2182 ALCcontext
*context
;
2186 context
= GetContextRef();
2187 if(!context
) return;
2190 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2191 for(i
= 0;i
< n
;i
++)
2193 if(!LookupSource(context
, sources
[i
]))
2194 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2197 LockContext(context
);
2198 for(i
= 0;i
< n
;i
++)
2200 source
= LookupSource(context
, sources
[i
]);
2201 if(context
->DeferUpdates
) source
->new_state
= AL_PAUSED
;
2202 else SetSourceState(source
, context
, AL_PAUSED
);
2204 UnlockContext(context
);
2207 ALCcontext_DecRef(context
);
2210 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2212 alSourceStopv(1, &source
);
2214 AL_API ALvoid AL_APIENTRY
alSourceStopv(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 source
->new_state
= AL_NONE
;
2236 SetSourceState(source
, context
, AL_STOPPED
);
2238 UnlockContext(context
);
2241 ALCcontext_DecRef(context
);
2244 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2246 alSourceRewindv(1, &source
);
2248 AL_API ALvoid AL_APIENTRY
alSourceRewindv(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_INITIAL
);
2272 UnlockContext(context
);
2275 ALCcontext_DecRef(context
);
2279 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint src
, ALsizei nb
, const ALuint
*buffers
)
2282 ALCcontext
*context
;
2285 ALbufferlistitem
*BufferListStart
;
2286 ALbufferlistitem
*BufferList
;
2287 ALbuffer
*BufferFmt
= NULL
;
2292 context
= GetContextRef();
2293 if(!context
) return;
2295 device
= context
->Device
;
2298 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2299 if((source
=LookupSource(context
, src
)) == NULL
)
2300 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2302 WriteLock(&source
->queue_lock
);
2303 if(source
->SourceType
== AL_STATIC
)
2305 WriteUnlock(&source
->queue_lock
);
2306 /* Can't queue on a Static Source */
2307 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
2310 /* Check for a valid Buffer, for its frequency and format */
2311 BufferList
= ATOMIC_LOAD(&source
->queue
);
2314 if(BufferList
->buffer
)
2316 BufferFmt
= BufferList
->buffer
;
2319 BufferList
= BufferList
->next
;
2322 BufferListStart
= NULL
;
2324 for(i
= 0;i
< nb
;i
++)
2326 ALbuffer
*buffer
= NULL
;
2327 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2329 WriteUnlock(&source
->queue_lock
);
2330 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, buffer_error
);
2333 if(!BufferListStart
)
2335 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2336 BufferList
= BufferListStart
;
2340 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2341 BufferList
= BufferList
->next
;
2343 BufferList
->buffer
= buffer
;
2344 BufferList
->next
= NULL
;
2345 if(!buffer
) continue;
2347 /* Hold a read lock on each buffer being queued while checking all
2348 * provided buffers. This is done so other threads don't see an extra
2349 * reference on some buffers if this operation ends up failing. */
2350 ReadLock(&buffer
->lock
);
2351 IncrementRef(&buffer
->ref
);
2353 if(BufferFmt
== NULL
)
2357 source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2358 source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2360 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2361 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2362 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2364 WriteUnlock(&source
->queue_lock
);
2365 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, buffer_error
);
2368 /* A buffer failed (invalid ID or format), so unlock and release
2369 * each buffer we had. */
2370 while(BufferListStart
)
2372 ALbufferlistitem
*next
= BufferListStart
->next
;
2373 if((buffer
=BufferListStart
->buffer
) != NULL
)
2375 DecrementRef(&buffer
->ref
);
2376 ReadUnlock(&buffer
->lock
);
2378 free(BufferListStart
);
2379 BufferListStart
= next
;
2384 /* All buffers good, unlock them now. */
2385 BufferList
= BufferListStart
;
2386 while(BufferList
!= NULL
)
2388 ALbuffer
*buffer
= BufferList
->buffer
;
2389 if(buffer
) ReadUnlock(&buffer
->lock
);
2390 BufferList
= BufferList
->next
;
2393 /* Source is now streaming */
2394 source
->SourceType
= AL_STREAMING
;
2397 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->queue
, &BufferList
, BufferListStart
))
2399 /* Queue head is not NULL, append to the end of the queue */
2400 while(BufferList
->next
!= NULL
)
2401 BufferList
= BufferList
->next
;
2402 BufferList
->next
= BufferListStart
;
2404 /* If the current buffer was at the end (NULL), put it at the start of the newly queued
2408 ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->current_buffer
, &BufferList
, BufferListStart
);
2409 WriteUnlock(&source
->queue_lock
);
2412 ALCcontext_DecRef(context
);
2415 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint src
, ALsizei nb
, ALuint
*buffers
)
2417 ALCcontext
*context
;
2419 ALbufferlistitem
*OldHead
;
2420 ALbufferlistitem
*OldTail
;
2421 ALbufferlistitem
*Current
;
2427 context
= GetContextRef();
2428 if(!context
) return;
2431 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2433 if((source
=LookupSource(context
, src
)) == NULL
)
2434 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2436 WriteLock(&source
->queue_lock
);
2437 /* Find the new buffer queue head */
2438 OldTail
= ATOMIC_LOAD(&source
->queue
);
2439 Current
= ATOMIC_LOAD(&source
->current_buffer
);
2440 if(OldTail
!= Current
)
2442 for(i
= 1;i
< nb
;i
++)
2444 ALbufferlistitem
*next
= OldTail
->next
;
2445 if(!next
|| next
== Current
) break;
2449 if(source
->Looping
|| source
->SourceType
!= AL_STREAMING
|| i
!= nb
)
2451 WriteUnlock(&source
->queue_lock
);
2452 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2453 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2456 /* Swap it, and cut the new head from the old. */
2457 OldHead
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &source
->queue
, OldTail
->next
);
2460 ALCdevice
*device
= context
->Device
;
2463 /* Once the active mix (if any) is done, it's safe to cut the old tail
2464 * from the new head.
2466 if(((count
=ReadRef(&device
->MixCount
))&1) != 0)
2468 while(count
== ReadRef(&device
->MixCount
))
2471 OldTail
->next
= NULL
;
2473 WriteUnlock(&source
->queue_lock
);
2475 while(OldHead
!= NULL
)
2477 ALbufferlistitem
*next
= OldHead
->next
;
2478 ALbuffer
*buffer
= OldHead
->buffer
;
2484 *(buffers
++) = buffer
->id
;
2485 DecrementRef(&buffer
->ref
);
2493 ALCcontext_DecRef(context
);
2497 static ALvoid
InitSourceParams(ALsource
*Source
)
2501 RWLockInit(&Source
->queue_lock
);
2503 Source
->InnerAngle
= 360.0f
;
2504 Source
->OuterAngle
= 360.0f
;
2505 Source
->Pitch
= 1.0f
;
2506 aluVectorSet(&Source
->Position
, 0.0f
, 0.0f
, 0.0f
, 1.0f
);
2507 aluVectorSet(&Source
->Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2508 aluVectorSet(&Source
->Direction
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2509 Source
->Orientation
[0][0] = 0.0f
;
2510 Source
->Orientation
[0][1] = 0.0f
;
2511 Source
->Orientation
[0][2] = -1.0f
;
2512 Source
->Orientation
[1][0] = 0.0f
;
2513 Source
->Orientation
[1][1] = 1.0f
;
2514 Source
->Orientation
[1][2] = 0.0f
;
2515 Source
->RefDistance
= 1.0f
;
2516 Source
->MaxDistance
= FLT_MAX
;
2517 Source
->RollOffFactor
= 1.0f
;
2518 Source
->Looping
= AL_FALSE
;
2519 Source
->Gain
= 1.0f
;
2520 Source
->MinGain
= 0.0f
;
2521 Source
->MaxGain
= 1.0f
;
2522 Source
->OuterGain
= 0.0f
;
2523 Source
->OuterGainHF
= 1.0f
;
2525 Source
->DryGainHFAuto
= AL_TRUE
;
2526 Source
->WetGainAuto
= AL_TRUE
;
2527 Source
->WetGainHFAuto
= AL_TRUE
;
2528 Source
->AirAbsorptionFactor
= 0.0f
;
2529 Source
->RoomRolloffFactor
= 0.0f
;
2530 Source
->DopplerFactor
= 1.0f
;
2531 Source
->DirectChannels
= AL_FALSE
;
2533 Source
->Radius
= 0.0f
;
2535 Source
->DistanceModel
= DefaultDistanceModel
;
2537 Source
->state
= AL_INITIAL
;
2538 Source
->new_state
= AL_NONE
;
2539 Source
->SourceType
= AL_UNDETERMINED
;
2540 Source
->Offset
= -1.0;
2542 ATOMIC_INIT(&Source
->queue
, NULL
);
2543 ATOMIC_INIT(&Source
->current_buffer
, NULL
);
2545 Source
->Direct
.Gain
= 1.0f
;
2546 Source
->Direct
.GainHF
= 1.0f
;
2547 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
2548 Source
->Direct
.GainLF
= 1.0f
;
2549 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
2550 for(i
= 0;i
< MAX_SENDS
;i
++)
2552 Source
->Send
[i
].Gain
= 1.0f
;
2553 Source
->Send
[i
].GainHF
= 1.0f
;
2554 Source
->Send
[i
].HFReference
= LOWPASSFREQREF
;
2555 Source
->Send
[i
].GainLF
= 1.0f
;
2556 Source
->Send
[i
].LFReference
= HIGHPASSFREQREF
;
2559 ATOMIC_INIT(&Source
->NeedsUpdate
, AL_TRUE
);
2565 * Sets the source's new play state given its current state.
2567 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2569 WriteLock(&Source
->queue_lock
);
2570 if(state
== AL_PLAYING
)
2572 ALCdevice
*device
= Context
->Device
;
2573 ALbufferlistitem
*BufferList
;
2574 ALboolean discontinuity
;
2575 ALvoice
*voice
= NULL
;
2578 /* Check that there is a queue containing at least one valid, non zero
2580 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2584 if((buffer
=BufferList
->buffer
) != NULL
&& buffer
->SampleLen
> 0)
2586 BufferList
= BufferList
->next
;
2589 if(Source
->state
!= AL_PAUSED
)
2591 Source
->state
= AL_PLAYING
;
2592 Source
->position
= 0;
2593 Source
->position_fraction
= 0;
2594 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
2595 discontinuity
= AL_TRUE
;
2599 Source
->state
= AL_PLAYING
;
2600 discontinuity
= AL_FALSE
;
2603 // Check if an Offset has been set
2604 if(Source
->Offset
>= 0.0)
2606 ApplyOffset(Source
);
2607 /* discontinuity = AL_TRUE;??? */
2610 /* If there's nothing to play, or device is disconnected, go right to
2612 if(!BufferList
|| !device
->Connected
)
2615 /* Make sure this source isn't already active, while looking for an
2616 * unused active source slot to put it in. */
2617 for(i
= 0;i
< Context
->VoiceCount
;i
++)
2619 ALsource
*old
= Source
;
2620 if(COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, NULL
))
2624 voice
= &Context
->Voices
[i
];
2625 voice
->Source
= Source
;
2630 if(voice
== NULL
&& COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, Source
))
2631 voice
= &Context
->Voices
[i
];
2635 voice
= &Context
->Voices
[Context
->VoiceCount
++];
2636 voice
->Source
= Source
;
2639 /* Clear previous samples if playback is discontinuous. */
2641 memset(voice
->PrevSamples
, 0, sizeof(voice
->PrevSamples
));
2643 voice
->Direct
.Moving
= AL_FALSE
;
2644 voice
->Direct
.Counter
= 0;
2645 for(i
= 0;i
< MAX_INPUT_CHANNELS
;i
++)
2648 for(j
= 0;j
< HRTF_HISTORY_LENGTH
;j
++)
2649 voice
->Direct
.Hrtf
[i
].State
.History
[j
] = 0.0f
;
2650 for(j
= 0;j
< HRIR_LENGTH
;j
++)
2652 voice
->Direct
.Hrtf
[i
].State
.Values
[j
][0] = 0.0f
;
2653 voice
->Direct
.Hrtf
[i
].State
.Values
[j
][1] = 0.0f
;
2656 for(i
= 0;i
< (ALsizei
)device
->NumAuxSends
;i
++)
2658 voice
->Send
[i
].Moving
= AL_FALSE
;
2659 voice
->Send
[i
].Counter
= 0;
2662 if(BufferList
->buffer
->FmtChannels
== FmtMono
)
2663 voice
->Update
= CalcSourceParams
;
2665 voice
->Update
= CalcNonAttnSourceParams
;
2667 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
2669 else if(state
== AL_PAUSED
)
2671 if(Source
->state
== AL_PLAYING
)
2672 Source
->state
= AL_PAUSED
;
2674 else if(state
== AL_STOPPED
)
2677 if(Source
->state
!= AL_INITIAL
)
2679 Source
->state
= AL_STOPPED
;
2680 ATOMIC_STORE(&Source
->current_buffer
, NULL
);
2682 Source
->Offset
= -1.0;
2684 else if(state
== AL_INITIAL
)
2686 if(Source
->state
!= AL_INITIAL
)
2688 Source
->state
= AL_INITIAL
;
2689 Source
->position
= 0;
2690 Source
->position_fraction
= 0;
2691 ATOMIC_STORE(&Source
->current_buffer
, ATOMIC_LOAD(&Source
->queue
));
2693 Source
->Offset
= -1.0;
2695 WriteUnlock(&Source
->queue_lock
);
2698 /* GetSourceSampleOffset
2700 * Gets the current read offset for the given Source, in 32.32 fixed-point
2701 * samples. The offset is relative to the start of the queue (not the start of
2702 * the current buffer).
2704 ALint64
GetSourceSampleOffset(ALsource
*Source
)
2706 const ALbufferlistitem
*BufferList
;
2707 const ALbufferlistitem
*Current
;
2710 ReadLock(&Source
->queue_lock
);
2711 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2713 ReadUnlock(&Source
->queue_lock
);
2717 /* NOTE: This is the offset into the *current* buffer, so add the length of
2718 * any played buffers */
2719 readPos
= (ALuint64
)Source
->position
<< 32;
2720 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2721 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2722 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2723 while(BufferList
&& BufferList
!= Current
)
2725 if(BufferList
->buffer
)
2726 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2727 BufferList
= BufferList
->next
;
2730 ReadUnlock(&Source
->queue_lock
);
2731 return (ALint64
)minu64(readPos
, U64(0x7fffffffffffffff));
2734 /* GetSourceSecOffset
2736 * Gets the current read offset for the given Source, in seconds. The offset is
2737 * relative to the start of the queue (not the start of the current buffer).
2739 static ALdouble
GetSourceSecOffset(ALsource
*Source
)
2741 const ALbufferlistitem
*BufferList
;
2742 const ALbufferlistitem
*Current
;
2743 const ALbuffer
*Buffer
= NULL
;
2746 ReadLock(&Source
->queue_lock
);
2747 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2749 ReadUnlock(&Source
->queue_lock
);
2753 /* NOTE: This is the offset into the *current* buffer, so add the length of
2754 * any played buffers */
2755 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2756 readPos
|= (ALuint64
)Source
->position_fraction
;
2757 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2758 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2759 while(BufferList
&& BufferList
!= Current
)
2761 const ALbuffer
*buffer
= BufferList
->buffer
;
2764 if(!Buffer
) Buffer
= buffer
;
2765 readPos
+= (ALuint64
)buffer
->SampleLen
<< FRACTIONBITS
;
2767 BufferList
= BufferList
->next
;
2770 while(BufferList
&& !Buffer
)
2772 Buffer
= BufferList
->buffer
;
2773 BufferList
= BufferList
->next
;
2775 assert(Buffer
!= NULL
);
2777 ReadUnlock(&Source
->queue_lock
);
2778 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2783 * Gets the current read and write offsets for the given Source, in the
2784 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2785 * the start of the queue (not the start of the current buffer).
2787 static ALvoid
GetSourceOffsets(ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2789 const ALbufferlistitem
*BufferList
;
2790 const ALbufferlistitem
*Current
;
2791 const ALbuffer
*Buffer
= NULL
;
2792 ALboolean readFin
= AL_FALSE
;
2793 ALuint readPos
, readPosFrac
, writePos
;
2794 ALuint totalBufferLen
;
2796 ReadLock(&Source
->queue_lock
);
2797 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2801 ReadUnlock(&Source
->queue_lock
);
2805 if(updateLen
> 0.0 && updateLen
< 0.015)
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
);
2829 if(Source
->state
== AL_PLAYING
)
2830 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
+ 0.5f
);
2836 readPos
%= totalBufferLen
;
2837 writePos
%= totalBufferLen
;
2841 /* Wrap positions back to 0 */
2842 if(readPos
>= totalBufferLen
)
2843 readPos
= readPosFrac
= 0;
2844 if(writePos
>= totalBufferLen
)
2851 offset
[0] = (readPos
+ (ALdouble
)readPosFrac
/FRACTIONONE
)/Buffer
->Frequency
;
2852 offset
[1] = (ALdouble
)writePos
/Buffer
->Frequency
;
2855 case AL_SAMPLE_OFFSET
:
2856 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2857 offset
[0] = readPos
+ (ALdouble
)readPosFrac
/FRACTIONONE
;
2858 offset
[1] = (ALdouble
)writePos
;
2861 case AL_BYTE_OFFSET
:
2862 case AL_BYTE_RW_OFFSETS_SOFT
:
2863 if(Buffer
->OriginalType
== UserFmtIMA4
)
2865 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
2866 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2867 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2869 /* Round down to nearest ADPCM block */
2870 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2871 if(Source
->state
!= AL_PLAYING
)
2872 offset
[1] = offset
[0];
2875 /* Round up to nearest ADPCM block */
2876 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2877 FrameBlockSize
* BlockSize
);
2880 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
2882 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
2883 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2884 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2886 /* Round down to nearest ADPCM block */
2887 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2888 if(Source
->state
!= AL_PLAYING
)
2889 offset
[1] = offset
[0];
2892 /* Round up to nearest ADPCM block */
2893 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2894 FrameBlockSize
* BlockSize
);
2899 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2900 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2901 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2906 ReadUnlock(&Source
->queue_lock
);
2912 * Apply the stored playback offset to the Source. This function will update
2913 * the number of buffers "played" given the stored offset.
2915 ALboolean
ApplyOffset(ALsource
*Source
)
2917 ALbufferlistitem
*BufferList
;
2918 const ALbuffer
*Buffer
;
2919 ALuint bufferLen
, totalBufferLen
;
2920 ALuint offset
=0, frac
=0;
2922 /* Get sample frame offset */
2923 if(!GetSampleOffset(Source
, &offset
, &frac
))
2927 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2928 while(BufferList
&& totalBufferLen
<= offset
)
2930 Buffer
= BufferList
->buffer
;
2931 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2933 if(bufferLen
> offset
-totalBufferLen
)
2935 /* Offset is in this buffer */
2936 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
2938 Source
->position
= offset
- totalBufferLen
;
2939 Source
->position_fraction
= frac
;
2943 totalBufferLen
+= bufferLen
;
2945 BufferList
= BufferList
->next
;
2948 /* Offset is out of range of the queue */
2955 * Retrieves the sample offset into the Source's queue (from the Sample, Byte
2956 * or Second offset supplied by the application). This takes into account the
2957 * fact that the buffer format may have been modifed since.
2959 static ALboolean
GetSampleOffset(ALsource
*Source
, ALuint
*offset
, ALuint
*frac
)
2961 const ALbuffer
*Buffer
= NULL
;
2962 const ALbufferlistitem
*BufferList
;
2963 ALdouble dbloff
, dblfrac
;
2965 /* Find the first valid Buffer in the Queue */
2966 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2969 if(BufferList
->buffer
)
2971 Buffer
= BufferList
->buffer
;
2974 BufferList
= BufferList
->next
;
2978 Source
->Offset
= -1.0;
2982 switch(Source
->OffsetType
)
2984 case AL_BYTE_OFFSET
:
2985 /* Determine the ByteOffset (and ensure it is block aligned) */
2986 *offset
= (ALuint
)Source
->Offset
;
2987 if(Buffer
->OriginalType
== UserFmtIMA4
)
2989 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
2990 *offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2991 *offset
*= Buffer
->OriginalAlign
;
2993 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
2995 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
2996 *offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2997 *offset
*= Buffer
->OriginalAlign
;
3000 *offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
3004 case AL_SAMPLE_OFFSET
:
3005 dblfrac
= modf(Source
->Offset
, &dbloff
);
3006 *offset
= (ALuint
)mind(dbloff
, UINT_MAX
);
3007 *frac
= (ALuint
)mind(dblfrac
*FRACTIONONE
, FRACTIONONE
-1.0);
3011 dblfrac
= modf(Source
->Offset
*Buffer
->Frequency
, &dbloff
);
3012 *offset
= (ALuint
)mind(dbloff
, UINT_MAX
);
3013 *frac
= (ALuint
)mind(dblfrac
*FRACTIONONE
, FRACTIONONE
-1.0);
3016 Source
->Offset
= -1.0;
3024 * Destroys all sources in the source map.
3026 ALvoid
ReleaseALSources(ALCcontext
*Context
)
3028 ALbufferlistitem
*item
;
3031 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
3033 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
3034 Context
->SourceMap
.array
[pos
].value
= NULL
;
3036 item
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &temp
->queue
, NULL
);
3039 ALbufferlistitem
*next
= item
->next
;
3040 if(item
->buffer
!= NULL
)
3041 DecrementRef(&item
->buffer
->ref
);
3046 for(j
= 0;j
< MAX_SENDS
;++j
)
3048 if(temp
->Send
[j
].Slot
)
3049 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
3050 temp
->Send
[j
].Slot
= NULL
;
3053 FreeThunkEntry(temp
->id
);
3054 memset(temp
, 0, sizeof(*temp
));