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 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALfloat
*values
);
57 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint
*values
);
58 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint64SOFT
*values
);
60 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALdouble
*values
);
61 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint
*values
);
62 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint64
*values
);
65 #define RETERR(x) do { \
66 alSetError(Context, (x)); \
70 #define CHECKVAL(x) do { \
72 RETERR(AL_INVALID_VALUE); \
75 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALfloat
*values
)
80 CHECKVAL(*values
>= 0.0f
);
82 Source
->Pitch
= *values
;
83 Source
->NeedsUpdate
= AL_TRUE
;
86 case AL_CONE_INNER_ANGLE
:
87 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
89 Source
->InnerAngle
= *values
;
90 Source
->NeedsUpdate
= AL_TRUE
;
93 case AL_CONE_OUTER_ANGLE
:
94 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
96 Source
->OuterAngle
= *values
;
97 Source
->NeedsUpdate
= AL_TRUE
;
101 CHECKVAL(*values
>= 0.0f
);
103 Source
->Gain
= *values
;
104 Source
->NeedsUpdate
= AL_TRUE
;
107 case AL_MAX_DISTANCE
:
108 CHECKVAL(*values
>= 0.0f
);
110 Source
->MaxDistance
= *values
;
111 Source
->NeedsUpdate
= AL_TRUE
;
114 case AL_ROLLOFF_FACTOR
:
115 CHECKVAL(*values
>= 0.0f
);
117 Source
->RollOffFactor
= *values
;
118 Source
->NeedsUpdate
= AL_TRUE
;
121 case AL_REFERENCE_DISTANCE
:
122 CHECKVAL(*values
>= 0.0f
);
124 Source
->RefDistance
= *values
;
125 Source
->NeedsUpdate
= AL_TRUE
;
129 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
131 Source
->MinGain
= *values
;
132 Source
->NeedsUpdate
= AL_TRUE
;
136 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
138 Source
->MaxGain
= *values
;
139 Source
->NeedsUpdate
= AL_TRUE
;
142 case AL_CONE_OUTER_GAIN
:
143 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
145 Source
->OuterGain
= *values
;
146 Source
->NeedsUpdate
= AL_TRUE
;
149 case AL_CONE_OUTER_GAINHF
:
150 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
152 Source
->OuterGainHF
= *values
;
153 Source
->NeedsUpdate
= AL_TRUE
;
156 case AL_AIR_ABSORPTION_FACTOR
:
157 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
159 Source
->AirAbsorptionFactor
= *values
;
160 Source
->NeedsUpdate
= AL_TRUE
;
163 case AL_ROOM_ROLLOFF_FACTOR
:
164 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
166 Source
->RoomRolloffFactor
= *values
;
167 Source
->NeedsUpdate
= AL_TRUE
;
170 case AL_DOPPLER_FACTOR
:
171 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
173 Source
->DopplerFactor
= *values
;
174 Source
->NeedsUpdate
= AL_TRUE
;
178 case AL_SAMPLE_OFFSET
:
180 CHECKVAL(*values
>= 0.0f
);
182 LockContext(Context
);
183 Source
->OffsetType
= name
;
184 Source
->Offset
= *values
;
186 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
187 !Context
->DeferUpdates
)
189 if(ApplyOffset(Source
) == AL_FALSE
)
191 UnlockContext(Context
);
192 RETERR(AL_INVALID_VALUE
);
195 UnlockContext(Context
);
199 case AL_SEC_OFFSET_LATENCY_SOFT
:
201 RETERR(AL_INVALID_OPERATION
);
205 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
207 LockContext(Context
);
208 Source
->Position
[0] = values
[0];
209 Source
->Position
[1] = values
[1];
210 Source
->Position
[2] = values
[2];
211 UnlockContext(Context
);
212 Source
->NeedsUpdate
= AL_TRUE
;
216 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
218 LockContext(Context
);
219 Source
->Velocity
[0] = values
[0];
220 Source
->Velocity
[1] = values
[1];
221 Source
->Velocity
[2] = values
[2];
222 UnlockContext(Context
);
223 Source
->NeedsUpdate
= AL_TRUE
;
227 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
229 LockContext(Context
);
230 Source
->Orientation
[0] = values
[0];
231 Source
->Orientation
[1] = values
[1];
232 Source
->Orientation
[2] = values
[2];
233 UnlockContext(Context
);
234 Source
->NeedsUpdate
= AL_TRUE
;
238 RETERR(AL_INVALID_ENUM
);
244 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint
*values
)
246 ALCdevice
*device
= Context
->Device
;
247 ALbuffer
*buffer
= NULL
;
248 ALfilter
*filter
= NULL
;
249 ALeffectslot
*slot
= NULL
;
250 ALbufferlistitem
*oldlist
;
256 case AL_SOURCE_RELATIVE
:
257 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
259 Source
->HeadRelative
= (ALboolean
)*values
;
260 Source
->NeedsUpdate
= AL_TRUE
;
264 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
266 Source
->Looping
= (ALboolean
)*values
;
270 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
272 LockContext(Context
);
273 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
275 UnlockContext(Context
);
276 RETERR(AL_INVALID_OPERATION
);
279 Source
->BuffersInQueue
= 0;
280 Source
->BuffersPlayed
= 0;
284 ALbufferlistitem
*BufferListItem
;
286 /* Source is now Static */
287 Source
->SourceType
= AL_STATIC
;
289 /* Add the selected buffer to a one-item queue */
290 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
291 BufferListItem
->buffer
= buffer
;
292 BufferListItem
->next
= NULL
;
293 BufferListItem
->prev
= NULL
;
294 IncrementRef(&buffer
->ref
);
296 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, BufferListItem
);
297 Source
->BuffersInQueue
= 1;
299 ReadLock(&buffer
->lock
);
300 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
301 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
302 ReadUnlock(&buffer
->lock
);
303 if(buffer
->FmtChannels
== FmtMono
)
304 Source
->Update
= CalcSourceParams
;
306 Source
->Update
= CalcNonAttnSourceParams
;
307 Source
->NeedsUpdate
= AL_TRUE
;
311 /* Source is now Undetermined */
312 Source
->SourceType
= AL_UNDETERMINED
;
313 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, NULL
);
316 /* Delete all elements in the previous queue */
317 while(oldlist
!= NULL
)
319 ALbufferlistitem
*temp
= oldlist
;
320 oldlist
= temp
->next
;
323 DecrementRef(&temp
->buffer
->ref
);
326 UnlockContext(Context
);
329 case AL_SOURCE_STATE
:
331 RETERR(AL_INVALID_OPERATION
);
334 case AL_SAMPLE_OFFSET
:
336 CHECKVAL(*values
>= 0);
338 LockContext(Context
);
339 Source
->OffsetType
= name
;
340 Source
->Offset
= *values
;
342 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
343 !Context
->DeferUpdates
)
345 if(ApplyOffset(Source
) == AL_FALSE
)
347 UnlockContext(Context
);
348 RETERR(AL_INVALID_VALUE
);
351 UnlockContext(Context
);
354 case AL_DIRECT_FILTER
:
355 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
357 LockContext(Context
);
360 Source
->DirectGain
= 1.0f
;
361 Source
->DirectGainHF
= 1.0f
;
365 Source
->DirectGain
= filter
->Gain
;
366 Source
->DirectGainHF
= filter
->GainHF
;
368 UnlockContext(Context
);
369 Source
->NeedsUpdate
= AL_TRUE
;
372 case AL_DIRECT_FILTER_GAINHF_AUTO
:
373 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
375 Source
->DryGainHFAuto
= *values
;
376 Source
->NeedsUpdate
= AL_TRUE
;
379 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
380 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
382 Source
->WetGainAuto
= *values
;
383 Source
->NeedsUpdate
= AL_TRUE
;
386 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
387 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
389 Source
->WetGainHFAuto
= *values
;
390 Source
->NeedsUpdate
= AL_TRUE
;
393 case AL_DIRECT_CHANNELS_SOFT
:
394 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
396 Source
->DirectChannels
= *values
;
397 Source
->NeedsUpdate
= AL_TRUE
;
400 case AL_DISTANCE_MODEL
:
401 CHECKVAL(*values
== AL_NONE
||
402 *values
== AL_INVERSE_DISTANCE
||
403 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
404 *values
== AL_LINEAR_DISTANCE
||
405 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
406 *values
== AL_EXPONENT_DISTANCE
||
407 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
409 Source
->DistanceModel
= *values
;
410 if(Context
->SourceDistanceModel
)
411 Source
->NeedsUpdate
= AL_TRUE
;
415 case AL_AUXILIARY_SEND_FILTER
:
416 LockContext(Context
);
417 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
418 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
419 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
421 UnlockContext(Context
);
422 RETERR(AL_INVALID_VALUE
);
425 /* Add refcount on the new slot, and release the previous slot */
426 if(slot
) IncrementRef(&slot
->ref
);
427 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
428 if(slot
) DecrementRef(&slot
->ref
);
433 Source
->Send
[values
[1]].Gain
= 1.0f
;
434 Source
->Send
[values
[1]].GainHF
= 1.0f
;
438 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
439 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
441 Source
->NeedsUpdate
= AL_TRUE
;
442 UnlockContext(Context
);
446 case AL_MAX_DISTANCE
:
447 case AL_ROLLOFF_FACTOR
:
448 case AL_CONE_INNER_ANGLE
:
449 case AL_CONE_OUTER_ANGLE
:
450 case AL_REFERENCE_DISTANCE
:
451 fvals
[0] = (ALfloat
)*values
;
452 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
459 fvals
[0] = (ALfloat
)values
[0];
460 fvals
[1] = (ALfloat
)values
[1];
461 fvals
[2] = (ALfloat
)values
[2];
462 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
467 RETERR(AL_INVALID_ENUM
);
473 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint64SOFT
*values
)
481 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
483 RETERR(AL_INVALID_OPERATION
);
487 case AL_SOURCE_RELATIVE
:
489 case AL_SOURCE_STATE
:
491 case AL_SAMPLE_OFFSET
:
492 case AL_DIRECT_FILTER_GAINHF_AUTO
:
493 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
494 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
495 case AL_DIRECT_CHANNELS_SOFT
:
496 case AL_DISTANCE_MODEL
:
497 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
499 ivals
[0] = (ALint
)*values
;
500 if((err
=SetSourceiv(Source
, Context
, name
, ivals
)))
506 case AL_DIRECT_FILTER
:
507 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
509 ivals
[0] = (ALuint
)*values
;
510 if((err
=SetSourceiv(Source
, Context
, name
, ivals
)))
515 case AL_AUXILIARY_SEND_FILTER
:
516 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
517 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
518 values
[2] <= UINT_MAX
&& values
[2] >= 0);
520 ivals
[0] = (ALuint
)values
[0];
521 ivals
[1] = (ALuint
)values
[1];
522 ivals
[2] = (ALuint
)values
[2];
523 if((err
=SetSourceiv(Source
, Context
, name
, ivals
)))
528 case AL_MAX_DISTANCE
:
529 case AL_ROLLOFF_FACTOR
:
530 case AL_CONE_INNER_ANGLE
:
531 case AL_CONE_OUTER_ANGLE
:
532 case AL_REFERENCE_DISTANCE
:
534 fvals
[0] = (ALfloat
)*values
;
535 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
543 fvals
[0] = (ALfloat
)values
[0];
544 fvals
[1] = (ALfloat
)values
[1];
545 fvals
[2] = (ALfloat
)values
[2];
546 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
551 RETERR(AL_INVALID_ENUM
);
560 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALdouble
*values
)
570 *values
= Source
->Pitch
;
573 case AL_MAX_DISTANCE
:
574 *values
= Source
->MaxDistance
;
577 case AL_ROLLOFF_FACTOR
:
578 *values
= Source
->RollOffFactor
;
581 case AL_REFERENCE_DISTANCE
:
582 *values
= Source
->RefDistance
;
585 case AL_CONE_INNER_ANGLE
:
586 *values
= Source
->InnerAngle
;
589 case AL_CONE_OUTER_ANGLE
:
590 *values
= Source
->OuterAngle
;
594 *values
= Source
->MinGain
;
598 *values
= Source
->MaxGain
;
601 case AL_CONE_OUTER_GAIN
:
602 *values
= Source
->OuterGain
;
606 case AL_SAMPLE_OFFSET
:
608 LockContext(Context
);
609 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
610 Context
->Device
->Frequency
;
611 GetSourceOffsets(Source
, name
, offsets
, updateLen
);
612 UnlockContext(Context
);
613 *values
= offsets
[0];
616 case AL_CONE_OUTER_GAINHF
:
617 *values
= Source
->OuterGainHF
;
620 case AL_AIR_ABSORPTION_FACTOR
:
621 *values
= Source
->AirAbsorptionFactor
;
624 case AL_ROOM_ROLLOFF_FACTOR
:
625 *values
= Source
->RoomRolloffFactor
;
628 case AL_DOPPLER_FACTOR
:
629 *values
= Source
->DopplerFactor
;
632 case AL_SAMPLE_RW_OFFSETS_SOFT
:
633 case AL_BYTE_RW_OFFSETS_SOFT
:
634 LockContext(Context
);
635 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
636 Context
->Device
->Frequency
;
637 GetSourceOffsets(Source
, name
, values
, updateLen
);
638 UnlockContext(Context
);
641 case AL_SEC_OFFSET_LATENCY_SOFT
:
642 LockContext(Context
);
643 values
[0] = GetSourceSecOffset(Source
);
644 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
646 UnlockContext(Context
);
650 LockContext(Context
);
651 values
[0] = Source
->Position
[0];
652 values
[1] = Source
->Position
[1];
653 values
[2] = Source
->Position
[2];
654 UnlockContext(Context
);
658 LockContext(Context
);
659 values
[0] = Source
->Velocity
[0];
660 values
[1] = Source
->Velocity
[1];
661 values
[2] = Source
->Velocity
[2];
662 UnlockContext(Context
);
666 LockContext(Context
);
667 values
[0] = Source
->Orientation
[0];
668 values
[1] = Source
->Orientation
[1];
669 values
[2] = Source
->Orientation
[2];
670 UnlockContext(Context
);
673 case AL_SOURCE_RELATIVE
:
676 case AL_SOURCE_STATE
:
677 case AL_BUFFERS_QUEUED
:
678 case AL_BUFFERS_PROCESSED
:
680 case AL_DIRECT_FILTER_GAINHF_AUTO
:
681 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
682 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
683 case AL_DIRECT_CHANNELS_SOFT
:
684 case AL_DISTANCE_MODEL
:
685 if((err
=GetSourceiv(Source
, Context
, name
, ivals
)) != AL_NO_ERROR
)
687 *values
= (ALdouble
)ivals
[0];
691 RETERR(AL_INVALID_ENUM
);
697 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint
*values
)
699 ALbufferlistitem
*BufferList
;
705 case AL_SOURCE_RELATIVE
:
706 *values
= Source
->HeadRelative
;
710 *values
= Source
->Looping
;
714 LockContext(Context
);
715 BufferList
= Source
->queue
;
716 if(Source
->SourceType
!= AL_STATIC
)
718 ALuint i
= Source
->BuffersPlayed
;
721 BufferList
= BufferList
->next
;
725 *values
= ((BufferList
&& BufferList
->buffer
) ?
726 BufferList
->buffer
->id
: 0);
727 UnlockContext(Context
);
730 case AL_SOURCE_STATE
:
731 *values
= Source
->state
;
734 case AL_BUFFERS_QUEUED
:
735 *values
= Source
->BuffersInQueue
;
738 case AL_BUFFERS_PROCESSED
:
739 LockContext(Context
);
740 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
742 /* Buffers on a looping source are in a perpetual state of
743 * PENDING, so don't report any as PROCESSED */
747 *values
= Source
->BuffersPlayed
;
748 UnlockContext(Context
);
752 *values
= Source
->SourceType
;
755 case AL_DIRECT_FILTER_GAINHF_AUTO
:
756 *values
= Source
->DryGainHFAuto
;
759 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
760 *values
= Source
->WetGainAuto
;
763 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
764 *values
= Source
->WetGainHFAuto
;
767 case AL_DIRECT_CHANNELS_SOFT
:
768 *values
= Source
->DirectChannels
;
771 case AL_DISTANCE_MODEL
:
772 *values
= Source
->DistanceModel
;
775 case AL_MAX_DISTANCE
:
776 case AL_ROLLOFF_FACTOR
:
777 case AL_REFERENCE_DISTANCE
:
778 case AL_CONE_INNER_ANGLE
:
779 case AL_CONE_OUTER_ANGLE
:
781 case AL_SAMPLE_OFFSET
:
783 case AL_DOPPLER_FACTOR
:
784 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
786 *values
= (ALint
)dvals
[0];
789 case AL_SAMPLE_RW_OFFSETS_SOFT
:
790 case AL_BYTE_RW_OFFSETS_SOFT
:
791 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
793 values
[0] = (ALint
)dvals
[0];
794 values
[1] = (ALint
)dvals
[1];
800 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
802 values
[0] = (ALint
)dvals
[0];
803 values
[1] = (ALint
)dvals
[1];
804 values
[2] = (ALint
)dvals
[2];
808 RETERR(AL_INVALID_ENUM
);
814 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint64
*values
)
822 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
823 LockContext(Context
);
824 values
[0] = GetSourceOffset(Source
);
825 values
[1] = ALCdevice_GetLatency(Context
->Device
);
826 UnlockContext(Context
);
829 case AL_MAX_DISTANCE
:
830 case AL_ROLLOFF_FACTOR
:
831 case AL_REFERENCE_DISTANCE
:
832 case AL_CONE_INNER_ANGLE
:
833 case AL_CONE_OUTER_ANGLE
:
835 case AL_SAMPLE_OFFSET
:
837 case AL_DOPPLER_FACTOR
:
838 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
840 *values
= (ALint64
)dvals
[0];
843 case AL_SAMPLE_RW_OFFSETS_SOFT
:
844 case AL_BYTE_RW_OFFSETS_SOFT
:
845 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
847 values
[0] = (ALint64
)dvals
[0];
848 values
[1] = (ALint64
)dvals
[1];
854 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
856 values
[0] = (ALint64
)dvals
[0];
857 values
[1] = (ALint64
)dvals
[1];
858 values
[2] = (ALint64
)dvals
[2];
861 case AL_SOURCE_RELATIVE
:
864 case AL_SOURCE_STATE
:
865 case AL_BUFFERS_QUEUED
:
866 case AL_BUFFERS_PROCESSED
:
868 case AL_DIRECT_FILTER_GAINHF_AUTO
:
869 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
870 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
871 case AL_DIRECT_CHANNELS_SOFT
:
872 case AL_DISTANCE_MODEL
:
873 if((err
=GetSourceiv(Source
, Context
, name
, ivals
)) != AL_NO_ERROR
)
879 RETERR(AL_INVALID_ENUM
);
888 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
893 Context
= GetContextRef();
900 CHECK_VALUE(Context
, n
>= 0);
901 for(cur
= 0;cur
< n
;cur
++)
903 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
905 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
906 InitSourceParams(source
);
908 err
= NewThunkEntry(&source
->id
);
909 if(err
== AL_NO_ERROR
)
910 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->id
, source
);
911 if(err
!= AL_NO_ERROR
)
913 FreeThunkEntry(source
->id
);
914 memset(source
, 0, sizeof(ALsource
));
917 al_throwerr(Context
, err
);
920 sources
[cur
] = source
->id
;
926 alDeleteSources(cur
, sources
);
930 ALCcontext_DecRef(Context
);
934 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
938 Context
= GetContextRef();
943 ALbufferlistitem
*BufferList
;
947 CHECK_VALUE(Context
, n
>= 0);
949 /* Check that all Sources are valid */
952 if(LookupSource(Context
, sources
[i
]) == NULL
)
953 al_throwerr(Context
, AL_INVALID_NAME
);
958 ALsource
**srclist
, **srclistend
;
960 if((Source
=RemoveSource(Context
, sources
[i
])) == NULL
)
962 FreeThunkEntry(Source
->id
);
964 LockContext(Context
);
965 srclist
= Context
->ActiveSources
;
966 srclistend
= srclist
+ Context
->ActiveSourceCount
;
967 while(srclist
!= srclistend
)
969 if(*srclist
== Source
)
971 Context
->ActiveSourceCount
--;
972 *srclist
= *(--srclistend
);
977 UnlockContext(Context
);
979 while(Source
->queue
!= NULL
)
981 BufferList
= Source
->queue
;
982 Source
->queue
= BufferList
->next
;
984 if(BufferList
->buffer
!= NULL
)
985 DecrementRef(&BufferList
->buffer
->ref
);
989 for(j
= 0;j
< MAX_SENDS
;++j
)
991 if(Source
->Send
[j
].Slot
)
992 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
993 Source
->Send
[j
].Slot
= NULL
;
996 memset(Source
, 0, sizeof(*Source
));
1002 ALCcontext_DecRef(Context
);
1006 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1008 ALCcontext
*Context
;
1011 Context
= GetContextRef();
1012 if(!Context
) return AL_FALSE
;
1014 result
= (LookupSource(Context
, source
) ? AL_TRUE
: AL_FALSE
);
1016 ALCcontext_DecRef(Context
);
1022 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1024 ALCcontext
*Context
;
1027 Context
= GetContextRef();
1028 if(!Context
) return;
1030 if((Source
=LookupSource(Context
, source
)) == NULL
)
1031 alSetError(Context
, AL_INVALID_NAME
);
1035 case AL_CONE_INNER_ANGLE
:
1036 case AL_CONE_OUTER_ANGLE
:
1038 case AL_MAX_DISTANCE
:
1039 case AL_ROLLOFF_FACTOR
:
1040 case AL_REFERENCE_DISTANCE
:
1043 case AL_CONE_OUTER_GAIN
:
1044 case AL_CONE_OUTER_GAINHF
:
1045 case AL_AIR_ABSORPTION_FACTOR
:
1046 case AL_ROOM_ROLLOFF_FACTOR
:
1047 case AL_DOPPLER_FACTOR
:
1049 case AL_SAMPLE_OFFSET
:
1050 case AL_BYTE_OFFSET
:
1051 SetSourcefv(Source
, Context
, param
, &value
);
1055 alSetError(Context
, AL_INVALID_ENUM
);
1058 ALCcontext_DecRef(Context
);
1061 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1063 ALCcontext
*Context
;
1067 Context
= GetContextRef();
1068 if(!Context
) return;
1070 if((Source
=LookupSource(Context
, source
)) == NULL
)
1071 alSetError(Context
, AL_INVALID_NAME
);
1080 SetSourcefv(Source
, Context
, param
, fvals
);
1084 alSetError(Context
, AL_INVALID_ENUM
);
1087 ALCcontext_DecRef(Context
);
1090 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1092 ALCcontext
*Context
;
1095 Context
= GetContextRef();
1096 if(!Context
) return;
1098 if((Source
=LookupSource(Context
, source
)) == NULL
)
1099 alSetError(Context
, AL_INVALID_NAME
);
1101 alSetError(Context
, AL_INVALID_VALUE
);
1105 case AL_CONE_INNER_ANGLE
:
1106 case AL_CONE_OUTER_ANGLE
:
1108 case AL_MAX_DISTANCE
:
1109 case AL_ROLLOFF_FACTOR
:
1110 case AL_REFERENCE_DISTANCE
:
1113 case AL_CONE_OUTER_GAIN
:
1114 case AL_CONE_OUTER_GAINHF
:
1116 case AL_SAMPLE_OFFSET
:
1117 case AL_BYTE_OFFSET
:
1118 case AL_AIR_ABSORPTION_FACTOR
:
1119 case AL_ROOM_ROLLOFF_FACTOR
:
1124 SetSourcefv(Source
, Context
, param
, values
);
1128 alSetError(Context
, AL_INVALID_ENUM
);
1131 ALCcontext_DecRef(Context
);
1135 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1137 ALCcontext
*Context
;
1141 Context
= GetContextRef();
1142 if(!Context
) return;
1144 if((Source
=LookupSource(Context
, source
)) == NULL
)
1145 alSetError(Context
, AL_INVALID_NAME
);
1149 case AL_CONE_INNER_ANGLE
:
1150 case AL_CONE_OUTER_ANGLE
:
1152 case AL_MAX_DISTANCE
:
1153 case AL_ROLLOFF_FACTOR
:
1154 case AL_REFERENCE_DISTANCE
:
1157 case AL_CONE_OUTER_GAIN
:
1158 case AL_CONE_OUTER_GAINHF
:
1159 case AL_AIR_ABSORPTION_FACTOR
:
1160 case AL_ROOM_ROLLOFF_FACTOR
:
1161 case AL_DOPPLER_FACTOR
:
1163 case AL_SAMPLE_OFFSET
:
1164 case AL_BYTE_OFFSET
:
1165 fval
= (ALfloat
)value
;
1166 SetSourcefv(Source
, Context
, param
, &fval
);
1170 alSetError(Context
, AL_INVALID_ENUM
);
1173 ALCcontext_DecRef(Context
);
1176 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1178 ALCcontext
*Context
;
1182 Context
= GetContextRef();
1183 if(!Context
) return;
1185 if((Source
=LookupSource(Context
, source
)) == NULL
)
1186 alSetError(Context
, AL_INVALID_NAME
);
1192 fvals
[0] = (ALfloat
)value1
;
1193 fvals
[1] = (ALfloat
)value2
;
1194 fvals
[2] = (ALfloat
)value3
;
1195 SetSourcefv(Source
, Context
, param
, fvals
);
1199 alSetError(Context
, AL_INVALID_ENUM
);
1202 ALCcontext_DecRef(Context
);
1205 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1207 ALCcontext
*Context
;
1211 Context
= GetContextRef();
1212 if(!Context
) return;
1214 if((Source
=LookupSource(Context
, source
)) == NULL
)
1215 alSetError(Context
, AL_INVALID_NAME
);
1217 alSetError(Context
, AL_INVALID_VALUE
);
1221 case AL_CONE_INNER_ANGLE
:
1222 case AL_CONE_OUTER_ANGLE
:
1224 case AL_MAX_DISTANCE
:
1225 case AL_ROLLOFF_FACTOR
:
1226 case AL_REFERENCE_DISTANCE
:
1229 case AL_CONE_OUTER_GAIN
:
1230 case AL_CONE_OUTER_GAINHF
:
1232 case AL_SAMPLE_OFFSET
:
1233 case AL_BYTE_OFFSET
:
1234 case AL_AIR_ABSORPTION_FACTOR
:
1235 case AL_ROOM_ROLLOFF_FACTOR
:
1236 fvals
[0] = (ALfloat
)values
[0];
1237 SetSourcefv(Source
, Context
, param
, fvals
);
1240 case AL_SEC_OFFSET_LATENCY_SOFT
:
1241 fvals
[0] = (ALfloat
)values
[0];
1242 fvals
[1] = (ALfloat
)values
[1];
1243 SetSourcefv(Source
, Context
, param
, fvals
);
1249 fvals
[0] = (ALfloat
)values
[0];
1250 fvals
[1] = (ALfloat
)values
[1];
1251 fvals
[2] = (ALfloat
)values
[2];
1252 SetSourcefv(Source
, Context
, param
, fvals
);
1256 alSetError(Context
, AL_INVALID_ENUM
);
1259 ALCcontext_DecRef(Context
);
1263 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1265 ALCcontext
*Context
;
1268 Context
= GetContextRef();
1269 if(!Context
) return;
1271 if((Source
=LookupSource(Context
, source
)) == NULL
)
1272 alSetError(Context
, AL_INVALID_NAME
);
1275 case AL_MAX_DISTANCE
:
1276 case AL_ROLLOFF_FACTOR
:
1277 case AL_CONE_INNER_ANGLE
:
1278 case AL_CONE_OUTER_ANGLE
:
1279 case AL_REFERENCE_DISTANCE
:
1280 case AL_SOURCE_RELATIVE
:
1283 case AL_SOURCE_STATE
:
1285 case AL_SAMPLE_OFFSET
:
1286 case AL_BYTE_OFFSET
:
1287 case AL_DIRECT_FILTER
:
1288 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1289 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1290 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1291 case AL_DIRECT_CHANNELS_SOFT
:
1292 case AL_DISTANCE_MODEL
:
1293 SetSourceiv(Source
, Context
, param
, &value
);
1297 alSetError(Context
, AL_INVALID_ENUM
);
1300 ALCcontext_DecRef(Context
);
1303 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1305 ALCcontext
*Context
;
1309 Context
= GetContextRef();
1310 if(!Context
) return;
1312 if((Source
=LookupSource(Context
, source
)) == NULL
)
1313 alSetError(Context
, AL_INVALID_NAME
);
1319 case AL_AUXILIARY_SEND_FILTER
:
1323 SetSourceiv(Source
, Context
, param
, ivals
);
1327 alSetError(Context
, AL_INVALID_ENUM
);
1330 ALCcontext_DecRef(Context
);
1333 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1335 ALCcontext
*Context
;
1338 Context
= GetContextRef();
1339 if(!Context
) return;
1341 if((Source
=LookupSource(Context
, source
)) == NULL
)
1342 alSetError(Context
, AL_INVALID_NAME
);
1344 alSetError(Context
, AL_INVALID_VALUE
);
1347 case AL_SOURCE_RELATIVE
:
1348 case AL_CONE_INNER_ANGLE
:
1349 case AL_CONE_OUTER_ANGLE
:
1352 case AL_SOURCE_STATE
:
1354 case AL_SAMPLE_OFFSET
:
1355 case AL_BYTE_OFFSET
:
1356 case AL_MAX_DISTANCE
:
1357 case AL_ROLLOFF_FACTOR
:
1358 case AL_REFERENCE_DISTANCE
:
1359 case AL_DIRECT_FILTER
:
1360 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1361 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1362 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1363 case AL_DISTANCE_MODEL
:
1364 case AL_DIRECT_CHANNELS_SOFT
:
1369 case AL_AUXILIARY_SEND_FILTER
:
1370 SetSourceiv(Source
, Context
, param
, values
);
1374 alSetError(Context
, AL_INVALID_ENUM
);
1377 ALCcontext_DecRef(Context
);
1381 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1383 ALCcontext
*Context
;
1386 Context
= GetContextRef();
1387 if(!Context
) return;
1389 if((Source
=LookupSource(Context
, source
)) == NULL
)
1390 alSetError(Context
, AL_INVALID_NAME
);
1393 case AL_MAX_DISTANCE
:
1394 case AL_ROLLOFF_FACTOR
:
1395 case AL_CONE_INNER_ANGLE
:
1396 case AL_CONE_OUTER_ANGLE
:
1397 case AL_REFERENCE_DISTANCE
:
1398 case AL_SOURCE_RELATIVE
:
1400 case AL_SOURCE_STATE
:
1402 case AL_SAMPLE_OFFSET
:
1403 case AL_BYTE_OFFSET
:
1404 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1405 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1406 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1407 case AL_DIRECT_CHANNELS_SOFT
:
1408 case AL_DISTANCE_MODEL
:
1410 case AL_DIRECT_FILTER
:
1411 SetSourcei64v(Source
, Context
, param
, &value
);
1415 alSetError(Context
, AL_INVALID_ENUM
);
1418 ALCcontext_DecRef(Context
);
1421 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1423 ALCcontext
*Context
;
1425 ALint64SOFT i64vals
[3];
1427 Context
= GetContextRef();
1428 if(!Context
) return;
1430 if((Source
=LookupSource(Context
, source
)) == NULL
)
1431 alSetError(Context
, AL_INVALID_NAME
);
1437 case AL_AUXILIARY_SEND_FILTER
:
1438 i64vals
[0] = value1
;
1439 i64vals
[1] = value2
;
1440 i64vals
[2] = value3
;
1441 SetSourcei64v(Source
, Context
, param
, i64vals
);
1445 alSetError(Context
, AL_INVALID_ENUM
);
1448 ALCcontext_DecRef(Context
);
1451 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1453 ALCcontext
*Context
;
1456 Context
= GetContextRef();
1457 if(!Context
) return;
1459 if((Source
=LookupSource(Context
, source
)) == NULL
)
1460 alSetError(Context
, AL_INVALID_NAME
);
1462 alSetError(Context
, AL_INVALID_VALUE
);
1465 case AL_SOURCE_RELATIVE
:
1466 case AL_CONE_INNER_ANGLE
:
1467 case AL_CONE_OUTER_ANGLE
:
1469 case AL_SOURCE_STATE
:
1471 case AL_SAMPLE_OFFSET
:
1472 case AL_BYTE_OFFSET
:
1473 case AL_MAX_DISTANCE
:
1474 case AL_ROLLOFF_FACTOR
:
1475 case AL_REFERENCE_DISTANCE
:
1476 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1477 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1478 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1479 case AL_DISTANCE_MODEL
:
1480 case AL_DIRECT_CHANNELS_SOFT
:
1482 case AL_DIRECT_FILTER
:
1484 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1489 case AL_AUXILIARY_SEND_FILTER
:
1490 SetSourcei64v(Source
, Context
, param
, values
);
1494 alSetError(Context
, AL_INVALID_ENUM
);
1497 ALCcontext_DecRef(Context
);
1501 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1503 ALCcontext
*Context
;
1507 Context
= GetContextRef();
1508 if(!Context
) return;
1510 if((Source
=LookupSource(Context
, source
)) == NULL
)
1511 alSetError(Context
, AL_INVALID_NAME
);
1513 alSetError(Context
, AL_INVALID_VALUE
);
1520 case AL_MAX_DISTANCE
:
1521 case AL_ROLLOFF_FACTOR
:
1522 case AL_CONE_OUTER_GAIN
:
1523 case AL_CONE_OUTER_GAINHF
:
1525 case AL_SAMPLE_OFFSET
:
1526 case AL_BYTE_OFFSET
:
1527 case AL_CONE_INNER_ANGLE
:
1528 case AL_CONE_OUTER_ANGLE
:
1529 case AL_REFERENCE_DISTANCE
:
1530 case AL_AIR_ABSORPTION_FACTOR
:
1531 case AL_ROOM_ROLLOFF_FACTOR
:
1532 case AL_DOPPLER_FACTOR
:
1533 if(GetSourcedv(Source
, Context
, param
, &dval
) == AL_NO_ERROR
)
1534 *value
= (ALfloat
)dval
;
1538 alSetError(Context
, AL_INVALID_ENUM
);
1541 ALCcontext_DecRef(Context
);
1545 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1547 ALCcontext
*Context
;
1551 Context
= GetContextRef();
1552 if(!Context
) return;
1554 if((Source
=LookupSource(Context
, source
)) == NULL
)
1555 alSetError(Context
, AL_INVALID_NAME
);
1556 else if(!(value1
&& value2
&& value3
))
1557 alSetError(Context
, AL_INVALID_VALUE
);
1563 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1565 *value1
= (ALfloat
)dvals
[0];
1566 *value2
= (ALfloat
)dvals
[1];
1567 *value3
= (ALfloat
)dvals
[2];
1572 alSetError(Context
, AL_INVALID_ENUM
);
1575 ALCcontext_DecRef(Context
);
1579 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1581 ALCcontext
*Context
;
1591 case AL_MAX_DISTANCE
:
1592 case AL_ROLLOFF_FACTOR
:
1593 case AL_DOPPLER_FACTOR
:
1594 case AL_CONE_OUTER_GAIN
:
1596 case AL_SAMPLE_OFFSET
:
1597 case AL_BYTE_OFFSET
:
1598 case AL_CONE_INNER_ANGLE
:
1599 case AL_CONE_OUTER_ANGLE
:
1600 case AL_REFERENCE_DISTANCE
:
1601 case AL_CONE_OUTER_GAINHF
:
1602 case AL_AIR_ABSORPTION_FACTOR
:
1603 case AL_ROOM_ROLLOFF_FACTOR
:
1604 alGetSourcef(source
, param
, values
);
1610 alGetSource3f(source
, param
, values
+0, values
+1, values
+2);
1614 Context
= GetContextRef();
1615 if(!Context
) return;
1617 if((Source
=LookupSource(Context
, source
)) == NULL
)
1618 alSetError(Context
, AL_INVALID_NAME
);
1620 alSetError(Context
, AL_INVALID_VALUE
);
1623 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1624 case AL_BYTE_RW_OFFSETS_SOFT
:
1625 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1627 values
[0] = (ALfloat
)dvals
[0];
1628 values
[1] = (ALfloat
)dvals
[1];
1633 alSetError(Context
, AL_INVALID_ENUM
);
1636 ALCcontext_DecRef(Context
);
1640 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1642 ALCcontext
*Context
;
1645 Context
= GetContextRef();
1646 if(!Context
) return;
1648 if((Source
=LookupSource(Context
, source
)) == NULL
)
1649 alSetError(Context
, AL_INVALID_NAME
);
1651 alSetError(Context
, AL_INVALID_VALUE
);
1658 case AL_MAX_DISTANCE
:
1659 case AL_ROLLOFF_FACTOR
:
1660 case AL_CONE_OUTER_GAIN
:
1661 case AL_CONE_OUTER_GAINHF
:
1663 case AL_SAMPLE_OFFSET
:
1664 case AL_BYTE_OFFSET
:
1665 case AL_CONE_INNER_ANGLE
:
1666 case AL_CONE_OUTER_ANGLE
:
1667 case AL_REFERENCE_DISTANCE
:
1668 case AL_AIR_ABSORPTION_FACTOR
:
1669 case AL_ROOM_ROLLOFF_FACTOR
:
1670 case AL_DOPPLER_FACTOR
:
1671 GetSourcedv(Source
, Context
, param
, value
);
1675 alSetError(Context
, AL_INVALID_ENUM
);
1678 ALCcontext_DecRef(Context
);
1681 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1683 ALCcontext
*Context
;
1687 Context
= GetContextRef();
1688 if(!Context
) return;
1690 if((Source
=LookupSource(Context
, source
)) == NULL
)
1691 alSetError(Context
, AL_INVALID_NAME
);
1692 else if(!(value1
&& value2
&& value3
))
1693 alSetError(Context
, AL_INVALID_VALUE
);
1699 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1708 alSetError(Context
, AL_INVALID_ENUM
);
1711 ALCcontext_DecRef(Context
);
1714 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1716 ALCcontext
*Context
;
1719 Context
= GetContextRef();
1720 if(!Context
) return;
1722 if((Source
=LookupSource(Context
, source
)) == NULL
)
1723 alSetError(Context
, AL_INVALID_NAME
);
1725 alSetError(Context
, AL_INVALID_VALUE
);
1732 case AL_MAX_DISTANCE
:
1733 case AL_ROLLOFF_FACTOR
:
1734 case AL_DOPPLER_FACTOR
:
1735 case AL_CONE_OUTER_GAIN
:
1737 case AL_SAMPLE_OFFSET
:
1738 case AL_BYTE_OFFSET
:
1739 case AL_CONE_INNER_ANGLE
:
1740 case AL_CONE_OUTER_ANGLE
:
1741 case AL_REFERENCE_DISTANCE
:
1742 case AL_CONE_OUTER_GAINHF
:
1743 case AL_AIR_ABSORPTION_FACTOR
:
1744 case AL_ROOM_ROLLOFF_FACTOR
:
1746 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1747 case AL_BYTE_RW_OFFSETS_SOFT
:
1748 case AL_SEC_OFFSET_LATENCY_SOFT
:
1753 GetSourcedv(Source
, Context
, param
, values
);
1757 alSetError(Context
, AL_INVALID_ENUM
);
1760 ALCcontext_DecRef(Context
);
1764 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1766 ALCcontext
*Context
;
1769 Context
= GetContextRef();
1770 if(!Context
) return;
1772 if((Source
=LookupSource(Context
, source
)) == NULL
)
1773 alSetError(Context
, AL_INVALID_NAME
);
1775 alSetError(Context
, AL_INVALID_VALUE
);
1778 case AL_MAX_DISTANCE
:
1779 case AL_ROLLOFF_FACTOR
:
1780 case AL_REFERENCE_DISTANCE
:
1781 case AL_SOURCE_RELATIVE
:
1782 case AL_CONE_INNER_ANGLE
:
1783 case AL_CONE_OUTER_ANGLE
:
1786 case AL_SOURCE_STATE
:
1787 case AL_BUFFERS_QUEUED
:
1788 case AL_BUFFERS_PROCESSED
:
1789 case AL_SOURCE_TYPE
:
1791 case AL_SAMPLE_OFFSET
:
1792 case AL_BYTE_OFFSET
:
1793 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1794 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1795 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1796 case AL_DOPPLER_FACTOR
:
1797 case AL_DIRECT_CHANNELS_SOFT
:
1798 case AL_DISTANCE_MODEL
:
1799 GetSourceiv(Source
, Context
, param
, value
);
1803 alSetError(Context
, AL_INVALID_ENUM
);
1806 ALCcontext_DecRef(Context
);
1810 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1812 ALCcontext
*Context
;
1816 Context
= GetContextRef();
1817 if(!Context
) return;
1819 if((Source
=LookupSource(Context
, source
)) == NULL
)
1820 alSetError(Context
, AL_INVALID_NAME
);
1821 else if(!(value1
&& value2
&& value3
))
1822 alSetError(Context
, AL_INVALID_VALUE
);
1828 if(GetSourceiv(Source
, Context
, param
, ivals
) == AL_NO_ERROR
)
1837 alSetError(Context
, AL_INVALID_ENUM
);
1840 ALCcontext_DecRef(Context
);
1844 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1846 ALCcontext
*Context
;
1849 Context
= GetContextRef();
1850 if(!Context
) return;
1852 if((Source
=LookupSource(Context
, source
)) == NULL
)
1853 alSetError(Context
, AL_INVALID_NAME
);
1855 alSetError(Context
, AL_INVALID_VALUE
);
1858 case AL_SOURCE_RELATIVE
:
1859 case AL_CONE_INNER_ANGLE
:
1860 case AL_CONE_OUTER_ANGLE
:
1863 case AL_SOURCE_STATE
:
1864 case AL_BUFFERS_QUEUED
:
1865 case AL_BUFFERS_PROCESSED
:
1867 case AL_SAMPLE_OFFSET
:
1868 case AL_BYTE_OFFSET
:
1869 case AL_MAX_DISTANCE
:
1870 case AL_ROLLOFF_FACTOR
:
1871 case AL_DOPPLER_FACTOR
:
1872 case AL_REFERENCE_DISTANCE
:
1873 case AL_SOURCE_TYPE
:
1874 case AL_DIRECT_FILTER
:
1875 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1876 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1877 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1878 case AL_DISTANCE_MODEL
:
1879 case AL_DIRECT_CHANNELS_SOFT
:
1881 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1882 case AL_BYTE_RW_OFFSETS_SOFT
:
1887 GetSourceiv(Source
, Context
, param
, values
);
1891 alSetError(Context
, AL_INVALID_ENUM
);
1894 ALCcontext_DecRef(Context
);
1898 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
1900 ALCcontext
*Context
;
1903 Context
= GetContextRef();
1904 if(!Context
) return;
1906 if((Source
=LookupSource(Context
, source
)) == NULL
)
1907 alSetError(Context
, AL_INVALID_NAME
);
1909 alSetError(Context
, AL_INVALID_VALUE
);
1912 case AL_MAX_DISTANCE
:
1913 case AL_ROLLOFF_FACTOR
:
1914 case AL_REFERENCE_DISTANCE
:
1915 case AL_SOURCE_RELATIVE
:
1916 case AL_CONE_INNER_ANGLE
:
1917 case AL_CONE_OUTER_ANGLE
:
1920 case AL_SOURCE_STATE
:
1921 case AL_BUFFERS_QUEUED
:
1922 case AL_BUFFERS_PROCESSED
:
1923 case AL_SOURCE_TYPE
:
1925 case AL_SAMPLE_OFFSET
:
1926 case AL_BYTE_OFFSET
:
1927 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1928 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1929 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1930 case AL_DOPPLER_FACTOR
:
1931 case AL_DIRECT_CHANNELS_SOFT
:
1932 case AL_DISTANCE_MODEL
:
1933 GetSourcei64v(Source
, Context
, param
, value
);
1937 alSetError(Context
, AL_INVALID_ENUM
);
1940 ALCcontext_DecRef(Context
);
1943 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
1945 ALCcontext
*Context
;
1949 Context
= GetContextRef();
1950 if(!Context
) return;
1952 if((Source
=LookupSource(Context
, source
)) == NULL
)
1953 alSetError(Context
, AL_INVALID_NAME
);
1954 else if(!(value1
&& value2
&& value3
))
1955 alSetError(Context
, AL_INVALID_VALUE
);
1961 if(GetSourcei64v(Source
, Context
, param
, i64vals
) == AL_NO_ERROR
)
1963 *value1
= i64vals
[0];
1964 *value2
= i64vals
[1];
1965 *value3
= i64vals
[2];
1970 alSetError(Context
, AL_INVALID_ENUM
);
1973 ALCcontext_DecRef(Context
);
1976 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
1978 ALCcontext
*Context
;
1981 Context
= GetContextRef();
1982 if(!Context
) return;
1984 if((Source
=LookupSource(Context
, source
)) == NULL
)
1985 alSetError(Context
, AL_INVALID_NAME
);
1987 alSetError(Context
, AL_INVALID_VALUE
);
1990 case AL_MAX_DISTANCE
:
1991 case AL_ROLLOFF_FACTOR
:
1992 case AL_REFERENCE_DISTANCE
:
1993 case AL_SOURCE_RELATIVE
:
1994 case AL_CONE_INNER_ANGLE
:
1995 case AL_CONE_OUTER_ANGLE
:
1998 case AL_SOURCE_STATE
:
1999 case AL_BUFFERS_QUEUED
:
2000 case AL_BUFFERS_PROCESSED
:
2001 case AL_SOURCE_TYPE
:
2003 case AL_SAMPLE_OFFSET
:
2004 case AL_BYTE_OFFSET
:
2005 case AL_DIRECT_FILTER_GAINHF_AUTO
:
2006 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
2007 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
2008 case AL_DOPPLER_FACTOR
:
2009 case AL_DIRECT_CHANNELS_SOFT
:
2010 case AL_DISTANCE_MODEL
:
2012 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2013 case AL_BYTE_RW_OFFSETS_SOFT
:
2014 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
2019 GetSourcei64v(Source
, Context
, param
, values
);
2023 alSetError(Context
, AL_INVALID_ENUM
);
2026 ALCcontext_DecRef(Context
);
2030 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
2032 alSourcePlayv(1, &source
);
2034 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2036 ALCcontext
*Context
;
2040 Context
= GetContextRef();
2041 if(!Context
) return;
2045 CHECK_VALUE(Context
, n
>= 0);
2046 for(i
= 0;i
< n
;i
++)
2048 if(!LookupSource(Context
, sources
[i
]))
2049 al_throwerr(Context
, AL_INVALID_NAME
);
2052 LockContext(Context
);
2053 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
2058 newcount
= Context
->MaxActiveSources
<< 1;
2060 temp
= realloc(Context
->ActiveSources
,
2061 sizeof(*Context
->ActiveSources
) * newcount
);
2064 UnlockContext(Context
);
2065 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
2068 Context
->ActiveSources
= temp
;
2069 Context
->MaxActiveSources
= newcount
;
2072 for(i
= 0;i
< n
;i
++)
2074 Source
= LookupSource(Context
, sources
[i
]);
2075 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
2076 else SetSourceState(Source
, Context
, AL_PLAYING
);
2078 UnlockContext(Context
);
2082 ALCcontext_DecRef(Context
);
2085 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2087 alSourcePausev(1, &source
);
2089 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2091 ALCcontext
*Context
;
2095 Context
= GetContextRef();
2096 if(!Context
) return;
2100 CHECK_VALUE(Context
, n
>= 0);
2101 for(i
= 0;i
< n
;i
++)
2103 if(!LookupSource(Context
, sources
[i
]))
2104 al_throwerr(Context
, AL_INVALID_NAME
);
2107 LockContext(Context
);
2108 for(i
= 0;i
< n
;i
++)
2110 Source
= LookupSource(Context
, sources
[i
]);
2111 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
2112 else SetSourceState(Source
, Context
, AL_PAUSED
);
2114 UnlockContext(Context
);
2118 ALCcontext_DecRef(Context
);
2121 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2123 alSourceStopv(1, &source
);
2125 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2127 ALCcontext
*Context
;
2131 Context
= GetContextRef();
2132 if(!Context
) return;
2136 CHECK_VALUE(Context
, n
>= 0);
2137 for(i
= 0;i
< n
;i
++)
2139 if(!LookupSource(Context
, sources
[i
]))
2140 al_throwerr(Context
, AL_INVALID_NAME
);
2143 LockContext(Context
);
2144 for(i
= 0;i
< n
;i
++)
2146 Source
= LookupSource(Context
, sources
[i
]);
2147 Source
->new_state
= AL_NONE
;
2148 SetSourceState(Source
, Context
, AL_STOPPED
);
2150 UnlockContext(Context
);
2154 ALCcontext_DecRef(Context
);
2157 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2159 alSourceRewindv(1, &source
);
2161 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2163 ALCcontext
*Context
;
2167 Context
= GetContextRef();
2168 if(!Context
) return;
2172 CHECK_VALUE(Context
, n
>= 0);
2173 for(i
= 0;i
< n
;i
++)
2175 if(!LookupSource(Context
, sources
[i
]))
2176 al_throwerr(Context
, AL_INVALID_NAME
);
2179 LockContext(Context
);
2180 for(i
= 0;i
< n
;i
++)
2182 Source
= LookupSource(Context
, sources
[i
]);
2183 Source
->new_state
= AL_NONE
;
2184 SetSourceState(Source
, Context
, AL_INITIAL
);
2186 UnlockContext(Context
);
2190 ALCcontext_DecRef(Context
);
2194 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei nb
, const ALuint
*buffers
)
2196 ALCcontext
*Context
;
2199 ALbufferlistitem
*BufferListStart
= NULL
;
2200 ALbufferlistitem
*BufferList
;
2201 ALbuffer
*BufferFmt
;
2206 Context
= GetContextRef();
2207 if(!Context
) return;
2211 ALCdevice
*device
= Context
->Device
;
2213 CHECK_VALUE(Context
, nb
>= 0);
2215 if((Source
=LookupSource(Context
, source
)) == NULL
)
2216 al_throwerr(Context
, AL_INVALID_NAME
);
2218 LockContext(Context
);
2219 if(Source
->SourceType
== AL_STATIC
)
2221 UnlockContext(Context
);
2222 /* Can't queue on a Static Source */
2223 al_throwerr(Context
, AL_INVALID_OPERATION
);
2228 /* Check for a valid Buffer, for its frequency and format */
2229 BufferList
= Source
->queue
;
2232 if(BufferList
->buffer
)
2234 BufferFmt
= BufferList
->buffer
;
2237 BufferList
= BufferList
->next
;
2240 for(i
= 0;i
< nb
;i
++)
2242 ALbuffer
*buffer
= NULL
;
2243 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2245 UnlockContext(Context
);
2246 al_throwerr(Context
, AL_INVALID_NAME
);
2249 if(!BufferListStart
)
2251 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2252 BufferListStart
->buffer
= buffer
;
2253 BufferListStart
->next
= NULL
;
2254 BufferListStart
->prev
= NULL
;
2255 BufferList
= BufferListStart
;
2259 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2260 BufferList
->next
->buffer
= buffer
;
2261 BufferList
->next
->next
= NULL
;
2262 BufferList
->next
->prev
= BufferList
;
2263 BufferList
= BufferList
->next
;
2265 if(!buffer
) continue;
2266 IncrementRef(&buffer
->ref
);
2268 ReadLock(&buffer
->lock
);
2269 if(BufferFmt
== NULL
)
2273 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2274 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2275 if(buffer
->FmtChannels
== FmtMono
)
2276 Source
->Update
= CalcSourceParams
;
2278 Source
->Update
= CalcNonAttnSourceParams
;
2280 Source
->NeedsUpdate
= AL_TRUE
;
2282 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2283 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2284 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2286 ReadUnlock(&buffer
->lock
);
2287 UnlockContext(Context
);
2288 al_throwerr(Context
, AL_INVALID_OPERATION
);
2290 ReadUnlock(&buffer
->lock
);
2293 /* Source is now streaming */
2294 Source
->SourceType
= AL_STREAMING
;
2296 if(Source
->queue
== NULL
)
2297 Source
->queue
= BufferListStart
;
2300 /* Append to the end of the queue */
2301 BufferList
= Source
->queue
;
2302 while(BufferList
->next
!= NULL
)
2303 BufferList
= BufferList
->next
;
2305 BufferListStart
->prev
= BufferList
;
2306 BufferList
->next
= BufferListStart
;
2309 Source
->BuffersInQueue
+= nb
;
2311 UnlockContext(Context
);
2315 while(BufferListStart
)
2317 BufferList
= BufferListStart
;
2318 BufferListStart
= BufferList
->next
;
2320 if(BufferList
->buffer
)
2321 DecrementRef(&BufferList
->buffer
->ref
);
2327 ALCcontext_DecRef(Context
);
2330 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint source
, ALsizei nb
, ALuint
*buffers
)
2332 ALCcontext
*Context
;
2335 ALbufferlistitem
*BufferList
;
2340 Context
= GetContextRef();
2341 if(!Context
) return;
2345 CHECK_VALUE(Context
, nb
>= 0);
2347 if((Source
=LookupSource(Context
, source
)) == NULL
)
2348 al_throwerr(Context
, AL_INVALID_NAME
);
2350 LockContext(Context
);
2351 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
||
2352 (ALuint
)nb
> Source
->BuffersPlayed
)
2354 UnlockContext(Context
);
2355 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2356 al_throwerr(Context
, AL_INVALID_VALUE
);
2359 for(i
= 0;i
< nb
;i
++)
2361 BufferList
= Source
->queue
;
2362 Source
->queue
= BufferList
->next
;
2363 Source
->BuffersInQueue
--;
2364 Source
->BuffersPlayed
--;
2366 if(BufferList
->buffer
)
2368 buffers
[i
] = BufferList
->buffer
->id
;
2369 DecrementRef(&BufferList
->buffer
->ref
);
2377 Source
->queue
->prev
= NULL
;
2378 UnlockContext(Context
);
2382 ALCcontext_DecRef(Context
);
2386 static ALvoid
InitSourceParams(ALsource
*Source
)
2390 Source
->InnerAngle
= 360.0f
;
2391 Source
->OuterAngle
= 360.0f
;
2392 Source
->Pitch
= 1.0f
;
2393 Source
->Position
[0] = 0.0f
;
2394 Source
->Position
[1] = 0.0f
;
2395 Source
->Position
[2] = 0.0f
;
2396 Source
->Orientation
[0] = 0.0f
;
2397 Source
->Orientation
[1] = 0.0f
;
2398 Source
->Orientation
[2] = 0.0f
;
2399 Source
->Velocity
[0] = 0.0f
;
2400 Source
->Velocity
[1] = 0.0f
;
2401 Source
->Velocity
[2] = 0.0f
;
2402 Source
->RefDistance
= 1.0f
;
2403 Source
->MaxDistance
= FLT_MAX
;
2404 Source
->RollOffFactor
= 1.0f
;
2405 Source
->Looping
= AL_FALSE
;
2406 Source
->Gain
= 1.0f
;
2407 Source
->MinGain
= 0.0f
;
2408 Source
->MaxGain
= 1.0f
;
2409 Source
->OuterGain
= 0.0f
;
2410 Source
->OuterGainHF
= 1.0f
;
2412 Source
->DryGainHFAuto
= AL_TRUE
;
2413 Source
->WetGainAuto
= AL_TRUE
;
2414 Source
->WetGainHFAuto
= AL_TRUE
;
2415 Source
->AirAbsorptionFactor
= 0.0f
;
2416 Source
->RoomRolloffFactor
= 0.0f
;
2417 Source
->DopplerFactor
= 1.0f
;
2418 Source
->DirectChannels
= AL_FALSE
;
2420 Source
->DistanceModel
= DefaultDistanceModel
;
2422 Source
->Resampler
= DefaultResampler
;
2424 Source
->state
= AL_INITIAL
;
2425 Source
->new_state
= AL_NONE
;
2426 Source
->SourceType
= AL_UNDETERMINED
;
2427 Source
->Offset
= -1.0;
2429 Source
->DirectGain
= 1.0f
;
2430 Source
->DirectGainHF
= 1.0f
;
2431 for(i
= 0;i
< MAX_SENDS
;i
++)
2433 Source
->Send
[i
].Gain
= 1.0f
;
2434 Source
->Send
[i
].GainHF
= 1.0f
;
2437 Source
->NeedsUpdate
= AL_TRUE
;
2439 Source
->Hrtf
.Moving
= AL_FALSE
;
2440 Source
->Hrtf
.Counter
= 0;
2446 * Sets the source's new play state given its current state.
2448 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2450 if(state
== AL_PLAYING
)
2452 ALbufferlistitem
*BufferList
;
2455 /* Check that there is a queue containing at least one valid, non zero
2457 BufferList
= Source
->queue
;
2460 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
2462 BufferList
= BufferList
->next
;
2465 if(Source
->state
!= AL_PLAYING
)
2467 for(j
= 0;j
< MaxChannels
;j
++)
2469 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
2470 Source
->Hrtf
.History
[j
][k
] = 0.0f
;
2471 for(k
= 0;k
< HRIR_LENGTH
;k
++)
2473 Source
->Hrtf
.Values
[j
][k
][0] = 0.0f
;
2474 Source
->Hrtf
.Values
[j
][k
][1] = 0.0f
;
2479 if(Source
->state
!= AL_PAUSED
)
2481 Source
->state
= AL_PLAYING
;
2482 Source
->position
= 0;
2483 Source
->position_fraction
= 0;
2484 Source
->BuffersPlayed
= 0;
2487 Source
->state
= AL_PLAYING
;
2489 // Check if an Offset has been set
2490 if(Source
->Offset
>= 0.0)
2491 ApplyOffset(Source
);
2493 /* If there's nothing to play, or device is disconnected, go right to
2495 if(!BufferList
|| !Context
->Device
->Connected
)
2497 SetSourceState(Source
, Context
, AL_STOPPED
);
2501 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
2503 if(Context
->ActiveSources
[j
] == Source
)
2506 if(j
== Context
->ActiveSourceCount
)
2507 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
2509 else if(state
== AL_PAUSED
)
2511 if(Source
->state
== AL_PLAYING
)
2513 Source
->state
= AL_PAUSED
;
2514 Source
->Hrtf
.Moving
= AL_FALSE
;
2515 Source
->Hrtf
.Counter
= 0;
2518 else if(state
== AL_STOPPED
)
2520 if(Source
->state
!= AL_INITIAL
)
2522 Source
->state
= AL_STOPPED
;
2523 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
2524 Source
->Hrtf
.Moving
= AL_FALSE
;
2525 Source
->Hrtf
.Counter
= 0;
2527 Source
->Offset
= -1.0;
2529 else if(state
== AL_INITIAL
)
2531 if(Source
->state
!= AL_INITIAL
)
2533 Source
->state
= AL_INITIAL
;
2534 Source
->position
= 0;
2535 Source
->position_fraction
= 0;
2536 Source
->BuffersPlayed
= 0;
2537 Source
->Hrtf
.Moving
= AL_FALSE
;
2538 Source
->Hrtf
.Counter
= 0;
2540 Source
->Offset
= -1.0;
2546 * Gets the current read offset for the given Source, in 32.32 fixed-point
2547 * samples. The offset is relative to the start of the queue (not the start of
2548 * the current buffer).
2550 static ALint64
GetSourceOffset(const ALsource
*Source
)
2552 const ALbufferlistitem
*BufferList
;
2556 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2559 /* NOTE: This is the offset into the *current* buffer, so add the length of
2560 * any played buffers */
2561 readPos
= (ALuint64
)Source
->position
<< 32;
2562 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2563 BufferList
= Source
->queue
;
2564 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2566 if(BufferList
->buffer
)
2567 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2568 BufferList
= BufferList
->next
;
2571 return (ALint64
)minu64(readPos
, MAKEU64(0x7fffffff,0xffffffff));
2574 /* GetSourceSecOffset
2576 * Gets the current read offset for the given Source, in seconds. The offset is
2577 * relative to the start of the queue (not the start of the current buffer).
2579 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2581 const ALbufferlistitem
*BufferList
;
2582 const ALbuffer
*Buffer
= NULL
;
2586 BufferList
= Source
->queue
;
2589 if(BufferList
->buffer
)
2591 Buffer
= BufferList
->buffer
;
2594 BufferList
= BufferList
->next
;
2597 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2600 /* NOTE: This is the offset into the *current* buffer, so add the length of
2601 * any played buffers */
2602 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2603 readPos
|= (ALuint64
)Source
->position_fraction
;
2604 BufferList
= Source
->queue
;
2605 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2607 if(BufferList
->buffer
)
2608 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< FRACTIONBITS
;
2609 BufferList
= BufferList
->next
;
2612 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2617 * Gets the current read and write offsets for the given Source, in the
2618 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2619 * the start of the queue (not the start of the current buffer).
2621 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2623 const ALbufferlistitem
*BufferList
;
2624 const ALbuffer
*Buffer
= NULL
;
2625 ALuint readPos
, writePos
;
2626 ALuint totalBufferLen
;
2629 // Find the first valid Buffer in the Queue
2630 BufferList
= Source
->queue
;
2633 if(BufferList
->buffer
)
2635 Buffer
= BufferList
->buffer
;
2638 BufferList
= BufferList
->next
;
2641 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2648 if(updateLen
> 0.0 && updateLen
< 0.015)
2651 /* NOTE: This is the offset into the *current* buffer, so add the length of
2652 * any played buffers */
2653 readPos
= Source
->position
;
2655 BufferList
= Source
->queue
;
2656 for(i
= 0;BufferList
;i
++)
2658 if(BufferList
->buffer
)
2660 if(i
< Source
->BuffersPlayed
)
2661 readPos
+= BufferList
->buffer
->SampleLen
;
2662 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
2664 BufferList
= BufferList
->next
;
2666 if(Source
->state
== AL_PLAYING
)
2667 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2673 readPos
%= totalBufferLen
;
2674 writePos
%= totalBufferLen
;
2678 /* Wrap positions back to 0 */
2679 if(readPos
>= totalBufferLen
)
2681 if(writePos
>= totalBufferLen
)
2688 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2689 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2692 case AL_SAMPLE_OFFSET
:
2693 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2694 offset
[0] = (ALdouble
)readPos
;
2695 offset
[1] = (ALdouble
)writePos
;
2698 case AL_BYTE_OFFSET
:
2699 case AL_BYTE_RW_OFFSETS_SOFT
:
2700 if(Buffer
->OriginalType
== UserFmtIMA4
)
2702 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
2703 ALuint FrameBlockSize
= 65;
2705 /* Round down to nearest ADPCM block */
2706 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2707 if(Source
->state
!= AL_PLAYING
)
2708 offset
[1] = offset
[0];
2711 /* Round up to nearest ADPCM block */
2712 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2713 FrameBlockSize
* BlockSize
);
2718 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2719 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2720 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2729 * Apply the stored playback offset to the Source. This function will update
2730 * the number of buffers "played" given the stored offset.
2732 ALboolean
ApplyOffset(ALsource
*Source
)
2734 const ALbufferlistitem
*BufferList
;
2735 const ALbuffer
*Buffer
;
2736 ALint bufferLen
, totalBufferLen
;
2737 ALint buffersPlayed
;
2740 /* Get sample frame offset */
2741 offset
= GetSampleOffset(Source
);
2748 BufferList
= Source
->queue
;
2751 Buffer
= BufferList
->buffer
;
2752 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2754 if(bufferLen
<= offset
-totalBufferLen
)
2756 /* Offset is past this buffer so increment to the next buffer */
2759 else if(totalBufferLen
<= offset
)
2761 /* Offset is in this buffer */
2762 Source
->BuffersPlayed
= buffersPlayed
;
2764 Source
->position
= offset
- totalBufferLen
;
2765 Source
->position_fraction
= 0;
2769 totalBufferLen
+= bufferLen
;
2771 BufferList
= BufferList
->next
;
2774 /* Offset is out of range of the queue */
2781 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2782 * Second offset supplied by the application). This takes into account the fact
2783 * that the buffer format may have been modifed since.
2785 static ALint
GetSampleOffset(ALsource
*Source
)
2787 const ALbuffer
*Buffer
= NULL
;
2788 const ALbufferlistitem
*BufferList
;
2791 /* Find the first valid Buffer in the Queue */
2792 BufferList
= Source
->queue
;
2795 if(BufferList
->buffer
)
2797 Buffer
= BufferList
->buffer
;
2800 BufferList
= BufferList
->next
;
2805 Source
->Offset
= -1.0;
2809 switch(Source
->OffsetType
)
2811 case AL_BYTE_OFFSET
:
2812 /* Determine the ByteOffset (and ensure it is block aligned) */
2813 Offset
= (ALint
)Source
->Offset
;
2814 if(Buffer
->OriginalType
== UserFmtIMA4
)
2816 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2820 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2823 case AL_SAMPLE_OFFSET
:
2824 Offset
= (ALint
)Source
->Offset
;
2828 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2831 Source
->Offset
= -1.0;
2839 * Destroys all sources in the source map.
2841 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2845 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2847 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2848 Context
->SourceMap
.array
[pos
].value
= NULL
;
2850 while(temp
->queue
!= NULL
)
2852 ALbufferlistitem
*BufferList
= temp
->queue
;
2853 temp
->queue
= BufferList
->next
;
2855 if(BufferList
->buffer
!= NULL
)
2856 DecrementRef(&BufferList
->buffer
->ref
);
2860 for(j
= 0;j
< MAX_SENDS
;++j
)
2862 if(temp
->Send
[j
].Slot
)
2863 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2864 temp
->Send
[j
].Slot
= NULL
;
2867 FreeThunkEntry(temp
->id
);
2868 memset(temp
, 0, sizeof(*temp
));