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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
34 #include "alAuxEffectSlot.h"
37 enum Resampler DefaultResampler
= LinearResampler
;
38 const ALsizei ResamplerPadding
[ResamplerMax
] = {
43 const ALsizei ResamplerPrePadding
[ResamplerMax
] = {
50 extern inline struct ALsource
*LookupSource(ALCcontext
*context
, ALuint id
);
51 extern inline struct ALsource
*RemoveSource(ALCcontext
*context
, ALuint id
);
53 static ALvoid
InitSourceParams(ALsource
*Source
);
54 static ALint64
GetSourceOffset(const ALsource
*Source
);
55 static ALdouble
GetSourceSecOffset(const ALsource
*Source
);
56 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offsets
, ALdouble updateLen
);
57 static ALint
GetSampleOffset(ALsource
*Source
);
59 typedef enum SrcFloatProp
{
62 sfMinGain
= AL_MIN_GAIN
,
63 sfMaxGain
= AL_MAX_GAIN
,
64 sfMaxDistance
= AL_MAX_DISTANCE
,
65 sfRolloffFactor
= AL_ROLLOFF_FACTOR
,
66 sfDopplerFactor
= AL_DOPPLER_FACTOR
,
67 sfConeOuterGain
= AL_CONE_OUTER_GAIN
,
68 sfSecOffset
= AL_SEC_OFFSET
,
69 sfSampleOffset
= AL_SAMPLE_OFFSET
,
70 sfByteOffset
= AL_BYTE_OFFSET
,
71 sfConeInnerAngle
= AL_CONE_INNER_ANGLE
,
72 sfConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
73 sfRefDistance
= AL_REFERENCE_DISTANCE
,
75 sfPosition
= AL_POSITION
,
76 sfVelocity
= AL_VELOCITY
,
77 sfDirection
= AL_DIRECTION
,
79 sfSourceRelative
= AL_SOURCE_RELATIVE
,
80 sfLooping
= AL_LOOPING
,
82 sfSourceState
= AL_SOURCE_STATE
,
83 sfBuffersQueued
= AL_BUFFERS_QUEUED
,
84 sfBuffersProcessed
= AL_BUFFERS_PROCESSED
,
85 sfSourceType
= AL_SOURCE_TYPE
,
88 sfConeOuterGainHF
= AL_CONE_OUTER_GAINHF
,
89 sfAirAbsorptionFactor
= AL_AIR_ABSORPTION_FACTOR
,
90 sfRoomRolloffFactor
= AL_ROOM_ROLLOFF_FACTOR
,
91 sfDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
92 sfAuxSendFilterGainAuto
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
93 sfAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
95 /* AL_SOFT_direct_channels */
96 sfDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
98 /* AL_EXT_source_distance_model */
99 sfDistanceModel
= AL_DISTANCE_MODEL
,
101 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
102 sfSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
103 sfByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
105 /* AL_SOFT_source_latency */
106 sfSecOffsetLatencySOFT
= AL_SEC_OFFSET_LATENCY_SOFT
,
109 typedef enum SrcIntProp
{
110 siMaxDistance
= AL_MAX_DISTANCE
,
111 siRolloffFactor
= AL_ROLLOFF_FACTOR
,
112 siRefDistance
= AL_REFERENCE_DISTANCE
,
113 siSourceRelative
= AL_SOURCE_RELATIVE
,
114 siConeInnerAngle
= AL_CONE_INNER_ANGLE
,
115 siConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
116 siLooping
= AL_LOOPING
,
117 siBuffer
= AL_BUFFER
,
118 siSourceState
= AL_SOURCE_STATE
,
119 siBuffersQueued
= AL_BUFFERS_QUEUED
,
120 siBuffersProcessed
= AL_BUFFERS_PROCESSED
,
121 siSourceType
= AL_SOURCE_TYPE
,
122 siSecOffset
= AL_SEC_OFFSET
,
123 siSampleOffset
= AL_SAMPLE_OFFSET
,
124 siByteOffset
= AL_BYTE_OFFSET
,
125 siDopplerFactor
= AL_DOPPLER_FACTOR
,
126 siPosition
= AL_POSITION
,
127 siVelocity
= AL_VELOCITY
,
128 siDirection
= AL_DIRECTION
,
131 siDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
132 siAuxSendFilterGainAutio
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
133 siAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
134 siDirectFilter
= AL_DIRECT_FILTER
,
135 siAuxSendFilter
= AL_AUXILIARY_SEND_FILTER
,
137 /* AL_SOFT_direct_channels */
138 siDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
140 /* AL_EXT_source_distance_model */
141 siDistanceModel
= AL_DISTANCE_MODEL
,
143 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
144 siSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
145 siByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
147 /* AL_SOFT_source_latency */
148 siSampleOffsetLatencySOFT
= AL_SAMPLE_OFFSET_LATENCY_SOFT
,
151 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
);
152 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
);
153 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
);
155 static ALboolean
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
);
156 static ALboolean
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
);
157 static ALboolean
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
);
159 static ALint
FloatValsByProp(ALenum prop
)
161 if(prop
!= (ALenum
)((SrcFloatProp
)prop
))
163 switch((SrcFloatProp
)prop
)
170 case sfRolloffFactor
:
171 case sfDopplerFactor
:
172 case sfConeOuterGain
:
176 case sfConeInnerAngle
:
177 case sfConeOuterAngle
:
179 case sfConeOuterGainHF
:
180 case sfAirAbsorptionFactor
:
181 case sfRoomRolloffFactor
:
182 case sfDirectFilterGainHFAuto
:
183 case sfAuxSendFilterGainAuto
:
184 case sfAuxSendFilterGainHFAuto
:
185 case sfDirectChannelsSOFT
:
186 case sfDistanceModel
:
187 case sfSourceRelative
:
191 case sfBuffersQueued
:
192 case sfBuffersProcessed
:
196 case sfSampleRWOffsetsSOFT
:
197 case sfByteRWOffsetsSOFT
:
205 case sfSecOffsetLatencySOFT
:
206 break; /* Double only */
210 static ALint
DoubleValsByProp(ALenum prop
)
212 if(prop
!= (ALenum
)((SrcFloatProp
)prop
))
214 switch((SrcFloatProp
)prop
)
221 case sfRolloffFactor
:
222 case sfDopplerFactor
:
223 case sfConeOuterGain
:
227 case sfConeInnerAngle
:
228 case sfConeOuterAngle
:
230 case sfConeOuterGainHF
:
231 case sfAirAbsorptionFactor
:
232 case sfRoomRolloffFactor
:
233 case sfDirectFilterGainHFAuto
:
234 case sfAuxSendFilterGainAuto
:
235 case sfAuxSendFilterGainHFAuto
:
236 case sfDirectChannelsSOFT
:
237 case sfDistanceModel
:
238 case sfSourceRelative
:
242 case sfBuffersQueued
:
243 case sfBuffersProcessed
:
247 case sfSampleRWOffsetsSOFT
:
248 case sfByteRWOffsetsSOFT
:
249 case sfSecOffsetLatencySOFT
:
260 static ALint
IntValsByProp(ALenum prop
)
262 if(prop
!= (ALenum
)((SrcIntProp
)prop
))
264 switch((SrcIntProp
)prop
)
267 case siRolloffFactor
:
269 case siSourceRelative
:
270 case siConeInnerAngle
:
271 case siConeOuterAngle
:
275 case siBuffersQueued
:
276 case siBuffersProcessed
:
281 case siDopplerFactor
:
282 case siDirectFilterGainHFAuto
:
283 case siAuxSendFilterGainAutio
:
284 case siAuxSendFilterGainHFAuto
:
286 case siDirectChannelsSOFT
:
287 case siDistanceModel
:
290 case siSampleRWOffsetsSOFT
:
291 case siByteRWOffsetsSOFT
:
297 case siAuxSendFilter
:
300 case siSampleOffsetLatencySOFT
:
301 break; /* i64 only */
305 static ALint
Int64ValsByProp(ALenum prop
)
307 if(prop
!= (ALenum
)((SrcIntProp
)prop
))
309 switch((SrcIntProp
)prop
)
312 case siRolloffFactor
:
314 case siSourceRelative
:
315 case siConeInnerAngle
:
316 case siConeOuterAngle
:
320 case siBuffersQueued
:
321 case siBuffersProcessed
:
326 case siDopplerFactor
:
327 case siDirectFilterGainHFAuto
:
328 case siAuxSendFilterGainAutio
:
329 case siAuxSendFilterGainHFAuto
:
331 case siDirectChannelsSOFT
:
332 case siDistanceModel
:
335 case siSampleRWOffsetsSOFT
:
336 case siByteRWOffsetsSOFT
:
337 case siSampleOffsetLatencySOFT
:
343 case siAuxSendFilter
:
350 #define CHECKVAL(x) do { \
352 SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); \
355 static ALboolean
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
)
362 CHECKVAL(*values
>= 0.0f
);
364 Source
->Pitch
= *values
;
365 Source
->NeedsUpdate
= AL_TRUE
;
368 case AL_CONE_INNER_ANGLE
:
369 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
371 Source
->InnerAngle
= *values
;
372 Source
->NeedsUpdate
= AL_TRUE
;
375 case AL_CONE_OUTER_ANGLE
:
376 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
378 Source
->OuterAngle
= *values
;
379 Source
->NeedsUpdate
= AL_TRUE
;
383 CHECKVAL(*values
>= 0.0f
);
385 Source
->Gain
= *values
;
386 Source
->NeedsUpdate
= AL_TRUE
;
389 case AL_MAX_DISTANCE
:
390 CHECKVAL(*values
>= 0.0f
);
392 Source
->MaxDistance
= *values
;
393 Source
->NeedsUpdate
= AL_TRUE
;
396 case AL_ROLLOFF_FACTOR
:
397 CHECKVAL(*values
>= 0.0f
);
399 Source
->RollOffFactor
= *values
;
400 Source
->NeedsUpdate
= AL_TRUE
;
403 case AL_REFERENCE_DISTANCE
:
404 CHECKVAL(*values
>= 0.0f
);
406 Source
->RefDistance
= *values
;
407 Source
->NeedsUpdate
= AL_TRUE
;
411 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
413 Source
->MinGain
= *values
;
414 Source
->NeedsUpdate
= AL_TRUE
;
418 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
420 Source
->MaxGain
= *values
;
421 Source
->NeedsUpdate
= AL_TRUE
;
424 case AL_CONE_OUTER_GAIN
:
425 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
427 Source
->OuterGain
= *values
;
428 Source
->NeedsUpdate
= AL_TRUE
;
431 case AL_CONE_OUTER_GAINHF
:
432 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
434 Source
->OuterGainHF
= *values
;
435 Source
->NeedsUpdate
= AL_TRUE
;
438 case AL_AIR_ABSORPTION_FACTOR
:
439 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
441 Source
->AirAbsorptionFactor
= *values
;
442 Source
->NeedsUpdate
= AL_TRUE
;
445 case AL_ROOM_ROLLOFF_FACTOR
:
446 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
448 Source
->RoomRolloffFactor
= *values
;
449 Source
->NeedsUpdate
= AL_TRUE
;
452 case AL_DOPPLER_FACTOR
:
453 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
455 Source
->DopplerFactor
= *values
;
456 Source
->NeedsUpdate
= AL_TRUE
;
460 case AL_SAMPLE_OFFSET
:
462 CHECKVAL(*values
>= 0.0f
);
464 LockContext(Context
);
465 Source
->OffsetType
= prop
;
466 Source
->Offset
= *values
;
468 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
469 !Context
->DeferUpdates
)
471 if(ApplyOffset(Source
) == AL_FALSE
)
473 UnlockContext(Context
);
474 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
477 UnlockContext(Context
);
481 case AL_SEC_OFFSET_LATENCY_SOFT
:
483 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
487 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
489 LockContext(Context
);
490 Source
->Position
[0] = values
[0];
491 Source
->Position
[1] = values
[1];
492 Source
->Position
[2] = values
[2];
493 UnlockContext(Context
);
494 Source
->NeedsUpdate
= AL_TRUE
;
498 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
500 LockContext(Context
);
501 Source
->Velocity
[0] = values
[0];
502 Source
->Velocity
[1] = values
[1];
503 Source
->Velocity
[2] = values
[2];
504 UnlockContext(Context
);
505 Source
->NeedsUpdate
= AL_TRUE
;
509 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
511 LockContext(Context
);
512 Source
->Orientation
[0] = values
[0];
513 Source
->Orientation
[1] = values
[1];
514 Source
->Orientation
[2] = values
[2];
515 UnlockContext(Context
);
516 Source
->NeedsUpdate
= AL_TRUE
;
520 case sfSampleRWOffsetsSOFT
:
521 case sfByteRWOffsetsSOFT
:
522 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
525 case sfSourceRelative
:
529 case sfDistanceModel
:
530 case sfDirectFilterGainHFAuto
:
531 case sfAuxSendFilterGainAuto
:
532 case sfAuxSendFilterGainHFAuto
:
533 case sfDirectChannelsSOFT
:
534 ival
= (ALint
)values
[0];
535 return SetSourceiv(Source
, Context
, (SrcIntProp
)prop
, &ival
);
538 case sfBuffersQueued
:
539 case sfBuffersProcessed
:
540 ival
= (ALint
)((ALuint
)values
[0]);
541 return SetSourceiv(Source
, Context
, (SrcIntProp
)prop
, &ival
);
544 ERR("Unexpected property: 0x%04x\n", prop
);
545 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
548 static ALboolean
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
)
550 ALCdevice
*device
= Context
->Device
;
551 ALbuffer
*buffer
= NULL
;
552 ALfilter
*filter
= NULL
;
553 ALeffectslot
*slot
= NULL
;
554 ALbufferlistitem
*oldlist
;
559 case AL_SOURCE_RELATIVE
:
560 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
562 Source
->HeadRelative
= (ALboolean
)*values
;
563 Source
->NeedsUpdate
= AL_TRUE
;
567 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
569 Source
->Looping
= (ALboolean
)*values
;
573 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
575 LockContext(Context
);
576 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
578 UnlockContext(Context
);
579 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
582 Source
->BuffersInQueue
= 0;
583 Source
->BuffersPlayed
= 0;
587 ALbufferlistitem
*BufferListItem
;
589 /* Source is now Static */
590 Source
->SourceType
= AL_STATIC
;
592 /* Add the selected buffer to a one-item queue */
593 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
594 BufferListItem
->buffer
= buffer
;
595 BufferListItem
->next
= NULL
;
596 BufferListItem
->prev
= NULL
;
597 IncrementRef(&buffer
->ref
);
599 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, BufferListItem
);
600 Source
->BuffersInQueue
= 1;
602 ReadLock(&buffer
->lock
);
603 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
604 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
605 ReadUnlock(&buffer
->lock
);
609 /* Source is now Undetermined */
610 Source
->SourceType
= AL_UNDETERMINED
;
611 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, NULL
);
614 /* Delete all elements in the previous queue */
615 while(oldlist
!= NULL
)
617 ALbufferlistitem
*temp
= oldlist
;
618 oldlist
= temp
->next
;
621 DecrementRef(&temp
->buffer
->ref
);
624 UnlockContext(Context
);
629 case siBuffersQueued
:
630 case siBuffersProcessed
:
632 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
635 case AL_SAMPLE_OFFSET
:
637 CHECKVAL(*values
>= 0);
639 LockContext(Context
);
640 Source
->OffsetType
= prop
;
641 Source
->Offset
= *values
;
643 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
644 !Context
->DeferUpdates
)
646 if(ApplyOffset(Source
) == AL_FALSE
)
648 UnlockContext(Context
);
649 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
652 UnlockContext(Context
);
656 case siSampleRWOffsetsSOFT
:
657 case siByteRWOffsetsSOFT
:
659 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
662 case AL_DIRECT_FILTER
:
663 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
665 LockContext(Context
);
668 Source
->DirectGain
= 1.0f
;
669 Source
->DirectGainHF
= 1.0f
;
673 Source
->DirectGain
= filter
->Gain
;
674 Source
->DirectGainHF
= filter
->GainHF
;
676 UnlockContext(Context
);
677 Source
->NeedsUpdate
= AL_TRUE
;
680 case AL_DIRECT_FILTER_GAINHF_AUTO
:
681 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
683 Source
->DryGainHFAuto
= *values
;
684 Source
->NeedsUpdate
= AL_TRUE
;
687 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
688 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
690 Source
->WetGainAuto
= *values
;
691 Source
->NeedsUpdate
= AL_TRUE
;
694 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
695 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
697 Source
->WetGainHFAuto
= *values
;
698 Source
->NeedsUpdate
= AL_TRUE
;
701 case AL_DIRECT_CHANNELS_SOFT
:
702 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
704 Source
->DirectChannels
= *values
;
705 Source
->NeedsUpdate
= AL_TRUE
;
708 case AL_DISTANCE_MODEL
:
709 CHECKVAL(*values
== AL_NONE
||
710 *values
== AL_INVERSE_DISTANCE
||
711 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
712 *values
== AL_LINEAR_DISTANCE
||
713 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
714 *values
== AL_EXPONENT_DISTANCE
||
715 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
717 Source
->DistanceModel
= *values
;
718 if(Context
->SourceDistanceModel
)
719 Source
->NeedsUpdate
= AL_TRUE
;
723 case AL_AUXILIARY_SEND_FILTER
:
724 LockContext(Context
);
725 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
726 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
727 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
729 UnlockContext(Context
);
730 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_VALUE
, AL_FALSE
);
733 /* Add refcount on the new slot, and release the previous slot */
734 if(slot
) IncrementRef(&slot
->ref
);
735 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
736 if(slot
) DecrementRef(&slot
->ref
);
741 Source
->Send
[values
[1]].Gain
= 1.0f
;
742 Source
->Send
[values
[1]].GainHF
= 1.0f
;
746 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
747 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
749 Source
->NeedsUpdate
= AL_TRUE
;
750 UnlockContext(Context
);
754 case AL_MAX_DISTANCE
:
755 case AL_ROLLOFF_FACTOR
:
756 case AL_CONE_INNER_ANGLE
:
757 case AL_CONE_OUTER_ANGLE
:
758 case AL_REFERENCE_DISTANCE
:
759 case siDopplerFactor
:
760 fvals
[0] = (ALfloat
)*values
;
761 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
766 fvals
[0] = (ALfloat
)values
[0];
767 fvals
[1] = (ALfloat
)values
[1];
768 fvals
[2] = (ALfloat
)values
[2];
769 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
771 case siSampleOffsetLatencySOFT
:
776 ERR("Unexpected property: 0x%04x\n", prop
);
777 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
780 static ALboolean
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
)
787 case siSampleRWOffsetsSOFT
:
788 case siByteRWOffsetsSOFT
:
789 case siSampleOffsetLatencySOFT
:
791 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_OPERATION
, AL_FALSE
);
795 case AL_SOURCE_RELATIVE
:
797 case AL_SOURCE_STATE
:
799 case AL_SAMPLE_OFFSET
:
801 case siBuffersQueued
:
802 case siBuffersProcessed
:
803 case AL_DIRECT_FILTER_GAINHF_AUTO
:
804 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
805 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
806 case AL_DIRECT_CHANNELS_SOFT
:
807 case AL_DISTANCE_MODEL
:
808 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
810 ivals
[0] = (ALint
)*values
;
811 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
815 case AL_DIRECT_FILTER
:
816 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
818 ivals
[0] = (ALuint
)*values
;
819 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
822 case AL_AUXILIARY_SEND_FILTER
:
823 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
824 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
825 values
[2] <= UINT_MAX
&& values
[2] >= 0);
827 ivals
[0] = (ALuint
)values
[0];
828 ivals
[1] = (ALuint
)values
[1];
829 ivals
[2] = (ALuint
)values
[2];
830 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
833 case AL_MAX_DISTANCE
:
834 case AL_ROLLOFF_FACTOR
:
835 case AL_CONE_INNER_ANGLE
:
836 case AL_CONE_OUTER_ANGLE
:
837 case AL_REFERENCE_DISTANCE
:
839 case siDopplerFactor
:
840 fvals
[0] = (ALfloat
)*values
;
841 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
847 fvals
[0] = (ALfloat
)values
[0];
848 fvals
[1] = (ALfloat
)values
[1];
849 fvals
[2] = (ALfloat
)values
[2];
850 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
853 ERR("Unexpected property: 0x%04x\n", prop
);
854 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
860 static ALboolean
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
)
870 *values
= Source
->Gain
;
874 *values
= Source
->Pitch
;
877 case AL_MAX_DISTANCE
:
878 *values
= Source
->MaxDistance
;
881 case AL_ROLLOFF_FACTOR
:
882 *values
= Source
->RollOffFactor
;
885 case AL_REFERENCE_DISTANCE
:
886 *values
= Source
->RefDistance
;
889 case AL_CONE_INNER_ANGLE
:
890 *values
= Source
->InnerAngle
;
893 case AL_CONE_OUTER_ANGLE
:
894 *values
= Source
->OuterAngle
;
898 *values
= Source
->MinGain
;
902 *values
= Source
->MaxGain
;
905 case AL_CONE_OUTER_GAIN
:
906 *values
= Source
->OuterGain
;
910 case AL_SAMPLE_OFFSET
:
912 LockContext(Context
);
913 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
914 Context
->Device
->Frequency
;
915 GetSourceOffsets(Source
, prop
, offsets
, updateLen
);
916 UnlockContext(Context
);
917 *values
= offsets
[0];
920 case AL_CONE_OUTER_GAINHF
:
921 *values
= Source
->OuterGainHF
;
924 case AL_AIR_ABSORPTION_FACTOR
:
925 *values
= Source
->AirAbsorptionFactor
;
928 case AL_ROOM_ROLLOFF_FACTOR
:
929 *values
= Source
->RoomRolloffFactor
;
932 case AL_DOPPLER_FACTOR
:
933 *values
= Source
->DopplerFactor
;
936 case AL_SAMPLE_RW_OFFSETS_SOFT
:
937 case AL_BYTE_RW_OFFSETS_SOFT
:
938 LockContext(Context
);
939 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
940 Context
->Device
->Frequency
;
941 GetSourceOffsets(Source
, prop
, values
, updateLen
);
942 UnlockContext(Context
);
945 case AL_SEC_OFFSET_LATENCY_SOFT
:
946 LockContext(Context
);
947 values
[0] = GetSourceSecOffset(Source
);
948 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
950 UnlockContext(Context
);
954 LockContext(Context
);
955 values
[0] = Source
->Position
[0];
956 values
[1] = Source
->Position
[1];
957 values
[2] = Source
->Position
[2];
958 UnlockContext(Context
);
962 LockContext(Context
);
963 values
[0] = Source
->Velocity
[0];
964 values
[1] = Source
->Velocity
[1];
965 values
[2] = Source
->Velocity
[2];
966 UnlockContext(Context
);
970 LockContext(Context
);
971 values
[0] = Source
->Orientation
[0];
972 values
[1] = Source
->Orientation
[1];
973 values
[2] = Source
->Orientation
[2];
974 UnlockContext(Context
);
977 case AL_SOURCE_RELATIVE
:
980 case AL_SOURCE_STATE
:
981 case AL_BUFFERS_QUEUED
:
982 case AL_BUFFERS_PROCESSED
:
984 case AL_DIRECT_FILTER_GAINHF_AUTO
:
985 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
986 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
987 case AL_DIRECT_CHANNELS_SOFT
:
988 case AL_DISTANCE_MODEL
:
989 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
990 *values
= (ALdouble
)ivals
[0];
994 ERR("Unexpected property: 0x%04x\n", prop
);
995 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
998 static ALboolean
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
)
1000 ALbufferlistitem
*BufferList
;
1006 case AL_SOURCE_RELATIVE
:
1007 *values
= Source
->HeadRelative
;
1011 *values
= Source
->Looping
;
1015 LockContext(Context
);
1016 BufferList
= Source
->queue
;
1017 if(Source
->SourceType
!= AL_STATIC
)
1019 ALuint i
= Source
->BuffersPlayed
;
1022 BufferList
= BufferList
->next
;
1026 *values
= ((BufferList
&& BufferList
->buffer
) ?
1027 BufferList
->buffer
->id
: 0);
1028 UnlockContext(Context
);
1031 case AL_SOURCE_STATE
:
1032 *values
= Source
->state
;
1035 case AL_BUFFERS_QUEUED
:
1036 *values
= Source
->BuffersInQueue
;
1039 case AL_BUFFERS_PROCESSED
:
1040 LockContext(Context
);
1041 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
1043 /* Buffers on a looping source are in a perpetual state of
1044 * PENDING, so don't report any as PROCESSED */
1048 *values
= Source
->BuffersPlayed
;
1049 UnlockContext(Context
);
1052 case AL_SOURCE_TYPE
:
1053 *values
= Source
->SourceType
;
1056 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1057 *values
= Source
->DryGainHFAuto
;
1060 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1061 *values
= Source
->WetGainAuto
;
1064 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1065 *values
= Source
->WetGainHFAuto
;
1068 case AL_DIRECT_CHANNELS_SOFT
:
1069 *values
= Source
->DirectChannels
;
1072 case AL_DISTANCE_MODEL
:
1073 *values
= Source
->DistanceModel
;
1076 case AL_MAX_DISTANCE
:
1077 case AL_ROLLOFF_FACTOR
:
1078 case AL_REFERENCE_DISTANCE
:
1079 case AL_CONE_INNER_ANGLE
:
1080 case AL_CONE_OUTER_ANGLE
:
1082 case AL_SAMPLE_OFFSET
:
1083 case AL_BYTE_OFFSET
:
1084 case AL_DOPPLER_FACTOR
:
1085 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1086 *values
= (ALint
)dvals
[0];
1089 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1090 case AL_BYTE_RW_OFFSETS_SOFT
:
1091 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1093 values
[0] = (ALint
)dvals
[0];
1094 values
[1] = (ALint
)dvals
[1];
1101 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1103 values
[0] = (ALint
)dvals
[0];
1104 values
[1] = (ALint
)dvals
[1];
1105 values
[2] = (ALint
)dvals
[2];
1109 case siSampleOffsetLatencySOFT
:
1113 case siDirectFilter
:
1114 case siAuxSendFilter
:
1119 ERR("Unexpected property: 0x%04x\n", prop
);
1120 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1123 static ALboolean
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
)
1131 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1132 LockContext(Context
);
1133 values
[0] = GetSourceOffset(Source
);
1134 values
[1] = ALCdevice_GetLatency(Context
->Device
);
1135 UnlockContext(Context
);
1138 case AL_MAX_DISTANCE
:
1139 case AL_ROLLOFF_FACTOR
:
1140 case AL_REFERENCE_DISTANCE
:
1141 case AL_CONE_INNER_ANGLE
:
1142 case AL_CONE_OUTER_ANGLE
:
1144 case AL_SAMPLE_OFFSET
:
1145 case AL_BYTE_OFFSET
:
1146 case AL_DOPPLER_FACTOR
:
1147 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1148 *values
= (ALint64
)dvals
[0];
1151 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1152 case AL_BYTE_RW_OFFSETS_SOFT
:
1153 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1155 values
[0] = (ALint64
)dvals
[0];
1156 values
[1] = (ALint64
)dvals
[1];
1163 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) != AL_FALSE
)
1165 values
[0] = (ALint64
)dvals
[0];
1166 values
[1] = (ALint64
)dvals
[1];
1167 values
[2] = (ALint64
)dvals
[2];
1171 case AL_SOURCE_RELATIVE
:
1173 case AL_SOURCE_STATE
:
1174 case AL_BUFFERS_QUEUED
:
1175 case AL_BUFFERS_PROCESSED
:
1176 case AL_SOURCE_TYPE
:
1177 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1178 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1179 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1180 case AL_DIRECT_CHANNELS_SOFT
:
1181 case AL_DISTANCE_MODEL
:
1182 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1187 case siDirectFilter
:
1188 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1189 *values
= ((ALuint
*)ivals
)[0];
1192 case siAuxSendFilter
:
1193 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) != AL_FALSE
)
1195 values
[0] = ((ALuint
*)ivals
)[0];
1196 values
[1] = ((ALuint
*)ivals
)[1];
1197 values
[2] = ((ALuint
*)ivals
)[2];
1202 ERR("Unexpected property: 0x%04x\n", prop
);
1203 SET_ERROR_AND_RETURN_VALUE(Context
, AL_INVALID_ENUM
, AL_FALSE
);
1207 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
1209 ALCcontext
*context
;
1213 context
= GetContextRef();
1214 if(!context
) return;
1217 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1218 for(cur
= 0;cur
< n
;cur
++)
1220 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
1223 alDeleteSources(cur
, sources
);
1224 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
1226 InitSourceParams(source
);
1228 err
= NewThunkEntry(&source
->id
);
1229 if(err
== AL_NO_ERROR
)
1230 err
= InsertUIntMapEntry(&context
->SourceMap
, source
->id
, source
);
1231 if(err
!= AL_NO_ERROR
)
1233 FreeThunkEntry(source
->id
);
1234 memset(source
, 0, sizeof(ALsource
));
1237 alDeleteSources(cur
, sources
);
1238 SET_ERROR_AND_GOTO(context
, err
, done
);
1241 sources
[cur
] = source
->id
;
1245 ALCcontext_DecRef(context
);
1249 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
1251 ALCcontext
*context
;
1252 ALbufferlistitem
*BufferList
;
1256 context
= GetContextRef();
1257 if(!context
) return;
1260 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1262 /* Check that all Sources are valid */
1263 for(i
= 0;i
< n
;i
++)
1265 if(LookupSource(context
, sources
[i
]) == NULL
)
1266 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
1268 for(i
= 0;i
< n
;i
++)
1270 ALactivesource
**srclist
, **srclistend
;
1272 if((Source
=RemoveSource(context
, sources
[i
])) == NULL
)
1274 FreeThunkEntry(Source
->id
);
1276 LockContext(context
);
1277 srclist
= context
->ActiveSources
;
1278 srclistend
= srclist
+ context
->ActiveSourceCount
;
1279 while(srclist
!= srclistend
)
1281 if((*srclist
)->Source
== Source
)
1283 ALactivesource
*temp
= *(--srclistend
);
1284 *srclistend
= *srclist
;
1286 --(context
->ActiveSourceCount
);
1291 UnlockContext(context
);
1293 while(Source
->queue
!= NULL
)
1295 BufferList
= Source
->queue
;
1296 Source
->queue
= BufferList
->next
;
1298 if(BufferList
->buffer
!= NULL
)
1299 DecrementRef(&BufferList
->buffer
->ref
);
1303 for(j
= 0;j
< MAX_SENDS
;++j
)
1305 if(Source
->Send
[j
].Slot
)
1306 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
1307 Source
->Send
[j
].Slot
= NULL
;
1310 memset(Source
, 0, sizeof(*Source
));
1315 ALCcontext_DecRef(context
);
1319 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1321 ALCcontext
*context
;
1324 context
= GetContextRef();
1325 if(!context
) return AL_FALSE
;
1327 ret
= (LookupSource(context
, source
) ? AL_TRUE
: AL_FALSE
);
1329 ALCcontext_DecRef(context
);
1335 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1337 ALCcontext
*Context
;
1340 Context
= GetContextRef();
1341 if(!Context
) return;
1343 if((Source
=LookupSource(Context
, source
)) == NULL
)
1344 alSetError(Context
, AL_INVALID_NAME
);
1345 else if(!(FloatValsByProp(param
) == 1))
1346 alSetError(Context
, AL_INVALID_ENUM
);
1348 SetSourcefv(Source
, Context
, param
, &value
);
1350 ALCcontext_DecRef(Context
);
1353 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1355 ALCcontext
*Context
;
1358 Context
= GetContextRef();
1359 if(!Context
) return;
1361 if((Source
=LookupSource(Context
, source
)) == NULL
)
1362 alSetError(Context
, AL_INVALID_NAME
);
1363 else if(!(FloatValsByProp(param
) == 3))
1364 alSetError(Context
, AL_INVALID_ENUM
);
1367 ALfloat fvals
[3] = { value1
, value2
, value3
};
1368 SetSourcefv(Source
, Context
, param
, fvals
);
1371 ALCcontext_DecRef(Context
);
1374 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1376 ALCcontext
*Context
;
1379 Context
= GetContextRef();
1380 if(!Context
) return;
1382 if((Source
=LookupSource(Context
, source
)) == NULL
)
1383 alSetError(Context
, AL_INVALID_NAME
);
1385 alSetError(Context
, AL_INVALID_VALUE
);
1386 else if(!(FloatValsByProp(param
) > 0))
1387 alSetError(Context
, AL_INVALID_ENUM
);
1389 SetSourcefv(Source
, Context
, param
, values
);
1391 ALCcontext_DecRef(Context
);
1395 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1397 ALCcontext
*Context
;
1400 Context
= GetContextRef();
1401 if(!Context
) return;
1403 if((Source
=LookupSource(Context
, source
)) == NULL
)
1404 alSetError(Context
, AL_INVALID_NAME
);
1405 else if(!(DoubleValsByProp(param
) == 1))
1406 alSetError(Context
, AL_INVALID_ENUM
);
1409 ALfloat fval
= (ALfloat
)value
;
1410 SetSourcefv(Source
, Context
, param
, &fval
);
1413 ALCcontext_DecRef(Context
);
1416 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1418 ALCcontext
*Context
;
1421 Context
= GetContextRef();
1422 if(!Context
) return;
1424 if((Source
=LookupSource(Context
, source
)) == NULL
)
1425 alSetError(Context
, AL_INVALID_NAME
);
1426 else if(!(DoubleValsByProp(param
) == 3))
1427 alSetError(Context
, AL_INVALID_ENUM
);
1430 ALfloat fvals
[3] = { (ALfloat
)value1
, (ALfloat
)value2
, (ALfloat
)value3
};
1431 SetSourcefv(Source
, Context
, param
, fvals
);
1434 ALCcontext_DecRef(Context
);
1437 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1439 ALCcontext
*Context
;
1443 Context
= GetContextRef();
1444 if(!Context
) return;
1446 if((Source
=LookupSource(Context
, source
)) == NULL
)
1447 alSetError(Context
, AL_INVALID_NAME
);
1449 alSetError(Context
, AL_INVALID_VALUE
);
1450 else if(!((count
=DoubleValsByProp(param
)) > 0 && count
<= 3))
1451 alSetError(Context
, AL_INVALID_ENUM
);
1457 for(i
= 0;i
< count
;i
++)
1458 fvals
[i
] = (ALfloat
)values
[i
];
1459 SetSourcefv(Source
, Context
, param
, fvals
);
1462 ALCcontext_DecRef(Context
);
1466 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1468 ALCcontext
*Context
;
1471 Context
= GetContextRef();
1472 if(!Context
) return;
1474 if((Source
=LookupSource(Context
, source
)) == NULL
)
1475 alSetError(Context
, AL_INVALID_NAME
);
1476 else if(!(IntValsByProp(param
) == 1))
1477 alSetError(Context
, AL_INVALID_ENUM
);
1479 SetSourceiv(Source
, Context
, param
, &value
);
1481 ALCcontext_DecRef(Context
);
1484 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1486 ALCcontext
*Context
;
1489 Context
= GetContextRef();
1490 if(!Context
) return;
1492 if((Source
=LookupSource(Context
, source
)) == NULL
)
1493 alSetError(Context
, AL_INVALID_NAME
);
1494 else if(!(IntValsByProp(param
) == 3))
1495 alSetError(Context
, AL_INVALID_ENUM
);
1498 ALint ivals
[3] = { value1
, value2
, value3
};
1499 SetSourceiv(Source
, Context
, param
, ivals
);
1502 ALCcontext_DecRef(Context
);
1505 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1507 ALCcontext
*Context
;
1510 Context
= GetContextRef();
1511 if(!Context
) return;
1513 if((Source
=LookupSource(Context
, source
)) == NULL
)
1514 alSetError(Context
, AL_INVALID_NAME
);
1516 alSetError(Context
, AL_INVALID_VALUE
);
1517 else if(!(IntValsByProp(param
) > 0))
1518 alSetError(Context
, AL_INVALID_ENUM
);
1520 SetSourceiv(Source
, Context
, param
, values
);
1522 ALCcontext_DecRef(Context
);
1526 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1528 ALCcontext
*Context
;
1531 Context
= GetContextRef();
1532 if(!Context
) return;
1534 if((Source
=LookupSource(Context
, source
)) == NULL
)
1535 alSetError(Context
, AL_INVALID_NAME
);
1536 else if(!(Int64ValsByProp(param
) == 1))
1537 alSetError(Context
, AL_INVALID_ENUM
);
1539 SetSourcei64v(Source
, Context
, param
, &value
);
1541 ALCcontext_DecRef(Context
);
1544 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1546 ALCcontext
*Context
;
1549 Context
= GetContextRef();
1550 if(!Context
) return;
1552 if((Source
=LookupSource(Context
, source
)) == NULL
)
1553 alSetError(Context
, AL_INVALID_NAME
);
1554 else if(!(Int64ValsByProp(param
) == 3))
1555 alSetError(Context
, AL_INVALID_ENUM
);
1558 ALint64SOFT i64vals
[3] = { value1
, value2
, value3
};
1559 SetSourcei64v(Source
, Context
, param
, i64vals
);
1562 ALCcontext_DecRef(Context
);
1565 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1567 ALCcontext
*Context
;
1570 Context
= GetContextRef();
1571 if(!Context
) return;
1573 if((Source
=LookupSource(Context
, source
)) == NULL
)
1574 alSetError(Context
, AL_INVALID_NAME
);
1576 alSetError(Context
, AL_INVALID_VALUE
);
1577 else if(!(Int64ValsByProp(param
) > 0))
1578 alSetError(Context
, AL_INVALID_ENUM
);
1580 SetSourcei64v(Source
, Context
, param
, values
);
1582 ALCcontext_DecRef(Context
);
1586 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1588 ALCcontext
*Context
;
1591 Context
= GetContextRef();
1592 if(!Context
) return;
1594 if((Source
=LookupSource(Context
, source
)) == NULL
)
1595 alSetError(Context
, AL_INVALID_NAME
);
1597 alSetError(Context
, AL_INVALID_VALUE
);
1598 else if(!(FloatValsByProp(param
) == 1))
1599 alSetError(Context
, AL_INVALID_ENUM
);
1603 if(GetSourcedv(Source
, Context
, param
, &dval
))
1604 *value
= (ALfloat
)dval
;
1607 ALCcontext_DecRef(Context
);
1611 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1613 ALCcontext
*Context
;
1616 Context
= GetContextRef();
1617 if(!Context
) return;
1619 if((Source
=LookupSource(Context
, source
)) == NULL
)
1620 alSetError(Context
, AL_INVALID_NAME
);
1621 else if(!(value1
&& value2
&& value3
))
1622 alSetError(Context
, AL_INVALID_VALUE
);
1623 else if(!(FloatValsByProp(param
) == 3))
1624 alSetError(Context
, AL_INVALID_ENUM
);
1628 if(GetSourcedv(Source
, Context
, param
, dvals
))
1630 *value1
= (ALfloat
)dvals
[0];
1631 *value2
= (ALfloat
)dvals
[1];
1632 *value3
= (ALfloat
)dvals
[2];
1636 ALCcontext_DecRef(Context
);
1640 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1642 ALCcontext
*Context
;
1646 Context
= GetContextRef();
1647 if(!Context
) return;
1649 if((Source
=LookupSource(Context
, source
)) == NULL
)
1650 alSetError(Context
, AL_INVALID_NAME
);
1652 alSetError(Context
, AL_INVALID_VALUE
);
1653 else if(!((count
=FloatValsByProp(param
)) > 0 && count
<= 3))
1654 alSetError(Context
, AL_INVALID_ENUM
);
1658 if(GetSourcedv(Source
, Context
, param
, dvals
))
1661 for(i
= 0;i
< count
;i
++)
1662 values
[i
] = (ALfloat
)dvals
[i
];
1666 ALCcontext_DecRef(Context
);
1670 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1672 ALCcontext
*Context
;
1675 Context
= GetContextRef();
1676 if(!Context
) return;
1678 if((Source
=LookupSource(Context
, source
)) == NULL
)
1679 alSetError(Context
, AL_INVALID_NAME
);
1681 alSetError(Context
, AL_INVALID_VALUE
);
1682 else if(!(DoubleValsByProp(param
) == 1))
1683 alSetError(Context
, AL_INVALID_ENUM
);
1685 GetSourcedv(Source
, Context
, param
, value
);
1687 ALCcontext_DecRef(Context
);
1690 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1692 ALCcontext
*Context
;
1695 Context
= GetContextRef();
1696 if(!Context
) return;
1698 if((Source
=LookupSource(Context
, source
)) == NULL
)
1699 alSetError(Context
, AL_INVALID_NAME
);
1700 else if(!(value1
&& value2
&& value3
))
1701 alSetError(Context
, AL_INVALID_VALUE
);
1702 else if(!(DoubleValsByProp(param
) == 3))
1703 alSetError(Context
, AL_INVALID_ENUM
);
1707 if(GetSourcedv(Source
, Context
, param
, dvals
))
1715 ALCcontext_DecRef(Context
);
1718 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1720 ALCcontext
*Context
;
1723 Context
= GetContextRef();
1724 if(!Context
) return;
1726 if((Source
=LookupSource(Context
, source
)) == NULL
)
1727 alSetError(Context
, AL_INVALID_NAME
);
1729 alSetError(Context
, AL_INVALID_VALUE
);
1730 else if(!(DoubleValsByProp(param
) > 0))
1731 alSetError(Context
, AL_INVALID_ENUM
);
1733 GetSourcedv(Source
, Context
, param
, values
);
1735 ALCcontext_DecRef(Context
);
1739 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1741 ALCcontext
*Context
;
1744 Context
= GetContextRef();
1745 if(!Context
) return;
1747 if((Source
=LookupSource(Context
, source
)) == NULL
)
1748 alSetError(Context
, AL_INVALID_NAME
);
1750 alSetError(Context
, AL_INVALID_VALUE
);
1751 else if(!(IntValsByProp(param
) == 1))
1752 alSetError(Context
, AL_INVALID_ENUM
);
1754 GetSourceiv(Source
, Context
, param
, value
);
1756 ALCcontext_DecRef(Context
);
1760 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1762 ALCcontext
*Context
;
1765 Context
= GetContextRef();
1766 if(!Context
) return;
1768 if((Source
=LookupSource(Context
, source
)) == NULL
)
1769 alSetError(Context
, AL_INVALID_NAME
);
1770 else if(!(value1
&& value2
&& value3
))
1771 alSetError(Context
, AL_INVALID_VALUE
);
1772 else if(!(IntValsByProp(param
) == 3))
1773 alSetError(Context
, AL_INVALID_ENUM
);
1777 if(GetSourceiv(Source
, Context
, param
, ivals
))
1785 ALCcontext_DecRef(Context
);
1789 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1791 ALCcontext
*Context
;
1794 Context
= GetContextRef();
1795 if(!Context
) return;
1797 if((Source
=LookupSource(Context
, source
)) == NULL
)
1798 alSetError(Context
, AL_INVALID_NAME
);
1800 alSetError(Context
, AL_INVALID_VALUE
);
1801 else if(!(IntValsByProp(param
) > 0))
1802 alSetError(Context
, AL_INVALID_ENUM
);
1804 GetSourceiv(Source
, Context
, param
, values
);
1806 ALCcontext_DecRef(Context
);
1810 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
1812 ALCcontext
*Context
;
1815 Context
= GetContextRef();
1816 if(!Context
) return;
1818 if((Source
=LookupSource(Context
, source
)) == NULL
)
1819 alSetError(Context
, AL_INVALID_NAME
);
1821 alSetError(Context
, AL_INVALID_VALUE
);
1822 else if(!(Int64ValsByProp(param
) == 1))
1823 alSetError(Context
, AL_INVALID_ENUM
);
1825 GetSourcei64v(Source
, Context
, param
, value
);
1827 ALCcontext_DecRef(Context
);
1830 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
1832 ALCcontext
*Context
;
1835 Context
= GetContextRef();
1836 if(!Context
) return;
1838 if((Source
=LookupSource(Context
, source
)) == NULL
)
1839 alSetError(Context
, AL_INVALID_NAME
);
1840 else if(!(value1
&& value2
&& value3
))
1841 alSetError(Context
, AL_INVALID_VALUE
);
1842 else if(!(Int64ValsByProp(param
) == 3))
1843 alSetError(Context
, AL_INVALID_ENUM
);
1847 if(GetSourcei64v(Source
, Context
, param
, i64vals
))
1849 *value1
= i64vals
[0];
1850 *value2
= i64vals
[1];
1851 *value3
= i64vals
[2];
1855 ALCcontext_DecRef(Context
);
1858 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
1860 ALCcontext
*Context
;
1863 Context
= GetContextRef();
1864 if(!Context
) return;
1866 if((Source
=LookupSource(Context
, source
)) == NULL
)
1867 alSetError(Context
, AL_INVALID_NAME
);
1869 alSetError(Context
, AL_INVALID_VALUE
);
1870 else if(!(Int64ValsByProp(param
) > 0))
1871 alSetError(Context
, AL_INVALID_ENUM
);
1873 GetSourcei64v(Source
, Context
, param
, values
);
1875 ALCcontext_DecRef(Context
);
1879 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
1881 alSourcePlayv(1, &source
);
1883 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
1885 ALCcontext
*context
;
1889 context
= GetContextRef();
1890 if(!context
) return;
1893 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1894 for(i
= 0;i
< n
;i
++)
1896 if(!LookupSource(context
, sources
[i
]))
1897 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
1900 LockContext(context
);
1901 while(n
> context
->MaxActiveSources
-context
->ActiveSourceCount
)
1903 ALactivesource
**temp
= NULL
;
1906 newcount
= context
->MaxActiveSources
<< 1;
1908 temp
= realloc(context
->ActiveSources
,
1909 newcount
* sizeof(context
->ActiveSources
[0]));
1912 UnlockContext(context
);
1913 SET_ERROR_AND_GOTO(context
, AL_OUT_OF_MEMORY
, done
);
1915 for(i
= context
->MaxActiveSources
;i
< newcount
;i
++)
1918 context
->ActiveSources
= temp
;
1919 context
->MaxActiveSources
= newcount
;
1922 for(i
= 0;i
< n
;i
++)
1924 source
= LookupSource(context
, sources
[i
]);
1925 if(context
->DeferUpdates
) source
->new_state
= AL_PLAYING
;
1926 else SetSourceState(source
, context
, AL_PLAYING
);
1928 UnlockContext(context
);
1931 ALCcontext_DecRef(context
);
1934 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
1936 alSourcePausev(1, &source
);
1938 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1940 ALCcontext
*context
;
1944 context
= GetContextRef();
1945 if(!context
) return;
1948 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1949 for(i
= 0;i
< n
;i
++)
1951 if(!LookupSource(context
, sources
[i
]))
1952 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
1955 LockContext(context
);
1956 for(i
= 0;i
< n
;i
++)
1958 source
= LookupSource(context
, sources
[i
]);
1959 if(context
->DeferUpdates
) source
->new_state
= AL_PAUSED
;
1960 else SetSourceState(source
, context
, AL_PAUSED
);
1962 UnlockContext(context
);
1965 ALCcontext_DecRef(context
);
1968 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
1970 alSourceStopv(1, &source
);
1972 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1974 ALCcontext
*context
;
1978 context
= GetContextRef();
1979 if(!context
) return;
1982 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
1983 for(i
= 0;i
< n
;i
++)
1985 if(!LookupSource(context
, sources
[i
]))
1986 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
1989 LockContext(context
);
1990 for(i
= 0;i
< n
;i
++)
1992 source
= LookupSource(context
, sources
[i
]);
1993 source
->new_state
= AL_NONE
;
1994 SetSourceState(source
, context
, AL_STOPPED
);
1996 UnlockContext(context
);
1999 ALCcontext_DecRef(context
);
2002 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2004 alSourceRewindv(1, &source
);
2006 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2008 ALCcontext
*context
;
2012 context
= GetContextRef();
2013 if(!context
) return;
2016 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2017 for(i
= 0;i
< n
;i
++)
2019 if(!LookupSource(context
, sources
[i
]))
2020 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2023 LockContext(context
);
2024 for(i
= 0;i
< n
;i
++)
2026 source
= LookupSource(context
, sources
[i
]);
2027 source
->new_state
= AL_NONE
;
2028 SetSourceState(source
, context
, AL_INITIAL
);
2030 UnlockContext(context
);
2033 ALCcontext_DecRef(context
);
2037 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint src
, ALsizei nb
, const ALuint
*buffers
)
2040 ALCcontext
*context
;
2043 ALbufferlistitem
*BufferListStart
= NULL
;
2044 ALbufferlistitem
*BufferList
;
2045 ALbuffer
*BufferFmt
= NULL
;
2050 context
= GetContextRef();
2051 if(!context
) return;
2053 device
= context
->Device
;
2056 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2057 if((source
=LookupSource(context
, src
)) == NULL
)
2058 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2060 LockContext(context
);
2061 if(source
->SourceType
== AL_STATIC
)
2063 UnlockContext(context
);
2064 /* Can't queue on a Static Source */
2065 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
2068 /* Check for a valid Buffer, for its frequency and format */
2069 BufferList
= source
->queue
;
2072 if(BufferList
->buffer
)
2074 BufferFmt
= BufferList
->buffer
;
2077 BufferList
= BufferList
->next
;
2080 for(i
= 0;i
< nb
;i
++)
2082 ALbuffer
*buffer
= NULL
;
2083 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2085 UnlockContext(context
);
2086 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2089 if(!BufferListStart
)
2091 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2092 BufferListStart
->buffer
= buffer
;
2093 BufferListStart
->next
= NULL
;
2094 BufferListStart
->prev
= NULL
;
2095 BufferList
= BufferListStart
;
2099 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2100 BufferList
->next
->buffer
= buffer
;
2101 BufferList
->next
->next
= NULL
;
2102 BufferList
->next
->prev
= BufferList
;
2103 BufferList
= BufferList
->next
;
2105 if(!buffer
) continue;
2106 IncrementRef(&buffer
->ref
);
2108 ReadLock(&buffer
->lock
);
2109 if(BufferFmt
== NULL
)
2113 source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2114 source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2116 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2117 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2118 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2120 ReadUnlock(&buffer
->lock
);
2121 UnlockContext(context
);
2122 SET_ERROR_AND_GOTO(context
, AL_INVALID_OPERATION
, done
);
2124 ReadUnlock(&buffer
->lock
);
2127 /* Source is now streaming */
2128 source
->SourceType
= AL_STREAMING
;
2130 if(source
->queue
== NULL
)
2131 source
->queue
= BufferListStart
;
2134 /* Append to the end of the queue */
2135 BufferList
= source
->queue
;
2136 while(BufferList
->next
!= NULL
)
2137 BufferList
= BufferList
->next
;
2139 BufferListStart
->prev
= BufferList
;
2140 BufferList
->next
= BufferListStart
;
2142 BufferListStart
= NULL
;
2144 source
->BuffersInQueue
+= nb
;
2146 UnlockContext(context
);
2149 while(BufferListStart
)
2151 BufferList
= BufferListStart
;
2152 BufferListStart
= BufferList
->next
;
2154 if(BufferList
->buffer
)
2155 DecrementRef(&BufferList
->buffer
->ref
);
2159 ALCcontext_DecRef(context
);
2162 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint src
, ALsizei nb
, ALuint
*buffers
)
2164 ALCcontext
*context
;
2167 ALbufferlistitem
*BufferList
;
2172 context
= GetContextRef();
2173 if(!context
) return;
2176 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2178 if((source
=LookupSource(context
, src
)) == NULL
)
2179 SET_ERROR_AND_GOTO(context
, AL_INVALID_NAME
, done
);
2181 LockContext(context
);
2182 if(source
->Looping
|| source
->SourceType
!= AL_STREAMING
||
2183 (ALuint
)nb
> source
->BuffersPlayed
)
2185 UnlockContext(context
);
2186 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2187 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
2190 for(i
= 0;i
< nb
;i
++)
2192 BufferList
= source
->queue
;
2193 source
->queue
= BufferList
->next
;
2194 source
->BuffersInQueue
--;
2195 source
->BuffersPlayed
--;
2197 if(BufferList
->buffer
)
2199 buffers
[i
] = BufferList
->buffer
->id
;
2200 DecrementRef(&BufferList
->buffer
->ref
);
2208 source
->queue
->prev
= NULL
;
2209 UnlockContext(context
);
2212 ALCcontext_DecRef(context
);
2216 static ALvoid
InitSourceParams(ALsource
*Source
)
2220 Source
->InnerAngle
= 360.0f
;
2221 Source
->OuterAngle
= 360.0f
;
2222 Source
->Pitch
= 1.0f
;
2223 Source
->Position
[0] = 0.0f
;
2224 Source
->Position
[1] = 0.0f
;
2225 Source
->Position
[2] = 0.0f
;
2226 Source
->Orientation
[0] = 0.0f
;
2227 Source
->Orientation
[1] = 0.0f
;
2228 Source
->Orientation
[2] = 0.0f
;
2229 Source
->Velocity
[0] = 0.0f
;
2230 Source
->Velocity
[1] = 0.0f
;
2231 Source
->Velocity
[2] = 0.0f
;
2232 Source
->RefDistance
= 1.0f
;
2233 Source
->MaxDistance
= FLT_MAX
;
2234 Source
->RollOffFactor
= 1.0f
;
2235 Source
->Looping
= AL_FALSE
;
2236 Source
->Gain
= 1.0f
;
2237 Source
->MinGain
= 0.0f
;
2238 Source
->MaxGain
= 1.0f
;
2239 Source
->OuterGain
= 0.0f
;
2240 Source
->OuterGainHF
= 1.0f
;
2242 Source
->DryGainHFAuto
= AL_TRUE
;
2243 Source
->WetGainAuto
= AL_TRUE
;
2244 Source
->WetGainHFAuto
= AL_TRUE
;
2245 Source
->AirAbsorptionFactor
= 0.0f
;
2246 Source
->RoomRolloffFactor
= 0.0f
;
2247 Source
->DopplerFactor
= 1.0f
;
2248 Source
->DirectChannels
= AL_FALSE
;
2250 Source
->DistanceModel
= DefaultDistanceModel
;
2252 Source
->Resampler
= DefaultResampler
;
2254 Source
->state
= AL_INITIAL
;
2255 Source
->new_state
= AL_NONE
;
2256 Source
->SourceType
= AL_UNDETERMINED
;
2257 Source
->Offset
= -1.0;
2259 Source
->DirectGain
= 1.0f
;
2260 Source
->DirectGainHF
= 1.0f
;
2261 for(i
= 0;i
< MAX_SENDS
;i
++)
2263 Source
->Send
[i
].Gain
= 1.0f
;
2264 Source
->Send
[i
].GainHF
= 1.0f
;
2267 Source
->NeedsUpdate
= AL_TRUE
;
2273 * Sets the source's new play state given its current state.
2275 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2277 if(state
== AL_PLAYING
)
2279 ALCdevice
*device
= Context
->Device
;
2280 ALbufferlistitem
*BufferList
;
2281 ALactivesource
*src
= NULL
;
2284 /* Check that there is a queue containing at least one valid, non zero
2286 BufferList
= Source
->queue
;
2289 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
2291 BufferList
= BufferList
->next
;
2294 if(Source
->state
!= AL_PAUSED
)
2296 Source
->state
= AL_PLAYING
;
2297 Source
->position
= 0;
2298 Source
->position_fraction
= 0;
2299 Source
->BuffersPlayed
= 0;
2302 Source
->state
= AL_PLAYING
;
2304 // Check if an Offset has been set
2305 if(Source
->Offset
>= 0.0)
2306 ApplyOffset(Source
);
2308 /* If there's nothing to play, or device is disconnected, go right to
2310 if(!BufferList
|| !device
->Connected
)
2312 SetSourceState(Source
, Context
, AL_STOPPED
);
2316 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
2318 if(Context
->ActiveSources
[j
]->Source
== Source
)
2320 src
= Context
->ActiveSources
[j
];
2326 src
= Context
->ActiveSources
[Context
->ActiveSourceCount
];
2329 src
= al_malloc(16, sizeof(src
[0]));
2330 Context
->ActiveSources
[Context
->ActiveSourceCount
] = src
;
2332 memset(src
, 0, sizeof(*src
));
2334 src
->Source
= Source
;
2335 if(BufferList
->buffer
->FmtChannels
== FmtMono
)
2336 src
->Update
= CalcSourceParams
;
2338 src
->Update
= CalcNonAttnSourceParams
;
2339 Context
->ActiveSourceCount
++;
2345 src
->Direct
.Moving
= AL_FALSE
;
2346 src
->Direct
.Counter
= 0;
2347 for(j
= 0;j
< MAX_INPUT_CHANNELS
;j
++)
2349 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
2350 src
->Direct
.Mix
.Hrtf
.State
[j
].History
[k
] = 0.0f
;
2351 for(k
= 0;k
< HRIR_LENGTH
;k
++)
2353 src
->Direct
.Mix
.Hrtf
.State
[j
].Values
[k
][0] = 0.0f
;
2354 src
->Direct
.Mix
.Hrtf
.State
[j
].Values
[k
][1] = 0.0f
;
2357 for(i
= 0;i
< device
->NumAuxSends
;i
++)
2359 src
->Send
[i
].Counter
= 0;
2360 src
->Send
[i
].Moving
= AL_FALSE
;
2363 Source
->NeedsUpdate
= AL_TRUE
;
2365 else if(state
== AL_PAUSED
)
2367 if(Source
->state
== AL_PLAYING
)
2368 Source
->state
= AL_PAUSED
;
2370 else if(state
== AL_STOPPED
)
2372 if(Source
->state
!= AL_INITIAL
)
2374 Source
->state
= AL_STOPPED
;
2375 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
2377 Source
->Offset
= -1.0;
2379 else if(state
== AL_INITIAL
)
2381 if(Source
->state
!= AL_INITIAL
)
2383 Source
->state
= AL_INITIAL
;
2384 Source
->position
= 0;
2385 Source
->position_fraction
= 0;
2386 Source
->BuffersPlayed
= 0;
2388 Source
->Offset
= -1.0;
2394 * Gets the current read offset for the given Source, in 32.32 fixed-point
2395 * samples. The offset is relative to the start of the queue (not the start of
2396 * the current buffer).
2398 static ALint64
GetSourceOffset(const ALsource
*Source
)
2400 const ALbufferlistitem
*BufferList
;
2404 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2407 /* NOTE: This is the offset into the *current* buffer, so add the length of
2408 * any played buffers */
2409 readPos
= (ALuint64
)Source
->position
<< 32;
2410 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2411 BufferList
= Source
->queue
;
2412 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2414 if(BufferList
->buffer
)
2415 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2416 BufferList
= BufferList
->next
;
2419 return (ALint64
)minu64(readPos
, U64(0x7fffffffffffffff));
2422 /* GetSourceSecOffset
2424 * Gets the current read offset for the given Source, in seconds. The offset is
2425 * relative to the start of the queue (not the start of the current buffer).
2427 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2429 const ALbufferlistitem
*BufferList
;
2430 const ALbuffer
*Buffer
= NULL
;
2434 BufferList
= Source
->queue
;
2437 if(BufferList
->buffer
)
2439 Buffer
= BufferList
->buffer
;
2442 BufferList
= BufferList
->next
;
2445 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2448 /* NOTE: This is the offset into the *current* buffer, so add the length of
2449 * any played buffers */
2450 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2451 readPos
|= (ALuint64
)Source
->position_fraction
;
2452 BufferList
= Source
->queue
;
2453 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2455 if(BufferList
->buffer
)
2456 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< FRACTIONBITS
;
2457 BufferList
= BufferList
->next
;
2460 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2465 * Gets the current read and write offsets for the given Source, in the
2466 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2467 * the start of the queue (not the start of the current buffer).
2469 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2471 const ALbufferlistitem
*BufferList
;
2472 const ALbuffer
*Buffer
= NULL
;
2473 ALuint readPos
, writePos
;
2474 ALuint totalBufferLen
;
2477 // Find the first valid Buffer in the Queue
2478 BufferList
= Source
->queue
;
2481 if(BufferList
->buffer
)
2483 Buffer
= BufferList
->buffer
;
2486 BufferList
= BufferList
->next
;
2489 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2496 if(updateLen
> 0.0 && updateLen
< 0.015)
2499 /* NOTE: This is the offset into the *current* buffer, so add the length of
2500 * any played buffers */
2501 readPos
= Source
->position
;
2503 BufferList
= Source
->queue
;
2504 for(i
= 0;BufferList
;i
++)
2506 if(BufferList
->buffer
)
2508 if(i
< Source
->BuffersPlayed
)
2509 readPos
+= BufferList
->buffer
->SampleLen
;
2510 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
2512 BufferList
= BufferList
->next
;
2514 if(Source
->state
== AL_PLAYING
)
2515 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2521 readPos
%= totalBufferLen
;
2522 writePos
%= totalBufferLen
;
2526 /* Wrap positions back to 0 */
2527 if(readPos
>= totalBufferLen
)
2529 if(writePos
>= totalBufferLen
)
2536 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2537 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2540 case AL_SAMPLE_OFFSET
:
2541 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2542 offset
[0] = (ALdouble
)readPos
;
2543 offset
[1] = (ALdouble
)writePos
;
2546 case AL_BYTE_OFFSET
:
2547 case AL_BYTE_RW_OFFSETS_SOFT
:
2548 if(Buffer
->OriginalType
== UserFmtIMA4
)
2550 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
2551 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2552 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2554 /* Round down to nearest ADPCM block */
2555 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2556 if(Source
->state
!= AL_PLAYING
)
2557 offset
[1] = offset
[0];
2560 /* Round up to nearest ADPCM block */
2561 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2562 FrameBlockSize
* BlockSize
);
2565 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
2567 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
2568 ALuint BlockSize
= align
* ChannelsFromFmt(Buffer
->FmtChannels
);
2569 ALuint FrameBlockSize
= Buffer
->OriginalAlign
;
2571 /* Round down to nearest ADPCM block */
2572 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2573 if(Source
->state
!= AL_PLAYING
)
2574 offset
[1] = offset
[0];
2577 /* Round up to nearest ADPCM block */
2578 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2579 FrameBlockSize
* BlockSize
);
2584 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2585 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2586 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2595 * Apply the stored playback offset to the Source. This function will update
2596 * the number of buffers "played" given the stored offset.
2598 ALboolean
ApplyOffset(ALsource
*Source
)
2600 const ALbufferlistitem
*BufferList
;
2601 const ALbuffer
*Buffer
;
2602 ALint bufferLen
, totalBufferLen
;
2603 ALint buffersPlayed
;
2606 /* Get sample frame offset */
2607 offset
= GetSampleOffset(Source
);
2614 BufferList
= Source
->queue
;
2617 Buffer
= BufferList
->buffer
;
2618 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2620 if(bufferLen
<= offset
-totalBufferLen
)
2622 /* Offset is past this buffer so increment to the next buffer */
2625 else if(totalBufferLen
<= offset
)
2627 /* Offset is in this buffer */
2628 Source
->BuffersPlayed
= buffersPlayed
;
2630 Source
->position
= offset
- totalBufferLen
;
2631 Source
->position_fraction
= 0;
2635 totalBufferLen
+= bufferLen
;
2637 BufferList
= BufferList
->next
;
2640 /* Offset is out of range of the queue */
2647 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2648 * Second offset supplied by the application). This takes into account the fact
2649 * that the buffer format may have been modifed since.
2651 static ALint
GetSampleOffset(ALsource
*Source
)
2653 const ALbuffer
*Buffer
= NULL
;
2654 const ALbufferlistitem
*BufferList
;
2657 /* Find the first valid Buffer in the Queue */
2658 BufferList
= Source
->queue
;
2661 if(BufferList
->buffer
)
2663 Buffer
= BufferList
->buffer
;
2666 BufferList
= BufferList
->next
;
2671 Source
->Offset
= -1.0;
2675 switch(Source
->OffsetType
)
2677 case AL_BYTE_OFFSET
:
2678 /* Determine the ByteOffset (and ensure it is block aligned) */
2679 Offset
= (ALint
)Source
->Offset
;
2680 if(Buffer
->OriginalType
== UserFmtIMA4
)
2682 ALsizei align
= (Buffer
->OriginalAlign
-1)/2 + 4;
2683 Offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2684 Offset
*= Buffer
->OriginalAlign
;
2686 else if(Buffer
->OriginalType
== UserFmtMSADPCM
)
2688 ALsizei align
= (Buffer
->OriginalAlign
-2)/2 + 7;
2689 Offset
/= align
* ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2690 Offset
*= Buffer
->OriginalAlign
;
2693 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2696 case AL_SAMPLE_OFFSET
:
2697 Offset
= (ALint
)Source
->Offset
;
2701 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2704 Source
->Offset
= -1.0;
2712 * Destroys all sources in the source map.
2714 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2718 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2720 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2721 Context
->SourceMap
.array
[pos
].value
= NULL
;
2723 while(temp
->queue
!= NULL
)
2725 ALbufferlistitem
*BufferList
= temp
->queue
;
2726 temp
->queue
= BufferList
->next
;
2728 if(BufferList
->buffer
!= NULL
)
2729 DecrementRef(&BufferList
->buffer
->ref
);
2733 for(j
= 0;j
< MAX_SENDS
;++j
)
2735 if(temp
->Send
[j
].Slot
)
2736 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2737 temp
->Send
[j
].Slot
= NULL
;
2740 FreeThunkEntry(temp
->id
);
2741 memset(temp
, 0, sizeof(*temp
));