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
34 #include "alAuxEffectSlot.h"
39 enum Resampler DefaultResampler
= LinearResampler
;
40 const ALsizei ResamplerPadding
[ResamplerMax
] = {
45 const ALsizei ResamplerPrePadding
[ResamplerMax
] = {
52 extern inline struct ALsource
*LookupSource(ALCcontext
*context
, ALuint id
);
53 extern inline struct ALsource
*RemoveSource(ALCcontext
*context
, ALuint id
);
55 static ALvoid
InitSourceParams(ALsource
*Source
);
56 static ALint64
GetSourceOffset(const ALsource
*Source
);
57 static ALdouble
GetSourceSecOffset(const ALsource
*Source
);
58 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offsets
, ALdouble updateLen
);
59 static ALint
GetSampleOffset(ALsource
*Source
);
61 typedef enum SrcFloatProp
{
64 sfMinGain
= AL_MIN_GAIN
,
65 sfMaxGain
= AL_MAX_GAIN
,
66 sfMaxDistance
= AL_MAX_DISTANCE
,
67 sfRolloffFactor
= AL_ROLLOFF_FACTOR
,
68 sfDopplerFactor
= AL_DOPPLER_FACTOR
,
69 sfConeOuterGain
= AL_CONE_OUTER_GAIN
,
70 sfSecOffset
= AL_SEC_OFFSET
,
71 sfSampleOffset
= AL_SAMPLE_OFFSET
,
72 sfByteOffset
= AL_BYTE_OFFSET
,
73 sfConeInnerAngle
= AL_CONE_INNER_ANGLE
,
74 sfConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
75 sfRefDistance
= AL_REFERENCE_DISTANCE
,
77 sfPosition
= AL_POSITION
,
78 sfVelocity
= AL_VELOCITY
,
79 sfDirection
= AL_DIRECTION
,
81 sfSourceRelative
= AL_SOURCE_RELATIVE
,
82 sfLooping
= AL_LOOPING
,
84 sfSourceState
= AL_SOURCE_STATE
,
85 sfBuffersQueued
= AL_BUFFERS_QUEUED
,
86 sfBuffersProcessed
= AL_BUFFERS_PROCESSED
,
87 sfSourceType
= AL_SOURCE_TYPE
,
90 sfConeOuterGainHF
= AL_CONE_OUTER_GAINHF
,
91 sfAirAbsorptionFactor
= AL_AIR_ABSORPTION_FACTOR
,
92 sfRoomRolloffFactor
= AL_ROOM_ROLLOFF_FACTOR
,
93 sfDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
94 sfAuxSendFilterGainAuto
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
95 sfAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
97 /* AL_SOFT_direct_channels */
98 sfDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
100 /* AL_EXT_source_distance_model */
101 sfDistanceModel
= AL_DISTANCE_MODEL
,
103 sfSecLength
= AL_SEC_LENGTH_SOFT
,
105 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
106 sfSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
107 sfByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
109 /* AL_SOFT_source_latency */
110 sfSecOffsetLatencySOFT
= AL_SEC_OFFSET_LATENCY_SOFT
,
113 typedef enum SrcIntProp
{
114 siMaxDistance
= AL_MAX_DISTANCE
,
115 siRolloffFactor
= AL_ROLLOFF_FACTOR
,
116 siRefDistance
= AL_REFERENCE_DISTANCE
,
117 siSourceRelative
= AL_SOURCE_RELATIVE
,
118 siConeInnerAngle
= AL_CONE_INNER_ANGLE
,
119 siConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
120 siLooping
= AL_LOOPING
,
121 siBuffer
= AL_BUFFER
,
122 siSourceState
= AL_SOURCE_STATE
,
123 siBuffersQueued
= AL_BUFFERS_QUEUED
,
124 siBuffersProcessed
= AL_BUFFERS_PROCESSED
,
125 siSourceType
= AL_SOURCE_TYPE
,
126 siSecOffset
= AL_SEC_OFFSET
,
127 siSampleOffset
= AL_SAMPLE_OFFSET
,
128 siByteOffset
= AL_BYTE_OFFSET
,
129 siDopplerFactor
= AL_DOPPLER_FACTOR
,
130 siPosition
= AL_POSITION
,
131 siVelocity
= AL_VELOCITY
,
132 siDirection
= AL_DIRECTION
,
135 siDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
136 siAuxSendFilterGainAutio
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
137 siAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
138 siDirectFilter
= AL_DIRECT_FILTER
,
139 siAuxSendFilter
= AL_AUXILIARY_SEND_FILTER
,
141 /* AL_SOFT_direct_channels */
142 siDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
144 /* AL_EXT_source_distance_model */
145 siDistanceModel
= AL_DISTANCE_MODEL
,
147 siByteLength
= AL_BYTE_LENGTH_SOFT
,
148 siSampleLength
= AL_SAMPLE_LENGTH_SOFT
,
150 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
151 siSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
152 siByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
154 /* AL_SOFT_source_latency */
155 siSampleOffsetLatencySOFT
= AL_SAMPLE_OFFSET_LATENCY_SOFT
,
158 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
);
159 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
);
160 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
);
162 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
);
163 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
);
164 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
);
166 static ALint
FloatValsByProp(ALenum prop
)
168 if(prop
!= (ALenum
)((SrcFloatProp
)prop
))
170 switch((SrcFloatProp
)prop
)
177 case sfRolloffFactor
:
178 case sfDopplerFactor
:
179 case sfConeOuterGain
:
183 case sfConeInnerAngle
:
184 case sfConeOuterAngle
:
186 case sfConeOuterGainHF
:
187 case sfAirAbsorptionFactor
:
188 case sfRoomRolloffFactor
:
189 case sfDirectFilterGainHFAuto
:
190 case sfAuxSendFilterGainAuto
:
191 case sfAuxSendFilterGainHFAuto
:
192 case sfDirectChannelsSOFT
:
193 case sfDistanceModel
:
194 case sfSourceRelative
:
198 case sfBuffersQueued
:
199 case sfBuffersProcessed
:
204 case sfSampleRWOffsetsSOFT
:
205 case sfByteRWOffsetsSOFT
:
213 case sfSecOffsetLatencySOFT
:
214 break; /* Double only */
218 static ALint
DoubleValsByProp(ALenum prop
)
220 if(prop
!= (ALenum
)((SrcFloatProp
)prop
))
222 switch((SrcFloatProp
)prop
)
229 case sfRolloffFactor
:
230 case sfDopplerFactor
:
231 case sfConeOuterGain
:
235 case sfConeInnerAngle
:
236 case sfConeOuterAngle
:
238 case sfConeOuterGainHF
:
239 case sfAirAbsorptionFactor
:
240 case sfRoomRolloffFactor
:
241 case sfDirectFilterGainHFAuto
:
242 case sfAuxSendFilterGainAuto
:
243 case sfAuxSendFilterGainHFAuto
:
244 case sfDirectChannelsSOFT
:
245 case sfDistanceModel
:
246 case sfSourceRelative
:
250 case sfBuffersQueued
:
251 case sfBuffersProcessed
:
256 case sfSampleRWOffsetsSOFT
:
257 case sfByteRWOffsetsSOFT
:
258 case sfSecOffsetLatencySOFT
:
269 static ALint
IntValsByProp(ALenum prop
)
271 if(prop
!= (ALenum
)((SrcIntProp
)prop
))
273 switch((SrcIntProp
)prop
)
276 case siRolloffFactor
:
278 case siSourceRelative
:
279 case siConeInnerAngle
:
280 case siConeOuterAngle
:
284 case siBuffersQueued
:
285 case siBuffersProcessed
:
290 case siDopplerFactor
:
291 case siDirectFilterGainHFAuto
:
292 case siAuxSendFilterGainAutio
:
293 case siAuxSendFilterGainHFAuto
:
295 case siDirectChannelsSOFT
:
296 case siDistanceModel
:
301 case siSampleRWOffsetsSOFT
:
302 case siByteRWOffsetsSOFT
:
308 case siAuxSendFilter
:
311 case siSampleOffsetLatencySOFT
:
312 break; /* i64 only */
316 static ALint
Int64ValsByProp(ALenum prop
)
318 if(prop
!= (ALenum
)((SrcIntProp
)prop
))
320 switch((SrcIntProp
)prop
)
323 case siRolloffFactor
:
325 case siSourceRelative
:
326 case siConeInnerAngle
:
327 case siConeOuterAngle
:
331 case siBuffersQueued
:
332 case siBuffersProcessed
:
337 case siDopplerFactor
:
338 case siDirectFilterGainHFAuto
:
339 case siAuxSendFilterGainAutio
:
340 case siAuxSendFilterGainHFAuto
:
342 case siDirectChannelsSOFT
:
343 case siDistanceModel
:
348 case siSampleRWOffsetsSOFT
:
349 case siByteRWOffsetsSOFT
:
350 case siSampleOffsetLatencySOFT
:
356 case siAuxSendFilter
:
363 #define CHECKVAL(x) do { \
365 SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); \
368 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
)
375 CHECKVAL(*values
>= 0.0f
);
377 Source
->Pitch
= *values
;
378 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
381 case AL_CONE_INNER_ANGLE
:
382 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
384 Source
->InnerAngle
= *values
;
385 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
388 case AL_CONE_OUTER_ANGLE
:
389 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
391 Source
->OuterAngle
= *values
;
392 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
396 CHECKVAL(*values
>= 0.0f
);
398 Source
->Gain
= *values
;
399 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
402 case AL_MAX_DISTANCE
:
403 CHECKVAL(*values
>= 0.0f
);
405 Source
->MaxDistance
= *values
;
406 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
409 case AL_ROLLOFF_FACTOR
:
410 CHECKVAL(*values
>= 0.0f
);
412 Source
->RollOffFactor
= *values
;
413 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
416 case AL_REFERENCE_DISTANCE
:
417 CHECKVAL(*values
>= 0.0f
);
419 Source
->RefDistance
= *values
;
420 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
424 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
426 Source
->MinGain
= *values
;
427 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
431 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
433 Source
->MaxGain
= *values
;
434 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
437 case AL_CONE_OUTER_GAIN
:
438 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
440 Source
->OuterGain
= *values
;
441 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
444 case AL_CONE_OUTER_GAINHF
:
445 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
447 Source
->OuterGainHF
= *values
;
448 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
451 case AL_AIR_ABSORPTION_FACTOR
:
452 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
454 Source
->AirAbsorptionFactor
= *values
;
455 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
458 case AL_ROOM_ROLLOFF_FACTOR
:
459 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
461 Source
->RoomRolloffFactor
= *values
;
462 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
465 case AL_DOPPLER_FACTOR
:
466 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
468 Source
->DopplerFactor
= *values
;
469 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
473 case AL_SAMPLE_OFFSET
:
475 CHECKVAL(*values
>= 0.0f
);
477 LockContext(Context
);
478 Source
->OffsetType
= prop
;
479 Source
->Offset
= *values
;
481 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
482 !Context
->DeferUpdates
)
484 if(ApplyOffset(Source
) == AL_FALSE
)
486 UnlockContext(Context
);
487 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
490 UnlockContext(Context
);
495 case AL_SEC_OFFSET_LATENCY_SOFT
:
497 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
501 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
503 LockContext(Context
);
504 Source
->Position
[0] = values
[0];
505 Source
->Position
[1] = values
[1];
506 Source
->Position
[2] = values
[2];
507 UnlockContext(Context
);
508 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
512 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
514 LockContext(Context
);
515 Source
->Velocity
[0] = values
[0];
516 Source
->Velocity
[1] = values
[1];
517 Source
->Velocity
[2] = values
[2];
518 UnlockContext(Context
);
519 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
523 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
525 LockContext(Context
);
526 Source
->Direction
[0] = values
[0];
527 Source
->Direction
[1] = values
[1];
528 Source
->Direction
[2] = values
[2];
529 UnlockContext(Context
);
530 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
534 case sfSampleRWOffsetsSOFT
:
535 case sfByteRWOffsetsSOFT
:
536 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
539 case sfSourceRelative
:
543 case sfDistanceModel
:
544 case sfDirectFilterGainHFAuto
:
545 case sfAuxSendFilterGainAuto
:
546 case sfAuxSendFilterGainHFAuto
:
547 case sfDirectChannelsSOFT
:
548 ival
= (ALint
)values
[0];
549 return SetSourceiv(Source
, Context
, (SrcIntProp
)prop
, &ival
);
552 case sfBuffersQueued
:
553 case sfBuffersProcessed
:
554 ival
= (ALint
)((ALuint
)values
[0]);
555 return SetSourceiv(Source
, Context
, (SrcIntProp
)prop
, &ival
);
558 ERR("Unexpected property: 0x%04x\n", prop
);
559 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
562 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
)
564 ALCdevice
*device
= Context
->Device
;
565 ALbuffer
*buffer
= NULL
;
566 ALfilter
*filter
= NULL
;
567 ALeffectslot
*slot
= NULL
;
568 ALbufferlistitem
*oldlist
;
569 ALbufferlistitem
*newlist
;
574 case AL_SOURCE_RELATIVE
:
575 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
577 Source
->HeadRelative
= (ALboolean
)*values
;
578 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
582 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
584 Source
->Looping
= (ALboolean
)*values
;
588 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
590 WriteLock(&Source
->queue_lock
);
591 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
593 WriteUnlock(&Source
->queue_lock
);
594 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
599 /* Add the selected buffer to a one-item queue */
600 newlist
= malloc(sizeof(ALbufferlistitem
));
601 newlist
->buffer
= buffer
;
602 newlist
->next
= NULL
;
603 newlist
->prev
= NULL
;
604 IncrementRef(&buffer
->ref
);
606 /* Source is now Static */
607 Source
->SourceType
= AL_STATIC
;
609 ReadLock(&buffer
->lock
);
610 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
611 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
612 ReadUnlock(&buffer
->lock
);
616 /* Source is now Undetermined */
617 Source
->SourceType
= AL_UNDETERMINED
;
620 oldlist
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &Source
->queue
, newlist
);
621 ATOMIC_STORE(&Source
->current_buffer
, newlist
);
622 WriteUnlock(&Source
->queue_lock
);
624 /* Delete all elements in the previous queue */
625 while(oldlist
!= NULL
)
627 ALbufferlistitem
*temp
= oldlist
;
628 oldlist
= temp
->next
;
631 DecrementRef(&temp
->buffer
->ref
);
638 case siBuffersQueued
:
639 case siBuffersProcessed
:
641 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
644 case AL_SAMPLE_OFFSET
:
646 CHECKVAL(*values
>= 0);
648 LockContext(Context
);
649 Source
->OffsetType
= prop
;
650 Source
->Offset
= *values
;
652 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
653 !Context
->DeferUpdates
)
655 if(ApplyOffset(Source
) == AL_FALSE
)
657 UnlockContext(Context
);
658 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
661 UnlockContext(Context
);
667 case siSampleRWOffsetsSOFT
:
668 case siByteRWOffsetsSOFT
:
670 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
673 case AL_DIRECT_FILTER
:
674 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
676 LockContext(Context
);
679 Source
->Direct
.Gain
= 1.0f
;
680 Source
->Direct
.GainHF
= 1.0f
;
681 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
682 Source
->Direct
.GainLF
= 1.0f
;
683 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
687 Source
->Direct
.Gain
= filter
->Gain
;
688 Source
->Direct
.GainHF
= filter
->GainHF
;
689 Source
->Direct
.HFReference
= filter
->HFReference
;
690 Source
->Direct
.GainLF
= filter
->GainLF
;
691 Source
->Direct
.LFReference
= filter
->LFReference
;
693 UnlockContext(Context
);
694 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
697 case AL_DIRECT_FILTER_GAINHF_AUTO
:
698 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
700 Source
->DryGainHFAuto
= *values
;
701 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
704 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
705 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
707 Source
->WetGainAuto
= *values
;
708 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
711 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
712 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
714 Source
->WetGainHFAuto
= *values
;
715 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
718 case AL_DIRECT_CHANNELS_SOFT
:
719 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
721 Source
->DirectChannels
= *values
;
722 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
725 case AL_DISTANCE_MODEL
:
726 CHECKVAL(*values
== AL_NONE
||
727 *values
== AL_INVERSE_DISTANCE
||
728 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
729 *values
== AL_LINEAR_DISTANCE
||
730 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
731 *values
== AL_EXPONENT_DISTANCE
||
732 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
734 Source
->DistanceModel
= *values
;
735 if(Context
->SourceDistanceModel
)
736 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
740 case AL_AUXILIARY_SEND_FILTER
:
741 LockContext(Context
);
742 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
743 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
744 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
746 UnlockContext(Context
);
747 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
750 /* Add refcount on the new slot, and release the previous slot */
751 if(slot
) IncrementRef(&slot
->ref
);
752 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
753 if(slot
) DecrementRef(&slot
->ref
);
758 Source
->Send
[values
[1]].Gain
= 1.0f
;
759 Source
->Send
[values
[1]].GainHF
= 1.0f
;
760 Source
->Send
[values
[1]].HFReference
= LOWPASSFREQREF
;
761 Source
->Send
[values
[1]].GainLF
= 1.0f
;
762 Source
->Send
[values
[1]].LFReference
= HIGHPASSFREQREF
;
766 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
767 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
768 Source
->Send
[values
[1]].HFReference
= filter
->HFReference
;
769 Source
->Send
[values
[1]].GainLF
= filter
->GainLF
;
770 Source
->Send
[values
[1]].LFReference
= filter
->LFReference
;
772 UnlockContext(Context
);
773 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
777 case AL_MAX_DISTANCE
:
778 case AL_ROLLOFF_FACTOR
:
779 case AL_CONE_INNER_ANGLE
:
780 case AL_CONE_OUTER_ANGLE
:
781 case AL_REFERENCE_DISTANCE
:
782 case siDopplerFactor
:
783 fvals
[0] = (ALfloat
)*values
;
784 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
789 fvals
[0] = (ALfloat
)values
[0];
790 fvals
[1] = (ALfloat
)values
[1];
791 fvals
[2] = (ALfloat
)values
[2];
792 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
794 case siSampleOffsetLatencySOFT
:
799 ERR("Unexpected property: 0x%04x\n", prop
);
800 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
803 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
)
810 case siSampleRWOffsetsSOFT
:
811 case siByteRWOffsetsSOFT
:
812 case siSampleOffsetLatencySOFT
:
814 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
818 case AL_SOURCE_RELATIVE
:
820 case AL_SOURCE_STATE
:
822 case AL_SAMPLE_OFFSET
:
826 case siBuffersQueued
:
827 case siBuffersProcessed
:
828 case AL_DIRECT_FILTER_GAINHF_AUTO
:
829 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
830 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
831 case AL_DIRECT_CHANNELS_SOFT
:
832 case AL_DISTANCE_MODEL
:
833 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
835 ivals
[0] = (ALint
)*values
;
836 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
840 case AL_DIRECT_FILTER
:
841 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
843 ivals
[0] = (ALuint
)*values
;
844 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
847 case AL_AUXILIARY_SEND_FILTER
:
848 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
849 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
850 values
[2] <= UINT_MAX
&& values
[2] >= 0);
852 ivals
[0] = (ALuint
)values
[0];
853 ivals
[1] = (ALuint
)values
[1];
854 ivals
[2] = (ALuint
)values
[2];
855 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
858 case AL_MAX_DISTANCE
:
859 case AL_ROLLOFF_FACTOR
:
860 case AL_CONE_INNER_ANGLE
:
861 case AL_CONE_OUTER_ANGLE
:
862 case AL_REFERENCE_DISTANCE
:
864 case siDopplerFactor
:
865 fvals
[0] = (ALfloat
)*values
;
866 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
872 fvals
[0] = (ALfloat
)values
[0];
873 fvals
[1] = (ALfloat
)values
[1];
874 fvals
[2] = (ALfloat
)values
[2];
875 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
878 ERR("Unexpected property: 0x%04x\n", prop
);
879 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
885 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
)
887 ALbufferlistitem
*BufferList
;
896 *values
= Source
->Gain
;
900 *values
= Source
->Pitch
;
903 case AL_MAX_DISTANCE
:
904 *values
= Source
->MaxDistance
;
907 case AL_ROLLOFF_FACTOR
:
908 *values
= Source
->RollOffFactor
;
911 case AL_REFERENCE_DISTANCE
:
912 *values
= Source
->RefDistance
;
915 case AL_CONE_INNER_ANGLE
:
916 *values
= Source
->InnerAngle
;
919 case AL_CONE_OUTER_ANGLE
:
920 *values
= Source
->OuterAngle
;
924 *values
= Source
->MinGain
;
928 *values
= Source
->MaxGain
;
931 case AL_CONE_OUTER_GAIN
:
932 *values
= Source
->OuterGain
;
936 case AL_SAMPLE_OFFSET
:
938 LockContext(Context
);
939 ReadLock(&Source
->queue_lock
);
940 GetSourceOffsets(Source
, prop
, offsets
, 0.0);
941 ReadUnlock(&Source
->queue_lock
);
942 UnlockContext(Context
);
943 *values
= offsets
[0];
946 case AL_CONE_OUTER_GAINHF
:
947 *values
= Source
->OuterGainHF
;
950 case AL_AIR_ABSORPTION_FACTOR
:
951 *values
= Source
->AirAbsorptionFactor
;
954 case AL_ROOM_ROLLOFF_FACTOR
:
955 *values
= Source
->RoomRolloffFactor
;
958 case AL_DOPPLER_FACTOR
:
959 *values
= Source
->DopplerFactor
;
963 ReadLock(&Source
->queue_lock
);
964 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
971 ALbuffer
*buffer
= BufferList
->buffer
;
972 if(buffer
&& buffer
->SampleLen
> 0)
974 freq
= buffer
->Frequency
;
975 length
+= buffer
->SampleLen
;
977 } while((BufferList
=BufferList
->next
) != NULL
);
978 *values
= (ALdouble
)length
/ (ALdouble
)freq
;
980 ReadUnlock(&Source
->queue_lock
);
983 case AL_SAMPLE_RW_OFFSETS_SOFT
:
984 case AL_BYTE_RW_OFFSETS_SOFT
:
985 LockContext(Context
);
986 ReadLock(&Source
->queue_lock
);
987 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
988 Context
->Device
->Frequency
;
989 GetSourceOffsets(Source
, prop
, values
, updateLen
);
990 ReadUnlock(&Source
->queue_lock
);
991 UnlockContext(Context
);
994 case AL_SEC_OFFSET_LATENCY_SOFT
:
995 LockContext(Context
);
996 ReadLock(&Source
->queue_lock
);
997 values
[0] = GetSourceSecOffset(Source
);
998 ReadUnlock(&Source
->queue_lock
);
999 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
1001 UnlockContext(Context
);
1005 LockContext(Context
);
1006 values
[0] = Source
->Position
[0];
1007 values
[1] = Source
->Position
[1];
1008 values
[2] = Source
->Position
[2];
1009 UnlockContext(Context
);
1013 LockContext(Context
);
1014 values
[0] = Source
->Velocity
[0];
1015 values
[1] = Source
->Velocity
[1];
1016 values
[2] = Source
->Velocity
[2];
1017 UnlockContext(Context
);
1021 LockContext(Context
);
1022 values
[0] = Source
->Direction
[0];
1023 values
[1] = Source
->Direction
[1];
1024 values
[2] = Source
->Direction
[2];
1025 UnlockContext(Context
);
1028 case AL_SOURCE_RELATIVE
:
1031 case AL_SOURCE_STATE
:
1032 case AL_BUFFERS_QUEUED
:
1033 case AL_BUFFERS_PROCESSED
:
1034 case AL_SOURCE_TYPE
:
1035 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1036 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1037 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1038 case AL_DIRECT_CHANNELS_SOFT
:
1039 case AL_DISTANCE_MODEL
:
1040 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1041 *values
= (ALdouble
)ivals
[0];
1045 ERR("Unexpected property: 0x%04x\n", prop
);
1046 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1049 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
)
1051 ALbufferlistitem
*BufferList
;
1057 case AL_SOURCE_RELATIVE
:
1058 *values
= Source
->HeadRelative
;
1062 *values
= Source
->Looping
;
1066 ReadLock(&Source
->queue_lock
);
1067 BufferList
= (Source
->SourceType
== AL_STATIC
) ? ATOMIC_LOAD(&Source
->queue
) :
1068 ATOMIC_LOAD(&Source
->current_buffer
);
1069 *values
= (BufferList
&& BufferList
->buffer
) ? BufferList
->buffer
->id
: 0;
1070 ReadUnlock(&Source
->queue_lock
);
1073 case AL_SOURCE_STATE
:
1074 *values
= Source
->state
;
1078 ReadLock(&Source
->queue_lock
);
1079 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1085 ALbuffer
*buffer
= BufferList
->buffer
;
1086 if(buffer
&& buffer
->SampleLen
> 0)
1088 ALuint byte_align
, sample_align
;
1089 if(buffer
->OriginalType
== UserFmtIMA4
)
1091 ALsizei align
= (buffer
->OriginalAlign
-1)/2 + 4;
1092 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1093 sample_align
= buffer
->OriginalAlign
;
1095 else if(buffer
->OriginalType
== UserFmtMSADPCM
)
1097 ALsizei align
= (buffer
->OriginalAlign
-2)/2 + 7;
1098 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1099 sample_align
= buffer
->OriginalAlign
;
1103 ALsizei align
= buffer
->OriginalAlign
;
1104 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1105 sample_align
= buffer
->OriginalAlign
;
1108 length
+= buffer
->SampleLen
/ sample_align
* byte_align
;
1110 } while((BufferList
=BufferList
->next
) != NULL
);
1113 ReadUnlock(&Source
->queue_lock
);
1116 case siSampleLength
:
1117 ReadLock(&Source
->queue_lock
);
1118 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1124 ALbuffer
*buffer
= BufferList
->buffer
;
1125 if(buffer
) length
+= buffer
->SampleLen
;
1126 } while((BufferList
=BufferList
->next
) != NULL
);
1129 ReadUnlock(&Source
->queue_lock
);
1132 case AL_BUFFERS_QUEUED
:
1133 ReadLock(&Source
->queue_lock
);
1134 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1141 } while((BufferList
=BufferList
->next
) != NULL
);
1144 ReadUnlock(&Source
->queue_lock
);
1147 case AL_BUFFERS_PROCESSED
:
1148 ReadLock(&Source
->queue_lock
);
1149 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
1151 /* Buffers on a looping source are in a perpetual state of
1152 * PENDING, so don't report any as PROCESSED */
1157 const ALbufferlistitem
*BufferList
= ATOMIC_LOAD(&Source
->queue
);
1158 const ALbufferlistitem
*Current
= ATOMIC_LOAD(&Source
->current_buffer
);
1160 while(BufferList
&& BufferList
!= Current
)
1163 BufferList
= BufferList
->next
;
1167 ReadUnlock(&Source
->queue_lock
);
1170 case AL_SOURCE_TYPE
:
1171 *values
= Source
->SourceType
;
1174 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1175 *values
= Source
->DryGainHFAuto
;
1178 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1179 *values
= Source
->WetGainAuto
;
1182 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1183 *values
= Source
->WetGainHFAuto
;
1186 case AL_DIRECT_CHANNELS_SOFT
:
1187 *values
= Source
->DirectChannels
;
1190 case AL_DISTANCE_MODEL
:
1191 *values
= Source
->DistanceModel
;
1194 case AL_MAX_DISTANCE
:
1195 case AL_ROLLOFF_FACTOR
:
1196 case AL_REFERENCE_DISTANCE
:
1197 case AL_CONE_INNER_ANGLE
:
1198 case AL_CONE_OUTER_ANGLE
:
1200 case AL_SAMPLE_OFFSET
:
1201 case AL_BYTE_OFFSET
:
1202 case AL_DOPPLER_FACTOR
:
1203 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1204 *values
= (ALint
)dvals
[0];
1207 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1208 case AL_BYTE_RW_OFFSETS_SOFT
:
1209 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1211 values
[0] = (ALint
)dvals
[0];
1212 values
[1] = (ALint
)dvals
[1];
1219 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1221 values
[0] = (ALint
)dvals
[0];
1222 values
[1] = (ALint
)dvals
[1];
1223 values
[2] = (ALint
)dvals
[2];
1227 case siSampleOffsetLatencySOFT
:
1231 case siDirectFilter
:
1232 case siAuxSendFilter
:
1237 ERR("Unexpected property: 0x%04x\n", prop
);
1238 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1241 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
)
1249 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1250 LockContext(Context
);
1251 ReadLock(&Source
->queue_lock
);
1252 values
[0] = GetSourceOffset(Source
);
1253 ReadUnlock(&Source
->queue_lock
);
1254 values
[1] = ALCdevice_GetLatency(Context
->Device
);
1255 UnlockContext(Context
);
1258 case AL_MAX_DISTANCE
:
1259 case AL_ROLLOFF_FACTOR
:
1260 case AL_REFERENCE_DISTANCE
:
1261 case AL_CONE_INNER_ANGLE
:
1262 case AL_CONE_OUTER_ANGLE
:
1264 case AL_SAMPLE_OFFSET
:
1265 case AL_BYTE_OFFSET
:
1266 case AL_DOPPLER_FACTOR
:
1267 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1268 *values
= (ALint64
)dvals
[0];
1271 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1272 case AL_BYTE_RW_OFFSETS_SOFT
:
1273 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1275 values
[0] = (ALint64
)dvals
[0];
1276 values
[1] = (ALint64
)dvals
[1];
1283 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1285 values
[0] = (ALint64
)dvals
[0];
1286 values
[1] = (ALint64
)dvals
[1];
1287 values
[2] = (ALint64
)dvals
[2];
1291 case AL_SOURCE_RELATIVE
:
1293 case AL_SOURCE_STATE
:
1294 case AL_BUFFERS_QUEUED
:
1295 case AL_BUFFERS_PROCESSED
:
1297 case siSampleLength
:
1298 case AL_SOURCE_TYPE
:
1299 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1300 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1301 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1302 case AL_DIRECT_CHANNELS_SOFT
:
1303 case AL_DISTANCE_MODEL
:
1304 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1309 case siDirectFilter
:
1310 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1311 *values
= (ALuint
)ivals
[0];
1314 case siAuxSendFilter
:
1315 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1317 values
[0] = (ALuint
)ivals
[0];
1318 values
[1] = (ALuint
)ivals
[1];
1319 values
[2] = (ALuint
)ivals
[2];
1324 ERR("Unexpected property: 0x%04x\n", prop
);
1325 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1329 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
1331 ALCcontext
*context
;
1335 context
= GetContextRef();
1336 if(!context
) return;
1339 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1340 for(cur
= 0;cur
< n
;cur
++)
1342 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
1345 alDeleteSources(cur
, sources
);
1346 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
1348 InitSourceParams(source
);
1350 err
= NewThunkEntry(&source
->id
);
1351 if(err
== AL_NO_ERROR
)
1352 err
= InsertUIntMapEntry(&context
->SourceMap
, source
->id
, source
);
1353 if(err
!= AL_NO_ERROR
)
1355 FreeThunkEntry(source
->id
);
1356 memset(source
, 0, sizeof(ALsource
));
1359 alDeleteSources(cur
, sources
);
1360 SET_ERROR_AND_GOTO(context
, err
, done
);
1363 sources
[cur
] = source
->id
;
1367 ALCcontext_DecRef(context
);
1371 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
1373 ALCcontext
*context
;
1374 ALbufferlistitem
*BufferList
;
1378 context
= GetContextRef();
1379 if(!context
) return;
1382 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1384 /* Check that all Sources are valid */
1385 for(i
= 0;i
< n
;i
++)
1387 if(LookupSource(context
, sources
[i
]) == NULL
)
1388 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
1390 for(i
= 0;i
< n
;i
++)
1392 ALvoice
*voice
, *voice_end
;
1394 if((Source
=RemoveSource(context
, sources
[i
])) == NULL
)
1396 FreeThunkEntry(Source
->id
);
1398 LockContext(context
);
1399 voice
= context
->Voices
;
1400 voice_end
= voice
+ context
->VoiceCount
;
1401 while(voice
!= voice_end
)
1403 ALsource
*old
= Source
;
1404 if(COMPARE_EXCHANGE(&voice
->Source
, &old
, NULL
))
1408 UnlockContext(context
);
1410 BufferList
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &Source
->queue
, NULL
);
1411 while(BufferList
!= NULL
)
1413 ALbufferlistitem
*next
= BufferList
->next
;
1414 if(BufferList
->buffer
!= NULL
)
1415 DecrementRef(&BufferList
->buffer
->ref
);
1420 for(j
= 0;j
< MAX_SENDS
;++j
)
1422 if(Source
->Send
[j
].Slot
)
1423 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
1424 Source
->Send
[j
].Slot
= NULL
;
1427 memset(Source
, 0, sizeof(*Source
));
1432 ALCcontext_DecRef(context
);
1436 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1438 ALCcontext
*context
;
1441 context
= GetContextRef();
1442 if(!context
) return AL_FALSE
;
1444 ret
= (LookupSource(context
, source
) ? AL_TRUE
: AL_FALSE
);
1446 ALCcontext_DecRef(context
);
1452 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1454 ALCcontext
*Context
;
1457 Context
= GetContextRef();
1458 if(!Context
) return;
1460 if((Source
=LookupSource(Context
, source
)) == NULL
)
1461 alSetError(Context
, AL_INVALID_NAME
);
1462 else if(!(FloatValsByProp(param
) == 1))
1463 alSetError(Context
, AL_INVALID_ENUM
);
1465 SetSourcefv(Source
, Context
, param
, &value
);
1467 ALCcontext_DecRef(Context
);
1470 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1472 ALCcontext
*Context
;
1475 Context
= GetContextRef();
1476 if(!Context
) return;
1478 if((Source
=LookupSource(Context
, source
)) == NULL
)
1479 alSetError(Context
, AL_INVALID_NAME
);
1480 else if(!(FloatValsByProp(param
) == 3))
1481 alSetError(Context
, AL_INVALID_ENUM
);
1484 ALfloat fvals
[3] = { value1
, value2
, value3
};
1485 SetSourcefv(Source
, Context
, param
, fvals
);
1488 ALCcontext_DecRef(Context
);
1491 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1493 ALCcontext
*Context
;
1496 Context
= GetContextRef();
1497 if(!Context
) return;
1499 if((Source
=LookupSource(Context
, source
)) == NULL
)
1500 alSetError(Context
, AL_INVALID_NAME
);
1502 alSetError(Context
, AL_INVALID_VALUE
);
1503 else if(!(FloatValsByProp(param
) > 0))
1504 alSetError(Context
, AL_INVALID_ENUM
);
1506 SetSourcefv(Source
, Context
, param
, values
);
1508 ALCcontext_DecRef(Context
);
1512 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1514 ALCcontext
*Context
;
1517 Context
= GetContextRef();
1518 if(!Context
) return;
1520 if((Source
=LookupSource(Context
, source
)) == NULL
)
1521 alSetError(Context
, AL_INVALID_NAME
);
1522 else if(!(DoubleValsByProp(param
) == 1))
1523 alSetError(Context
, AL_INVALID_ENUM
);
1526 ALfloat fval
= (ALfloat
)value
;
1527 SetSourcefv(Source
, Context
, param
, &fval
);
1530 ALCcontext_DecRef(Context
);
1533 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1535 ALCcontext
*Context
;
1538 Context
= GetContextRef();
1539 if(!Context
) return;
1541 if((Source
=LookupSource(Context
, source
)) == NULL
)
1542 alSetError(Context
, AL_INVALID_NAME
);
1543 else if(!(DoubleValsByProp(param
) == 3))
1544 alSetError(Context
, AL_INVALID_ENUM
);
1547 ALfloat fvals
[3] = { (ALfloat
)value1
, (ALfloat
)value2
, (ALfloat
)value3
};
1548 SetSourcefv(Source
, Context
, param
, fvals
);
1551 ALCcontext_DecRef(Context
);
1554 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1556 ALCcontext
*Context
;
1560 Context
= GetContextRef();
1561 if(!Context
) return;
1563 if((Source
=LookupSource(Context
, source
)) == NULL
)
1564 alSetError(Context
, AL_INVALID_NAME
);
1566 alSetError(Context
, AL_INVALID_VALUE
);
1567 else if(!((count
=DoubleValsByProp(param
)) > 0 && count
<= 3))
1568 alSetError(Context
, AL_INVALID_ENUM
);
1574 for(i
= 0;i
< count
;i
++)
1575 fvals
[i
] = (ALfloat
)values
[i
];
1576 SetSourcefv(Source
, Context
, param
, fvals
);
1579 ALCcontext_DecRef(Context
);
1583 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1585 ALCcontext
*Context
;
1588 Context
= GetContextRef();
1589 if(!Context
) return;
1591 if((Source
=LookupSource(Context
, source
)) == NULL
)
1592 alSetError(Context
, AL_INVALID_NAME
);
1593 else if(!(IntValsByProp(param
) == 1))
1594 alSetError(Context
, AL_INVALID_ENUM
);
1596 SetSourceiv(Source
, Context
, param
, &value
);
1598 ALCcontext_DecRef(Context
);
1601 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1603 ALCcontext
*Context
;
1606 Context
= GetContextRef();
1607 if(!Context
) return;
1609 if((Source
=LookupSource(Context
, source
)) == NULL
)
1610 alSetError(Context
, AL_INVALID_NAME
);
1611 else if(!(IntValsByProp(param
) == 3))
1612 alSetError(Context
, AL_INVALID_ENUM
);
1615 ALint ivals
[3] = { value1
, value2
, value3
};
1616 SetSourceiv(Source
, Context
, param
, ivals
);
1619 ALCcontext_DecRef(Context
);
1622 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1624 ALCcontext
*Context
;
1627 Context
= GetContextRef();
1628 if(!Context
) return;
1630 if((Source
=LookupSource(Context
, source
)) == NULL
)
1631 alSetError(Context
, AL_INVALID_NAME
);
1633 alSetError(Context
, AL_INVALID_VALUE
);
1634 else if(!(IntValsByProp(param
) > 0))
1635 alSetError(Context
, AL_INVALID_ENUM
);
1637 SetSourceiv(Source
, Context
, param
, values
);
1639 ALCcontext_DecRef(Context
);
1643 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1645 ALCcontext
*Context
;
1648 Context
= GetContextRef();
1649 if(!Context
) return;
1651 if((Source
=LookupSource(Context
, source
)) == NULL
)
1652 alSetError(Context
, AL_INVALID_NAME
);
1653 else if(!(Int64ValsByProp(param
) == 1))
1654 alSetError(Context
, AL_INVALID_ENUM
);
1656 SetSourcei64v(Source
, Context
, param
, &value
);
1658 ALCcontext_DecRef(Context
);
1661 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1663 ALCcontext
*Context
;
1666 Context
= GetContextRef();
1667 if(!Context
) return;
1669 if((Source
=LookupSource(Context
, source
)) == NULL
)
1670 alSetError(Context
, AL_INVALID_NAME
);
1671 else if(!(Int64ValsByProp(param
) == 3))
1672 alSetError(Context
, AL_INVALID_ENUM
);
1675 ALint64SOFT i64vals
[3] = { value1
, value2
, value3
};
1676 SetSourcei64v(Source
, Context
, param
, i64vals
);
1679 ALCcontext_DecRef(Context
);
1682 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1684 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(!(Int64ValsByProp(param
) > 0))
1695 alSetError(Context
, AL_INVALID_ENUM
);
1697 SetSourcei64v(Source
, Context
, param
, values
);
1699 ALCcontext_DecRef(Context
);
1703 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1705 ALCcontext
*Context
;
1708 Context
= GetContextRef();
1709 if(!Context
) return;
1711 if((Source
=LookupSource(Context
, source
)) == NULL
)
1712 alSetError(Context
, AL_INVALID_NAME
);
1714 alSetError(Context
, AL_INVALID_VALUE
);
1715 else if(!(FloatValsByProp(param
) == 1))
1716 alSetError(Context
, AL_INVALID_ENUM
);
1720 if(GetSourcedv(Source
, Context
, param
, &dval
))
1721 *value
= (ALfloat
)dval
;
1724 ALCcontext_DecRef(Context
);
1728 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*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(!(value1
&& value2
&& value3
))
1739 alSetError(Context
, AL_INVALID_VALUE
);
1740 else if(!(FloatValsByProp(param
) == 3))
1741 alSetError(Context
, AL_INVALID_ENUM
);
1745 if(GetSourcedv(Source
, Context
, param
, dvals
))
1747 *value1
= (ALfloat
)dvals
[0];
1748 *value2
= (ALfloat
)dvals
[1];
1749 *value3
= (ALfloat
)dvals
[2];
1753 ALCcontext_DecRef(Context
);
1757 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1759 ALCcontext
*Context
;
1763 Context
= GetContextRef();
1764 if(!Context
) return;
1766 if((Source
=LookupSource(Context
, source
)) == NULL
)
1767 alSetError(Context
, AL_INVALID_NAME
);
1769 alSetError(Context
, AL_INVALID_VALUE
);
1770 else if(!((count
=FloatValsByProp(param
)) > 0 && count
<= 3))
1771 alSetError(Context
, AL_INVALID_ENUM
);
1775 if(GetSourcedv(Source
, Context
, param
, dvals
))
1778 for(i
= 0;i
< count
;i
++)
1779 values
[i
] = (ALfloat
)dvals
[i
];
1783 ALCcontext_DecRef(Context
);
1787 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1789 ALCcontext
*Context
;
1792 Context
= GetContextRef();
1793 if(!Context
) return;
1795 if((Source
=LookupSource(Context
, source
)) == NULL
)
1796 alSetError(Context
, AL_INVALID_NAME
);
1798 alSetError(Context
, AL_INVALID_VALUE
);
1799 else if(!(DoubleValsByProp(param
) == 1))
1800 alSetError(Context
, AL_INVALID_ENUM
);
1802 GetSourcedv(Source
, Context
, param
, value
);
1804 ALCcontext_DecRef(Context
);
1807 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1809 ALCcontext
*Context
;
1812 Context
= GetContextRef();
1813 if(!Context
) return;
1815 if((Source
=LookupSource(Context
, source
)) == NULL
)
1816 alSetError(Context
, AL_INVALID_NAME
);
1817 else if(!(value1
&& value2
&& value3
))
1818 alSetError(Context
, AL_INVALID_VALUE
);
1819 else if(!(DoubleValsByProp(param
) == 3))
1820 alSetError(Context
, AL_INVALID_ENUM
);
1824 if(GetSourcedv(Source
, Context
, param
, dvals
))
1832 ALCcontext_DecRef(Context
);
1835 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1837 ALCcontext
*Context
;
1840 Context
= GetContextRef();
1841 if(!Context
) return;
1843 if((Source
=LookupSource(Context
, source
)) == NULL
)
1844 alSetError(Context
, AL_INVALID_NAME
);
1846 alSetError(Context
, AL_INVALID_VALUE
);
1847 else if(!(DoubleValsByProp(param
) > 0))
1848 alSetError(Context
, AL_INVALID_ENUM
);
1850 GetSourcedv(Source
, Context
, param
, values
);
1852 ALCcontext_DecRef(Context
);
1856 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1858 ALCcontext
*Context
;
1861 Context
= GetContextRef();
1862 if(!Context
) return;
1864 if((Source
=LookupSource(Context
, source
)) == NULL
)
1865 alSetError(Context
, AL_INVALID_NAME
);
1867 alSetError(Context
, AL_INVALID_VALUE
);
1868 else if(!(IntValsByProp(param
) == 1))
1869 alSetError(Context
, AL_INVALID_ENUM
);
1871 GetSourceiv(Source
, Context
, param
, value
);
1873 ALCcontext_DecRef(Context
);
1877 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1879 ALCcontext
*Context
;
1882 Context
= GetContextRef();
1883 if(!Context
) return;
1885 if((Source
=LookupSource(Context
, source
)) == NULL
)
1886 alSetError(Context
, AL_INVALID_NAME
);
1887 else if(!(value1
&& value2
&& value3
))
1888 alSetError(Context
, AL_INVALID_VALUE
);
1889 else if(!(IntValsByProp(param
) == 3))
1890 alSetError(Context
, AL_INVALID_ENUM
);
1894 if(GetSourceiv(Source
, Context
, param
, ivals
))
1902 ALCcontext_DecRef(Context
);
1906 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1908 ALCcontext
*Context
;
1911 Context
= GetContextRef();
1912 if(!Context
) return;
1914 if((Source
=LookupSource(Context
, source
)) == NULL
)
1915 alSetError(Context
, AL_INVALID_NAME
);
1917 alSetError(Context
, AL_INVALID_VALUE
);
1918 else if(!(IntValsByProp(param
) > 0))
1919 alSetError(Context
, AL_INVALID_ENUM
);
1921 GetSourceiv(Source
, Context
, param
, values
);
1923 ALCcontext_DecRef(Context
);
1927 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
1929 ALCcontext
*Context
;
1932 Context
= GetContextRef();
1933 if(!Context
) return;
1935 if((Source
=LookupSource(Context
, source
)) == NULL
)
1936 alSetError(Context
, AL_INVALID_NAME
);
1938 alSetError(Context
, AL_INVALID_VALUE
);
1939 else if(!(Int64ValsByProp(param
) == 1))
1940 alSetError(Context
, AL_INVALID_ENUM
);
1942 GetSourcei64v(Source
, Context
, param
, value
);
1944 ALCcontext_DecRef(Context
);
1947 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
1949 ALCcontext
*Context
;
1952 Context
= GetContextRef();
1953 if(!Context
) return;
1955 if((Source
=LookupSource(Context
, source
)) == NULL
)
1956 alSetError(Context
, AL_INVALID_NAME
);
1957 else if(!(value1
&& value2
&& value3
))
1958 alSetError(Context
, AL_INVALID_VALUE
);
1959 else if(!(Int64ValsByProp(param
) == 3))
1960 alSetError(Context
, AL_INVALID_ENUM
);
1964 if(GetSourcei64v(Source
, Context
, param
, i64vals
))
1966 *value1
= i64vals
[0];
1967 *value2
= i64vals
[1];
1968 *value3
= i64vals
[2];
1972 ALCcontext_DecRef(Context
);
1975 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
1977 ALCcontext
*Context
;
1980 Context
= GetContextRef();
1981 if(!Context
) return;
1983 if((Source
=LookupSource(Context
, source
)) == NULL
)
1984 alSetError(Context
, AL_INVALID_NAME
);
1986 alSetError(Context
, AL_INVALID_VALUE
);
1987 else if(!(Int64ValsByProp(param
) > 0))
1988 alSetError(Context
, AL_INVALID_ENUM
);
1990 GetSourcei64v(Source
, Context
, param
, values
);
1992 ALCcontext_DecRef(Context
);
1996 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
1998 alSourcePlayv(1, &source
);
2000 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2002 ALCcontext
*context
;
2006 context
= GetContextRef();
2007 if(!context
) return;
2010 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2011 for(i
= 0;i
< n
;i
++)
2013 if(!LookupSource(context
, sources
[i
]))
2014 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2017 LockContext(context
);
2018 while(n
> context
->MaxVoices
-context
->VoiceCount
)
2020 ALvoice
*temp
= NULL
;
2023 newcount
= context
->MaxVoices
<< 1;
2025 temp
= realloc(context
->Voices
, newcount
* sizeof(context
->Voices
[0]));
2028 UnlockContext(context
);
2029 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
2031 memset(&temp
[context
->MaxVoices
], 0, (newcount
-context
->MaxVoices
) * sizeof(temp
[0]));
2033 context
->Voices
= temp
;
2034 context
->MaxVoices
= newcount
;
2037 for(i
= 0;i
< n
;i
++)
2039 source
= LookupSource(context
, sources
[i
]);
2040 if(context
->DeferUpdates
) source
->new_state
= AL_PLAYING
;
2041 else SetSourceState(source
, context
, AL_PLAYING
);
2043 UnlockContext(context
);
2046 ALCcontext_DecRef(context
);
2049 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2051 alSourcePausev(1, &source
);
2053 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2055 ALCcontext
*context
;
2059 context
= GetContextRef();
2060 if(!context
) return;
2063 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2064 for(i
= 0;i
< n
;i
++)
2066 if(!LookupSource(context
, sources
[i
]))
2067 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2070 LockContext(context
);
2071 for(i
= 0;i
< n
;i
++)
2073 source
= LookupSource(context
, sources
[i
]);
2074 if(context
->DeferUpdates
) source
->new_state
= AL_PAUSED
;
2075 else SetSourceState(source
, context
, AL_PAUSED
);
2077 UnlockContext(context
);
2080 ALCcontext_DecRef(context
);
2083 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2085 alSourceStopv(1, &source
);
2087 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2089 ALCcontext
*context
;
2093 context
= GetContextRef();
2094 if(!context
) return;
2097 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2098 for(i
= 0;i
< n
;i
++)
2100 if(!LookupSource(context
, sources
[i
]))
2101 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2104 LockContext(context
);
2105 for(i
= 0;i
< n
;i
++)
2107 source
= LookupSource(context
, sources
[i
]);
2108 source
->new_state
= AL_NONE
;
2109 SetSourceState(source
, context
, AL_STOPPED
);
2111 UnlockContext(context
);
2114 ALCcontext_DecRef(context
);
2117 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2119 alSourceRewindv(1, &source
);
2121 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2123 ALCcontext
*context
;
2127 context
= GetContextRef();
2128 if(!context
) return;
2131 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2132 for(i
= 0;i
< n
;i
++)
2134 if(!LookupSource(context
, sources
[i
]))
2135 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2138 LockContext(context
);
2139 for(i
= 0;i
< n
;i
++)
2141 source
= LookupSource(context
, sources
[i
]);
2142 source
->new_state
= AL_NONE
;
2143 SetSourceState(source
, context
, AL_INITIAL
);
2145 UnlockContext(context
);
2148 ALCcontext_DecRef(context
);
2152 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint src
, ALsizei nb
, const ALuint
*buffers
)
2155 ALCcontext
*context
;
2158 ALbufferlistitem
*BufferListStart
;
2159 ALbufferlistitem
*BufferList
;
2160 ALbuffer
*BufferFmt
= NULL
;
2165 context
= GetContextRef();
2166 if(!context
) return;
2168 device
= context
->Device
;
2171 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2172 if((source
=LookupSource(context
, src
)) == NULL
)
2173 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2175 WriteLock(&source
->queue_lock
);
2176 if(source
->SourceType
== AL_STATIC
)
2178 WriteUnlock(&source
->queue_lock
);
2179 /* Can't queue on a Static Source */
2180 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
2183 /* Check for a valid Buffer, for its frequency and format */
2184 BufferList
= ATOMIC_LOAD(&source
->queue
);
2187 if(BufferList
->buffer
)
2189 BufferFmt
= BufferList
->buffer
;
2192 BufferList
= BufferList
->next
;
2195 BufferListStart
= NULL
;
2197 for(i
= 0;i
< nb
;i
++)
2199 ALbuffer
*buffer
= NULL
;
2200 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2202 WriteUnlock(&source
->queue_lock
);
2203 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, buffer_error
);
2206 if(!BufferListStart
)
2208 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2209 BufferListStart
->buffer
= buffer
;
2210 BufferListStart
->next
= NULL
;
2211 BufferListStart
->prev
= NULL
;
2212 BufferList
= BufferListStart
;
2216 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2217 BufferList
->next
->buffer
= buffer
;
2218 BufferList
->next
->next
= NULL
;
2219 BufferList
->next
->prev
= BufferList
;
2220 BufferList
= BufferList
->next
;
2222 if(!buffer
) continue;
2224 /* Hold a read lock on each buffer being queued while checking all
2225 * provided buffers. This is done so other threads don't see an extra
2226 * reference on some buffers if this operation ends up failing. */
2227 ReadLock(&buffer
->lock
);
2228 IncrementRef(&buffer
->ref
);
2230 if(BufferFmt
== NULL
)
2234 source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2235 source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2237 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2238 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2239 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2241 WriteUnlock(&source
->queue_lock
);
2242 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, buffer_error
);
2245 /* A buffer failed (invalid ID or format), so unlock and release
2246 * each buffer we had. */
2247 while(BufferList
!= NULL
)
2249 ALbufferlistitem
*prev
= BufferList
->prev
;
2250 if((buffer
=BufferList
->buffer
) != NULL
)
2252 DecrementRef(&buffer
->ref
);
2253 ReadUnlock(&buffer
->lock
);
2261 /* All buffers good, unlock them now. */
2262 while(BufferList
!= NULL
)
2264 ALbuffer
*buffer
= BufferList
->buffer
;
2265 if(buffer
) ReadUnlock(&buffer
->lock
);
2266 BufferList
= BufferList
->prev
;
2269 /* Source is now streaming */
2270 source
->SourceType
= AL_STREAMING
;
2273 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->queue
, &BufferList
, BufferListStart
))
2275 /* Queue head is not NULL, append to the end of the queue */
2276 while(BufferList
->next
!= NULL
)
2277 BufferList
= BufferList
->next
;
2279 BufferListStart
->prev
= BufferList
;
2280 BufferList
->next
= BufferListStart
;
2283 ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->current_buffer
, &BufferList
, BufferListStart
);
2284 WriteUnlock(&source
->queue_lock
);
2287 ALCcontext_DecRef(context
);
2290 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint src
, ALsizei nb
, ALuint
*buffers
)
2292 ALCcontext
*context
;
2294 ALbufferlistitem
*NewHead
;
2295 ALbufferlistitem
*OldHead
;
2296 ALbufferlistitem
*Current
;
2302 context
= GetContextRef();
2303 if(!context
) return;
2306 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2308 if((source
=LookupSource(context
, src
)) == NULL
)
2309 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2311 WriteLock(&source
->queue_lock
);
2312 /* Find the new buffer queue head */
2313 NewHead
= ATOMIC_LOAD(&source
->queue
);
2314 Current
= ATOMIC_LOAD(&source
->current_buffer
);
2315 for(i
= 0;i
< nb
&& NewHead
;i
++)
2317 if(NewHead
== Current
)
2319 NewHead
= NewHead
->next
;
2321 if(source
->Looping
|| source
->SourceType
!= AL_STREAMING
|| i
!= nb
)
2323 WriteUnlock(&source
->queue_lock
);
2324 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2325 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2328 /* Swap it, and cut the new head from the old. */
2329 OldHead
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &source
->queue
, NewHead
);
2332 ALCdevice
*device
= context
->Device
;
2333 ALbufferlistitem
*OldTail
= NewHead
->prev
;
2336 /* Cut the new head's link back to the old body. The mixer is robust
2337 * enough to handle the link back going away. Once the active mix (if
2338 * any) is complete, it's safe to finish cutting the old tail from the
2340 NewHead
->prev
= NULL
;
2341 if(((count
=ReadRef(&device
->MixCount
))&1) != 0)
2343 while(count
== ReadRef(&device
->MixCount
))
2346 OldTail
->next
= NULL
;
2348 WriteUnlock(&source
->queue_lock
);
2350 while(OldHead
!= NULL
)
2352 ALbufferlistitem
*next
= OldHead
->next
;
2353 ALbuffer
*buffer
= OldHead
->buffer
;
2359 *(buffers
++) = buffer
->id
;
2360 DecrementRef(&buffer
->ref
);
2368 ALCcontext_DecRef(context
);
2372 static ALvoid
InitSourceParams(ALsource
*Source
)
2376 RWLockInit(&Source
->queue_lock
);
2378 Source
->InnerAngle
= 360.0f
;
2379 Source
->OuterAngle
= 360.0f
;
2380 Source
->Pitch
= 1.0f
;
2381 Source
->Position
[0] = 0.0f
;
2382 Source
->Position
[1] = 0.0f
;
2383 Source
->Position
[2] = 0.0f
;
2384 Source
->Direction
[0] = 0.0f
;
2385 Source
->Direction
[1] = 0.0f
;
2386 Source
->Direction
[2] = 0.0f
;
2387 Source
->Velocity
[0] = 0.0f
;
2388 Source
->Velocity
[1] = 0.0f
;
2389 Source
->Velocity
[2] = 0.0f
;
2390 Source
->RefDistance
= 1.0f
;
2391 Source
->MaxDistance
= FLT_MAX
;
2392 Source
->RollOffFactor
= 1.0f
;
2393 Source
->Looping
= AL_FALSE
;
2394 Source
->Gain
= 1.0f
;
2395 Source
->MinGain
= 0.0f
;
2396 Source
->MaxGain
= 1.0f
;
2397 Source
->OuterGain
= 0.0f
;
2398 Source
->OuterGainHF
= 1.0f
;
2400 Source
->DryGainHFAuto
= AL_TRUE
;
2401 Source
->WetGainAuto
= AL_TRUE
;
2402 Source
->WetGainHFAuto
= AL_TRUE
;
2403 Source
->AirAbsorptionFactor
= 0.0f
;
2404 Source
->RoomRolloffFactor
= 0.0f
;
2405 Source
->DopplerFactor
= 1.0f
;
2406 Source
->DirectChannels
= AL_FALSE
;
2408 Source
->Radius
= 0.0f
;
2410 Source
->DistanceModel
= DefaultDistanceModel
;
2412 Source
->Resampler
= DefaultResampler
;
2414 Source
->state
= AL_INITIAL
;
2415 Source
->new_state
= AL_NONE
;
2416 Source
->SourceType
= AL_UNDETERMINED
;
2417 Source
->Offset
= -1.0;
2419 ATOMIC_INIT(&Source
->queue
, NULL
);
2420 ATOMIC_INIT(&Source
->current_buffer
, NULL
);
2422 Source
->Direct
.Gain
= 1.0f
;
2423 Source
->Direct
.GainHF
= 1.0f
;
2424 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
2425 Source
->Direct
.GainLF
= 1.0f
;
2426 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
2427 for(i
= 0;i
< MAX_SENDS
;i
++)
2429 Source
->Send
[i
].Gain
= 1.0f
;
2430 Source
->Send
[i
].GainHF
= 1.0f
;
2431 Source
->Send
[i
].HFReference
= LOWPASSFREQREF
;
2432 Source
->Send
[i
].GainLF
= 1.0f
;
2433 Source
->Send
[i
].LFReference
= HIGHPASSFREQREF
;
2436 ATOMIC_INIT(&Source
->NeedsUpdate
, AL_TRUE
);
2442 * Sets the source's new play state given its current state.
2444 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2446 ReadLock(&Source
->queue_lock
);
2447 if(state
== AL_PLAYING
)
2449 ALCdevice
*device
= Context
->Device
;
2450 ALbufferlistitem
*BufferList
;
2451 ALvoice
*voice
= NULL
;
2454 /* Check that there is a queue containing at least one valid, non zero
2456 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2460 if((buffer
=BufferList
->buffer
) != NULL
&& buffer
->SampleLen
> 0)
2462 BufferList
= BufferList
->next
;
2465 if(Source
->state
!= AL_PAUSED
)
2467 Source
->state
= AL_PLAYING
;
2468 Source
->position
= 0;
2469 Source
->position_fraction
= 0;
2470 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
2473 Source
->state
= AL_PLAYING
;
2475 // Check if an Offset has been set
2476 if(Source
->Offset
>= 0.0)
2477 ApplyOffset(Source
);
2479 /* If there's nothing to play, or device is disconnected, go right to
2481 if(!BufferList
|| !device
->Connected
)
2484 /* Make sure this source isn't already active, while looking for an
2485 * unused active source slot to put it in. */
2486 for(i
= 0;i
< Context
->VoiceCount
;i
++)
2488 ALsource
*old
= Source
;
2489 if(COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, NULL
))
2493 voice
= &Context
->Voices
[i
];
2494 voice
->Source
= Source
;
2499 if(voice
== NULL
&& COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, Source
))
2500 voice
= &Context
->Voices
[i
];
2504 voice
= &Context
->Voices
[Context
->VoiceCount
++];
2505 voice
->Source
= Source
;
2508 voice
->Direct
.Moving
= AL_FALSE
;
2509 voice
->Direct
.Counter
= 0;
2510 for(i
= 0;i
< MAX_INPUT_CHANNELS
;i
++)
2513 for(j
= 0;j
< SRC_HISTORY_LENGTH
;j
++)
2514 voice
->Direct
.Mix
.Hrtf
.State
[i
].History
[j
] = 0.0f
;
2515 for(j
= 0;j
< HRIR_LENGTH
;j
++)
2517 voice
->Direct
.Mix
.Hrtf
.State
[i
].Values
[j
][0] = 0.0f
;
2518 voice
->Direct
.Mix
.Hrtf
.State
[i
].Values
[j
][1] = 0.0f
;
2521 for(i
= 0;i
< (ALsizei
)device
->NumAuxSends
;i
++)
2523 voice
->Send
[i
].Counter
= 0;
2524 voice
->Send
[i
].Moving
= AL_FALSE
;
2527 if(BufferList
->buffer
->FmtChannels
== FmtMono
)
2528 voice
->Update
= CalcSourceParams
;
2530 voice
->Update
= CalcNonAttnSourceParams
;
2532 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
2534 else if(state
== AL_PAUSED
)
2536 if(Source
->state
== AL_PLAYING
)
2537 Source
->state
= AL_PAUSED
;
2539 else if(state
== AL_STOPPED
)
2542 if(Source
->state
!= AL_INITIAL
)
2544 Source
->state
= AL_STOPPED
;
2545 ATOMIC_STORE(&Source
->current_buffer
, NULL
);
2547 Source
->Offset
= -1.0;
2549 else if(state
== AL_INITIAL
)
2551 if(Source
->state
!= AL_INITIAL
)
2553 Source
->state
= AL_INITIAL
;
2554 Source
->position
= 0;
2555 Source
->position_fraction
= 0;
2556 ATOMIC_STORE(&Source
->current_buffer
, ATOMIC_LOAD(&Source
->queue
));
2558 Source
->Offset
= -1.0;
2560 ReadUnlock(&Source
->queue_lock
);
2565 * Gets the current read offset for the given Source, in 32.32 fixed-point
2566 * samples. The offset is relative to the start of the queue (not the start of
2567 * the current buffer).
2569 static ALint64
GetSourceOffset(const ALsource
*Source
)
2571 const ALbufferlistitem
*BufferList
;
2572 const ALbufferlistitem
*Current
;
2575 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2578 /* NOTE: This is the offset into the *current* buffer, so add the length of
2579 * any played buffers */
2580 readPos
= (ALuint64
)Source
->position
<< 32;
2581 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2582 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2583 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2584 while(BufferList
&& BufferList
!= Current
)
2586 if(BufferList
->buffer
)
2587 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2588 BufferList
= BufferList
->next
;
2591 return (ALint64
)minu64(readPos
, U64(0x7fffffffffffffff));
2594 /* GetSourceSecOffset
2596 * Gets the current read offset for the given Source, in seconds. The offset is
2597 * relative to the start of the queue (not the start of the current buffer).
2599 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2601 const ALbufferlistitem
*BufferList
;
2602 const ALbufferlistitem
*Current
;
2603 const ALbuffer
*Buffer
= NULL
;
2606 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2609 /* NOTE: This is the offset into the *current* buffer, so add the length of
2610 * any played buffers */
2611 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2612 readPos
|= (ALuint64
)Source
->position_fraction
;
2613 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2614 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2615 while(BufferList
&& BufferList
!= Current
)
2617 const ALbuffer
*buffer
= BufferList
->buffer
;
2620 if(!Buffer
) Buffer
= buffer
;
2621 readPos
+= (ALuint64
)buffer
->SampleLen
<< FRACTIONBITS
;
2623 BufferList
= BufferList
->next
;
2626 while(BufferList
&& !Buffer
)
2628 Buffer
= BufferList
->buffer
;
2629 BufferList
= BufferList
->next
;
2631 assert(Buffer
!= NULL
);
2633 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2638 * Gets the current read and write offsets for the given Source, in the
2639 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2640 * the start of the queue (not the start of the current buffer).
2642 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2644 const ALbufferlistitem
*BufferList
;
2645 const ALbufferlistitem
*Current
;
2646 const ALbuffer
*Buffer
= NULL
;
2647 ALboolean readFin
= AL_FALSE
;
2648 ALuint readPos
, writePos
;
2649 ALuint totalBufferLen
;
2651 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2658 if(updateLen
> 0.0 && updateLen
< 0.015)
2661 /* NOTE: This is the offset into the *current* buffer, so add the length of
2662 * any played buffers */
2664 readPos
= Source
->position
;
2665 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2666 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2667 while(BufferList
!= NULL
)
2669 const ALbuffer
*buffer
;
2670 readFin
= readFin
|| (BufferList
== Current
);
2671 if((buffer
=BufferList
->buffer
) != NULL
)
2673 if(!Buffer
) Buffer
= buffer
;
2674 totalBufferLen
+= buffer
->SampleLen
;
2675 if(!readFin
) readPos
+= buffer
->SampleLen
;
2677 BufferList
= BufferList
->next
;
2679 assert(Buffer
!= NULL
);
2681 if(Source
->state
== AL_PLAYING
)
2682 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2688 readPos
%= totalBufferLen
;
2689 writePos
%= totalBufferLen
;
2693 /* Wrap positions back to 0 */
2694 if(readPos
>= totalBufferLen
)
2696 if(writePos
>= totalBufferLen
)
2703 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2704 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2707 case AL_SAMPLE_OFFSET
:
2708 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2709 offset
[0] = (ALdouble
)readPos
;
2710 offset
[1] = (ALdouble
)writePos
;
2713 case AL_BYTE_OFFSET
:
2714 case AL_BYTE_RW_OFFSETS_SOFT
:
2715 if(Buffer
->OriginalType
== UserFmtIMA4
)
2717 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
2718 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2719 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2721 /* Round down to nearest ADPCM block */
2722 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2723 if(Source
->state
!= AL_PLAYING
)
2724 offset
[1] = offset
[0];
2727 /* Round up to nearest ADPCM block */
2728 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2729 FrameBlockSize
* BlockSize
);
2732 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
2734 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
2735 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2736 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2738 /* Round down to nearest ADPCM block */
2739 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2740 if(Source
->state
!= AL_PLAYING
)
2741 offset
[1] = offset
[0];
2744 /* Round up to nearest ADPCM block */
2745 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2746 FrameBlockSize
* BlockSize
);
2751 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2752 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2753 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2762 * Apply the stored playback offset to the Source. This function will update
2763 * the number of buffers "played" given the stored offset.
2765 ALboolean
ApplyOffset(ALsource
*Source
)
2767 ALbufferlistitem
*BufferList
;
2768 const ALbuffer
*Buffer
;
2769 ALint bufferLen
, totalBufferLen
;
2772 /* Get sample frame offset */
2773 offset
= GetSampleOffset(Source
);
2778 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2779 while(BufferList
&& totalBufferLen
<= offset
)
2781 Buffer
= BufferList
->buffer
;
2782 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2784 if(bufferLen
> offset
-totalBufferLen
)
2786 /* Offset is in this buffer */
2787 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
2789 Source
->position
= offset
- totalBufferLen
;
2790 Source
->position_fraction
= 0;
2794 totalBufferLen
+= bufferLen
;
2796 BufferList
= BufferList
->next
;
2799 /* Offset is out of range of the queue */
2806 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2807 * Second offset supplied by the application). This takes into account the fact
2808 * that the buffer format may have been modifed since.
2810 static ALint
GetSampleOffset(ALsource
*Source
)
2812 const ALbuffer
*Buffer
= NULL
;
2813 const ALbufferlistitem
*BufferList
;
2816 /* Find the first valid Buffer in the Queue */
2817 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2820 if(BufferList
->buffer
)
2822 Buffer
= BufferList
->buffer
;
2825 BufferList
= BufferList
->next
;
2830 Source
->Offset
= -1.0;
2834 switch(Source
->OffsetType
)
2836 case AL_BYTE_OFFSET
:
2837 /* Determine the ByteOffset (and ensure it is block aligned) */
2838 Offset
= (ALint
)Source
->Offset
;
2839 if(Buffer
->OriginalType
== UserFmtIMA4
)
2841 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
2842 Offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2843 Offset
*= Buffer
->OriginalAlign
;
2845 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
2847 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
2848 Offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2849 Offset
*= Buffer
->OriginalAlign
;
2852 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2855 case AL_SAMPLE_OFFSET
:
2856 Offset
= (ALint
)Source
->Offset
;
2860 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2863 Source
->Offset
= -1.0;
2871 * Destroys all sources in the source map.
2873 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2875 ALbufferlistitem
*item
;
2878 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2880 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2881 Context
->SourceMap
.array
[pos
].value
= NULL
;
2883 item
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &temp
->queue
, NULL
);
2886 ALbufferlistitem
*next
= item
->next
;
2887 if(item
->buffer
!= NULL
)
2888 DecrementRef(&item
->buffer
->ref
);
2893 for(j
= 0;j
< MAX_SENDS
;++j
)
2895 if(temp
->Send
[j
].Slot
)
2896 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2897 temp
->Send
[j
].Slot
= NULL
;
2900 FreeThunkEntry(temp
->id
);
2901 memset(temp
, 0, sizeof(*temp
));