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 static ALvoid
InitSourceParams(ALsource
*Source
);
51 static ALint64
GetSourceOffset(const ALsource
*Source
);
52 static ALdouble
GetSourceSecOffset(const ALsource
*Source
);
53 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offsets
, ALdouble updateLen
);
54 static ALint
GetSampleOffset(ALsource
*Source
);
56 typedef enum SrcFloatProp
{
59 sfMinGain
= AL_MIN_GAIN
,
60 sfMaxGain
= AL_MAX_GAIN
,
61 sfMaxDistance
= AL_MAX_DISTANCE
,
62 sfRolloffFactor
= AL_ROLLOFF_FACTOR
,
63 sfDopplerFactor
= AL_DOPPLER_FACTOR
,
64 sfConeOuterGain
= AL_CONE_OUTER_GAIN
,
65 sfSecOffset
= AL_SEC_OFFSET
,
66 sfSampleOffset
= AL_SAMPLE_OFFSET
,
67 sfByteOffset
= AL_BYTE_OFFSET
,
68 sfConeInnerAngle
= AL_CONE_INNER_ANGLE
,
69 sfConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
70 sfRefDistance
= AL_REFERENCE_DISTANCE
,
72 sfPosition
= AL_POSITION
,
73 sfVelocity
= AL_VELOCITY
,
74 sfDirection
= AL_DIRECTION
,
76 sfSourceRelative
= AL_SOURCE_RELATIVE
,
77 sfLooping
= AL_LOOPING
,
79 sfSourceState
= AL_SOURCE_STATE
,
80 sfBuffersQueued
= AL_BUFFERS_QUEUED
,
81 sfBuffersProcessed
= AL_BUFFERS_PROCESSED
,
82 sfSourceType
= AL_SOURCE_TYPE
,
85 sfConeOuterGainHF
= AL_CONE_OUTER_GAINHF
,
86 sfAirAbsorptionFactor
= AL_AIR_ABSORPTION_FACTOR
,
87 sfRoomRolloffFactor
= AL_ROOM_ROLLOFF_FACTOR
,
88 sfDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
89 sfAuxSendFilterGainAuto
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
90 sfAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
92 /* AL_SOFT_direct_channels */
93 sfDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
95 /* AL_EXT_source_distance_model */
96 sfDistanceModel
= AL_DISTANCE_MODEL
,
98 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
99 sfSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
100 sfByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
102 /* AL_SOFT_source_latency */
103 sfSecOffsetLatencySOFT
= AL_SEC_OFFSET_LATENCY_SOFT
,
106 typedef enum SrcIntProp
{
107 siMaxDistance
= AL_MAX_DISTANCE
,
108 siRolloffFactor
= AL_ROLLOFF_FACTOR
,
109 siRefDistance
= AL_REFERENCE_DISTANCE
,
110 siSourceRelative
= AL_SOURCE_RELATIVE
,
111 siConeInnerAngle
= AL_CONE_INNER_ANGLE
,
112 siConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
113 siLooping
= AL_LOOPING
,
114 siBuffer
= AL_BUFFER
,
115 siSourceState
= AL_SOURCE_STATE
,
116 siBuffersQueued
= AL_BUFFERS_QUEUED
,
117 siBuffersProcessed
= AL_BUFFERS_PROCESSED
,
118 siSourceType
= AL_SOURCE_TYPE
,
119 siSecOffset
= AL_SEC_OFFSET
,
120 siSampleOffset
= AL_SAMPLE_OFFSET
,
121 siByteOffset
= AL_BYTE_OFFSET
,
122 siDopplerFactor
= AL_DOPPLER_FACTOR
,
123 siPosition
= AL_POSITION
,
124 siVelocity
= AL_VELOCITY
,
125 siDirection
= AL_DIRECTION
,
128 siDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
129 siAuxSendFilterGainAutio
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
130 siAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
131 siDirectFilter
= AL_DIRECT_FILTER
,
132 siAuxSendFilter
= AL_AUXILIARY_SEND_FILTER
,
134 /* AL_SOFT_direct_channels */
135 siDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
137 /* AL_EXT_source_distance_model */
138 siDistanceModel
= AL_DISTANCE_MODEL
,
140 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
141 siSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
142 siByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
144 /* AL_SOFT_source_latency */
145 siSampleOffsetLatencySOFT
= AL_SAMPLE_OFFSET_LATENCY_SOFT
,
148 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
);
149 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
);
150 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
);
152 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
);
153 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
);
154 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
);
157 static ALint
IntValsByProp(ALenum prop
)
159 if(prop
!= (ALenum
)((SrcIntProp
)prop
))
161 switch((SrcIntProp
)prop
)
164 case siRolloffFactor
:
166 case siSourceRelative
:
167 case siConeInnerAngle
:
168 case siConeOuterAngle
:
172 case siBuffersQueued
:
173 case siBuffersProcessed
:
178 case siDopplerFactor
:
179 case siDirectFilterGainHFAuto
:
180 case siAuxSendFilterGainAutio
:
181 case siAuxSendFilterGainHFAuto
:
183 case siDirectChannelsSOFT
:
184 case siDistanceModel
:
187 case siSampleRWOffsetsSOFT
:
188 case siByteRWOffsetsSOFT
:
194 case siAuxSendFilter
:
197 case siSampleOffsetLatencySOFT
:
198 break; /* i64 only */
202 static ALint
Int64ValsByProp(ALenum prop
)
204 if(prop
!= (ALenum
)((SrcIntProp
)prop
))
206 switch((SrcIntProp
)prop
)
209 case siRolloffFactor
:
211 case siSourceRelative
:
212 case siConeInnerAngle
:
213 case siConeOuterAngle
:
217 case siBuffersQueued
:
218 case siBuffersProcessed
:
223 case siDopplerFactor
:
224 case siDirectFilterGainHFAuto
:
225 case siAuxSendFilterGainAutio
:
226 case siAuxSendFilterGainHFAuto
:
228 case siDirectChannelsSOFT
:
229 case siDistanceModel
:
232 case siSampleRWOffsetsSOFT
:
233 case siByteRWOffsetsSOFT
:
234 case siSampleOffsetLatencySOFT
:
240 case siAuxSendFilter
:
247 #define RETERR(x) do { \
248 alSetError(Context, (x)); \
252 #define CHECKVAL(x) do { \
254 RETERR(AL_INVALID_VALUE); \
257 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
)
264 CHECKVAL(*values
>= 0.0f
);
266 Source
->Pitch
= *values
;
267 Source
->NeedsUpdate
= AL_TRUE
;
270 case AL_CONE_INNER_ANGLE
:
271 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
273 Source
->InnerAngle
= *values
;
274 Source
->NeedsUpdate
= AL_TRUE
;
277 case AL_CONE_OUTER_ANGLE
:
278 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
280 Source
->OuterAngle
= *values
;
281 Source
->NeedsUpdate
= AL_TRUE
;
285 CHECKVAL(*values
>= 0.0f
);
287 Source
->Gain
= *values
;
288 Source
->NeedsUpdate
= AL_TRUE
;
291 case AL_MAX_DISTANCE
:
292 CHECKVAL(*values
>= 0.0f
);
294 Source
->MaxDistance
= *values
;
295 Source
->NeedsUpdate
= AL_TRUE
;
298 case AL_ROLLOFF_FACTOR
:
299 CHECKVAL(*values
>= 0.0f
);
301 Source
->RollOffFactor
= *values
;
302 Source
->NeedsUpdate
= AL_TRUE
;
305 case AL_REFERENCE_DISTANCE
:
306 CHECKVAL(*values
>= 0.0f
);
308 Source
->RefDistance
= *values
;
309 Source
->NeedsUpdate
= AL_TRUE
;
313 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
315 Source
->MinGain
= *values
;
316 Source
->NeedsUpdate
= AL_TRUE
;
320 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
322 Source
->MaxGain
= *values
;
323 Source
->NeedsUpdate
= AL_TRUE
;
326 case AL_CONE_OUTER_GAIN
:
327 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
329 Source
->OuterGain
= *values
;
330 Source
->NeedsUpdate
= AL_TRUE
;
333 case AL_CONE_OUTER_GAINHF
:
334 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
336 Source
->OuterGainHF
= *values
;
337 Source
->NeedsUpdate
= AL_TRUE
;
340 case AL_AIR_ABSORPTION_FACTOR
:
341 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
343 Source
->AirAbsorptionFactor
= *values
;
344 Source
->NeedsUpdate
= AL_TRUE
;
347 case AL_ROOM_ROLLOFF_FACTOR
:
348 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
350 Source
->RoomRolloffFactor
= *values
;
351 Source
->NeedsUpdate
= AL_TRUE
;
354 case AL_DOPPLER_FACTOR
:
355 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
357 Source
->DopplerFactor
= *values
;
358 Source
->NeedsUpdate
= AL_TRUE
;
362 case AL_SAMPLE_OFFSET
:
364 CHECKVAL(*values
>= 0.0f
);
366 LockContext(Context
);
367 Source
->OffsetType
= prop
;
368 Source
->Offset
= *values
;
370 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
371 !Context
->DeferUpdates
)
373 if(ApplyOffset(Source
) == AL_FALSE
)
375 UnlockContext(Context
);
376 RETERR(AL_INVALID_VALUE
);
379 UnlockContext(Context
);
383 case AL_SEC_OFFSET_LATENCY_SOFT
:
385 RETERR(AL_INVALID_OPERATION
);
389 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
391 LockContext(Context
);
392 Source
->Position
[0] = values
[0];
393 Source
->Position
[1] = values
[1];
394 Source
->Position
[2] = values
[2];
395 UnlockContext(Context
);
396 Source
->NeedsUpdate
= AL_TRUE
;
400 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
402 LockContext(Context
);
403 Source
->Velocity
[0] = values
[0];
404 Source
->Velocity
[1] = values
[1];
405 Source
->Velocity
[2] = values
[2];
406 UnlockContext(Context
);
407 Source
->NeedsUpdate
= AL_TRUE
;
411 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
413 LockContext(Context
);
414 Source
->Orientation
[0] = values
[0];
415 Source
->Orientation
[1] = values
[1];
416 Source
->Orientation
[2] = values
[2];
417 UnlockContext(Context
);
418 Source
->NeedsUpdate
= AL_TRUE
;
422 case sfSampleRWOffsetsSOFT
:
423 case sfByteRWOffsetsSOFT
:
424 RETERR(AL_INVALID_OPERATION
);
427 case sfSourceRelative
:
431 case sfDistanceModel
:
432 case sfDirectFilterGainHFAuto
:
433 case sfAuxSendFilterGainAuto
:
434 case sfAuxSendFilterGainHFAuto
:
435 case sfDirectChannelsSOFT
:
436 ival
= (ALint
)values
[0];
437 return SetSourceiv(Source
, Context
, prop
, &ival
);
440 case sfBuffersQueued
:
441 case sfBuffersProcessed
:
442 ival
= (ALint
)((ALuint
)values
[0]);
443 return SetSourceiv(Source
, Context
, prop
, &ival
);
446 ERR("Unexpected property: 0x%04x\n", prop
);
447 RETERR(AL_INVALID_ENUM
);
450 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
)
452 ALCdevice
*device
= Context
->Device
;
453 ALbuffer
*buffer
= NULL
;
454 ALfilter
*filter
= NULL
;
455 ALeffectslot
*slot
= NULL
;
456 ALbufferlistitem
*oldlist
;
461 case AL_SOURCE_RELATIVE
:
462 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
464 Source
->HeadRelative
= (ALboolean
)*values
;
465 Source
->NeedsUpdate
= AL_TRUE
;
469 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
471 Source
->Looping
= (ALboolean
)*values
;
475 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
477 LockContext(Context
);
478 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
480 UnlockContext(Context
);
481 RETERR(AL_INVALID_OPERATION
);
484 Source
->BuffersInQueue
= 0;
485 Source
->BuffersPlayed
= 0;
489 ALbufferlistitem
*BufferListItem
;
491 /* Source is now Static */
492 Source
->SourceType
= AL_STATIC
;
494 /* Add the selected buffer to a one-item queue */
495 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
496 BufferListItem
->buffer
= buffer
;
497 BufferListItem
->next
= NULL
;
498 BufferListItem
->prev
= NULL
;
499 IncrementRef(&buffer
->ref
);
501 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, BufferListItem
);
502 Source
->BuffersInQueue
= 1;
504 ReadLock(&buffer
->lock
);
505 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
506 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
507 ReadUnlock(&buffer
->lock
);
508 if(buffer
->FmtChannels
== FmtMono
)
509 Source
->Update
= CalcSourceParams
;
511 Source
->Update
= CalcNonAttnSourceParams
;
512 Source
->NeedsUpdate
= AL_TRUE
;
516 /* Source is now Undetermined */
517 Source
->SourceType
= AL_UNDETERMINED
;
518 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, NULL
);
521 /* Delete all elements in the previous queue */
522 while(oldlist
!= NULL
)
524 ALbufferlistitem
*temp
= oldlist
;
525 oldlist
= temp
->next
;
528 DecrementRef(&temp
->buffer
->ref
);
531 UnlockContext(Context
);
536 case siBuffersQueued
:
537 case siBuffersProcessed
:
539 RETERR(AL_INVALID_OPERATION
);
542 case AL_SAMPLE_OFFSET
:
544 CHECKVAL(*values
>= 0);
546 LockContext(Context
);
547 Source
->OffsetType
= prop
;
548 Source
->Offset
= *values
;
550 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
551 !Context
->DeferUpdates
)
553 if(ApplyOffset(Source
) == AL_FALSE
)
555 UnlockContext(Context
);
556 RETERR(AL_INVALID_VALUE
);
559 UnlockContext(Context
);
563 case siSampleRWOffsetsSOFT
:
564 case siByteRWOffsetsSOFT
:
565 case siSampleOffsetLatencySOFT
:
567 RETERR(AL_INVALID_OPERATION
);
570 case AL_DIRECT_FILTER
:
571 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
573 LockContext(Context
);
576 Source
->DirectGain
= 1.0f
;
577 Source
->DirectGainHF
= 1.0f
;
581 Source
->DirectGain
= filter
->Gain
;
582 Source
->DirectGainHF
= filter
->GainHF
;
584 UnlockContext(Context
);
585 Source
->NeedsUpdate
= AL_TRUE
;
588 case AL_DIRECT_FILTER_GAINHF_AUTO
:
589 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
591 Source
->DryGainHFAuto
= *values
;
592 Source
->NeedsUpdate
= AL_TRUE
;
595 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
596 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
598 Source
->WetGainAuto
= *values
;
599 Source
->NeedsUpdate
= AL_TRUE
;
602 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
603 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
605 Source
->WetGainHFAuto
= *values
;
606 Source
->NeedsUpdate
= AL_TRUE
;
609 case AL_DIRECT_CHANNELS_SOFT
:
610 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
612 Source
->DirectChannels
= *values
;
613 Source
->NeedsUpdate
= AL_TRUE
;
616 case AL_DISTANCE_MODEL
:
617 CHECKVAL(*values
== AL_NONE
||
618 *values
== AL_INVERSE_DISTANCE
||
619 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
620 *values
== AL_LINEAR_DISTANCE
||
621 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
622 *values
== AL_EXPONENT_DISTANCE
||
623 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
625 Source
->DistanceModel
= *values
;
626 if(Context
->SourceDistanceModel
)
627 Source
->NeedsUpdate
= AL_TRUE
;
631 case AL_AUXILIARY_SEND_FILTER
:
632 LockContext(Context
);
633 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
634 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
635 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
637 UnlockContext(Context
);
638 RETERR(AL_INVALID_VALUE
);
641 /* Add refcount on the new slot, and release the previous slot */
642 if(slot
) IncrementRef(&slot
->ref
);
643 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
644 if(slot
) DecrementRef(&slot
->ref
);
649 Source
->Send
[values
[1]].Gain
= 1.0f
;
650 Source
->Send
[values
[1]].GainHF
= 1.0f
;
654 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
655 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
657 Source
->NeedsUpdate
= AL_TRUE
;
658 UnlockContext(Context
);
662 case AL_MAX_DISTANCE
:
663 case AL_ROLLOFF_FACTOR
:
664 case AL_CONE_INNER_ANGLE
:
665 case AL_CONE_OUTER_ANGLE
:
666 case AL_REFERENCE_DISTANCE
:
667 case siDopplerFactor
:
668 fvals
[0] = (ALfloat
)*values
;
669 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
674 fvals
[0] = (ALfloat
)values
[0];
675 fvals
[1] = (ALfloat
)values
[1];
676 fvals
[2] = (ALfloat
)values
[2];
677 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
680 ERR("Unexpected property: 0x%04x\n", prop
);
681 RETERR(AL_INVALID_ENUM
);
684 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
)
691 case siSampleRWOffsetsSOFT
:
692 case siByteRWOffsetsSOFT
:
693 case siSampleOffsetLatencySOFT
:
695 RETERR(AL_INVALID_OPERATION
);
699 case AL_SOURCE_RELATIVE
:
701 case AL_SOURCE_STATE
:
703 case AL_SAMPLE_OFFSET
:
705 case siBuffersQueued
:
706 case siBuffersProcessed
:
707 case AL_DIRECT_FILTER_GAINHF_AUTO
:
708 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
709 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
710 case AL_DIRECT_CHANNELS_SOFT
:
711 case AL_DISTANCE_MODEL
:
712 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
714 ivals
[0] = (ALint
)*values
;
715 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
719 case AL_DIRECT_FILTER
:
720 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
722 ivals
[0] = (ALuint
)*values
;
723 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
726 case AL_AUXILIARY_SEND_FILTER
:
727 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
728 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
729 values
[2] <= UINT_MAX
&& values
[2] >= 0);
731 ivals
[0] = (ALuint
)values
[0];
732 ivals
[1] = (ALuint
)values
[1];
733 ivals
[2] = (ALuint
)values
[2];
734 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
737 case AL_MAX_DISTANCE
:
738 case AL_ROLLOFF_FACTOR
:
739 case AL_CONE_INNER_ANGLE
:
740 case AL_CONE_OUTER_ANGLE
:
741 case AL_REFERENCE_DISTANCE
:
743 case siDopplerFactor
:
744 fvals
[0] = (ALfloat
)*values
;
745 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
751 fvals
[0] = (ALfloat
)values
[0];
752 fvals
[1] = (ALfloat
)values
[1];
753 fvals
[2] = (ALfloat
)values
[2];
754 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
757 ERR("Unexpected property: 0x%04x\n", prop
);
758 RETERR(AL_INVALID_ENUM
);
764 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
)
774 *values
= Source
->Gain
;
778 *values
= Source
->Pitch
;
781 case AL_MAX_DISTANCE
:
782 *values
= Source
->MaxDistance
;
785 case AL_ROLLOFF_FACTOR
:
786 *values
= Source
->RollOffFactor
;
789 case AL_REFERENCE_DISTANCE
:
790 *values
= Source
->RefDistance
;
793 case AL_CONE_INNER_ANGLE
:
794 *values
= Source
->InnerAngle
;
797 case AL_CONE_OUTER_ANGLE
:
798 *values
= Source
->OuterAngle
;
802 *values
= Source
->MinGain
;
806 *values
= Source
->MaxGain
;
809 case AL_CONE_OUTER_GAIN
:
810 *values
= Source
->OuterGain
;
814 case AL_SAMPLE_OFFSET
:
816 LockContext(Context
);
817 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
818 Context
->Device
->Frequency
;
819 GetSourceOffsets(Source
, prop
, offsets
, updateLen
);
820 UnlockContext(Context
);
821 *values
= offsets
[0];
824 case AL_CONE_OUTER_GAINHF
:
825 *values
= Source
->OuterGainHF
;
828 case AL_AIR_ABSORPTION_FACTOR
:
829 *values
= Source
->AirAbsorptionFactor
;
832 case AL_ROOM_ROLLOFF_FACTOR
:
833 *values
= Source
->RoomRolloffFactor
;
836 case AL_DOPPLER_FACTOR
:
837 *values
= Source
->DopplerFactor
;
840 case AL_SAMPLE_RW_OFFSETS_SOFT
:
841 case AL_BYTE_RW_OFFSETS_SOFT
:
842 LockContext(Context
);
843 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
844 Context
->Device
->Frequency
;
845 GetSourceOffsets(Source
, prop
, values
, updateLen
);
846 UnlockContext(Context
);
849 case AL_SEC_OFFSET_LATENCY_SOFT
:
850 LockContext(Context
);
851 values
[0] = GetSourceSecOffset(Source
);
852 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
854 UnlockContext(Context
);
858 LockContext(Context
);
859 values
[0] = Source
->Position
[0];
860 values
[1] = Source
->Position
[1];
861 values
[2] = Source
->Position
[2];
862 UnlockContext(Context
);
866 LockContext(Context
);
867 values
[0] = Source
->Velocity
[0];
868 values
[1] = Source
->Velocity
[1];
869 values
[2] = Source
->Velocity
[2];
870 UnlockContext(Context
);
874 LockContext(Context
);
875 values
[0] = Source
->Orientation
[0];
876 values
[1] = Source
->Orientation
[1];
877 values
[2] = Source
->Orientation
[2];
878 UnlockContext(Context
);
881 case AL_SOURCE_RELATIVE
:
884 case AL_SOURCE_STATE
:
885 case AL_BUFFERS_QUEUED
:
886 case AL_BUFFERS_PROCESSED
:
888 case AL_DIRECT_FILTER_GAINHF_AUTO
:
889 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
890 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
891 case AL_DIRECT_CHANNELS_SOFT
:
892 case AL_DISTANCE_MODEL
:
893 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) == AL_NO_ERROR
)
894 *values
= (ALdouble
)ivals
[0];
898 ERR("Unexpected property: 0x%04x\n", prop
);
899 RETERR(AL_INVALID_ENUM
);
902 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
)
904 ALbufferlistitem
*BufferList
;
910 case AL_SOURCE_RELATIVE
:
911 *values
= Source
->HeadRelative
;
915 *values
= Source
->Looping
;
919 LockContext(Context
);
920 BufferList
= Source
->queue
;
921 if(Source
->SourceType
!= AL_STATIC
)
923 ALuint i
= Source
->BuffersPlayed
;
926 BufferList
= BufferList
->next
;
930 *values
= ((BufferList
&& BufferList
->buffer
) ?
931 BufferList
->buffer
->id
: 0);
932 UnlockContext(Context
);
935 case AL_SOURCE_STATE
:
936 *values
= Source
->state
;
939 case AL_BUFFERS_QUEUED
:
940 *values
= Source
->BuffersInQueue
;
943 case AL_BUFFERS_PROCESSED
:
944 LockContext(Context
);
945 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
947 /* Buffers on a looping source are in a perpetual state of
948 * PENDING, so don't report any as PROCESSED */
952 *values
= Source
->BuffersPlayed
;
953 UnlockContext(Context
);
957 *values
= Source
->SourceType
;
960 case AL_DIRECT_FILTER_GAINHF_AUTO
:
961 *values
= Source
->DryGainHFAuto
;
964 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
965 *values
= Source
->WetGainAuto
;
968 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
969 *values
= Source
->WetGainHFAuto
;
972 case AL_DIRECT_CHANNELS_SOFT
:
973 *values
= Source
->DirectChannels
;
976 case AL_DISTANCE_MODEL
:
977 *values
= Source
->DistanceModel
;
980 case AL_MAX_DISTANCE
:
981 case AL_ROLLOFF_FACTOR
:
982 case AL_REFERENCE_DISTANCE
:
983 case AL_CONE_INNER_ANGLE
:
984 case AL_CONE_OUTER_ANGLE
:
986 case AL_SAMPLE_OFFSET
:
988 case AL_DOPPLER_FACTOR
:
989 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
990 *values
= (ALint
)dvals
[0];
993 case AL_SAMPLE_RW_OFFSETS_SOFT
:
994 case AL_BYTE_RW_OFFSETS_SOFT
:
995 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
997 values
[0] = (ALint
)dvals
[0];
998 values
[1] = (ALint
)dvals
[1];
1005 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
1007 values
[0] = (ALint
)dvals
[0];
1008 values
[1] = (ALint
)dvals
[1];
1009 values
[2] = (ALint
)dvals
[2];
1013 case siSampleOffsetLatencySOFT
:
1017 case siDirectFilter
:
1018 case siAuxSendFilter
:
1023 ERR("Unexpected property: 0x%04x\n", prop
);
1024 RETERR(AL_INVALID_ENUM
);
1027 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
)
1035 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1036 LockContext(Context
);
1037 values
[0] = GetSourceOffset(Source
);
1038 values
[1] = ALCdevice_GetLatency(Context
->Device
);
1039 UnlockContext(Context
);
1042 case AL_MAX_DISTANCE
:
1043 case AL_ROLLOFF_FACTOR
:
1044 case AL_REFERENCE_DISTANCE
:
1045 case AL_CONE_INNER_ANGLE
:
1046 case AL_CONE_OUTER_ANGLE
:
1048 case AL_SAMPLE_OFFSET
:
1049 case AL_BYTE_OFFSET
:
1050 case AL_DOPPLER_FACTOR
:
1051 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
1052 *values
= (ALint64
)dvals
[0];
1055 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1056 case AL_BYTE_RW_OFFSETS_SOFT
:
1057 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
1059 values
[0] = (ALint64
)dvals
[0];
1060 values
[1] = (ALint64
)dvals
[1];
1067 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
1069 values
[0] = (ALint64
)dvals
[0];
1070 values
[1] = (ALint64
)dvals
[1];
1071 values
[2] = (ALint64
)dvals
[2];
1075 case AL_SOURCE_RELATIVE
:
1078 case AL_SOURCE_STATE
:
1079 case AL_BUFFERS_QUEUED
:
1080 case AL_BUFFERS_PROCESSED
:
1081 case AL_SOURCE_TYPE
:
1082 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1083 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1084 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1085 case AL_DIRECT_CHANNELS_SOFT
:
1086 case AL_DISTANCE_MODEL
:
1087 case siDirectFilter
:
1088 case siAuxSendFilter
:
1089 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) == AL_NO_ERROR
)
1094 ERR("Unexpected property: 0x%04x\n", prop
);
1095 RETERR(AL_INVALID_ENUM
);
1101 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
1103 ALCcontext
*Context
;
1106 Context
= GetContextRef();
1107 if(!Context
) return;
1113 CHECK_VALUE(Context
, n
>= 0);
1114 for(cur
= 0;cur
< n
;cur
++)
1116 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
1118 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
1119 InitSourceParams(source
);
1121 err
= NewThunkEntry(&source
->id
);
1122 if(err
== AL_NO_ERROR
)
1123 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->id
, source
);
1124 if(err
!= AL_NO_ERROR
)
1126 FreeThunkEntry(source
->id
);
1127 memset(source
, 0, sizeof(ALsource
));
1130 al_throwerr(Context
, err
);
1133 sources
[cur
] = source
->id
;
1139 alDeleteSources(cur
, sources
);
1143 ALCcontext_DecRef(Context
);
1147 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
1149 ALCcontext
*Context
;
1151 Context
= GetContextRef();
1152 if(!Context
) return;
1156 ALbufferlistitem
*BufferList
;
1160 CHECK_VALUE(Context
, n
>= 0);
1162 /* Check that all Sources are valid */
1163 for(i
= 0;i
< n
;i
++)
1165 if(LookupSource(Context
, sources
[i
]) == NULL
)
1166 al_throwerr(Context
, AL_INVALID_NAME
);
1169 for(i
= 0;i
< n
;i
++)
1171 ALsource
**srclist
, **srclistend
;
1173 if((Source
=RemoveSource(Context
, sources
[i
])) == NULL
)
1175 FreeThunkEntry(Source
->id
);
1177 LockContext(Context
);
1178 srclist
= Context
->ActiveSources
;
1179 srclistend
= srclist
+ Context
->ActiveSourceCount
;
1180 while(srclist
!= srclistend
)
1182 if(*srclist
== Source
)
1184 Context
->ActiveSourceCount
--;
1185 *srclist
= *(--srclistend
);
1190 UnlockContext(Context
);
1192 while(Source
->queue
!= NULL
)
1194 BufferList
= Source
->queue
;
1195 Source
->queue
= BufferList
->next
;
1197 if(BufferList
->buffer
!= NULL
)
1198 DecrementRef(&BufferList
->buffer
->ref
);
1202 for(j
= 0;j
< MAX_SENDS
;++j
)
1204 if(Source
->Send
[j
].Slot
)
1205 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
1206 Source
->Send
[j
].Slot
= NULL
;
1209 memset(Source
, 0, sizeof(*Source
));
1215 ALCcontext_DecRef(Context
);
1219 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1221 ALCcontext
*Context
;
1224 Context
= GetContextRef();
1225 if(!Context
) return AL_FALSE
;
1227 result
= (LookupSource(Context
, source
) ? AL_TRUE
: AL_FALSE
);
1229 ALCcontext_DecRef(Context
);
1235 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1237 ALCcontext
*Context
;
1240 Context
= GetContextRef();
1241 if(!Context
) return;
1243 if((Source
=LookupSource(Context
, source
)) == NULL
)
1244 alSetError(Context
, AL_INVALID_NAME
);
1248 case AL_CONE_INNER_ANGLE
:
1249 case AL_CONE_OUTER_ANGLE
:
1251 case AL_MAX_DISTANCE
:
1252 case AL_ROLLOFF_FACTOR
:
1253 case AL_REFERENCE_DISTANCE
:
1256 case AL_CONE_OUTER_GAIN
:
1257 case AL_CONE_OUTER_GAINHF
:
1258 case AL_AIR_ABSORPTION_FACTOR
:
1259 case AL_ROOM_ROLLOFF_FACTOR
:
1260 case AL_DOPPLER_FACTOR
:
1262 case AL_SAMPLE_OFFSET
:
1263 case AL_BYTE_OFFSET
:
1264 SetSourcefv(Source
, Context
, param
, &value
);
1268 alSetError(Context
, AL_INVALID_ENUM
);
1271 ALCcontext_DecRef(Context
);
1274 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1276 ALCcontext
*Context
;
1280 Context
= GetContextRef();
1281 if(!Context
) return;
1283 if((Source
=LookupSource(Context
, source
)) == NULL
)
1284 alSetError(Context
, AL_INVALID_NAME
);
1293 SetSourcefv(Source
, Context
, param
, fvals
);
1297 alSetError(Context
, AL_INVALID_ENUM
);
1300 ALCcontext_DecRef(Context
);
1303 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1305 ALCcontext
*Context
;
1308 Context
= GetContextRef();
1309 if(!Context
) return;
1311 if((Source
=LookupSource(Context
, source
)) == NULL
)
1312 alSetError(Context
, AL_INVALID_NAME
);
1314 alSetError(Context
, AL_INVALID_VALUE
);
1318 case AL_CONE_INNER_ANGLE
:
1319 case AL_CONE_OUTER_ANGLE
:
1321 case AL_MAX_DISTANCE
:
1322 case AL_ROLLOFF_FACTOR
:
1323 case AL_REFERENCE_DISTANCE
:
1326 case AL_CONE_OUTER_GAIN
:
1327 case AL_CONE_OUTER_GAINHF
:
1329 case AL_SAMPLE_OFFSET
:
1330 case AL_BYTE_OFFSET
:
1331 case AL_AIR_ABSORPTION_FACTOR
:
1332 case AL_ROOM_ROLLOFF_FACTOR
:
1337 SetSourcefv(Source
, Context
, param
, values
);
1341 alSetError(Context
, AL_INVALID_ENUM
);
1344 ALCcontext_DecRef(Context
);
1348 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1350 ALCcontext
*Context
;
1354 Context
= GetContextRef();
1355 if(!Context
) return;
1357 if((Source
=LookupSource(Context
, source
)) == NULL
)
1358 alSetError(Context
, AL_INVALID_NAME
);
1362 case AL_CONE_INNER_ANGLE
:
1363 case AL_CONE_OUTER_ANGLE
:
1365 case AL_MAX_DISTANCE
:
1366 case AL_ROLLOFF_FACTOR
:
1367 case AL_REFERENCE_DISTANCE
:
1370 case AL_CONE_OUTER_GAIN
:
1371 case AL_CONE_OUTER_GAINHF
:
1372 case AL_AIR_ABSORPTION_FACTOR
:
1373 case AL_ROOM_ROLLOFF_FACTOR
:
1374 case AL_DOPPLER_FACTOR
:
1376 case AL_SAMPLE_OFFSET
:
1377 case AL_BYTE_OFFSET
:
1378 fval
= (ALfloat
)value
;
1379 SetSourcefv(Source
, Context
, param
, &fval
);
1383 alSetError(Context
, AL_INVALID_ENUM
);
1386 ALCcontext_DecRef(Context
);
1389 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1391 ALCcontext
*Context
;
1395 Context
= GetContextRef();
1396 if(!Context
) return;
1398 if((Source
=LookupSource(Context
, source
)) == NULL
)
1399 alSetError(Context
, AL_INVALID_NAME
);
1405 fvals
[0] = (ALfloat
)value1
;
1406 fvals
[1] = (ALfloat
)value2
;
1407 fvals
[2] = (ALfloat
)value3
;
1408 SetSourcefv(Source
, Context
, param
, fvals
);
1412 alSetError(Context
, AL_INVALID_ENUM
);
1415 ALCcontext_DecRef(Context
);
1418 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1420 ALCcontext
*Context
;
1424 Context
= GetContextRef();
1425 if(!Context
) return;
1427 if((Source
=LookupSource(Context
, source
)) == NULL
)
1428 alSetError(Context
, AL_INVALID_NAME
);
1430 alSetError(Context
, AL_INVALID_VALUE
);
1434 case AL_CONE_INNER_ANGLE
:
1435 case AL_CONE_OUTER_ANGLE
:
1437 case AL_MAX_DISTANCE
:
1438 case AL_ROLLOFF_FACTOR
:
1439 case AL_REFERENCE_DISTANCE
:
1442 case AL_CONE_OUTER_GAIN
:
1443 case AL_CONE_OUTER_GAINHF
:
1445 case AL_SAMPLE_OFFSET
:
1446 case AL_BYTE_OFFSET
:
1447 case AL_AIR_ABSORPTION_FACTOR
:
1448 case AL_ROOM_ROLLOFF_FACTOR
:
1449 fvals
[0] = (ALfloat
)values
[0];
1450 SetSourcefv(Source
, Context
, param
, fvals
);
1453 case AL_SEC_OFFSET_LATENCY_SOFT
:
1454 fvals
[0] = (ALfloat
)values
[0];
1455 fvals
[1] = (ALfloat
)values
[1];
1456 SetSourcefv(Source
, Context
, param
, fvals
);
1462 fvals
[0] = (ALfloat
)values
[0];
1463 fvals
[1] = (ALfloat
)values
[1];
1464 fvals
[2] = (ALfloat
)values
[2];
1465 SetSourcefv(Source
, Context
, param
, fvals
);
1469 alSetError(Context
, AL_INVALID_ENUM
);
1472 ALCcontext_DecRef(Context
);
1476 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1478 ALCcontext
*Context
;
1481 Context
= GetContextRef();
1482 if(!Context
) return;
1484 if((Source
=LookupSource(Context
, source
)) == NULL
)
1485 alSetError(Context
, AL_INVALID_NAME
);
1486 else if(!(IntValsByProp(param
) == 1))
1487 alSetError(Context
, AL_INVALID_ENUM
);
1489 SetSourceiv(Source
, Context
, param
, &value
);
1491 ALCcontext_DecRef(Context
);
1494 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1496 ALCcontext
*Context
;
1499 Context
= GetContextRef();
1500 if(!Context
) return;
1502 if((Source
=LookupSource(Context
, source
)) == NULL
)
1503 alSetError(Context
, AL_INVALID_NAME
);
1504 else if(!(IntValsByProp(param
) == 3))
1505 alSetError(Context
, AL_INVALID_ENUM
);
1508 ALint ivals
[3] = { value1
, value2
, value3
};
1509 SetSourceiv(Source
, Context
, param
, ivals
);
1512 ALCcontext_DecRef(Context
);
1515 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1517 ALCcontext
*Context
;
1520 Context
= GetContextRef();
1521 if(!Context
) return;
1523 if((Source
=LookupSource(Context
, source
)) == NULL
)
1524 alSetError(Context
, AL_INVALID_NAME
);
1526 alSetError(Context
, AL_INVALID_VALUE
);
1527 else if(!(IntValsByProp(param
) > 0))
1528 alSetError(Context
, AL_INVALID_ENUM
);
1530 SetSourceiv(Source
, Context
, param
, values
);
1532 ALCcontext_DecRef(Context
);
1536 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1538 ALCcontext
*Context
;
1541 Context
= GetContextRef();
1542 if(!Context
) return;
1544 if((Source
=LookupSource(Context
, source
)) == NULL
)
1545 alSetError(Context
, AL_INVALID_NAME
);
1546 else if(!(Int64ValsByProp(param
) == 1))
1547 alSetError(Context
, AL_INVALID_ENUM
);
1549 SetSourcei64v(Source
, Context
, param
, &value
);
1551 ALCcontext_DecRef(Context
);
1554 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1556 ALCcontext
*Context
;
1559 Context
= GetContextRef();
1560 if(!Context
) return;
1562 if((Source
=LookupSource(Context
, source
)) == NULL
)
1563 alSetError(Context
, AL_INVALID_NAME
);
1564 else if(!(Int64ValsByProp(param
) == 3))
1565 alSetError(Context
, AL_INVALID_ENUM
);
1568 ALint64SOFT i64vals
[3] = { value1
, value2
, value3
};
1569 SetSourcei64v(Source
, Context
, param
, i64vals
);
1572 ALCcontext_DecRef(Context
);
1575 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1577 ALCcontext
*Context
;
1580 Context
= GetContextRef();
1581 if(!Context
) return;
1583 if((Source
=LookupSource(Context
, source
)) == NULL
)
1584 alSetError(Context
, AL_INVALID_NAME
);
1586 alSetError(Context
, AL_INVALID_VALUE
);
1587 else if(!(Int64ValsByProp(param
) > 0))
1588 alSetError(Context
, AL_INVALID_ENUM
);
1590 SetSourcei64v(Source
, Context
, param
, values
);
1592 ALCcontext_DecRef(Context
);
1596 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1598 ALCcontext
*Context
;
1602 Context
= GetContextRef();
1603 if(!Context
) return;
1605 if((Source
=LookupSource(Context
, source
)) == NULL
)
1606 alSetError(Context
, AL_INVALID_NAME
);
1608 alSetError(Context
, AL_INVALID_VALUE
);
1615 case AL_MAX_DISTANCE
:
1616 case AL_ROLLOFF_FACTOR
:
1617 case AL_CONE_OUTER_GAIN
:
1618 case AL_CONE_OUTER_GAINHF
:
1620 case AL_SAMPLE_OFFSET
:
1621 case AL_BYTE_OFFSET
:
1622 case AL_CONE_INNER_ANGLE
:
1623 case AL_CONE_OUTER_ANGLE
:
1624 case AL_REFERENCE_DISTANCE
:
1625 case AL_AIR_ABSORPTION_FACTOR
:
1626 case AL_ROOM_ROLLOFF_FACTOR
:
1627 case AL_DOPPLER_FACTOR
:
1628 if(GetSourcedv(Source
, Context
, param
, &dval
) == AL_NO_ERROR
)
1629 *value
= (ALfloat
)dval
;
1633 alSetError(Context
, AL_INVALID_ENUM
);
1636 ALCcontext_DecRef(Context
);
1640 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1642 ALCcontext
*Context
;
1646 Context
= GetContextRef();
1647 if(!Context
) return;
1649 if((Source
=LookupSource(Context
, source
)) == NULL
)
1650 alSetError(Context
, AL_INVALID_NAME
);
1651 else if(!(value1
&& value2
&& value3
))
1652 alSetError(Context
, AL_INVALID_VALUE
);
1658 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1660 *value1
= (ALfloat
)dvals
[0];
1661 *value2
= (ALfloat
)dvals
[1];
1662 *value3
= (ALfloat
)dvals
[2];
1667 alSetError(Context
, AL_INVALID_ENUM
);
1670 ALCcontext_DecRef(Context
);
1674 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1676 ALCcontext
*Context
;
1686 case AL_MAX_DISTANCE
:
1687 case AL_ROLLOFF_FACTOR
:
1688 case AL_DOPPLER_FACTOR
:
1689 case AL_CONE_OUTER_GAIN
:
1691 case AL_SAMPLE_OFFSET
:
1692 case AL_BYTE_OFFSET
:
1693 case AL_CONE_INNER_ANGLE
:
1694 case AL_CONE_OUTER_ANGLE
:
1695 case AL_REFERENCE_DISTANCE
:
1696 case AL_CONE_OUTER_GAINHF
:
1697 case AL_AIR_ABSORPTION_FACTOR
:
1698 case AL_ROOM_ROLLOFF_FACTOR
:
1699 alGetSourcef(source
, param
, values
);
1705 alGetSource3f(source
, param
, values
+0, values
+1, values
+2);
1709 Context
= GetContextRef();
1710 if(!Context
) return;
1712 if((Source
=LookupSource(Context
, source
)) == NULL
)
1713 alSetError(Context
, AL_INVALID_NAME
);
1715 alSetError(Context
, AL_INVALID_VALUE
);
1718 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1719 case AL_BYTE_RW_OFFSETS_SOFT
:
1720 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1722 values
[0] = (ALfloat
)dvals
[0];
1723 values
[1] = (ALfloat
)dvals
[1];
1728 alSetError(Context
, AL_INVALID_ENUM
);
1731 ALCcontext_DecRef(Context
);
1735 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1737 ALCcontext
*Context
;
1740 Context
= GetContextRef();
1741 if(!Context
) return;
1743 if((Source
=LookupSource(Context
, source
)) == NULL
)
1744 alSetError(Context
, AL_INVALID_NAME
);
1746 alSetError(Context
, AL_INVALID_VALUE
);
1753 case AL_MAX_DISTANCE
:
1754 case AL_ROLLOFF_FACTOR
:
1755 case AL_CONE_OUTER_GAIN
:
1756 case AL_CONE_OUTER_GAINHF
:
1758 case AL_SAMPLE_OFFSET
:
1759 case AL_BYTE_OFFSET
:
1760 case AL_CONE_INNER_ANGLE
:
1761 case AL_CONE_OUTER_ANGLE
:
1762 case AL_REFERENCE_DISTANCE
:
1763 case AL_AIR_ABSORPTION_FACTOR
:
1764 case AL_ROOM_ROLLOFF_FACTOR
:
1765 case AL_DOPPLER_FACTOR
:
1766 GetSourcedv(Source
, Context
, param
, value
);
1770 alSetError(Context
, AL_INVALID_ENUM
);
1773 ALCcontext_DecRef(Context
);
1776 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1778 ALCcontext
*Context
;
1782 Context
= GetContextRef();
1783 if(!Context
) return;
1785 if((Source
=LookupSource(Context
, source
)) == NULL
)
1786 alSetError(Context
, AL_INVALID_NAME
);
1787 else if(!(value1
&& value2
&& value3
))
1788 alSetError(Context
, AL_INVALID_VALUE
);
1794 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1803 alSetError(Context
, AL_INVALID_ENUM
);
1806 ALCcontext_DecRef(Context
);
1809 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1811 ALCcontext
*Context
;
1814 Context
= GetContextRef();
1815 if(!Context
) return;
1817 if((Source
=LookupSource(Context
, source
)) == NULL
)
1818 alSetError(Context
, AL_INVALID_NAME
);
1820 alSetError(Context
, AL_INVALID_VALUE
);
1827 case AL_MAX_DISTANCE
:
1828 case AL_ROLLOFF_FACTOR
:
1829 case AL_DOPPLER_FACTOR
:
1830 case AL_CONE_OUTER_GAIN
:
1832 case AL_SAMPLE_OFFSET
:
1833 case AL_BYTE_OFFSET
:
1834 case AL_CONE_INNER_ANGLE
:
1835 case AL_CONE_OUTER_ANGLE
:
1836 case AL_REFERENCE_DISTANCE
:
1837 case AL_CONE_OUTER_GAINHF
:
1838 case AL_AIR_ABSORPTION_FACTOR
:
1839 case AL_ROOM_ROLLOFF_FACTOR
:
1841 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1842 case AL_BYTE_RW_OFFSETS_SOFT
:
1843 case AL_SEC_OFFSET_LATENCY_SOFT
:
1848 GetSourcedv(Source
, Context
, param
, values
);
1852 alSetError(Context
, AL_INVALID_ENUM
);
1855 ALCcontext_DecRef(Context
);
1859 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1861 ALCcontext
*Context
;
1864 Context
= GetContextRef();
1865 if(!Context
) return;
1867 if((Source
=LookupSource(Context
, source
)) == NULL
)
1868 alSetError(Context
, AL_INVALID_NAME
);
1870 alSetError(Context
, AL_INVALID_VALUE
);
1871 else if(!(IntValsByProp(param
) == 1))
1872 alSetError(Context
, AL_INVALID_ENUM
);
1874 GetSourceiv(Source
, Context
, param
, value
);
1876 ALCcontext_DecRef(Context
);
1880 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1882 ALCcontext
*Context
;
1885 Context
= GetContextRef();
1886 if(!Context
) return;
1888 if((Source
=LookupSource(Context
, source
)) == NULL
)
1889 alSetError(Context
, AL_INVALID_NAME
);
1890 else if(!(value1
&& value2
&& value3
))
1891 alSetError(Context
, AL_INVALID_VALUE
);
1892 else if(!(IntValsByProp(param
) == 3))
1893 alSetError(Context
, AL_INVALID_ENUM
);
1897 if(GetSourceiv(Source
, Context
, param
, ivals
) == AL_NO_ERROR
)
1905 ALCcontext_DecRef(Context
);
1909 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1911 ALCcontext
*Context
;
1914 Context
= GetContextRef();
1915 if(!Context
) return;
1917 if((Source
=LookupSource(Context
, source
)) == NULL
)
1918 alSetError(Context
, AL_INVALID_NAME
);
1920 alSetError(Context
, AL_INVALID_VALUE
);
1921 else if(!(IntValsByProp(param
) > 0))
1922 alSetError(Context
, AL_INVALID_ENUM
);
1924 GetSourceiv(Source
, Context
, param
, values
);
1926 ALCcontext_DecRef(Context
);
1930 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
1932 ALCcontext
*Context
;
1935 Context
= GetContextRef();
1936 if(!Context
) return;
1938 if((Source
=LookupSource(Context
, source
)) == NULL
)
1939 alSetError(Context
, AL_INVALID_NAME
);
1941 alSetError(Context
, AL_INVALID_VALUE
);
1942 else if(!(Int64ValsByProp(param
) == 1))
1943 alSetError(Context
, AL_INVALID_ENUM
);
1945 GetSourcei64v(Source
, Context
, param
, value
);
1947 ALCcontext_DecRef(Context
);
1950 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
1952 ALCcontext
*Context
;
1955 Context
= GetContextRef();
1956 if(!Context
) return;
1958 if((Source
=LookupSource(Context
, source
)) == NULL
)
1959 alSetError(Context
, AL_INVALID_NAME
);
1960 else if(!(value1
&& value2
&& value3
))
1961 alSetError(Context
, AL_INVALID_VALUE
);
1962 else if(!(Int64ValsByProp(param
) == 3))
1963 alSetError(Context
, AL_INVALID_ENUM
);
1967 if(GetSourcei64v(Source
, Context
, param
, i64vals
) == AL_NO_ERROR
)
1969 *value1
= i64vals
[0];
1970 *value2
= i64vals
[1];
1971 *value3
= i64vals
[2];
1975 ALCcontext_DecRef(Context
);
1978 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
1980 ALCcontext
*Context
;
1983 Context
= GetContextRef();
1984 if(!Context
) return;
1986 if((Source
=LookupSource(Context
, source
)) == NULL
)
1987 alSetError(Context
, AL_INVALID_NAME
);
1989 alSetError(Context
, AL_INVALID_VALUE
);
1990 else if(!(Int64ValsByProp(param
) > 0))
1991 alSetError(Context
, AL_INVALID_ENUM
);
1993 GetSourcei64v(Source
, Context
, param
, values
);
1995 ALCcontext_DecRef(Context
);
1999 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
2001 alSourcePlayv(1, &source
);
2003 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2005 ALCcontext
*Context
;
2009 Context
= GetContextRef();
2010 if(!Context
) return;
2014 CHECK_VALUE(Context
, n
>= 0);
2015 for(i
= 0;i
< n
;i
++)
2017 if(!LookupSource(Context
, sources
[i
]))
2018 al_throwerr(Context
, AL_INVALID_NAME
);
2021 LockContext(Context
);
2022 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
2027 newcount
= Context
->MaxActiveSources
<< 1;
2029 temp
= realloc(Context
->ActiveSources
,
2030 sizeof(*Context
->ActiveSources
) * newcount
);
2033 UnlockContext(Context
);
2034 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
2037 Context
->ActiveSources
= temp
;
2038 Context
->MaxActiveSources
= newcount
;
2041 for(i
= 0;i
< n
;i
++)
2043 Source
= LookupSource(Context
, sources
[i
]);
2044 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
2045 else SetSourceState(Source
, Context
, AL_PLAYING
);
2047 UnlockContext(Context
);
2051 ALCcontext_DecRef(Context
);
2054 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2056 alSourcePausev(1, &source
);
2058 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2060 ALCcontext
*Context
;
2064 Context
= GetContextRef();
2065 if(!Context
) return;
2069 CHECK_VALUE(Context
, n
>= 0);
2070 for(i
= 0;i
< n
;i
++)
2072 if(!LookupSource(Context
, sources
[i
]))
2073 al_throwerr(Context
, AL_INVALID_NAME
);
2076 LockContext(Context
);
2077 for(i
= 0;i
< n
;i
++)
2079 Source
= LookupSource(Context
, sources
[i
]);
2080 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
2081 else SetSourceState(Source
, Context
, AL_PAUSED
);
2083 UnlockContext(Context
);
2087 ALCcontext_DecRef(Context
);
2090 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2092 alSourceStopv(1, &source
);
2094 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2096 ALCcontext
*Context
;
2100 Context
= GetContextRef();
2101 if(!Context
) return;
2105 CHECK_VALUE(Context
, n
>= 0);
2106 for(i
= 0;i
< n
;i
++)
2108 if(!LookupSource(Context
, sources
[i
]))
2109 al_throwerr(Context
, AL_INVALID_NAME
);
2112 LockContext(Context
);
2113 for(i
= 0;i
< n
;i
++)
2115 Source
= LookupSource(Context
, sources
[i
]);
2116 Source
->new_state
= AL_NONE
;
2117 SetSourceState(Source
, Context
, AL_STOPPED
);
2119 UnlockContext(Context
);
2123 ALCcontext_DecRef(Context
);
2126 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2128 alSourceRewindv(1, &source
);
2130 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2132 ALCcontext
*Context
;
2136 Context
= GetContextRef();
2137 if(!Context
) return;
2141 CHECK_VALUE(Context
, n
>= 0);
2142 for(i
= 0;i
< n
;i
++)
2144 if(!LookupSource(Context
, sources
[i
]))
2145 al_throwerr(Context
, AL_INVALID_NAME
);
2148 LockContext(Context
);
2149 for(i
= 0;i
< n
;i
++)
2151 Source
= LookupSource(Context
, sources
[i
]);
2152 Source
->new_state
= AL_NONE
;
2153 SetSourceState(Source
, Context
, AL_INITIAL
);
2155 UnlockContext(Context
);
2159 ALCcontext_DecRef(Context
);
2163 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei nb
, const ALuint
*buffers
)
2165 ALCcontext
*Context
;
2168 ALbufferlistitem
*BufferListStart
= NULL
;
2169 ALbufferlistitem
*BufferList
;
2170 ALbuffer
*BufferFmt
;
2175 Context
= GetContextRef();
2176 if(!Context
) return;
2180 ALCdevice
*device
= Context
->Device
;
2182 CHECK_VALUE(Context
, nb
>= 0);
2184 if((Source
=LookupSource(Context
, source
)) == NULL
)
2185 al_throwerr(Context
, AL_INVALID_NAME
);
2187 LockContext(Context
);
2188 if(Source
->SourceType
== AL_STATIC
)
2190 UnlockContext(Context
);
2191 /* Can't queue on a Static Source */
2192 al_throwerr(Context
, AL_INVALID_OPERATION
);
2197 /* Check for a valid Buffer, for its frequency and format */
2198 BufferList
= Source
->queue
;
2201 if(BufferList
->buffer
)
2203 BufferFmt
= BufferList
->buffer
;
2206 BufferList
= BufferList
->next
;
2209 for(i
= 0;i
< nb
;i
++)
2211 ALbuffer
*buffer
= NULL
;
2212 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2214 UnlockContext(Context
);
2215 al_throwerr(Context
, AL_INVALID_NAME
);
2218 if(!BufferListStart
)
2220 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2221 BufferListStart
->buffer
= buffer
;
2222 BufferListStart
->next
= NULL
;
2223 BufferListStart
->prev
= NULL
;
2224 BufferList
= BufferListStart
;
2228 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2229 BufferList
->next
->buffer
= buffer
;
2230 BufferList
->next
->next
= NULL
;
2231 BufferList
->next
->prev
= BufferList
;
2232 BufferList
= BufferList
->next
;
2234 if(!buffer
) continue;
2235 IncrementRef(&buffer
->ref
);
2237 ReadLock(&buffer
->lock
);
2238 if(BufferFmt
== NULL
)
2242 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2243 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2244 if(buffer
->FmtChannels
== FmtMono
)
2245 Source
->Update
= CalcSourceParams
;
2247 Source
->Update
= CalcNonAttnSourceParams
;
2249 Source
->NeedsUpdate
= AL_TRUE
;
2251 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2252 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2253 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2255 ReadUnlock(&buffer
->lock
);
2256 UnlockContext(Context
);
2257 al_throwerr(Context
, AL_INVALID_OPERATION
);
2259 ReadUnlock(&buffer
->lock
);
2262 /* Source is now streaming */
2263 Source
->SourceType
= AL_STREAMING
;
2265 if(Source
->queue
== NULL
)
2266 Source
->queue
= BufferListStart
;
2269 /* Append to the end of the queue */
2270 BufferList
= Source
->queue
;
2271 while(BufferList
->next
!= NULL
)
2272 BufferList
= BufferList
->next
;
2274 BufferListStart
->prev
= BufferList
;
2275 BufferList
->next
= BufferListStart
;
2278 Source
->BuffersInQueue
+= nb
;
2280 UnlockContext(Context
);
2284 while(BufferListStart
)
2286 BufferList
= BufferListStart
;
2287 BufferListStart
= BufferList
->next
;
2289 if(BufferList
->buffer
)
2290 DecrementRef(&BufferList
->buffer
->ref
);
2296 ALCcontext_DecRef(Context
);
2299 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint source
, ALsizei nb
, ALuint
*buffers
)
2301 ALCcontext
*Context
;
2304 ALbufferlistitem
*BufferList
;
2309 Context
= GetContextRef();
2310 if(!Context
) return;
2314 CHECK_VALUE(Context
, nb
>= 0);
2316 if((Source
=LookupSource(Context
, source
)) == NULL
)
2317 al_throwerr(Context
, AL_INVALID_NAME
);
2319 LockContext(Context
);
2320 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
||
2321 (ALuint
)nb
> Source
->BuffersPlayed
)
2323 UnlockContext(Context
);
2324 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2325 al_throwerr(Context
, AL_INVALID_VALUE
);
2328 for(i
= 0;i
< nb
;i
++)
2330 BufferList
= Source
->queue
;
2331 Source
->queue
= BufferList
->next
;
2332 Source
->BuffersInQueue
--;
2333 Source
->BuffersPlayed
--;
2335 if(BufferList
->buffer
)
2337 buffers
[i
] = BufferList
->buffer
->id
;
2338 DecrementRef(&BufferList
->buffer
->ref
);
2346 Source
->queue
->prev
= NULL
;
2347 UnlockContext(Context
);
2351 ALCcontext_DecRef(Context
);
2355 static ALvoid
InitSourceParams(ALsource
*Source
)
2359 Source
->InnerAngle
= 360.0f
;
2360 Source
->OuterAngle
= 360.0f
;
2361 Source
->Pitch
= 1.0f
;
2362 Source
->Position
[0] = 0.0f
;
2363 Source
->Position
[1] = 0.0f
;
2364 Source
->Position
[2] = 0.0f
;
2365 Source
->Orientation
[0] = 0.0f
;
2366 Source
->Orientation
[1] = 0.0f
;
2367 Source
->Orientation
[2] = 0.0f
;
2368 Source
->Velocity
[0] = 0.0f
;
2369 Source
->Velocity
[1] = 0.0f
;
2370 Source
->Velocity
[2] = 0.0f
;
2371 Source
->RefDistance
= 1.0f
;
2372 Source
->MaxDistance
= FLT_MAX
;
2373 Source
->RollOffFactor
= 1.0f
;
2374 Source
->Looping
= AL_FALSE
;
2375 Source
->Gain
= 1.0f
;
2376 Source
->MinGain
= 0.0f
;
2377 Source
->MaxGain
= 1.0f
;
2378 Source
->OuterGain
= 0.0f
;
2379 Source
->OuterGainHF
= 1.0f
;
2381 Source
->DryGainHFAuto
= AL_TRUE
;
2382 Source
->WetGainAuto
= AL_TRUE
;
2383 Source
->WetGainHFAuto
= AL_TRUE
;
2384 Source
->AirAbsorptionFactor
= 0.0f
;
2385 Source
->RoomRolloffFactor
= 0.0f
;
2386 Source
->DopplerFactor
= 1.0f
;
2387 Source
->DirectChannels
= AL_FALSE
;
2389 Source
->DistanceModel
= DefaultDistanceModel
;
2391 Source
->Resampler
= DefaultResampler
;
2393 Source
->state
= AL_INITIAL
;
2394 Source
->new_state
= AL_NONE
;
2395 Source
->SourceType
= AL_UNDETERMINED
;
2396 Source
->Offset
= -1.0;
2398 Source
->DirectGain
= 1.0f
;
2399 Source
->DirectGainHF
= 1.0f
;
2400 for(i
= 0;i
< MAX_SENDS
;i
++)
2402 Source
->Send
[i
].Gain
= 1.0f
;
2403 Source
->Send
[i
].GainHF
= 1.0f
;
2406 Source
->NeedsUpdate
= AL_TRUE
;
2408 Source
->Hrtf
.Moving
= AL_FALSE
;
2409 Source
->Hrtf
.Counter
= 0;
2415 * Sets the source's new play state given its current state.
2417 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2419 if(state
== AL_PLAYING
)
2421 ALbufferlistitem
*BufferList
;
2424 /* Check that there is a queue containing at least one valid, non zero
2426 BufferList
= Source
->queue
;
2429 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
2431 BufferList
= BufferList
->next
;
2434 if(Source
->state
!= AL_PLAYING
)
2436 for(j
= 0;j
< MaxChannels
;j
++)
2438 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
2439 Source
->Hrtf
.History
[j
][k
] = 0.0f
;
2440 for(k
= 0;k
< HRIR_LENGTH
;k
++)
2442 Source
->Hrtf
.Values
[j
][k
][0] = 0.0f
;
2443 Source
->Hrtf
.Values
[j
][k
][1] = 0.0f
;
2448 if(Source
->state
!= AL_PAUSED
)
2450 Source
->state
= AL_PLAYING
;
2451 Source
->position
= 0;
2452 Source
->position_fraction
= 0;
2453 Source
->BuffersPlayed
= 0;
2456 Source
->state
= AL_PLAYING
;
2458 // Check if an Offset has been set
2459 if(Source
->Offset
>= 0.0)
2460 ApplyOffset(Source
);
2462 /* If there's nothing to play, or device is disconnected, go right to
2464 if(!BufferList
|| !Context
->Device
->Connected
)
2466 SetSourceState(Source
, Context
, AL_STOPPED
);
2470 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
2472 if(Context
->ActiveSources
[j
] == Source
)
2475 if(j
== Context
->ActiveSourceCount
)
2476 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
2478 else if(state
== AL_PAUSED
)
2480 if(Source
->state
== AL_PLAYING
)
2482 Source
->state
= AL_PAUSED
;
2483 Source
->Hrtf
.Moving
= AL_FALSE
;
2484 Source
->Hrtf
.Counter
= 0;
2487 else if(state
== AL_STOPPED
)
2489 if(Source
->state
!= AL_INITIAL
)
2491 Source
->state
= AL_STOPPED
;
2492 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
2493 Source
->Hrtf
.Moving
= AL_FALSE
;
2494 Source
->Hrtf
.Counter
= 0;
2496 Source
->Offset
= -1.0;
2498 else if(state
== AL_INITIAL
)
2500 if(Source
->state
!= AL_INITIAL
)
2502 Source
->state
= AL_INITIAL
;
2503 Source
->position
= 0;
2504 Source
->position_fraction
= 0;
2505 Source
->BuffersPlayed
= 0;
2506 Source
->Hrtf
.Moving
= AL_FALSE
;
2507 Source
->Hrtf
.Counter
= 0;
2509 Source
->Offset
= -1.0;
2515 * Gets the current read offset for the given Source, in 32.32 fixed-point
2516 * samples. The offset is relative to the start of the queue (not the start of
2517 * the current buffer).
2519 static ALint64
GetSourceOffset(const ALsource
*Source
)
2521 const ALbufferlistitem
*BufferList
;
2525 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2528 /* NOTE: This is the offset into the *current* buffer, so add the length of
2529 * any played buffers */
2530 readPos
= (ALuint64
)Source
->position
<< 32;
2531 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2532 BufferList
= Source
->queue
;
2533 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2535 if(BufferList
->buffer
)
2536 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2537 BufferList
= BufferList
->next
;
2540 return (ALint64
)minu64(readPos
, MAKEU64(0x7fffffff,0xffffffff));
2543 /* GetSourceSecOffset
2545 * Gets the current read offset for the given Source, in seconds. The offset is
2546 * relative to the start of the queue (not the start of the current buffer).
2548 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2550 const ALbufferlistitem
*BufferList
;
2551 const ALbuffer
*Buffer
= NULL
;
2555 BufferList
= Source
->queue
;
2558 if(BufferList
->buffer
)
2560 Buffer
= BufferList
->buffer
;
2563 BufferList
= BufferList
->next
;
2566 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2569 /* NOTE: This is the offset into the *current* buffer, so add the length of
2570 * any played buffers */
2571 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2572 readPos
|= (ALuint64
)Source
->position_fraction
;
2573 BufferList
= Source
->queue
;
2574 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2576 if(BufferList
->buffer
)
2577 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< FRACTIONBITS
;
2578 BufferList
= BufferList
->next
;
2581 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2586 * Gets the current read and write offsets for the given Source, in the
2587 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2588 * the start of the queue (not the start of the current buffer).
2590 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2592 const ALbufferlistitem
*BufferList
;
2593 const ALbuffer
*Buffer
= NULL
;
2594 ALuint readPos
, writePos
;
2595 ALuint totalBufferLen
;
2598 // Find the first valid Buffer in the Queue
2599 BufferList
= Source
->queue
;
2602 if(BufferList
->buffer
)
2604 Buffer
= BufferList
->buffer
;
2607 BufferList
= BufferList
->next
;
2610 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2617 if(updateLen
> 0.0 && updateLen
< 0.015)
2620 /* NOTE: This is the offset into the *current* buffer, so add the length of
2621 * any played buffers */
2622 readPos
= Source
->position
;
2624 BufferList
= Source
->queue
;
2625 for(i
= 0;BufferList
;i
++)
2627 if(BufferList
->buffer
)
2629 if(i
< Source
->BuffersPlayed
)
2630 readPos
+= BufferList
->buffer
->SampleLen
;
2631 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
2633 BufferList
= BufferList
->next
;
2635 if(Source
->state
== AL_PLAYING
)
2636 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2642 readPos
%= totalBufferLen
;
2643 writePos
%= totalBufferLen
;
2647 /* Wrap positions back to 0 */
2648 if(readPos
>= totalBufferLen
)
2650 if(writePos
>= totalBufferLen
)
2657 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2658 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2661 case AL_SAMPLE_OFFSET
:
2662 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2663 offset
[0] = (ALdouble
)readPos
;
2664 offset
[1] = (ALdouble
)writePos
;
2667 case AL_BYTE_OFFSET
:
2668 case AL_BYTE_RW_OFFSETS_SOFT
:
2669 if(Buffer
->OriginalType
== UserFmtIMA4
)
2671 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
2672 ALuint FrameBlockSize
= 65;
2674 /* Round down to nearest ADPCM block */
2675 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2676 if(Source
->state
!= AL_PLAYING
)
2677 offset
[1] = offset
[0];
2680 /* Round up to nearest ADPCM block */
2681 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2682 FrameBlockSize
* BlockSize
);
2687 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2688 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2689 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2698 * Apply the stored playback offset to the Source. This function will update
2699 * the number of buffers "played" given the stored offset.
2701 ALboolean
ApplyOffset(ALsource
*Source
)
2703 const ALbufferlistitem
*BufferList
;
2704 const ALbuffer
*Buffer
;
2705 ALint bufferLen
, totalBufferLen
;
2706 ALint buffersPlayed
;
2709 /* Get sample frame offset */
2710 offset
= GetSampleOffset(Source
);
2717 BufferList
= Source
->queue
;
2720 Buffer
= BufferList
->buffer
;
2721 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2723 if(bufferLen
<= offset
-totalBufferLen
)
2725 /* Offset is past this buffer so increment to the next buffer */
2728 else if(totalBufferLen
<= offset
)
2730 /* Offset is in this buffer */
2731 Source
->BuffersPlayed
= buffersPlayed
;
2733 Source
->position
= offset
- totalBufferLen
;
2734 Source
->position_fraction
= 0;
2738 totalBufferLen
+= bufferLen
;
2740 BufferList
= BufferList
->next
;
2743 /* Offset is out of range of the queue */
2750 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2751 * Second offset supplied by the application). This takes into account the fact
2752 * that the buffer format may have been modifed since.
2754 static ALint
GetSampleOffset(ALsource
*Source
)
2756 const ALbuffer
*Buffer
= NULL
;
2757 const ALbufferlistitem
*BufferList
;
2760 /* Find the first valid Buffer in the Queue */
2761 BufferList
= Source
->queue
;
2764 if(BufferList
->buffer
)
2766 Buffer
= BufferList
->buffer
;
2769 BufferList
= BufferList
->next
;
2774 Source
->Offset
= -1.0;
2778 switch(Source
->OffsetType
)
2780 case AL_BYTE_OFFSET
:
2781 /* Determine the ByteOffset (and ensure it is block aligned) */
2782 Offset
= (ALint
)Source
->Offset
;
2783 if(Buffer
->OriginalType
== UserFmtIMA4
)
2785 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2789 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2792 case AL_SAMPLE_OFFSET
:
2793 Offset
= (ALint
)Source
->Offset
;
2797 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2800 Source
->Offset
= -1.0;
2808 * Destroys all sources in the source map.
2810 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2814 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2816 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2817 Context
->SourceMap
.array
[pos
].value
= NULL
;
2819 while(temp
->queue
!= NULL
)
2821 ALbufferlistitem
*BufferList
= temp
->queue
;
2822 temp
->queue
= BufferList
->next
;
2824 if(BufferList
->buffer
!= NULL
)
2825 DecrementRef(&BufferList
->buffer
->ref
);
2829 for(j
= 0;j
< MAX_SENDS
;++j
)
2831 if(temp
->Send
[j
].Slot
)
2832 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2833 temp
->Send
[j
].Slot
= NULL
;
2836 FreeThunkEntry(temp
->id
);
2837 memset(temp
, 0, sizeof(*temp
));