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 sfOrientation
= AL_ORIENTATION
,
116 typedef enum SrcIntProp
{
117 siMaxDistance
= AL_MAX_DISTANCE
,
118 siRolloffFactor
= AL_ROLLOFF_FACTOR
,
119 siRefDistance
= AL_REFERENCE_DISTANCE
,
120 siSourceRelative
= AL_SOURCE_RELATIVE
,
121 siConeInnerAngle
= AL_CONE_INNER_ANGLE
,
122 siConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
123 siLooping
= AL_LOOPING
,
124 siBuffer
= AL_BUFFER
,
125 siSourceState
= AL_SOURCE_STATE
,
126 siBuffersQueued
= AL_BUFFERS_QUEUED
,
127 siBuffersProcessed
= AL_BUFFERS_PROCESSED
,
128 siSourceType
= AL_SOURCE_TYPE
,
129 siSecOffset
= AL_SEC_OFFSET
,
130 siSampleOffset
= AL_SAMPLE_OFFSET
,
131 siByteOffset
= AL_BYTE_OFFSET
,
132 siDopplerFactor
= AL_DOPPLER_FACTOR
,
133 siPosition
= AL_POSITION
,
134 siVelocity
= AL_VELOCITY
,
135 siDirection
= AL_DIRECTION
,
138 siDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
139 siAuxSendFilterGainAutio
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
140 siAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
141 siDirectFilter
= AL_DIRECT_FILTER
,
142 siAuxSendFilter
= AL_AUXILIARY_SEND_FILTER
,
144 /* AL_SOFT_direct_channels */
145 siDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
147 /* AL_EXT_source_distance_model */
148 siDistanceModel
= AL_DISTANCE_MODEL
,
150 siByteLength
= AL_BYTE_LENGTH_SOFT
,
151 siSampleLength
= AL_SAMPLE_LENGTH_SOFT
,
153 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
154 siSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
155 siByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
157 /* AL_SOFT_source_latency */
158 siSampleOffsetLatencySOFT
= AL_SAMPLE_OFFSET_LATENCY_SOFT
,
161 siOrientation
= AL_ORIENTATION
,
164 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
);
165 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
);
166 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
);
168 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
);
169 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
);
170 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
);
172 static ALint
FloatValsByProp(ALenum prop
)
174 if(prop
!= (ALenum
)((SrcFloatProp
)prop
))
176 switch((SrcFloatProp
)prop
)
183 case sfRolloffFactor
:
184 case sfDopplerFactor
:
185 case sfConeOuterGain
:
189 case sfConeInnerAngle
:
190 case sfConeOuterAngle
:
192 case sfConeOuterGainHF
:
193 case sfAirAbsorptionFactor
:
194 case sfRoomRolloffFactor
:
195 case sfDirectFilterGainHFAuto
:
196 case sfAuxSendFilterGainAuto
:
197 case sfAuxSendFilterGainHFAuto
:
198 case sfDirectChannelsSOFT
:
199 case sfDistanceModel
:
200 case sfSourceRelative
:
204 case sfBuffersQueued
:
205 case sfBuffersProcessed
:
210 case sfSampleRWOffsetsSOFT
:
211 case sfByteRWOffsetsSOFT
:
222 case sfSecOffsetLatencySOFT
:
223 break; /* Double only */
227 static ALint
DoubleValsByProp(ALenum prop
)
229 if(prop
!= (ALenum
)((SrcFloatProp
)prop
))
231 switch((SrcFloatProp
)prop
)
238 case sfRolloffFactor
:
239 case sfDopplerFactor
:
240 case sfConeOuterGain
:
244 case sfConeInnerAngle
:
245 case sfConeOuterAngle
:
247 case sfConeOuterGainHF
:
248 case sfAirAbsorptionFactor
:
249 case sfRoomRolloffFactor
:
250 case sfDirectFilterGainHFAuto
:
251 case sfAuxSendFilterGainAuto
:
252 case sfAuxSendFilterGainHFAuto
:
253 case sfDirectChannelsSOFT
:
254 case sfDistanceModel
:
255 case sfSourceRelative
:
259 case sfBuffersQueued
:
260 case sfBuffersProcessed
:
265 case sfSampleRWOffsetsSOFT
:
266 case sfByteRWOffsetsSOFT
:
267 case sfSecOffsetLatencySOFT
:
281 static ALint
IntValsByProp(ALenum prop
)
283 if(prop
!= (ALenum
)((SrcIntProp
)prop
))
285 switch((SrcIntProp
)prop
)
288 case siRolloffFactor
:
290 case siSourceRelative
:
291 case siConeInnerAngle
:
292 case siConeOuterAngle
:
296 case siBuffersQueued
:
297 case siBuffersProcessed
:
302 case siDopplerFactor
:
303 case siDirectFilterGainHFAuto
:
304 case siAuxSendFilterGainAutio
:
305 case siAuxSendFilterGainHFAuto
:
307 case siDirectChannelsSOFT
:
308 case siDistanceModel
:
313 case siSampleRWOffsetsSOFT
:
314 case siByteRWOffsetsSOFT
:
320 case siAuxSendFilter
:
326 case siSampleOffsetLatencySOFT
:
327 break; /* i64 only */
331 static ALint
Int64ValsByProp(ALenum prop
)
333 if(prop
!= (ALenum
)((SrcIntProp
)prop
))
335 switch((SrcIntProp
)prop
)
338 case siRolloffFactor
:
340 case siSourceRelative
:
341 case siConeInnerAngle
:
342 case siConeOuterAngle
:
346 case siBuffersQueued
:
347 case siBuffersProcessed
:
352 case siDopplerFactor
:
353 case siDirectFilterGainHFAuto
:
354 case siAuxSendFilterGainAutio
:
355 case siAuxSendFilterGainHFAuto
:
357 case siDirectChannelsSOFT
:
358 case siDistanceModel
:
363 case siSampleRWOffsetsSOFT
:
364 case siByteRWOffsetsSOFT
:
365 case siSampleOffsetLatencySOFT
:
371 case siAuxSendFilter
:
381 #define CHECKVAL(x) do { \
383 SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); \
386 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
)
393 CHECKVAL(*values
>= 0.0f
);
395 Source
->Pitch
= *values
;
396 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
399 case AL_CONE_INNER_ANGLE
:
400 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
402 Source
->InnerAngle
= *values
;
403 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
406 case AL_CONE_OUTER_ANGLE
:
407 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
409 Source
->OuterAngle
= *values
;
410 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
414 CHECKVAL(*values
>= 0.0f
);
416 Source
->Gain
= *values
;
417 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
420 case AL_MAX_DISTANCE
:
421 CHECKVAL(*values
>= 0.0f
);
423 Source
->MaxDistance
= *values
;
424 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
427 case AL_ROLLOFF_FACTOR
:
428 CHECKVAL(*values
>= 0.0f
);
430 Source
->RollOffFactor
= *values
;
431 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
434 case AL_REFERENCE_DISTANCE
:
435 CHECKVAL(*values
>= 0.0f
);
437 Source
->RefDistance
= *values
;
438 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
442 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
444 Source
->MinGain
= *values
;
445 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
449 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
451 Source
->MaxGain
= *values
;
452 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
455 case AL_CONE_OUTER_GAIN
:
456 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
458 Source
->OuterGain
= *values
;
459 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
462 case AL_CONE_OUTER_GAINHF
:
463 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
465 Source
->OuterGainHF
= *values
;
466 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
469 case AL_AIR_ABSORPTION_FACTOR
:
470 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
472 Source
->AirAbsorptionFactor
= *values
;
473 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
476 case AL_ROOM_ROLLOFF_FACTOR
:
477 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
479 Source
->RoomRolloffFactor
= *values
;
480 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
483 case AL_DOPPLER_FACTOR
:
484 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
486 Source
->DopplerFactor
= *values
;
487 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
491 case AL_SAMPLE_OFFSET
:
493 CHECKVAL(*values
>= 0.0f
);
495 LockContext(Context
);
496 Source
->OffsetType
= prop
;
497 Source
->Offset
= *values
;
499 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
500 !Context
->DeferUpdates
)
502 if(ApplyOffset(Source
) == AL_FALSE
)
504 UnlockContext(Context
);
505 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
508 UnlockContext(Context
);
513 case AL_SEC_OFFSET_LATENCY_SOFT
:
515 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
519 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
521 LockContext(Context
);
522 aluVectorSet(&Source
->Position
, values
[0], values
[1], values
[2], 1.0f
);
523 UnlockContext(Context
);
524 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
528 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
530 LockContext(Context
);
531 aluVectorSet(&Source
->Velocity
, values
[0], values
[1], values
[2], 0.0f
);
532 UnlockContext(Context
);
533 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
537 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
539 LockContext(Context
);
540 aluVectorSet(&Source
->Direction
, values
[0], values
[1], values
[2], 0.0f
);
541 UnlockContext(Context
);
542 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
546 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]) &&
547 isfinite(values
[3]) && isfinite(values
[4]) && isfinite(values
[5]));
549 LockContext(Context
);
550 Source
->Orientation
[0][0] = values
[0];
551 Source
->Orientation
[0][1] = values
[1];
552 Source
->Orientation
[0][2] = values
[2];
553 Source
->Orientation
[1][0] = values
[3];
554 Source
->Orientation
[1][1] = values
[4];
555 Source
->Orientation
[1][2] = values
[5];
556 UnlockContext(Context
);
557 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
560 case sfSampleRWOffsetsSOFT
:
561 case sfByteRWOffsetsSOFT
:
562 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
565 case sfSourceRelative
:
569 case sfDistanceModel
:
570 case sfDirectFilterGainHFAuto
:
571 case sfAuxSendFilterGainAuto
:
572 case sfAuxSendFilterGainHFAuto
:
573 case sfDirectChannelsSOFT
:
574 ival
= (ALint
)values
[0];
575 return SetSourceiv(Source
, Context
, (SrcIntProp
)prop
, &ival
);
578 case sfBuffersQueued
:
579 case sfBuffersProcessed
:
580 ival
= (ALint
)((ALuint
)values
[0]);
581 return SetSourceiv(Source
, Context
, (SrcIntProp
)prop
, &ival
);
584 ERR("Unexpected property: 0x%04x\n", prop
);
585 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
588 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
)
590 ALCdevice
*device
= Context
->Device
;
591 ALbuffer
*buffer
= NULL
;
592 ALfilter
*filter
= NULL
;
593 ALeffectslot
*slot
= NULL
;
594 ALbufferlistitem
*oldlist
;
595 ALbufferlistitem
*newlist
;
600 case AL_SOURCE_RELATIVE
:
601 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
603 Source
->HeadRelative
= (ALboolean
)*values
;
604 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
608 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
610 Source
->Looping
= (ALboolean
)*values
;
614 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
616 WriteLock(&Source
->queue_lock
);
617 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
619 WriteUnlock(&Source
->queue_lock
);
620 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
625 /* Add the selected buffer to a one-item queue */
626 newlist
= malloc(sizeof(ALbufferlistitem
));
627 newlist
->buffer
= buffer
;
628 newlist
->next
= NULL
;
629 newlist
->prev
= NULL
;
630 IncrementRef(&buffer
->ref
);
632 /* Source is now Static */
633 Source
->SourceType
= AL_STATIC
;
635 ReadLock(&buffer
->lock
);
636 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
637 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
638 ReadUnlock(&buffer
->lock
);
642 /* Source is now Undetermined */
643 Source
->SourceType
= AL_UNDETERMINED
;
646 oldlist
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &Source
->queue
, newlist
);
647 ATOMIC_STORE(&Source
->current_buffer
, newlist
);
648 WriteUnlock(&Source
->queue_lock
);
650 /* Delete all elements in the previous queue */
651 while(oldlist
!= NULL
)
653 ALbufferlistitem
*temp
= oldlist
;
654 oldlist
= temp
->next
;
657 DecrementRef(&temp
->buffer
->ref
);
664 case siBuffersQueued
:
665 case siBuffersProcessed
:
667 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
670 case AL_SAMPLE_OFFSET
:
672 CHECKVAL(*values
>= 0);
674 LockContext(Context
);
675 Source
->OffsetType
= prop
;
676 Source
->Offset
= *values
;
678 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
679 !Context
->DeferUpdates
)
681 if(ApplyOffset(Source
) == AL_FALSE
)
683 UnlockContext(Context
);
684 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
687 UnlockContext(Context
);
693 case siSampleRWOffsetsSOFT
:
694 case siByteRWOffsetsSOFT
:
696 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
699 case AL_DIRECT_FILTER
:
700 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
702 LockContext(Context
);
705 Source
->Direct
.Gain
= 1.0f
;
706 Source
->Direct
.GainHF
= 1.0f
;
707 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
708 Source
->Direct
.GainLF
= 1.0f
;
709 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
713 Source
->Direct
.Gain
= filter
->Gain
;
714 Source
->Direct
.GainHF
= filter
->GainHF
;
715 Source
->Direct
.HFReference
= filter
->HFReference
;
716 Source
->Direct
.GainLF
= filter
->GainLF
;
717 Source
->Direct
.LFReference
= filter
->LFReference
;
719 UnlockContext(Context
);
720 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
723 case AL_DIRECT_FILTER_GAINHF_AUTO
:
724 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
726 Source
->DryGainHFAuto
= *values
;
727 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
730 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
731 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
733 Source
->WetGainAuto
= *values
;
734 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
737 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
738 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
740 Source
->WetGainHFAuto
= *values
;
741 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
744 case AL_DIRECT_CHANNELS_SOFT
:
745 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
747 Source
->DirectChannels
= *values
;
748 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
751 case AL_DISTANCE_MODEL
:
752 CHECKVAL(*values
== AL_NONE
||
753 *values
== AL_INVERSE_DISTANCE
||
754 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
755 *values
== AL_LINEAR_DISTANCE
||
756 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
757 *values
== AL_EXPONENT_DISTANCE
||
758 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
760 Source
->DistanceModel
= *values
;
761 if(Context
->SourceDistanceModel
)
762 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
766 case AL_AUXILIARY_SEND_FILTER
:
767 LockContext(Context
);
768 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
769 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
770 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
772 UnlockContext(Context
);
773 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
776 /* Add refcount on the new slot, and release the previous slot */
777 if(slot
) IncrementRef(&slot
->ref
);
778 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
779 if(slot
) DecrementRef(&slot
->ref
);
784 Source
->Send
[values
[1]].Gain
= 1.0f
;
785 Source
->Send
[values
[1]].GainHF
= 1.0f
;
786 Source
->Send
[values
[1]].HFReference
= LOWPASSFREQREF
;
787 Source
->Send
[values
[1]].GainLF
= 1.0f
;
788 Source
->Send
[values
[1]].LFReference
= HIGHPASSFREQREF
;
792 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
793 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
794 Source
->Send
[values
[1]].HFReference
= filter
->HFReference
;
795 Source
->Send
[values
[1]].GainLF
= filter
->GainLF
;
796 Source
->Send
[values
[1]].LFReference
= filter
->LFReference
;
798 UnlockContext(Context
);
799 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
803 case AL_MAX_DISTANCE
:
804 case AL_ROLLOFF_FACTOR
:
805 case AL_CONE_INNER_ANGLE
:
806 case AL_CONE_OUTER_ANGLE
:
807 case AL_REFERENCE_DISTANCE
:
808 case siDopplerFactor
:
809 fvals
[0] = (ALfloat
)*values
;
810 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
815 fvals
[0] = (ALfloat
)values
[0];
816 fvals
[1] = (ALfloat
)values
[1];
817 fvals
[2] = (ALfloat
)values
[2];
818 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
821 fvals
[0] = (ALfloat
)values
[0];
822 fvals
[1] = (ALfloat
)values
[1];
823 fvals
[2] = (ALfloat
)values
[2];
824 fvals
[3] = (ALfloat
)values
[3];
825 fvals
[4] = (ALfloat
)values
[4];
826 fvals
[5] = (ALfloat
)values
[5];
827 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
829 case siSampleOffsetLatencySOFT
:
834 ERR("Unexpected property: 0x%04x\n", prop
);
835 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
838 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
)
845 case siSampleRWOffsetsSOFT
:
846 case siByteRWOffsetsSOFT
:
847 case siSampleOffsetLatencySOFT
:
849 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
853 case AL_SOURCE_RELATIVE
:
855 case AL_SOURCE_STATE
:
857 case AL_SAMPLE_OFFSET
:
861 case siBuffersQueued
:
862 case siBuffersProcessed
:
863 case AL_DIRECT_FILTER_GAINHF_AUTO
:
864 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
865 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
866 case AL_DIRECT_CHANNELS_SOFT
:
867 case AL_DISTANCE_MODEL
:
868 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
870 ivals
[0] = (ALint
)*values
;
871 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
875 case AL_DIRECT_FILTER
:
876 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
878 ivals
[0] = (ALuint
)*values
;
879 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
882 case AL_AUXILIARY_SEND_FILTER
:
883 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
884 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
885 values
[2] <= UINT_MAX
&& values
[2] >= 0);
887 ivals
[0] = (ALuint
)values
[0];
888 ivals
[1] = (ALuint
)values
[1];
889 ivals
[2] = (ALuint
)values
[2];
890 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
893 case AL_MAX_DISTANCE
:
894 case AL_ROLLOFF_FACTOR
:
895 case AL_CONE_INNER_ANGLE
:
896 case AL_CONE_OUTER_ANGLE
:
897 case AL_REFERENCE_DISTANCE
:
899 case siDopplerFactor
:
900 fvals
[0] = (ALfloat
)*values
;
901 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
907 fvals
[0] = (ALfloat
)values
[0];
908 fvals
[1] = (ALfloat
)values
[1];
909 fvals
[2] = (ALfloat
)values
[2];
910 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
914 fvals
[0] = (ALfloat
)values
[0];
915 fvals
[1] = (ALfloat
)values
[1];
916 fvals
[2] = (ALfloat
)values
[2];
917 fvals
[3] = (ALfloat
)values
[3];
918 fvals
[4] = (ALfloat
)values
[4];
919 fvals
[5] = (ALfloat
)values
[5];
920 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
923 ERR("Unexpected property: 0x%04x\n", prop
);
924 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
930 static ALboolean
GetSourcedv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
)
932 ALbufferlistitem
*BufferList
;
941 *values
= Source
->Gain
;
945 *values
= Source
->Pitch
;
948 case AL_MAX_DISTANCE
:
949 *values
= Source
->MaxDistance
;
952 case AL_ROLLOFF_FACTOR
:
953 *values
= Source
->RollOffFactor
;
956 case AL_REFERENCE_DISTANCE
:
957 *values
= Source
->RefDistance
;
960 case AL_CONE_INNER_ANGLE
:
961 *values
= Source
->InnerAngle
;
964 case AL_CONE_OUTER_ANGLE
:
965 *values
= Source
->OuterAngle
;
969 *values
= Source
->MinGain
;
973 *values
= Source
->MaxGain
;
976 case AL_CONE_OUTER_GAIN
:
977 *values
= Source
->OuterGain
;
981 case AL_SAMPLE_OFFSET
:
983 LockContext(Context
);
984 ReadLock(&Source
->queue_lock
);
985 GetSourceOffsets(Source
, prop
, offsets
, 0.0);
986 ReadUnlock(&Source
->queue_lock
);
987 UnlockContext(Context
);
988 *values
= offsets
[0];
991 case AL_CONE_OUTER_GAINHF
:
992 *values
= Source
->OuterGainHF
;
995 case AL_AIR_ABSORPTION_FACTOR
:
996 *values
= Source
->AirAbsorptionFactor
;
999 case AL_ROOM_ROLLOFF_FACTOR
:
1000 *values
= Source
->RoomRolloffFactor
;
1003 case AL_DOPPLER_FACTOR
:
1004 *values
= Source
->DopplerFactor
;
1008 ReadLock(&Source
->queue_lock
);
1009 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1016 ALbuffer
*buffer
= BufferList
->buffer
;
1017 if(buffer
&& buffer
->SampleLen
> 0)
1019 freq
= buffer
->Frequency
;
1020 length
+= buffer
->SampleLen
;
1022 } while((BufferList
=BufferList
->next
) != NULL
);
1023 *values
= (ALdouble
)length
/ (ALdouble
)freq
;
1025 ReadUnlock(&Source
->queue_lock
);
1028 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1029 case AL_BYTE_RW_OFFSETS_SOFT
:
1030 LockContext(Context
);
1031 ReadLock(&Source
->queue_lock
);
1032 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
1033 Context
->Device
->Frequency
;
1034 GetSourceOffsets(Source
, prop
, values
, updateLen
);
1035 ReadUnlock(&Source
->queue_lock
);
1036 UnlockContext(Context
);
1039 case AL_SEC_OFFSET_LATENCY_SOFT
:
1040 LockContext(Context
);
1041 ReadLock(&Source
->queue_lock
);
1042 values
[0] = GetSourceSecOffset(Source
);
1043 ReadUnlock(&Source
->queue_lock
);
1044 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
1046 UnlockContext(Context
);
1050 LockContext(Context
);
1051 values
[0] = Source
->Position
.v
[0];
1052 values
[1] = Source
->Position
.v
[1];
1053 values
[2] = Source
->Position
.v
[2];
1054 UnlockContext(Context
);
1058 LockContext(Context
);
1059 values
[0] = Source
->Velocity
.v
[0];
1060 values
[1] = Source
->Velocity
.v
[1];
1061 values
[2] = Source
->Velocity
.v
[2];
1062 UnlockContext(Context
);
1066 LockContext(Context
);
1067 values
[0] = Source
->Direction
.v
[0];
1068 values
[1] = Source
->Direction
.v
[1];
1069 values
[2] = Source
->Direction
.v
[2];
1070 UnlockContext(Context
);
1073 case AL_ORIENTATION
:
1074 LockContext(Context
);
1075 values
[0] = Source
->Orientation
[0][0];
1076 values
[1] = Source
->Orientation
[0][1];
1077 values
[2] = Source
->Orientation
[0][2];
1078 values
[3] = Source
->Orientation
[1][0];
1079 values
[4] = Source
->Orientation
[1][1];
1080 values
[5] = Source
->Orientation
[1][2];
1081 UnlockContext(Context
);
1084 case AL_SOURCE_RELATIVE
:
1087 case AL_SOURCE_STATE
:
1088 case AL_BUFFERS_QUEUED
:
1089 case AL_BUFFERS_PROCESSED
:
1090 case AL_SOURCE_TYPE
:
1091 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1092 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1093 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1094 case AL_DIRECT_CHANNELS_SOFT
:
1095 case AL_DISTANCE_MODEL
:
1096 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1097 *values
= (ALdouble
)ivals
[0];
1101 ERR("Unexpected property: 0x%04x\n", prop
);
1102 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1105 static ALboolean
GetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
)
1107 ALbufferlistitem
*BufferList
;
1113 case AL_SOURCE_RELATIVE
:
1114 *values
= Source
->HeadRelative
;
1118 *values
= Source
->Looping
;
1122 ReadLock(&Source
->queue_lock
);
1123 BufferList
= (Source
->SourceType
== AL_STATIC
) ? ATOMIC_LOAD(&Source
->queue
) :
1124 ATOMIC_LOAD(&Source
->current_buffer
);
1125 *values
= (BufferList
&& BufferList
->buffer
) ? BufferList
->buffer
->id
: 0;
1126 ReadUnlock(&Source
->queue_lock
);
1129 case AL_SOURCE_STATE
:
1130 *values
= Source
->state
;
1134 ReadLock(&Source
->queue_lock
);
1135 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1141 ALbuffer
*buffer
= BufferList
->buffer
;
1142 if(buffer
&& buffer
->SampleLen
> 0)
1144 ALuint byte_align
, sample_align
;
1145 if(buffer
->OriginalType
== UserFmtIMA4
)
1147 ALsizei align
= (buffer
->OriginalAlign
-1)/2 + 4;
1148 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1149 sample_align
= buffer
->OriginalAlign
;
1151 else if(buffer
->OriginalType
== UserFmtMSADPCM
)
1153 ALsizei align
= (buffer
->OriginalAlign
-2)/2 + 7;
1154 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1155 sample_align
= buffer
->OriginalAlign
;
1159 ALsizei align
= buffer
->OriginalAlign
;
1160 byte_align
= align
* ChannelsFromFmt(buffer
->FmtChannels
);
1161 sample_align
= buffer
->OriginalAlign
;
1164 length
+= buffer
->SampleLen
/ sample_align
* byte_align
;
1166 } while((BufferList
=BufferList
->next
) != NULL
);
1169 ReadUnlock(&Source
->queue_lock
);
1172 case siSampleLength
:
1173 ReadLock(&Source
->queue_lock
);
1174 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1180 ALbuffer
*buffer
= BufferList
->buffer
;
1181 if(buffer
) length
+= buffer
->SampleLen
;
1182 } while((BufferList
=BufferList
->next
) != NULL
);
1185 ReadUnlock(&Source
->queue_lock
);
1188 case AL_BUFFERS_QUEUED
:
1189 ReadLock(&Source
->queue_lock
);
1190 if(!(BufferList
=ATOMIC_LOAD(&Source
->queue
)))
1197 } while((BufferList
=BufferList
->next
) != NULL
);
1200 ReadUnlock(&Source
->queue_lock
);
1203 case AL_BUFFERS_PROCESSED
:
1204 ReadLock(&Source
->queue_lock
);
1205 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
1207 /* Buffers on a looping source are in a perpetual state of
1208 * PENDING, so don't report any as PROCESSED */
1213 const ALbufferlistitem
*BufferList
= ATOMIC_LOAD(&Source
->queue
);
1214 const ALbufferlistitem
*Current
= ATOMIC_LOAD(&Source
->current_buffer
);
1216 while(BufferList
&& BufferList
!= Current
)
1219 BufferList
= BufferList
->next
;
1223 ReadUnlock(&Source
->queue_lock
);
1226 case AL_SOURCE_TYPE
:
1227 *values
= Source
->SourceType
;
1230 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1231 *values
= Source
->DryGainHFAuto
;
1234 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1235 *values
= Source
->WetGainAuto
;
1238 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1239 *values
= Source
->WetGainHFAuto
;
1242 case AL_DIRECT_CHANNELS_SOFT
:
1243 *values
= Source
->DirectChannels
;
1246 case AL_DISTANCE_MODEL
:
1247 *values
= Source
->DistanceModel
;
1250 case AL_MAX_DISTANCE
:
1251 case AL_ROLLOFF_FACTOR
:
1252 case AL_REFERENCE_DISTANCE
:
1253 case AL_CONE_INNER_ANGLE
:
1254 case AL_CONE_OUTER_ANGLE
:
1256 case AL_SAMPLE_OFFSET
:
1257 case AL_BYTE_OFFSET
:
1258 case AL_DOPPLER_FACTOR
:
1259 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1260 *values
= (ALint
)dvals
[0];
1263 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1264 case AL_BYTE_RW_OFFSETS_SOFT
:
1265 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1267 values
[0] = (ALint
)dvals
[0];
1268 values
[1] = (ALint
)dvals
[1];
1275 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1277 values
[0] = (ALint
)dvals
[0];
1278 values
[1] = (ALint
)dvals
[1];
1279 values
[2] = (ALint
)dvals
[2];
1283 case AL_ORIENTATION
:
1284 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1286 values
[0] = (ALint
)dvals
[0];
1287 values
[1] = (ALint
)dvals
[1];
1288 values
[2] = (ALint
)dvals
[2];
1289 values
[3] = (ALint
)dvals
[3];
1290 values
[4] = (ALint
)dvals
[4];
1291 values
[5] = (ALint
)dvals
[5];
1295 case siSampleOffsetLatencySOFT
:
1299 case siDirectFilter
:
1300 case siAuxSendFilter
:
1305 ERR("Unexpected property: 0x%04x\n", prop
);
1306 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1309 static ALboolean
GetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
)
1317 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1318 LockContext(Context
);
1319 ReadLock(&Source
->queue_lock
);
1320 values
[0] = GetSourceOffset(Source
);
1321 ReadUnlock(&Source
->queue_lock
);
1322 values
[1] = ALCdevice_GetLatency(Context
->Device
);
1323 UnlockContext(Context
);
1326 case AL_MAX_DISTANCE
:
1327 case AL_ROLLOFF_FACTOR
:
1328 case AL_REFERENCE_DISTANCE
:
1329 case AL_CONE_INNER_ANGLE
:
1330 case AL_CONE_OUTER_ANGLE
:
1332 case AL_SAMPLE_OFFSET
:
1333 case AL_BYTE_OFFSET
:
1334 case AL_DOPPLER_FACTOR
:
1335 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1336 *values
= (ALint64
)dvals
[0];
1339 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1340 case AL_BYTE_RW_OFFSETS_SOFT
:
1341 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1343 values
[0] = (ALint64
)dvals
[0];
1344 values
[1] = (ALint64
)dvals
[1];
1351 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1353 values
[0] = (ALint64
)dvals
[0];
1354 values
[1] = (ALint64
)dvals
[1];
1355 values
[2] = (ALint64
)dvals
[2];
1359 case AL_ORIENTATION
:
1360 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1362 values
[0] = (ALint64
)dvals
[0];
1363 values
[1] = (ALint64
)dvals
[1];
1364 values
[2] = (ALint64
)dvals
[2];
1365 values
[3] = (ALint64
)dvals
[3];
1366 values
[4] = (ALint64
)dvals
[4];
1367 values
[5] = (ALint64
)dvals
[5];
1371 case AL_SOURCE_RELATIVE
:
1373 case AL_SOURCE_STATE
:
1374 case AL_BUFFERS_QUEUED
:
1375 case AL_BUFFERS_PROCESSED
:
1377 case siSampleLength
:
1378 case AL_SOURCE_TYPE
:
1379 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1380 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1381 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1382 case AL_DIRECT_CHANNELS_SOFT
:
1383 case AL_DISTANCE_MODEL
:
1384 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1389 case siDirectFilter
:
1390 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1391 *values
= (ALuint
)ivals
[0];
1394 case siAuxSendFilter
:
1395 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1397 values
[0] = (ALuint
)ivals
[0];
1398 values
[1] = (ALuint
)ivals
[1];
1399 values
[2] = (ALuint
)ivals
[2];
1404 ERR("Unexpected property: 0x%04x\n", prop
);
1405 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1409 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
1411 ALCcontext
*context
;
1415 context
= GetContextRef();
1416 if(!context
) return;
1419 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1420 for(cur
= 0;cur
< n
;cur
++)
1422 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
1425 alDeleteSources(cur
, sources
);
1426 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
1428 InitSourceParams(source
);
1430 err
= NewThunkEntry(&source
->id
);
1431 if(err
== AL_NO_ERROR
)
1432 err
= InsertUIntMapEntry(&context
->SourceMap
, source
->id
, source
);
1433 if(err
!= AL_NO_ERROR
)
1435 FreeThunkEntry(source
->id
);
1436 memset(source
, 0, sizeof(ALsource
));
1439 alDeleteSources(cur
, sources
);
1440 SET_ERROR_AND_GOTO(context
, err
, done
);
1443 sources
[cur
] = source
->id
;
1447 ALCcontext_DecRef(context
);
1451 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
1453 ALCcontext
*context
;
1454 ALbufferlistitem
*BufferList
;
1458 context
= GetContextRef();
1459 if(!context
) return;
1462 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1464 /* Check that all Sources are valid */
1465 for(i
= 0;i
< n
;i
++)
1467 if(LookupSource(context
, sources
[i
]) == NULL
)
1468 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
1470 for(i
= 0;i
< n
;i
++)
1472 ALvoice
*voice
, *voice_end
;
1474 if((Source
=RemoveSource(context
, sources
[i
])) == NULL
)
1476 FreeThunkEntry(Source
->id
);
1478 LockContext(context
);
1479 voice
= context
->Voices
;
1480 voice_end
= voice
+ context
->VoiceCount
;
1481 while(voice
!= voice_end
)
1483 ALsource
*old
= Source
;
1484 if(COMPARE_EXCHANGE(&voice
->Source
, &old
, NULL
))
1488 UnlockContext(context
);
1490 BufferList
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &Source
->queue
, NULL
);
1491 while(BufferList
!= NULL
)
1493 ALbufferlistitem
*next
= BufferList
->next
;
1494 if(BufferList
->buffer
!= NULL
)
1495 DecrementRef(&BufferList
->buffer
->ref
);
1500 for(j
= 0;j
< MAX_SENDS
;++j
)
1502 if(Source
->Send
[j
].Slot
)
1503 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
1504 Source
->Send
[j
].Slot
= NULL
;
1507 memset(Source
, 0, sizeof(*Source
));
1512 ALCcontext_DecRef(context
);
1516 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1518 ALCcontext
*context
;
1521 context
= GetContextRef();
1522 if(!context
) return AL_FALSE
;
1524 ret
= (LookupSource(context
, source
) ? AL_TRUE
: AL_FALSE
);
1526 ALCcontext_DecRef(context
);
1532 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1534 ALCcontext
*Context
;
1537 Context
= GetContextRef();
1538 if(!Context
) return;
1540 if((Source
=LookupSource(Context
, source
)) == NULL
)
1541 alSetError(Context
, AL_INVALID_NAME
);
1542 else if(!(FloatValsByProp(param
) == 1))
1543 alSetError(Context
, AL_INVALID_ENUM
);
1545 SetSourcefv(Source
, Context
, param
, &value
);
1547 ALCcontext_DecRef(Context
);
1550 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1552 ALCcontext
*Context
;
1555 Context
= GetContextRef();
1556 if(!Context
) return;
1558 if((Source
=LookupSource(Context
, source
)) == NULL
)
1559 alSetError(Context
, AL_INVALID_NAME
);
1560 else if(!(FloatValsByProp(param
) == 3))
1561 alSetError(Context
, AL_INVALID_ENUM
);
1564 ALfloat fvals
[3] = { value1
, value2
, value3
};
1565 SetSourcefv(Source
, Context
, param
, fvals
);
1568 ALCcontext_DecRef(Context
);
1571 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1573 ALCcontext
*Context
;
1576 Context
= GetContextRef();
1577 if(!Context
) return;
1579 if((Source
=LookupSource(Context
, source
)) == NULL
)
1580 alSetError(Context
, AL_INVALID_NAME
);
1582 alSetError(Context
, AL_INVALID_VALUE
);
1583 else if(!(FloatValsByProp(param
) > 0))
1584 alSetError(Context
, AL_INVALID_ENUM
);
1586 SetSourcefv(Source
, Context
, param
, values
);
1588 ALCcontext_DecRef(Context
);
1592 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1594 ALCcontext
*Context
;
1597 Context
= GetContextRef();
1598 if(!Context
) return;
1600 if((Source
=LookupSource(Context
, source
)) == NULL
)
1601 alSetError(Context
, AL_INVALID_NAME
);
1602 else if(!(DoubleValsByProp(param
) == 1))
1603 alSetError(Context
, AL_INVALID_ENUM
);
1606 ALfloat fval
= (ALfloat
)value
;
1607 SetSourcefv(Source
, Context
, param
, &fval
);
1610 ALCcontext_DecRef(Context
);
1613 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1615 ALCcontext
*Context
;
1618 Context
= GetContextRef();
1619 if(!Context
) return;
1621 if((Source
=LookupSource(Context
, source
)) == NULL
)
1622 alSetError(Context
, AL_INVALID_NAME
);
1623 else if(!(DoubleValsByProp(param
) == 3))
1624 alSetError(Context
, AL_INVALID_ENUM
);
1627 ALfloat fvals
[3] = { (ALfloat
)value1
, (ALfloat
)value2
, (ALfloat
)value3
};
1628 SetSourcefv(Source
, Context
, param
, fvals
);
1631 ALCcontext_DecRef(Context
);
1634 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1636 ALCcontext
*Context
;
1640 Context
= GetContextRef();
1641 if(!Context
) return;
1643 if((Source
=LookupSource(Context
, source
)) == NULL
)
1644 alSetError(Context
, AL_INVALID_NAME
);
1646 alSetError(Context
, AL_INVALID_VALUE
);
1647 else if(!((count
=DoubleValsByProp(param
)) > 0 && count
<= 3))
1648 alSetError(Context
, AL_INVALID_ENUM
);
1654 for(i
= 0;i
< count
;i
++)
1655 fvals
[i
] = (ALfloat
)values
[i
];
1656 SetSourcefv(Source
, Context
, param
, fvals
);
1659 ALCcontext_DecRef(Context
);
1663 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1665 ALCcontext
*Context
;
1668 Context
= GetContextRef();
1669 if(!Context
) return;
1671 if((Source
=LookupSource(Context
, source
)) == NULL
)
1672 alSetError(Context
, AL_INVALID_NAME
);
1673 else if(!(IntValsByProp(param
) == 1))
1674 alSetError(Context
, AL_INVALID_ENUM
);
1676 SetSourceiv(Source
, Context
, param
, &value
);
1678 ALCcontext_DecRef(Context
);
1681 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1683 ALCcontext
*Context
;
1686 Context
= GetContextRef();
1687 if(!Context
) return;
1689 if((Source
=LookupSource(Context
, source
)) == NULL
)
1690 alSetError(Context
, AL_INVALID_NAME
);
1691 else if(!(IntValsByProp(param
) == 3))
1692 alSetError(Context
, AL_INVALID_ENUM
);
1695 ALint ivals
[3] = { value1
, value2
, value3
};
1696 SetSourceiv(Source
, Context
, param
, ivals
);
1699 ALCcontext_DecRef(Context
);
1702 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1704 ALCcontext
*Context
;
1707 Context
= GetContextRef();
1708 if(!Context
) return;
1710 if((Source
=LookupSource(Context
, source
)) == NULL
)
1711 alSetError(Context
, AL_INVALID_NAME
);
1713 alSetError(Context
, AL_INVALID_VALUE
);
1714 else if(!(IntValsByProp(param
) > 0))
1715 alSetError(Context
, AL_INVALID_ENUM
);
1717 SetSourceiv(Source
, Context
, param
, values
);
1719 ALCcontext_DecRef(Context
);
1723 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1725 ALCcontext
*Context
;
1728 Context
= GetContextRef();
1729 if(!Context
) return;
1731 if((Source
=LookupSource(Context
, source
)) == NULL
)
1732 alSetError(Context
, AL_INVALID_NAME
);
1733 else if(!(Int64ValsByProp(param
) == 1))
1734 alSetError(Context
, AL_INVALID_ENUM
);
1736 SetSourcei64v(Source
, Context
, param
, &value
);
1738 ALCcontext_DecRef(Context
);
1741 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1743 ALCcontext
*Context
;
1746 Context
= GetContextRef();
1747 if(!Context
) return;
1749 if((Source
=LookupSource(Context
, source
)) == NULL
)
1750 alSetError(Context
, AL_INVALID_NAME
);
1751 else if(!(Int64ValsByProp(param
) == 3))
1752 alSetError(Context
, AL_INVALID_ENUM
);
1755 ALint64SOFT i64vals
[3] = { value1
, value2
, value3
};
1756 SetSourcei64v(Source
, Context
, param
, i64vals
);
1759 ALCcontext_DecRef(Context
);
1762 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1764 ALCcontext
*Context
;
1767 Context
= GetContextRef();
1768 if(!Context
) return;
1770 if((Source
=LookupSource(Context
, source
)) == NULL
)
1771 alSetError(Context
, AL_INVALID_NAME
);
1773 alSetError(Context
, AL_INVALID_VALUE
);
1774 else if(!(Int64ValsByProp(param
) > 0))
1775 alSetError(Context
, AL_INVALID_ENUM
);
1777 SetSourcei64v(Source
, Context
, param
, values
);
1779 ALCcontext_DecRef(Context
);
1783 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1785 ALCcontext
*Context
;
1788 Context
= GetContextRef();
1789 if(!Context
) return;
1791 if((Source
=LookupSource(Context
, source
)) == NULL
)
1792 alSetError(Context
, AL_INVALID_NAME
);
1794 alSetError(Context
, AL_INVALID_VALUE
);
1795 else if(!(FloatValsByProp(param
) == 1))
1796 alSetError(Context
, AL_INVALID_ENUM
);
1800 if(GetSourcedv(Source
, Context
, param
, &dval
))
1801 *value
= (ALfloat
)dval
;
1804 ALCcontext_DecRef(Context
);
1808 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1810 ALCcontext
*Context
;
1813 Context
= GetContextRef();
1814 if(!Context
) return;
1816 if((Source
=LookupSource(Context
, source
)) == NULL
)
1817 alSetError(Context
, AL_INVALID_NAME
);
1818 else if(!(value1
&& value2
&& value3
))
1819 alSetError(Context
, AL_INVALID_VALUE
);
1820 else if(!(FloatValsByProp(param
) == 3))
1821 alSetError(Context
, AL_INVALID_ENUM
);
1825 if(GetSourcedv(Source
, Context
, param
, dvals
))
1827 *value1
= (ALfloat
)dvals
[0];
1828 *value2
= (ALfloat
)dvals
[1];
1829 *value3
= (ALfloat
)dvals
[2];
1833 ALCcontext_DecRef(Context
);
1837 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1839 ALCcontext
*Context
;
1843 Context
= GetContextRef();
1844 if(!Context
) return;
1846 if((Source
=LookupSource(Context
, source
)) == NULL
)
1847 alSetError(Context
, AL_INVALID_NAME
);
1849 alSetError(Context
, AL_INVALID_VALUE
);
1850 else if(!((count
=FloatValsByProp(param
)) > 0 && count
<= 3))
1851 alSetError(Context
, AL_INVALID_ENUM
);
1855 if(GetSourcedv(Source
, Context
, param
, dvals
))
1858 for(i
= 0;i
< count
;i
++)
1859 values
[i
] = (ALfloat
)dvals
[i
];
1863 ALCcontext_DecRef(Context
);
1867 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1869 ALCcontext
*Context
;
1872 Context
= GetContextRef();
1873 if(!Context
) return;
1875 if((Source
=LookupSource(Context
, source
)) == NULL
)
1876 alSetError(Context
, AL_INVALID_NAME
);
1878 alSetError(Context
, AL_INVALID_VALUE
);
1879 else if(!(DoubleValsByProp(param
) == 1))
1880 alSetError(Context
, AL_INVALID_ENUM
);
1882 GetSourcedv(Source
, Context
, param
, value
);
1884 ALCcontext_DecRef(Context
);
1887 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1889 ALCcontext
*Context
;
1892 Context
= GetContextRef();
1893 if(!Context
) return;
1895 if((Source
=LookupSource(Context
, source
)) == NULL
)
1896 alSetError(Context
, AL_INVALID_NAME
);
1897 else if(!(value1
&& value2
&& value3
))
1898 alSetError(Context
, AL_INVALID_VALUE
);
1899 else if(!(DoubleValsByProp(param
) == 3))
1900 alSetError(Context
, AL_INVALID_ENUM
);
1904 if(GetSourcedv(Source
, Context
, param
, dvals
))
1912 ALCcontext_DecRef(Context
);
1915 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1917 ALCcontext
*Context
;
1920 Context
= GetContextRef();
1921 if(!Context
) return;
1923 if((Source
=LookupSource(Context
, source
)) == NULL
)
1924 alSetError(Context
, AL_INVALID_NAME
);
1926 alSetError(Context
, AL_INVALID_VALUE
);
1927 else if(!(DoubleValsByProp(param
) > 0))
1928 alSetError(Context
, AL_INVALID_ENUM
);
1930 GetSourcedv(Source
, Context
, param
, values
);
1932 ALCcontext_DecRef(Context
);
1936 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1938 ALCcontext
*Context
;
1941 Context
= GetContextRef();
1942 if(!Context
) return;
1944 if((Source
=LookupSource(Context
, source
)) == NULL
)
1945 alSetError(Context
, AL_INVALID_NAME
);
1947 alSetError(Context
, AL_INVALID_VALUE
);
1948 else if(!(IntValsByProp(param
) == 1))
1949 alSetError(Context
, AL_INVALID_ENUM
);
1951 GetSourceiv(Source
, Context
, param
, value
);
1953 ALCcontext_DecRef(Context
);
1957 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1959 ALCcontext
*Context
;
1962 Context
= GetContextRef();
1963 if(!Context
) return;
1965 if((Source
=LookupSource(Context
, source
)) == NULL
)
1966 alSetError(Context
, AL_INVALID_NAME
);
1967 else if(!(value1
&& value2
&& value3
))
1968 alSetError(Context
, AL_INVALID_VALUE
);
1969 else if(!(IntValsByProp(param
) == 3))
1970 alSetError(Context
, AL_INVALID_ENUM
);
1974 if(GetSourceiv(Source
, Context
, param
, ivals
))
1982 ALCcontext_DecRef(Context
);
1986 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1988 ALCcontext
*Context
;
1991 Context
= GetContextRef();
1992 if(!Context
) return;
1994 if((Source
=LookupSource(Context
, source
)) == NULL
)
1995 alSetError(Context
, AL_INVALID_NAME
);
1997 alSetError(Context
, AL_INVALID_VALUE
);
1998 else if(!(IntValsByProp(param
) > 0))
1999 alSetError(Context
, AL_INVALID_ENUM
);
2001 GetSourceiv(Source
, Context
, param
, values
);
2003 ALCcontext_DecRef(Context
);
2007 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
2009 ALCcontext
*Context
;
2012 Context
= GetContextRef();
2013 if(!Context
) return;
2015 if((Source
=LookupSource(Context
, source
)) == NULL
)
2016 alSetError(Context
, AL_INVALID_NAME
);
2018 alSetError(Context
, AL_INVALID_VALUE
);
2019 else if(!(Int64ValsByProp(param
) == 1))
2020 alSetError(Context
, AL_INVALID_ENUM
);
2022 GetSourcei64v(Source
, Context
, param
, value
);
2024 ALCcontext_DecRef(Context
);
2027 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
2029 ALCcontext
*Context
;
2032 Context
= GetContextRef();
2033 if(!Context
) return;
2035 if((Source
=LookupSource(Context
, source
)) == NULL
)
2036 alSetError(Context
, AL_INVALID_NAME
);
2037 else if(!(value1
&& value2
&& value3
))
2038 alSetError(Context
, AL_INVALID_VALUE
);
2039 else if(!(Int64ValsByProp(param
) == 3))
2040 alSetError(Context
, AL_INVALID_ENUM
);
2044 if(GetSourcei64v(Source
, Context
, param
, i64vals
))
2046 *value1
= i64vals
[0];
2047 *value2
= i64vals
[1];
2048 *value3
= i64vals
[2];
2052 ALCcontext_DecRef(Context
);
2055 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
2057 ALCcontext
*Context
;
2060 Context
= GetContextRef();
2061 if(!Context
) return;
2063 if((Source
=LookupSource(Context
, source
)) == NULL
)
2064 alSetError(Context
, AL_INVALID_NAME
);
2066 alSetError(Context
, AL_INVALID_VALUE
);
2067 else if(!(Int64ValsByProp(param
) > 0))
2068 alSetError(Context
, AL_INVALID_ENUM
);
2070 GetSourcei64v(Source
, Context
, param
, values
);
2072 ALCcontext_DecRef(Context
);
2076 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
2078 alSourcePlayv(1, &source
);
2080 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2082 ALCcontext
*context
;
2086 context
= GetContextRef();
2087 if(!context
) return;
2090 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2091 for(i
= 0;i
< n
;i
++)
2093 if(!LookupSource(context
, sources
[i
]))
2094 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2097 LockContext(context
);
2098 while(n
> context
->MaxVoices
-context
->VoiceCount
)
2100 ALvoice
*temp
= NULL
;
2103 newcount
= context
->MaxVoices
<< 1;
2105 temp
= realloc(context
->Voices
, newcount
* sizeof(context
->Voices
[0]));
2108 UnlockContext(context
);
2109 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
2111 memset(&temp
[context
->MaxVoices
], 0, (newcount
-context
->MaxVoices
) * sizeof(temp
[0]));
2113 context
->Voices
= temp
;
2114 context
->MaxVoices
= newcount
;
2117 for(i
= 0;i
< n
;i
++)
2119 source
= LookupSource(context
, sources
[i
]);
2120 if(context
->DeferUpdates
) source
->new_state
= AL_PLAYING
;
2121 else SetSourceState(source
, context
, AL_PLAYING
);
2123 UnlockContext(context
);
2126 ALCcontext_DecRef(context
);
2129 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2131 alSourcePausev(1, &source
);
2133 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2135 ALCcontext
*context
;
2139 context
= GetContextRef();
2140 if(!context
) return;
2143 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2144 for(i
= 0;i
< n
;i
++)
2146 if(!LookupSource(context
, sources
[i
]))
2147 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2150 LockContext(context
);
2151 for(i
= 0;i
< n
;i
++)
2153 source
= LookupSource(context
, sources
[i
]);
2154 if(context
->DeferUpdates
) source
->new_state
= AL_PAUSED
;
2155 else SetSourceState(source
, context
, AL_PAUSED
);
2157 UnlockContext(context
);
2160 ALCcontext_DecRef(context
);
2163 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2165 alSourceStopv(1, &source
);
2167 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2169 ALCcontext
*context
;
2173 context
= GetContextRef();
2174 if(!context
) return;
2177 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2178 for(i
= 0;i
< n
;i
++)
2180 if(!LookupSource(context
, sources
[i
]))
2181 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2184 LockContext(context
);
2185 for(i
= 0;i
< n
;i
++)
2187 source
= LookupSource(context
, sources
[i
]);
2188 source
->new_state
= AL_NONE
;
2189 SetSourceState(source
, context
, AL_STOPPED
);
2191 UnlockContext(context
);
2194 ALCcontext_DecRef(context
);
2197 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2199 alSourceRewindv(1, &source
);
2201 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2203 ALCcontext
*context
;
2207 context
= GetContextRef();
2208 if(!context
) return;
2211 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2212 for(i
= 0;i
< n
;i
++)
2214 if(!LookupSource(context
, sources
[i
]))
2215 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2218 LockContext(context
);
2219 for(i
= 0;i
< n
;i
++)
2221 source
= LookupSource(context
, sources
[i
]);
2222 source
->new_state
= AL_NONE
;
2223 SetSourceState(source
, context
, AL_INITIAL
);
2225 UnlockContext(context
);
2228 ALCcontext_DecRef(context
);
2232 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint src
, ALsizei nb
, const ALuint
*buffers
)
2235 ALCcontext
*context
;
2238 ALbufferlistitem
*BufferListStart
;
2239 ALbufferlistitem
*BufferList
;
2240 ALbuffer
*BufferFmt
= NULL
;
2245 context
= GetContextRef();
2246 if(!context
) return;
2248 device
= context
->Device
;
2251 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2252 if((source
=LookupSource(context
, src
)) == NULL
)
2253 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2255 WriteLock(&source
->queue_lock
);
2256 if(source
->SourceType
== AL_STATIC
)
2258 WriteUnlock(&source
->queue_lock
);
2259 /* Can't queue on a Static Source */
2260 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
2263 /* Check for a valid Buffer, for its frequency and format */
2264 BufferList
= ATOMIC_LOAD(&source
->queue
);
2267 if(BufferList
->buffer
)
2269 BufferFmt
= BufferList
->buffer
;
2272 BufferList
= BufferList
->next
;
2275 BufferListStart
= NULL
;
2277 for(i
= 0;i
< nb
;i
++)
2279 ALbuffer
*buffer
= NULL
;
2280 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2282 WriteUnlock(&source
->queue_lock
);
2283 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, buffer_error
);
2286 if(!BufferListStart
)
2288 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2289 BufferListStart
->buffer
= buffer
;
2290 BufferListStart
->next
= NULL
;
2291 BufferListStart
->prev
= NULL
;
2292 BufferList
= BufferListStart
;
2296 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2297 BufferList
->next
->buffer
= buffer
;
2298 BufferList
->next
->next
= NULL
;
2299 BufferList
->next
->prev
= BufferList
;
2300 BufferList
= BufferList
->next
;
2302 if(!buffer
) continue;
2304 /* Hold a read lock on each buffer being queued while checking all
2305 * provided buffers. This is done so other threads don't see an extra
2306 * reference on some buffers if this operation ends up failing. */
2307 ReadLock(&buffer
->lock
);
2308 IncrementRef(&buffer
->ref
);
2310 if(BufferFmt
== NULL
)
2314 source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2315 source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2317 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2318 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2319 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2321 WriteUnlock(&source
->queue_lock
);
2322 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, buffer_error
);
2325 /* A buffer failed (invalid ID or format), so unlock and release
2326 * each buffer we had. */
2327 while(BufferList
!= NULL
)
2329 ALbufferlistitem
*prev
= BufferList
->prev
;
2330 if((buffer
=BufferList
->buffer
) != NULL
)
2332 DecrementRef(&buffer
->ref
);
2333 ReadUnlock(&buffer
->lock
);
2341 /* All buffers good, unlock them now. */
2342 while(BufferList
!= NULL
)
2344 ALbuffer
*buffer
= BufferList
->buffer
;
2345 if(buffer
) ReadUnlock(&buffer
->lock
);
2346 BufferList
= BufferList
->prev
;
2349 /* Source is now streaming */
2350 source
->SourceType
= AL_STREAMING
;
2353 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->queue
, &BufferList
, BufferListStart
))
2355 /* Queue head is not NULL, append to the end of the queue */
2356 while(BufferList
->next
!= NULL
)
2357 BufferList
= BufferList
->next
;
2359 BufferListStart
->prev
= BufferList
;
2360 BufferList
->next
= BufferListStart
;
2363 ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem
*, &source
->current_buffer
, &BufferList
, BufferListStart
);
2364 WriteUnlock(&source
->queue_lock
);
2367 ALCcontext_DecRef(context
);
2370 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint src
, ALsizei nb
, ALuint
*buffers
)
2372 ALCcontext
*context
;
2374 ALbufferlistitem
*NewHead
;
2375 ALbufferlistitem
*OldHead
;
2376 ALbufferlistitem
*Current
;
2382 context
= GetContextRef();
2383 if(!context
) return;
2386 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2388 if((source
=LookupSource(context
, src
)) == NULL
)
2389 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2391 WriteLock(&source
->queue_lock
);
2392 /* Find the new buffer queue head */
2393 NewHead
= ATOMIC_LOAD(&source
->queue
);
2394 Current
= ATOMIC_LOAD(&source
->current_buffer
);
2395 for(i
= 0;i
< nb
&& NewHead
;i
++)
2397 if(NewHead
== Current
)
2399 NewHead
= NewHead
->next
;
2401 if(source
->Looping
|| source
->SourceType
!= AL_STREAMING
|| i
!= nb
)
2403 WriteUnlock(&source
->queue_lock
);
2404 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2405 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2408 /* Swap it, and cut the new head from the old. */
2409 OldHead
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &source
->queue
, NewHead
);
2412 ALCdevice
*device
= context
->Device
;
2413 ALbufferlistitem
*OldTail
= NewHead
->prev
;
2416 /* Cut the new head's link back to the old body. The mixer is robust
2417 * enough to handle the link back going away. Once the active mix (if
2418 * any) is complete, it's safe to finish cutting the old tail from the
2420 NewHead
->prev
= NULL
;
2421 if(((count
=ReadRef(&device
->MixCount
))&1) != 0)
2423 while(count
== ReadRef(&device
->MixCount
))
2426 OldTail
->next
= NULL
;
2428 WriteUnlock(&source
->queue_lock
);
2430 while(OldHead
!= NULL
)
2432 ALbufferlistitem
*next
= OldHead
->next
;
2433 ALbuffer
*buffer
= OldHead
->buffer
;
2439 *(buffers
++) = buffer
->id
;
2440 DecrementRef(&buffer
->ref
);
2448 ALCcontext_DecRef(context
);
2452 static ALvoid
InitSourceParams(ALsource
*Source
)
2456 RWLockInit(&Source
->queue_lock
);
2458 Source
->InnerAngle
= 360.0f
;
2459 Source
->OuterAngle
= 360.0f
;
2460 Source
->Pitch
= 1.0f
;
2461 aluVectorSet(&Source
->Position
, 0.0f
, 0.0f
, 0.0f
, 1.0f
);
2462 aluVectorSet(&Source
->Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2463 aluVectorSet(&Source
->Direction
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2464 Source
->Orientation
[0][0] = 0.0f
;
2465 Source
->Orientation
[0][1] = 0.0f
;
2466 Source
->Orientation
[0][2] = -1.0f
;
2467 Source
->Orientation
[1][0] = 0.0f
;
2468 Source
->Orientation
[1][1] = 1.0f
;
2469 Source
->Orientation
[1][2] = 0.0f
;
2470 Source
->RefDistance
= 1.0f
;
2471 Source
->MaxDistance
= FLT_MAX
;
2472 Source
->RollOffFactor
= 1.0f
;
2473 Source
->Looping
= AL_FALSE
;
2474 Source
->Gain
= 1.0f
;
2475 Source
->MinGain
= 0.0f
;
2476 Source
->MaxGain
= 1.0f
;
2477 Source
->OuterGain
= 0.0f
;
2478 Source
->OuterGainHF
= 1.0f
;
2480 Source
->DryGainHFAuto
= AL_TRUE
;
2481 Source
->WetGainAuto
= AL_TRUE
;
2482 Source
->WetGainHFAuto
= AL_TRUE
;
2483 Source
->AirAbsorptionFactor
= 0.0f
;
2484 Source
->RoomRolloffFactor
= 0.0f
;
2485 Source
->DopplerFactor
= 1.0f
;
2486 Source
->DirectChannels
= AL_FALSE
;
2488 Source
->Radius
= 0.0f
;
2490 Source
->DistanceModel
= DefaultDistanceModel
;
2492 Source
->Resampler
= DefaultResampler
;
2494 Source
->state
= AL_INITIAL
;
2495 Source
->new_state
= AL_NONE
;
2496 Source
->SourceType
= AL_UNDETERMINED
;
2497 Source
->Offset
= -1.0;
2499 ATOMIC_INIT(&Source
->queue
, NULL
);
2500 ATOMIC_INIT(&Source
->current_buffer
, NULL
);
2502 Source
->Direct
.Gain
= 1.0f
;
2503 Source
->Direct
.GainHF
= 1.0f
;
2504 Source
->Direct
.HFReference
= LOWPASSFREQREF
;
2505 Source
->Direct
.GainLF
= 1.0f
;
2506 Source
->Direct
.LFReference
= HIGHPASSFREQREF
;
2507 for(i
= 0;i
< MAX_SENDS
;i
++)
2509 Source
->Send
[i
].Gain
= 1.0f
;
2510 Source
->Send
[i
].GainHF
= 1.0f
;
2511 Source
->Send
[i
].HFReference
= LOWPASSFREQREF
;
2512 Source
->Send
[i
].GainLF
= 1.0f
;
2513 Source
->Send
[i
].LFReference
= HIGHPASSFREQREF
;
2516 ATOMIC_INIT(&Source
->NeedsUpdate
, AL_TRUE
);
2522 * Sets the source's new play state given its current state.
2524 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2526 ReadLock(&Source
->queue_lock
);
2527 if(state
== AL_PLAYING
)
2529 ALCdevice
*device
= Context
->Device
;
2530 ALbufferlistitem
*BufferList
;
2531 ALvoice
*voice
= NULL
;
2534 /* Check that there is a queue containing at least one valid, non zero
2536 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2540 if((buffer
=BufferList
->buffer
) != NULL
&& buffer
->SampleLen
> 0)
2542 BufferList
= BufferList
->next
;
2545 if(Source
->state
!= AL_PAUSED
)
2547 Source
->state
= AL_PLAYING
;
2548 Source
->position
= 0;
2549 Source
->position_fraction
= 0;
2550 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
2553 Source
->state
= AL_PLAYING
;
2555 // Check if an Offset has been set
2556 if(Source
->Offset
>= 0.0)
2557 ApplyOffset(Source
);
2559 /* If there's nothing to play, or device is disconnected, go right to
2561 if(!BufferList
|| !device
->Connected
)
2564 /* Make sure this source isn't already active, while looking for an
2565 * unused active source slot to put it in. */
2566 for(i
= 0;i
< Context
->VoiceCount
;i
++)
2568 ALsource
*old
= Source
;
2569 if(COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, NULL
))
2573 voice
= &Context
->Voices
[i
];
2574 voice
->Source
= Source
;
2579 if(voice
== NULL
&& COMPARE_EXCHANGE(&Context
->Voices
[i
].Source
, &old
, Source
))
2580 voice
= &Context
->Voices
[i
];
2584 voice
= &Context
->Voices
[Context
->VoiceCount
++];
2585 voice
->Source
= Source
;
2588 voice
->Direct
.Moving
= AL_FALSE
;
2589 voice
->Direct
.Counter
= 0;
2590 for(i
= 0;i
< MAX_INPUT_CHANNELS
;i
++)
2593 for(j
= 0;j
< HRTF_HISTORY_LENGTH
;j
++)
2594 voice
->Direct
.Hrtf
.State
[i
].History
[j
] = 0.0f
;
2595 for(j
= 0;j
< HRIR_LENGTH
;j
++)
2597 voice
->Direct
.Hrtf
.State
[i
].Values
[j
][0] = 0.0f
;
2598 voice
->Direct
.Hrtf
.State
[i
].Values
[j
][1] = 0.0f
;
2601 for(i
= 0;i
< (ALsizei
)device
->NumAuxSends
;i
++)
2603 voice
->Send
[i
].Moving
= AL_FALSE
;
2604 voice
->Send
[i
].Counter
= 0;
2607 if(BufferList
->buffer
->FmtChannels
== FmtMono
)
2608 voice
->Update
= CalcSourceParams
;
2610 voice
->Update
= CalcNonAttnSourceParams
;
2612 ATOMIC_STORE(&Source
->NeedsUpdate
, AL_TRUE
);
2614 else if(state
== AL_PAUSED
)
2616 if(Source
->state
== AL_PLAYING
)
2617 Source
->state
= AL_PAUSED
;
2619 else if(state
== AL_STOPPED
)
2622 if(Source
->state
!= AL_INITIAL
)
2624 Source
->state
= AL_STOPPED
;
2625 ATOMIC_STORE(&Source
->current_buffer
, NULL
);
2627 Source
->Offset
= -1.0;
2629 else if(state
== AL_INITIAL
)
2631 if(Source
->state
!= AL_INITIAL
)
2633 Source
->state
= AL_INITIAL
;
2634 Source
->position
= 0;
2635 Source
->position_fraction
= 0;
2636 ATOMIC_STORE(&Source
->current_buffer
, ATOMIC_LOAD(&Source
->queue
));
2638 Source
->Offset
= -1.0;
2640 ReadUnlock(&Source
->queue_lock
);
2645 * Gets the current read offset for the given Source, in 32.32 fixed-point
2646 * samples. The offset is relative to the start of the queue (not the start of
2647 * the current buffer).
2649 static ALint64
GetSourceOffset(const ALsource
*Source
)
2651 const ALbufferlistitem
*BufferList
;
2652 const ALbufferlistitem
*Current
;
2655 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2658 /* NOTE: This is the offset into the *current* buffer, so add the length of
2659 * any played buffers */
2660 readPos
= (ALuint64
)Source
->position
<< 32;
2661 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2662 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2663 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2664 while(BufferList
&& BufferList
!= Current
)
2666 if(BufferList
->buffer
)
2667 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2668 BufferList
= BufferList
->next
;
2671 return (ALint64
)minu64(readPos
, U64(0x7fffffffffffffff));
2674 /* GetSourceSecOffset
2676 * Gets the current read offset for the given Source, in seconds. The offset is
2677 * relative to the start of the queue (not the start of the current buffer).
2679 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2681 const ALbufferlistitem
*BufferList
;
2682 const ALbufferlistitem
*Current
;
2683 const ALbuffer
*Buffer
= NULL
;
2686 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2689 /* NOTE: This is the offset into the *current* buffer, so add the length of
2690 * any played buffers */
2691 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2692 readPos
|= (ALuint64
)Source
->position_fraction
;
2693 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2694 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2695 while(BufferList
&& BufferList
!= Current
)
2697 const ALbuffer
*buffer
= BufferList
->buffer
;
2700 if(!Buffer
) Buffer
= buffer
;
2701 readPos
+= (ALuint64
)buffer
->SampleLen
<< FRACTIONBITS
;
2703 BufferList
= BufferList
->next
;
2706 while(BufferList
&& !Buffer
)
2708 Buffer
= BufferList
->buffer
;
2709 BufferList
= BufferList
->next
;
2711 assert(Buffer
!= NULL
);
2713 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2718 * Gets the current read and write offsets for the given Source, in the
2719 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2720 * the start of the queue (not the start of the current buffer).
2722 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2724 const ALbufferlistitem
*BufferList
;
2725 const ALbufferlistitem
*Current
;
2726 const ALbuffer
*Buffer
= NULL
;
2727 ALboolean readFin
= AL_FALSE
;
2728 ALuint readPos
, writePos
;
2729 ALuint totalBufferLen
;
2731 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2738 if(updateLen
> 0.0 && updateLen
< 0.015)
2741 /* NOTE: This is the offset into the *current* buffer, so add the length of
2742 * any played buffers */
2744 readPos
= Source
->position
;
2745 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2746 Current
= ATOMIC_LOAD(&Source
->current_buffer
);
2747 while(BufferList
!= NULL
)
2749 const ALbuffer
*buffer
;
2750 readFin
= readFin
|| (BufferList
== Current
);
2751 if((buffer
=BufferList
->buffer
) != NULL
)
2753 if(!Buffer
) Buffer
= buffer
;
2754 totalBufferLen
+= buffer
->SampleLen
;
2755 if(!readFin
) readPos
+= buffer
->SampleLen
;
2757 BufferList
= BufferList
->next
;
2759 assert(Buffer
!= NULL
);
2761 if(Source
->state
== AL_PLAYING
)
2762 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2768 readPos
%= totalBufferLen
;
2769 writePos
%= totalBufferLen
;
2773 /* Wrap positions back to 0 */
2774 if(readPos
>= totalBufferLen
)
2776 if(writePos
>= totalBufferLen
)
2783 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2784 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2787 case AL_SAMPLE_OFFSET
:
2788 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2789 offset
[0] = (ALdouble
)readPos
;
2790 offset
[1] = (ALdouble
)writePos
;
2793 case AL_BYTE_OFFSET
:
2794 case AL_BYTE_RW_OFFSETS_SOFT
:
2795 if(Buffer
->OriginalType
== UserFmtIMA4
)
2797 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
2798 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2799 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2801 /* Round down to nearest ADPCM block */
2802 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2803 if(Source
->state
!= AL_PLAYING
)
2804 offset
[1] = offset
[0];
2807 /* Round up to nearest ADPCM block */
2808 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2809 FrameBlockSize
* BlockSize
);
2812 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
2814 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
2815 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2816 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2818 /* Round down to nearest ADPCM block */
2819 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2820 if(Source
->state
!= AL_PLAYING
)
2821 offset
[1] = offset
[0];
2824 /* Round up to nearest ADPCM block */
2825 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2826 FrameBlockSize
* BlockSize
);
2831 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2832 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2833 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2842 * Apply the stored playback offset to the Source. This function will update
2843 * the number of buffers "played" given the stored offset.
2845 ALboolean
ApplyOffset(ALsource
*Source
)
2847 ALbufferlistitem
*BufferList
;
2848 const ALbuffer
*Buffer
;
2849 ALint bufferLen
, totalBufferLen
;
2852 /* Get sample frame offset */
2853 offset
= GetSampleOffset(Source
);
2858 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2859 while(BufferList
&& totalBufferLen
<= offset
)
2861 Buffer
= BufferList
->buffer
;
2862 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2864 if(bufferLen
> offset
-totalBufferLen
)
2866 /* Offset is in this buffer */
2867 ATOMIC_STORE(&Source
->current_buffer
, BufferList
);
2869 Source
->position
= offset
- totalBufferLen
;
2870 Source
->position_fraction
= 0;
2874 totalBufferLen
+= bufferLen
;
2876 BufferList
= BufferList
->next
;
2879 /* Offset is out of range of the queue */
2886 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2887 * Second offset supplied by the application). This takes into account the fact
2888 * that the buffer format may have been modifed since.
2890 static ALint
GetSampleOffset(ALsource
*Source
)
2892 const ALbuffer
*Buffer
= NULL
;
2893 const ALbufferlistitem
*BufferList
;
2896 /* Find the first valid Buffer in the Queue */
2897 BufferList
= ATOMIC_LOAD(&Source
->queue
);
2900 if(BufferList
->buffer
)
2902 Buffer
= BufferList
->buffer
;
2905 BufferList
= BufferList
->next
;
2910 Source
->Offset
= -1.0;
2914 switch(Source
->OffsetType
)
2916 case AL_BYTE_OFFSET
:
2917 /* Determine the ByteOffset (and ensure it is block aligned) */
2918 Offset
= (ALint
)Source
->Offset
;
2919 if(Buffer
->OriginalType
== UserFmtIMA4
)
2921 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
2922 Offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2923 Offset
*= Buffer
->OriginalAlign
;
2925 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
2927 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
2928 Offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2929 Offset
*= Buffer
->OriginalAlign
;
2932 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2935 case AL_SAMPLE_OFFSET
:
2936 Offset
= (ALint
)Source
->Offset
;
2940 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2943 Source
->Offset
= -1.0;
2951 * Destroys all sources in the source map.
2953 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2955 ALbufferlistitem
*item
;
2958 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2960 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2961 Context
->SourceMap
.array
[pos
].value
= NULL
;
2963 item
= ATOMIC_EXCHANGE(ALbufferlistitem
*, &temp
->queue
, NULL
);
2966 ALbufferlistitem
*next
= item
->next
;
2967 if(item
->buffer
!= NULL
)
2968 DecrementRef(&item
->buffer
->ref
);
2973 for(j
= 0;j
< MAX_SENDS
;++j
)
2975 if(temp
->Send
[j
].Slot
)
2976 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2977 temp
->Send
[j
].Slot
= NULL
;
2980 FreeThunkEntry(temp
->id
);
2981 memset(temp
, 0, sizeof(*temp
));