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
);
200 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
202 LockContext(Context
);
203 Source
->Position
[0] = values
[0];
204 Source
->Position
[1] = values
[1];
205 Source
->Position
[2] = values
[2];
206 UnlockContext(Context
);
207 Source
->NeedsUpdate
= AL_TRUE
;
211 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
213 LockContext(Context
);
214 Source
->Velocity
[0] = values
[0];
215 Source
->Velocity
[1] = values
[1];
216 Source
->Velocity
[2] = values
[2];
217 UnlockContext(Context
);
218 Source
->NeedsUpdate
= AL_TRUE
;
222 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
224 LockContext(Context
);
225 Source
->Orientation
[0] = values
[0];
226 Source
->Orientation
[1] = values
[1];
227 Source
->Orientation
[2] = values
[2];
228 UnlockContext(Context
);
229 Source
->NeedsUpdate
= AL_TRUE
;
234 RETERR(AL_INVALID_ENUM
);
240 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint
*values
)
242 ALCdevice
*device
= Context
->Device
;
243 ALbuffer
*buffer
= NULL
;
244 ALfilter
*filter
= NULL
;
245 ALeffectslot
*slot
= NULL
;
246 ALbufferlistitem
*oldlist
;
252 case AL_SOURCE_RELATIVE
:
253 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
255 Source
->HeadRelative
= (ALboolean
)*values
;
256 Source
->NeedsUpdate
= AL_TRUE
;
260 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
262 Source
->Looping
= (ALboolean
)*values
;
266 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
268 LockContext(Context
);
269 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
271 UnlockContext(Context
);
272 RETERR(AL_INVALID_OPERATION
);
275 Source
->BuffersInQueue
= 0;
276 Source
->BuffersPlayed
= 0;
280 ALbufferlistitem
*BufferListItem
;
282 /* Source is now Static */
283 Source
->SourceType
= AL_STATIC
;
285 /* Add the selected buffer to a one-item queue */
286 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
287 BufferListItem
->buffer
= buffer
;
288 BufferListItem
->next
= NULL
;
289 BufferListItem
->prev
= NULL
;
290 IncrementRef(&buffer
->ref
);
292 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, BufferListItem
);
293 Source
->BuffersInQueue
= 1;
295 ReadLock(&buffer
->lock
);
296 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
297 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
298 ReadUnlock(&buffer
->lock
);
299 if(buffer
->FmtChannels
== FmtMono
)
300 Source
->Update
= CalcSourceParams
;
302 Source
->Update
= CalcNonAttnSourceParams
;
303 Source
->NeedsUpdate
= AL_TRUE
;
307 /* Source is now Undetermined */
308 Source
->SourceType
= AL_UNDETERMINED
;
309 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, NULL
);
312 /* Delete all elements in the previous queue */
313 while(oldlist
!= NULL
)
315 ALbufferlistitem
*temp
= oldlist
;
316 oldlist
= temp
->next
;
319 DecrementRef(&temp
->buffer
->ref
);
322 UnlockContext(Context
);
325 case AL_SOURCE_STATE
:
327 RETERR(AL_INVALID_OPERATION
);
330 case AL_SAMPLE_OFFSET
:
332 CHECKVAL(*values
>= 0);
334 LockContext(Context
);
335 Source
->OffsetType
= name
;
336 Source
->Offset
= *values
;
338 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
339 !Context
->DeferUpdates
)
341 if(ApplyOffset(Source
) == AL_FALSE
)
343 UnlockContext(Context
);
344 RETERR(AL_INVALID_VALUE
);
347 UnlockContext(Context
);
350 case AL_DIRECT_FILTER
:
351 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
353 LockContext(Context
);
356 Source
->DirectGain
= 1.0f
;
357 Source
->DirectGainHF
= 1.0f
;
361 Source
->DirectGain
= filter
->Gain
;
362 Source
->DirectGainHF
= filter
->GainHF
;
364 UnlockContext(Context
);
365 Source
->NeedsUpdate
= AL_TRUE
;
368 case AL_DIRECT_FILTER_GAINHF_AUTO
:
369 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
371 Source
->DryGainHFAuto
= *values
;
372 Source
->NeedsUpdate
= AL_TRUE
;
375 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
376 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
378 Source
->WetGainAuto
= *values
;
379 Source
->NeedsUpdate
= AL_TRUE
;
382 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
383 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
385 Source
->WetGainHFAuto
= *values
;
386 Source
->NeedsUpdate
= AL_TRUE
;
389 case AL_DIRECT_CHANNELS_SOFT
:
390 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
392 Source
->DirectChannels
= *values
;
393 Source
->NeedsUpdate
= AL_TRUE
;
396 case AL_DISTANCE_MODEL
:
397 CHECKVAL(*values
== AL_NONE
||
398 *values
== AL_INVERSE_DISTANCE
||
399 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
400 *values
== AL_LINEAR_DISTANCE
||
401 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
402 *values
== AL_EXPONENT_DISTANCE
||
403 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
405 Source
->DistanceModel
= *values
;
406 if(Context
->SourceDistanceModel
)
407 Source
->NeedsUpdate
= AL_TRUE
;
411 case AL_AUXILIARY_SEND_FILTER
:
412 LockContext(Context
);
413 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
414 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
415 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
417 UnlockContext(Context
);
418 RETERR(AL_INVALID_VALUE
);
421 /* Add refcount on the new slot, and release the previous slot */
422 if(slot
) IncrementRef(&slot
->ref
);
423 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
424 if(slot
) DecrementRef(&slot
->ref
);
429 Source
->Send
[values
[1]].Gain
= 1.0f
;
430 Source
->Send
[values
[1]].GainHF
= 1.0f
;
434 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
435 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
437 Source
->NeedsUpdate
= AL_TRUE
;
438 UnlockContext(Context
);
442 case AL_MAX_DISTANCE
:
443 case AL_ROLLOFF_FACTOR
:
444 case AL_CONE_INNER_ANGLE
:
445 case AL_CONE_OUTER_ANGLE
:
446 case AL_REFERENCE_DISTANCE
:
447 fvals
[0] = (ALfloat
)*values
;
448 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
455 fvals
[0] = (ALfloat
)values
[0];
456 fvals
[1] = (ALfloat
)values
[1];
457 fvals
[2] = (ALfloat
)values
[2];
458 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
463 RETERR(AL_INVALID_ENUM
);
469 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint64SOFT
*values
)
478 case AL_SOURCE_RELATIVE
:
480 case AL_SOURCE_STATE
:
482 case AL_SAMPLE_OFFSET
:
483 case AL_DIRECT_FILTER_GAINHF_AUTO
:
484 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
485 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
486 case AL_DIRECT_CHANNELS_SOFT
:
487 case AL_DISTANCE_MODEL
:
488 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
491 if((err
=SetSourceiv(Source
, Context
, name
, ivals
)))
497 case AL_DIRECT_FILTER
:
498 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
500 ivals
[0] = (ALuint
)*values
;
501 if((err
=SetSourceiv(Source
, Context
, name
, ivals
)))
506 case AL_AUXILIARY_SEND_FILTER
:
507 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
508 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
509 values
[2] <= UINT_MAX
&& values
[2] >= 0);
511 ivals
[0] = (ALuint
)values
[0];
512 ivals
[1] = (ALuint
)values
[1];
513 ivals
[2] = (ALuint
)values
[2];
514 if((err
=SetSourceiv(Source
, Context
, name
, ivals
)))
519 case AL_MAX_DISTANCE
:
520 case AL_ROLLOFF_FACTOR
:
521 case AL_CONE_INNER_ANGLE
:
522 case AL_CONE_OUTER_ANGLE
:
523 case AL_REFERENCE_DISTANCE
:
525 fvals
[0] = (ALfloat
)*values
;
526 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
534 fvals
[0] = (ALfloat
)values
[0];
535 fvals
[1] = (ALfloat
)values
[1];
536 fvals
[2] = (ALfloat
)values
[2];
537 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
542 RETERR(AL_INVALID_ENUM
);
551 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALdouble
*values
)
561 *values
= Source
->Pitch
;
564 case AL_MAX_DISTANCE
:
565 *values
= Source
->MaxDistance
;
568 case AL_ROLLOFF_FACTOR
:
569 *values
= Source
->RollOffFactor
;
572 case AL_REFERENCE_DISTANCE
:
573 *values
= Source
->RefDistance
;
576 case AL_CONE_INNER_ANGLE
:
577 *values
= Source
->InnerAngle
;
580 case AL_CONE_OUTER_ANGLE
:
581 *values
= Source
->OuterAngle
;
585 *values
= Source
->MinGain
;
589 *values
= Source
->MaxGain
;
592 case AL_CONE_OUTER_GAIN
:
593 *values
= Source
->OuterGain
;
597 case AL_SAMPLE_OFFSET
:
599 LockContext(Context
);
600 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
601 Context
->Device
->Frequency
;
602 GetSourceOffsets(Source
, name
, offsets
, updateLen
);
603 UnlockContext(Context
);
604 *values
= offsets
[0];
607 case AL_CONE_OUTER_GAINHF
:
608 *values
= Source
->OuterGainHF
;
611 case AL_AIR_ABSORPTION_FACTOR
:
612 *values
= Source
->AirAbsorptionFactor
;
615 case AL_ROOM_ROLLOFF_FACTOR
:
616 *values
= Source
->RoomRolloffFactor
;
619 case AL_DOPPLER_FACTOR
:
620 *values
= Source
->DopplerFactor
;
623 case AL_SAMPLE_RW_OFFSETS_SOFT
:
624 case AL_BYTE_RW_OFFSETS_SOFT
:
625 LockContext(Context
);
626 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
627 Context
->Device
->Frequency
;
628 GetSourceOffsets(Source
, name
, values
, updateLen
);
629 UnlockContext(Context
);
632 case AL_SEC_OFFSET_LATENCY_SOFT
:
633 LockContext(Context
);
634 values
[0] = GetSourceSecOffset(Source
);
635 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
637 UnlockContext(Context
);
641 LockContext(Context
);
642 values
[0] = Source
->Position
[0];
643 values
[1] = Source
->Position
[1];
644 values
[2] = Source
->Position
[2];
645 UnlockContext(Context
);
649 LockContext(Context
);
650 values
[0] = Source
->Velocity
[0];
651 values
[1] = Source
->Velocity
[1];
652 values
[2] = Source
->Velocity
[2];
653 UnlockContext(Context
);
657 LockContext(Context
);
658 values
[0] = Source
->Orientation
[0];
659 values
[1] = Source
->Orientation
[1];
660 values
[2] = Source
->Orientation
[2];
661 UnlockContext(Context
);
664 case AL_SOURCE_RELATIVE
:
667 case AL_SOURCE_STATE
:
668 case AL_BUFFERS_QUEUED
:
669 case AL_BUFFERS_PROCESSED
:
671 case AL_DIRECT_FILTER_GAINHF_AUTO
:
672 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
673 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
674 case AL_DIRECT_CHANNELS_SOFT
:
675 case AL_DISTANCE_MODEL
:
676 if((err
=GetSourceiv(Source
, Context
, name
, ivals
)) != AL_NO_ERROR
)
678 *values
= (ALdouble
)ivals
[0];
682 RETERR(AL_INVALID_ENUM
);
688 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint
*values
)
690 ALbufferlistitem
*BufferList
;
696 case AL_SOURCE_RELATIVE
:
697 *values
= Source
->HeadRelative
;
701 *values
= Source
->Looping
;
705 LockContext(Context
);
706 BufferList
= Source
->queue
;
707 if(Source
->SourceType
!= AL_STATIC
)
709 ALuint i
= Source
->BuffersPlayed
;
712 BufferList
= BufferList
->next
;
716 *values
= ((BufferList
&& BufferList
->buffer
) ?
717 BufferList
->buffer
->id
: 0);
718 UnlockContext(Context
);
721 case AL_SOURCE_STATE
:
722 *values
= Source
->state
;
725 case AL_BUFFERS_QUEUED
:
726 *values
= Source
->BuffersInQueue
;
729 case AL_BUFFERS_PROCESSED
:
730 LockContext(Context
);
731 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
733 /* Buffers on a looping source are in a perpetual state of
734 * PENDING, so don't report any as PROCESSED */
738 *values
= Source
->BuffersPlayed
;
739 UnlockContext(Context
);
743 *values
= Source
->SourceType
;
746 case AL_DIRECT_FILTER_GAINHF_AUTO
:
747 *values
= Source
->DryGainHFAuto
;
750 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
751 *values
= Source
->WetGainAuto
;
754 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
755 *values
= Source
->WetGainHFAuto
;
758 case AL_DIRECT_CHANNELS_SOFT
:
759 *values
= Source
->DirectChannels
;
762 case AL_DISTANCE_MODEL
:
763 *values
= Source
->DistanceModel
;
766 case AL_MAX_DISTANCE
:
767 case AL_ROLLOFF_FACTOR
:
768 case AL_REFERENCE_DISTANCE
:
769 case AL_CONE_INNER_ANGLE
:
770 case AL_CONE_OUTER_ANGLE
:
772 case AL_SAMPLE_OFFSET
:
774 case AL_DOPPLER_FACTOR
:
775 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
777 *values
= (ALint
)dvals
[0];
780 case AL_SAMPLE_RW_OFFSETS_SOFT
:
781 case AL_BYTE_RW_OFFSETS_SOFT
:
782 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
784 values
[0] = (ALint
)dvals
[0];
785 values
[1] = (ALint
)dvals
[0];
791 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
793 values
[0] = (ALint
)dvals
[0];
794 values
[1] = (ALint
)dvals
[1];
795 values
[2] = (ALint
)dvals
[2];
799 RETERR(AL_INVALID_ENUM
);
805 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint64
*values
)
813 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
814 LockContext(Context
);
815 values
[0] = GetSourceOffset(Source
);
816 values
[1] = ALCdevice_GetLatency(Context
->Device
);
817 UnlockContext(Context
);
820 case AL_MAX_DISTANCE
:
821 case AL_ROLLOFF_FACTOR
:
822 case AL_REFERENCE_DISTANCE
:
823 case AL_CONE_INNER_ANGLE
:
824 case AL_CONE_OUTER_ANGLE
:
826 case AL_SAMPLE_OFFSET
:
828 case AL_DOPPLER_FACTOR
:
829 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
831 *values
= (ALint64
)dvals
[0];
834 case AL_SAMPLE_RW_OFFSETS_SOFT
:
835 case AL_BYTE_RW_OFFSETS_SOFT
:
836 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
838 values
[0] = (ALint64
)dvals
[0];
839 values
[1] = (ALint64
)dvals
[0];
845 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
847 values
[0] = (ALint64
)dvals
[0];
848 values
[1] = (ALint64
)dvals
[1];
849 values
[2] = (ALint64
)dvals
[2];
852 case AL_SOURCE_RELATIVE
:
855 case AL_SOURCE_STATE
:
856 case AL_BUFFERS_QUEUED
:
857 case AL_BUFFERS_PROCESSED
:
859 case AL_DIRECT_FILTER_GAINHF_AUTO
:
860 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
861 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
862 case AL_DIRECT_CHANNELS_SOFT
:
863 case AL_DISTANCE_MODEL
:
864 if((err
=GetSourceiv(Source
, Context
, name
, ivals
)) != AL_NO_ERROR
)
870 RETERR(AL_INVALID_ENUM
);
879 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
884 Context
= GetContextRef();
891 CHECK_VALUE(Context
, n
>= 0);
892 for(cur
= 0;cur
< n
;cur
++)
894 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
896 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
897 InitSourceParams(source
);
899 err
= NewThunkEntry(&source
->id
);
900 if(err
== AL_NO_ERROR
)
901 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->id
, source
);
902 if(err
!= AL_NO_ERROR
)
904 FreeThunkEntry(source
->id
);
905 memset(source
, 0, sizeof(ALsource
));
908 al_throwerr(Context
, err
);
911 sources
[cur
] = source
->id
;
917 alDeleteSources(cur
, sources
);
921 ALCcontext_DecRef(Context
);
925 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
929 Context
= GetContextRef();
934 ALbufferlistitem
*BufferList
;
938 CHECK_VALUE(Context
, n
>= 0);
940 /* Check that all Sources are valid */
943 if(LookupSource(Context
, sources
[i
]) == NULL
)
944 al_throwerr(Context
, AL_INVALID_NAME
);
949 ALsource
**srclist
, **srclistend
;
951 if((Source
=RemoveSource(Context
, sources
[i
])) == NULL
)
953 FreeThunkEntry(Source
->id
);
955 LockContext(Context
);
956 srclist
= Context
->ActiveSources
;
957 srclistend
= srclist
+ Context
->ActiveSourceCount
;
958 while(srclist
!= srclistend
)
960 if(*srclist
== Source
)
962 Context
->ActiveSourceCount
--;
963 *srclist
= *(--srclistend
);
968 UnlockContext(Context
);
970 while(Source
->queue
!= NULL
)
972 BufferList
= Source
->queue
;
973 Source
->queue
= BufferList
->next
;
975 if(BufferList
->buffer
!= NULL
)
976 DecrementRef(&BufferList
->buffer
->ref
);
980 for(j
= 0;j
< MAX_SENDS
;++j
)
982 if(Source
->Send
[j
].Slot
)
983 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
984 Source
->Send
[j
].Slot
= NULL
;
987 memset(Source
, 0, sizeof(*Source
));
993 ALCcontext_DecRef(Context
);
997 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1002 Context
= GetContextRef();
1003 if(!Context
) return AL_FALSE
;
1005 result
= (LookupSource(Context
, source
) ? AL_TRUE
: AL_FALSE
);
1007 ALCcontext_DecRef(Context
);
1013 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1015 ALCcontext
*Context
;
1018 Context
= GetContextRef();
1019 if(!Context
) return;
1021 if((Source
=LookupSource(Context
, source
)) == NULL
)
1022 alSetError(Context
, AL_INVALID_NAME
);
1026 case AL_CONE_INNER_ANGLE
:
1027 case AL_CONE_OUTER_ANGLE
:
1029 case AL_MAX_DISTANCE
:
1030 case AL_ROLLOFF_FACTOR
:
1031 case AL_REFERENCE_DISTANCE
:
1034 case AL_CONE_OUTER_GAIN
:
1035 case AL_CONE_OUTER_GAINHF
:
1036 case AL_AIR_ABSORPTION_FACTOR
:
1037 case AL_ROOM_ROLLOFF_FACTOR
:
1038 case AL_DOPPLER_FACTOR
:
1040 case AL_SAMPLE_OFFSET
:
1041 case AL_BYTE_OFFSET
:
1042 SetSourcefv(Source
, Context
, param
, &value
);
1046 alSetError(Context
, AL_INVALID_ENUM
);
1049 ALCcontext_DecRef(Context
);
1052 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1054 ALCcontext
*Context
;
1058 Context
= GetContextRef();
1059 if(!Context
) return;
1061 if((Source
=LookupSource(Context
, source
)) == NULL
)
1062 alSetError(Context
, AL_INVALID_NAME
);
1071 SetSourcefv(Source
, Context
, param
, fvals
);
1075 alSetError(Context
, AL_INVALID_ENUM
);
1078 ALCcontext_DecRef(Context
);
1081 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1083 ALCcontext
*Context
;
1086 Context
= GetContextRef();
1087 if(!Context
) return;
1089 if((Source
=LookupSource(Context
, source
)) == NULL
)
1090 alSetError(Context
, AL_INVALID_NAME
);
1092 alSetError(Context
, AL_INVALID_VALUE
);
1096 case AL_CONE_INNER_ANGLE
:
1097 case AL_CONE_OUTER_ANGLE
:
1099 case AL_MAX_DISTANCE
:
1100 case AL_ROLLOFF_FACTOR
:
1101 case AL_REFERENCE_DISTANCE
:
1104 case AL_CONE_OUTER_GAIN
:
1105 case AL_CONE_OUTER_GAINHF
:
1107 case AL_SAMPLE_OFFSET
:
1108 case AL_BYTE_OFFSET
:
1109 case AL_AIR_ABSORPTION_FACTOR
:
1110 case AL_ROOM_ROLLOFF_FACTOR
:
1115 SetSourcefv(Source
, Context
, param
, values
);
1119 alSetError(Context
, AL_INVALID_ENUM
);
1122 ALCcontext_DecRef(Context
);
1126 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1128 ALCcontext
*Context
;
1132 Context
= GetContextRef();
1133 if(!Context
) return;
1135 if((Source
=LookupSource(Context
, source
)) == NULL
)
1136 alSetError(Context
, AL_INVALID_NAME
);
1140 case AL_CONE_INNER_ANGLE
:
1141 case AL_CONE_OUTER_ANGLE
:
1143 case AL_MAX_DISTANCE
:
1144 case AL_ROLLOFF_FACTOR
:
1145 case AL_REFERENCE_DISTANCE
:
1148 case AL_CONE_OUTER_GAIN
:
1149 case AL_CONE_OUTER_GAINHF
:
1150 case AL_AIR_ABSORPTION_FACTOR
:
1151 case AL_ROOM_ROLLOFF_FACTOR
:
1152 case AL_DOPPLER_FACTOR
:
1154 case AL_SAMPLE_OFFSET
:
1155 case AL_BYTE_OFFSET
:
1157 SetSourcefv(Source
, Context
, param
, &fval
);
1161 alSetError(Context
, AL_INVALID_ENUM
);
1164 ALCcontext_DecRef(Context
);
1167 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1169 ALCcontext
*Context
;
1173 Context
= GetContextRef();
1174 if(!Context
) return;
1176 if((Source
=LookupSource(Context
, source
)) == NULL
)
1177 alSetError(Context
, AL_INVALID_NAME
);
1186 SetSourcefv(Source
, Context
, param
, fvals
);
1190 alSetError(Context
, AL_INVALID_ENUM
);
1193 ALCcontext_DecRef(Context
);
1196 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1198 ALCcontext
*Context
;
1202 Context
= GetContextRef();
1203 if(!Context
) return;
1205 if((Source
=LookupSource(Context
, source
)) == NULL
)
1206 alSetError(Context
, AL_INVALID_NAME
);
1208 alSetError(Context
, AL_INVALID_VALUE
);
1212 case AL_CONE_INNER_ANGLE
:
1213 case AL_CONE_OUTER_ANGLE
:
1215 case AL_MAX_DISTANCE
:
1216 case AL_ROLLOFF_FACTOR
:
1217 case AL_REFERENCE_DISTANCE
:
1220 case AL_CONE_OUTER_GAIN
:
1221 case AL_CONE_OUTER_GAINHF
:
1223 case AL_SAMPLE_OFFSET
:
1224 case AL_BYTE_OFFSET
:
1225 case AL_AIR_ABSORPTION_FACTOR
:
1226 case AL_ROOM_ROLLOFF_FACTOR
:
1227 fvals
[0] = values
[0];
1228 SetSourcefv(Source
, Context
, param
, fvals
);
1234 fvals
[0] = values
[0];
1235 fvals
[1] = values
[1];
1236 fvals
[2] = values
[2];
1237 SetSourcefv(Source
, Context
, param
, fvals
);
1241 alSetError(Context
, AL_INVALID_ENUM
);
1244 ALCcontext_DecRef(Context
);
1248 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1250 ALCcontext
*Context
;
1253 Context
= GetContextRef();
1254 if(!Context
) return;
1256 if((Source
=LookupSource(Context
, source
)) == NULL
)
1257 alSetError(Context
, AL_INVALID_NAME
);
1260 case AL_MAX_DISTANCE
:
1261 case AL_ROLLOFF_FACTOR
:
1262 case AL_CONE_INNER_ANGLE
:
1263 case AL_CONE_OUTER_ANGLE
:
1264 case AL_REFERENCE_DISTANCE
:
1265 case AL_SOURCE_RELATIVE
:
1268 case AL_SOURCE_STATE
:
1270 case AL_SAMPLE_OFFSET
:
1271 case AL_BYTE_OFFSET
:
1272 case AL_DIRECT_FILTER
:
1273 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1274 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1275 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1276 case AL_DIRECT_CHANNELS_SOFT
:
1277 case AL_DISTANCE_MODEL
:
1278 SetSourceiv(Source
, Context
, param
, &value
);
1282 alSetError(Context
, AL_INVALID_ENUM
);
1285 ALCcontext_DecRef(Context
);
1288 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1290 ALCcontext
*Context
;
1294 Context
= GetContextRef();
1295 if(!Context
) return;
1297 if((Source
=LookupSource(Context
, source
)) == NULL
)
1298 alSetError(Context
, AL_INVALID_NAME
);
1304 case AL_AUXILIARY_SEND_FILTER
:
1308 SetSourceiv(Source
, Context
, param
, ivals
);
1312 alSetError(Context
, AL_INVALID_ENUM
);
1315 ALCcontext_DecRef(Context
);
1318 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1320 ALCcontext
*Context
;
1323 Context
= GetContextRef();
1324 if(!Context
) return;
1326 if((Source
=LookupSource(Context
, source
)) == NULL
)
1327 alSetError(Context
, AL_INVALID_NAME
);
1329 alSetError(Context
, AL_INVALID_VALUE
);
1332 case AL_SOURCE_RELATIVE
:
1333 case AL_CONE_INNER_ANGLE
:
1334 case AL_CONE_OUTER_ANGLE
:
1337 case AL_SOURCE_STATE
:
1339 case AL_SAMPLE_OFFSET
:
1340 case AL_BYTE_OFFSET
:
1341 case AL_MAX_DISTANCE
:
1342 case AL_ROLLOFF_FACTOR
:
1343 case AL_REFERENCE_DISTANCE
:
1344 case AL_DIRECT_FILTER
:
1345 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1346 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1347 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1348 case AL_DISTANCE_MODEL
:
1349 case AL_DIRECT_CHANNELS_SOFT
:
1354 case AL_AUXILIARY_SEND_FILTER
:
1355 SetSourceiv(Source
, Context
, param
, values
);
1359 alSetError(Context
, AL_INVALID_ENUM
);
1362 ALCcontext_DecRef(Context
);
1366 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1368 ALCcontext
*Context
;
1371 Context
= GetContextRef();
1372 if(!Context
) return;
1374 if((Source
=LookupSource(Context
, source
)) == NULL
)
1375 alSetError(Context
, AL_INVALID_NAME
);
1378 case AL_MAX_DISTANCE
:
1379 case AL_ROLLOFF_FACTOR
:
1380 case AL_CONE_INNER_ANGLE
:
1381 case AL_CONE_OUTER_ANGLE
:
1382 case AL_REFERENCE_DISTANCE
:
1383 case AL_SOURCE_RELATIVE
:
1385 case AL_SOURCE_STATE
:
1387 case AL_SAMPLE_OFFSET
:
1388 case AL_BYTE_OFFSET
:
1389 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1390 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1391 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1392 case AL_DIRECT_CHANNELS_SOFT
:
1393 case AL_DISTANCE_MODEL
:
1395 case AL_DIRECT_FILTER
:
1396 SetSourcei64v(Source
, Context
, param
, &value
);
1400 alSetError(Context
, AL_INVALID_ENUM
);
1403 ALCcontext_DecRef(Context
);
1406 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1408 ALCcontext
*Context
;
1410 ALint64SOFT i64vals
[3];
1412 Context
= GetContextRef();
1413 if(!Context
) return;
1415 if((Source
=LookupSource(Context
, source
)) == NULL
)
1416 alSetError(Context
, AL_INVALID_NAME
);
1422 case AL_AUXILIARY_SEND_FILTER
:
1423 i64vals
[0] = value1
;
1424 i64vals
[1] = value2
;
1425 i64vals
[2] = value3
;
1426 SetSourcei64v(Source
, Context
, param
, i64vals
);
1430 alSetError(Context
, AL_INVALID_ENUM
);
1433 ALCcontext_DecRef(Context
);
1436 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1438 ALCcontext
*Context
;
1441 Context
= GetContextRef();
1442 if(!Context
) return;
1444 if((Source
=LookupSource(Context
, source
)) == NULL
)
1445 alSetError(Context
, AL_INVALID_NAME
);
1447 alSetError(Context
, AL_INVALID_VALUE
);
1450 case AL_SOURCE_RELATIVE
:
1451 case AL_CONE_INNER_ANGLE
:
1452 case AL_CONE_OUTER_ANGLE
:
1454 case AL_SOURCE_STATE
:
1456 case AL_SAMPLE_OFFSET
:
1457 case AL_BYTE_OFFSET
:
1458 case AL_MAX_DISTANCE
:
1459 case AL_ROLLOFF_FACTOR
:
1460 case AL_REFERENCE_DISTANCE
:
1461 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1462 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1463 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1464 case AL_DISTANCE_MODEL
:
1465 case AL_DIRECT_CHANNELS_SOFT
:
1467 case AL_DIRECT_FILTER
:
1472 case AL_AUXILIARY_SEND_FILTER
:
1473 SetSourcei64v(Source
, Context
, param
, values
);
1477 alSetError(Context
, AL_INVALID_ENUM
);
1480 ALCcontext_DecRef(Context
);
1484 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1486 ALCcontext
*Context
;
1490 Context
= GetContextRef();
1491 if(!Context
) return;
1493 if((Source
=LookupSource(Context
, source
)) == NULL
)
1494 alSetError(Context
, AL_INVALID_NAME
);
1496 alSetError(Context
, AL_INVALID_VALUE
);
1503 case AL_MAX_DISTANCE
:
1504 case AL_ROLLOFF_FACTOR
:
1505 case AL_CONE_OUTER_GAIN
:
1506 case AL_CONE_OUTER_GAINHF
:
1508 case AL_SAMPLE_OFFSET
:
1509 case AL_BYTE_OFFSET
:
1510 case AL_CONE_INNER_ANGLE
:
1511 case AL_CONE_OUTER_ANGLE
:
1512 case AL_REFERENCE_DISTANCE
:
1513 case AL_AIR_ABSORPTION_FACTOR
:
1514 case AL_ROOM_ROLLOFF_FACTOR
:
1515 case AL_DOPPLER_FACTOR
:
1516 if(GetSourcedv(Source
, Context
, param
, &dval
) == AL_NO_ERROR
)
1517 *value
= (ALfloat
)dval
;
1521 alSetError(Context
, AL_INVALID_ENUM
);
1524 ALCcontext_DecRef(Context
);
1528 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1530 ALCcontext
*Context
;
1534 Context
= GetContextRef();
1535 if(!Context
) return;
1537 if((Source
=LookupSource(Context
, source
)) == NULL
)
1538 alSetError(Context
, AL_INVALID_NAME
);
1539 else if(!(value1
&& value2
&& value3
))
1540 alSetError(Context
, AL_INVALID_VALUE
);
1546 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1548 *value1
= (ALfloat
)dvals
[0];
1549 *value2
= (ALfloat
)dvals
[1];
1550 *value3
= (ALfloat
)dvals
[2];
1555 alSetError(Context
, AL_INVALID_ENUM
);
1558 ALCcontext_DecRef(Context
);
1562 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1564 ALCcontext
*Context
;
1574 case AL_MAX_DISTANCE
:
1575 case AL_ROLLOFF_FACTOR
:
1576 case AL_DOPPLER_FACTOR
:
1577 case AL_CONE_OUTER_GAIN
:
1579 case AL_SAMPLE_OFFSET
:
1580 case AL_BYTE_OFFSET
:
1581 case AL_CONE_INNER_ANGLE
:
1582 case AL_CONE_OUTER_ANGLE
:
1583 case AL_REFERENCE_DISTANCE
:
1584 case AL_CONE_OUTER_GAINHF
:
1585 case AL_AIR_ABSORPTION_FACTOR
:
1586 case AL_ROOM_ROLLOFF_FACTOR
:
1587 alGetSourcef(source
, param
, values
);
1593 alGetSource3f(source
, param
, values
+0, values
+1, values
+2);
1597 Context
= GetContextRef();
1598 if(!Context
) return;
1600 if((Source
=LookupSource(Context
, source
)) == NULL
)
1601 alSetError(Context
, AL_INVALID_NAME
);
1603 alSetError(Context
, AL_INVALID_VALUE
);
1606 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1607 case AL_BYTE_RW_OFFSETS_SOFT
:
1608 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1610 values
[0] = (ALfloat
)dvals
[0];
1611 values
[1] = (ALfloat
)dvals
[1];
1616 alSetError(Context
, AL_INVALID_ENUM
);
1619 ALCcontext_DecRef(Context
);
1623 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1625 ALCcontext
*Context
;
1628 Context
= GetContextRef();
1629 if(!Context
) return;
1631 if((Source
=LookupSource(Context
, source
)) == NULL
)
1632 alSetError(Context
, AL_INVALID_NAME
);
1634 alSetError(Context
, AL_INVALID_VALUE
);
1641 case AL_MAX_DISTANCE
:
1642 case AL_ROLLOFF_FACTOR
:
1643 case AL_CONE_OUTER_GAIN
:
1644 case AL_CONE_OUTER_GAINHF
:
1646 case AL_SAMPLE_OFFSET
:
1647 case AL_BYTE_OFFSET
:
1648 case AL_CONE_INNER_ANGLE
:
1649 case AL_CONE_OUTER_ANGLE
:
1650 case AL_REFERENCE_DISTANCE
:
1651 case AL_AIR_ABSORPTION_FACTOR
:
1652 case AL_ROOM_ROLLOFF_FACTOR
:
1653 case AL_DOPPLER_FACTOR
:
1654 GetSourcedv(Source
, Context
, param
, value
);
1658 alSetError(Context
, AL_INVALID_ENUM
);
1661 ALCcontext_DecRef(Context
);
1664 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1666 ALCcontext
*Context
;
1670 Context
= GetContextRef();
1671 if(!Context
) return;
1673 if((Source
=LookupSource(Context
, source
)) == NULL
)
1674 alSetError(Context
, AL_INVALID_NAME
);
1675 else if(!(value1
&& value2
&& value3
))
1676 alSetError(Context
, AL_INVALID_VALUE
);
1682 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1691 alSetError(Context
, AL_INVALID_ENUM
);
1694 ALCcontext_DecRef(Context
);
1697 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1699 ALCcontext
*Context
;
1702 Context
= GetContextRef();
1703 if(!Context
) return;
1705 if((Source
=LookupSource(Context
, source
)) == NULL
)
1706 alSetError(Context
, AL_INVALID_NAME
);
1708 alSetError(Context
, AL_INVALID_VALUE
);
1715 case AL_MAX_DISTANCE
:
1716 case AL_ROLLOFF_FACTOR
:
1717 case AL_DOPPLER_FACTOR
:
1718 case AL_CONE_OUTER_GAIN
:
1720 case AL_SAMPLE_OFFSET
:
1721 case AL_BYTE_OFFSET
:
1722 case AL_CONE_INNER_ANGLE
:
1723 case AL_CONE_OUTER_ANGLE
:
1724 case AL_REFERENCE_DISTANCE
:
1725 case AL_CONE_OUTER_GAINHF
:
1726 case AL_AIR_ABSORPTION_FACTOR
:
1727 case AL_ROOM_ROLLOFF_FACTOR
:
1729 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1730 case AL_BYTE_RW_OFFSETS_SOFT
:
1731 case AL_SEC_OFFSET_LATENCY_SOFT
:
1736 GetSourcedv(Source
, Context
, param
, values
);
1740 alSetError(Context
, AL_INVALID_ENUM
);
1743 ALCcontext_DecRef(Context
);
1747 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1749 ALCcontext
*Context
;
1752 Context
= GetContextRef();
1753 if(!Context
) return;
1755 if((Source
=LookupSource(Context
, source
)) == NULL
)
1756 alSetError(Context
, AL_INVALID_NAME
);
1758 alSetError(Context
, AL_INVALID_VALUE
);
1761 case AL_MAX_DISTANCE
:
1762 case AL_ROLLOFF_FACTOR
:
1763 case AL_REFERENCE_DISTANCE
:
1764 case AL_SOURCE_RELATIVE
:
1765 case AL_CONE_INNER_ANGLE
:
1766 case AL_CONE_OUTER_ANGLE
:
1769 case AL_SOURCE_STATE
:
1770 case AL_BUFFERS_QUEUED
:
1771 case AL_BUFFERS_PROCESSED
:
1772 case AL_SOURCE_TYPE
:
1774 case AL_SAMPLE_OFFSET
:
1775 case AL_BYTE_OFFSET
:
1776 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1777 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1778 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1779 case AL_DOPPLER_FACTOR
:
1780 case AL_DIRECT_CHANNELS_SOFT
:
1781 case AL_DISTANCE_MODEL
:
1782 GetSourceiv(Source
, Context
, param
, value
);
1786 alSetError(Context
, AL_INVALID_ENUM
);
1789 ALCcontext_DecRef(Context
);
1793 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1795 ALCcontext
*Context
;
1799 Context
= GetContextRef();
1800 if(!Context
) return;
1802 if((Source
=LookupSource(Context
, source
)) == NULL
)
1803 alSetError(Context
, AL_INVALID_NAME
);
1804 else if(!(value1
&& value2
&& value3
))
1805 alSetError(Context
, AL_INVALID_VALUE
);
1811 if(GetSourceiv(Source
, Context
, param
, ivals
) == AL_NO_ERROR
)
1820 alSetError(Context
, AL_INVALID_ENUM
);
1823 ALCcontext_DecRef(Context
);
1827 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1829 ALCcontext
*Context
;
1832 Context
= GetContextRef();
1833 if(!Context
) return;
1835 if((Source
=LookupSource(Context
, source
)) == NULL
)
1836 alSetError(Context
, AL_INVALID_NAME
);
1838 alSetError(Context
, AL_INVALID_VALUE
);
1841 case AL_SOURCE_RELATIVE
:
1842 case AL_CONE_INNER_ANGLE
:
1843 case AL_CONE_OUTER_ANGLE
:
1846 case AL_SOURCE_STATE
:
1847 case AL_BUFFERS_QUEUED
:
1848 case AL_BUFFERS_PROCESSED
:
1850 case AL_SAMPLE_OFFSET
:
1851 case AL_BYTE_OFFSET
:
1852 case AL_MAX_DISTANCE
:
1853 case AL_ROLLOFF_FACTOR
:
1854 case AL_DOPPLER_FACTOR
:
1855 case AL_REFERENCE_DISTANCE
:
1856 case AL_SOURCE_TYPE
:
1857 case AL_DIRECT_FILTER
:
1858 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1859 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1860 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1861 case AL_DISTANCE_MODEL
:
1862 case AL_DIRECT_CHANNELS_SOFT
:
1864 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1865 case AL_BYTE_RW_OFFSETS_SOFT
:
1870 GetSourceiv(Source
, Context
, param
, values
);
1874 alSetError(Context
, AL_INVALID_ENUM
);
1877 ALCcontext_DecRef(Context
);
1881 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
1883 ALCcontext
*Context
;
1886 Context
= GetContextRef();
1887 if(!Context
) return;
1889 if((Source
=LookupSource(Context
, source
)) == NULL
)
1890 alSetError(Context
, AL_INVALID_NAME
);
1892 alSetError(Context
, AL_INVALID_VALUE
);
1895 case AL_MAX_DISTANCE
:
1896 case AL_ROLLOFF_FACTOR
:
1897 case AL_REFERENCE_DISTANCE
:
1898 case AL_SOURCE_RELATIVE
:
1899 case AL_CONE_INNER_ANGLE
:
1900 case AL_CONE_OUTER_ANGLE
:
1903 case AL_SOURCE_STATE
:
1904 case AL_BUFFERS_QUEUED
:
1905 case AL_BUFFERS_PROCESSED
:
1906 case AL_SOURCE_TYPE
:
1908 case AL_SAMPLE_OFFSET
:
1909 case AL_BYTE_OFFSET
:
1910 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1911 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1912 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1913 case AL_DOPPLER_FACTOR
:
1914 case AL_DIRECT_CHANNELS_SOFT
:
1915 case AL_DISTANCE_MODEL
:
1916 GetSourcei64v(Source
, Context
, param
, value
);
1920 alSetError(Context
, AL_INVALID_ENUM
);
1923 ALCcontext_DecRef(Context
);
1926 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
1928 ALCcontext
*Context
;
1932 Context
= GetContextRef();
1933 if(!Context
) return;
1935 if((Source
=LookupSource(Context
, source
)) == NULL
)
1936 alSetError(Context
, AL_INVALID_NAME
);
1937 else if(!(value1
&& value2
&& value3
))
1938 alSetError(Context
, AL_INVALID_VALUE
);
1944 if(GetSourcei64v(Source
, Context
, param
, i64vals
) == AL_NO_ERROR
)
1946 *value1
= i64vals
[0];
1947 *value2
= i64vals
[1];
1948 *value3
= i64vals
[2];
1953 alSetError(Context
, AL_INVALID_ENUM
);
1956 ALCcontext_DecRef(Context
);
1959 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
1961 ALCcontext
*Context
;
1964 Context
= GetContextRef();
1965 if(!Context
) return;
1967 if((Source
=LookupSource(Context
, source
)) == NULL
)
1968 alSetError(Context
, AL_INVALID_NAME
);
1970 alSetError(Context
, AL_INVALID_VALUE
);
1973 case AL_MAX_DISTANCE
:
1974 case AL_ROLLOFF_FACTOR
:
1975 case AL_REFERENCE_DISTANCE
:
1976 case AL_SOURCE_RELATIVE
:
1977 case AL_CONE_INNER_ANGLE
:
1978 case AL_CONE_OUTER_ANGLE
:
1981 case AL_SOURCE_STATE
:
1982 case AL_BUFFERS_QUEUED
:
1983 case AL_BUFFERS_PROCESSED
:
1984 case AL_SOURCE_TYPE
:
1986 case AL_SAMPLE_OFFSET
:
1987 case AL_BYTE_OFFSET
:
1988 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1989 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1990 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1991 case AL_DOPPLER_FACTOR
:
1992 case AL_DIRECT_CHANNELS_SOFT
:
1993 case AL_DISTANCE_MODEL
:
1995 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1996 case AL_BYTE_RW_OFFSETS_SOFT
:
1997 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
2002 GetSourcei64v(Source
, Context
, param
, values
);
2006 alSetError(Context
, AL_INVALID_ENUM
);
2009 ALCcontext_DecRef(Context
);
2013 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
2015 alSourcePlayv(1, &source
);
2017 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2019 ALCcontext
*Context
;
2023 Context
= GetContextRef();
2024 if(!Context
) return;
2028 CHECK_VALUE(Context
, n
>= 0);
2029 for(i
= 0;i
< n
;i
++)
2031 if(!LookupSource(Context
, sources
[i
]))
2032 al_throwerr(Context
, AL_INVALID_NAME
);
2035 LockContext(Context
);
2036 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
2041 newcount
= Context
->MaxActiveSources
<< 1;
2043 temp
= realloc(Context
->ActiveSources
,
2044 sizeof(*Context
->ActiveSources
) * newcount
);
2047 UnlockContext(Context
);
2048 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
2051 Context
->ActiveSources
= temp
;
2052 Context
->MaxActiveSources
= newcount
;
2055 for(i
= 0;i
< n
;i
++)
2057 Source
= LookupSource(Context
, sources
[i
]);
2058 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
2059 else SetSourceState(Source
, Context
, AL_PLAYING
);
2061 UnlockContext(Context
);
2065 ALCcontext_DecRef(Context
);
2068 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2070 alSourcePausev(1, &source
);
2072 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2074 ALCcontext
*Context
;
2078 Context
= GetContextRef();
2079 if(!Context
) return;
2083 CHECK_VALUE(Context
, n
>= 0);
2084 for(i
= 0;i
< n
;i
++)
2086 if(!LookupSource(Context
, sources
[i
]))
2087 al_throwerr(Context
, AL_INVALID_NAME
);
2090 LockContext(Context
);
2091 for(i
= 0;i
< n
;i
++)
2093 Source
= LookupSource(Context
, sources
[i
]);
2094 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
2095 else SetSourceState(Source
, Context
, AL_PAUSED
);
2097 UnlockContext(Context
);
2101 ALCcontext_DecRef(Context
);
2104 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2106 alSourceStopv(1, &source
);
2108 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2110 ALCcontext
*Context
;
2114 Context
= GetContextRef();
2115 if(!Context
) return;
2119 CHECK_VALUE(Context
, n
>= 0);
2120 for(i
= 0;i
< n
;i
++)
2122 if(!LookupSource(Context
, sources
[i
]))
2123 al_throwerr(Context
, AL_INVALID_NAME
);
2126 LockContext(Context
);
2127 for(i
= 0;i
< n
;i
++)
2129 Source
= LookupSource(Context
, sources
[i
]);
2130 Source
->new_state
= AL_NONE
;
2131 SetSourceState(Source
, Context
, AL_STOPPED
);
2133 UnlockContext(Context
);
2137 ALCcontext_DecRef(Context
);
2140 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2142 alSourceRewindv(1, &source
);
2144 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2146 ALCcontext
*Context
;
2150 Context
= GetContextRef();
2151 if(!Context
) return;
2155 CHECK_VALUE(Context
, n
>= 0);
2156 for(i
= 0;i
< n
;i
++)
2158 if(!LookupSource(Context
, sources
[i
]))
2159 al_throwerr(Context
, AL_INVALID_NAME
);
2162 LockContext(Context
);
2163 for(i
= 0;i
< n
;i
++)
2165 Source
= LookupSource(Context
, sources
[i
]);
2166 Source
->new_state
= AL_NONE
;
2167 SetSourceState(Source
, Context
, AL_INITIAL
);
2169 UnlockContext(Context
);
2173 ALCcontext_DecRef(Context
);
2177 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei nb
, const ALuint
*buffers
)
2179 ALCcontext
*Context
;
2182 ALbufferlistitem
*BufferListStart
= NULL
;
2183 ALbufferlistitem
*BufferList
;
2184 ALbuffer
*BufferFmt
;
2189 Context
= GetContextRef();
2190 if(!Context
) return;
2194 ALCdevice
*device
= Context
->Device
;
2196 CHECK_VALUE(Context
, nb
>= 0);
2198 if((Source
=LookupSource(Context
, source
)) == NULL
)
2199 al_throwerr(Context
, AL_INVALID_NAME
);
2201 LockContext(Context
);
2202 if(Source
->SourceType
== AL_STATIC
)
2204 UnlockContext(Context
);
2205 /* Can't queue on a Static Source */
2206 al_throwerr(Context
, AL_INVALID_OPERATION
);
2211 /* Check for a valid Buffer, for its frequency and format */
2212 BufferList
= Source
->queue
;
2215 if(BufferList
->buffer
)
2217 BufferFmt
= BufferList
->buffer
;
2220 BufferList
= BufferList
->next
;
2223 for(i
= 0;i
< nb
;i
++)
2225 ALbuffer
*buffer
= NULL
;
2226 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2228 UnlockContext(Context
);
2229 al_throwerr(Context
, AL_INVALID_NAME
);
2232 if(!BufferListStart
)
2234 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2235 BufferListStart
->buffer
= buffer
;
2236 BufferListStart
->next
= NULL
;
2237 BufferListStart
->prev
= NULL
;
2238 BufferList
= BufferListStart
;
2242 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2243 BufferList
->next
->buffer
= buffer
;
2244 BufferList
->next
->next
= NULL
;
2245 BufferList
->next
->prev
= BufferList
;
2246 BufferList
= BufferList
->next
;
2248 if(!buffer
) continue;
2249 IncrementRef(&buffer
->ref
);
2251 ReadLock(&buffer
->lock
);
2252 if(BufferFmt
== NULL
)
2256 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2257 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2258 if(buffer
->FmtChannels
== FmtMono
)
2259 Source
->Update
= CalcSourceParams
;
2261 Source
->Update
= CalcNonAttnSourceParams
;
2263 Source
->NeedsUpdate
= AL_TRUE
;
2265 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2266 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2267 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2269 ReadUnlock(&buffer
->lock
);
2270 UnlockContext(Context
);
2271 al_throwerr(Context
, AL_INVALID_OPERATION
);
2273 ReadUnlock(&buffer
->lock
);
2276 /* Source is now streaming */
2277 Source
->SourceType
= AL_STREAMING
;
2279 if(Source
->queue
== NULL
)
2280 Source
->queue
= BufferListStart
;
2283 /* Append to the end of the queue */
2284 BufferList
= Source
->queue
;
2285 while(BufferList
->next
!= NULL
)
2286 BufferList
= BufferList
->next
;
2288 BufferListStart
->prev
= BufferList
;
2289 BufferList
->next
= BufferListStart
;
2292 Source
->BuffersInQueue
+= nb
;
2294 UnlockContext(Context
);
2298 while(BufferListStart
)
2300 BufferList
= BufferListStart
;
2301 BufferListStart
= BufferList
->next
;
2303 if(BufferList
->buffer
)
2304 DecrementRef(&BufferList
->buffer
->ref
);
2310 ALCcontext_DecRef(Context
);
2313 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint source
, ALsizei nb
, ALuint
*buffers
)
2315 ALCcontext
*Context
;
2318 ALbufferlistitem
*BufferList
;
2323 Context
= GetContextRef();
2324 if(!Context
) return;
2328 CHECK_VALUE(Context
, nb
>= 0);
2330 if((Source
=LookupSource(Context
, source
)) == NULL
)
2331 al_throwerr(Context
, AL_INVALID_NAME
);
2333 LockContext(Context
);
2334 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
||
2335 (ALuint
)nb
> Source
->BuffersPlayed
)
2337 UnlockContext(Context
);
2338 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2339 al_throwerr(Context
, AL_INVALID_VALUE
);
2342 for(i
= 0;i
< nb
;i
++)
2344 BufferList
= Source
->queue
;
2345 Source
->queue
= BufferList
->next
;
2346 Source
->BuffersInQueue
--;
2347 Source
->BuffersPlayed
--;
2349 if(BufferList
->buffer
)
2351 buffers
[i
] = BufferList
->buffer
->id
;
2352 DecrementRef(&BufferList
->buffer
->ref
);
2360 Source
->queue
->prev
= NULL
;
2361 UnlockContext(Context
);
2365 ALCcontext_DecRef(Context
);
2369 static ALvoid
InitSourceParams(ALsource
*Source
)
2373 Source
->InnerAngle
= 360.0f
;
2374 Source
->OuterAngle
= 360.0f
;
2375 Source
->Pitch
= 1.0f
;
2376 Source
->Position
[0] = 0.0f
;
2377 Source
->Position
[1] = 0.0f
;
2378 Source
->Position
[2] = 0.0f
;
2379 Source
->Orientation
[0] = 0.0f
;
2380 Source
->Orientation
[1] = 0.0f
;
2381 Source
->Orientation
[2] = 0.0f
;
2382 Source
->Velocity
[0] = 0.0f
;
2383 Source
->Velocity
[1] = 0.0f
;
2384 Source
->Velocity
[2] = 0.0f
;
2385 Source
->RefDistance
= 1.0f
;
2386 Source
->MaxDistance
= FLT_MAX
;
2387 Source
->RollOffFactor
= 1.0f
;
2388 Source
->Looping
= AL_FALSE
;
2389 Source
->Gain
= 1.0f
;
2390 Source
->MinGain
= 0.0f
;
2391 Source
->MaxGain
= 1.0f
;
2392 Source
->OuterGain
= 0.0f
;
2393 Source
->OuterGainHF
= 1.0f
;
2395 Source
->DryGainHFAuto
= AL_TRUE
;
2396 Source
->WetGainAuto
= AL_TRUE
;
2397 Source
->WetGainHFAuto
= AL_TRUE
;
2398 Source
->AirAbsorptionFactor
= 0.0f
;
2399 Source
->RoomRolloffFactor
= 0.0f
;
2400 Source
->DopplerFactor
= 1.0f
;
2401 Source
->DirectChannels
= AL_FALSE
;
2403 Source
->DistanceModel
= DefaultDistanceModel
;
2405 Source
->Resampler
= DefaultResampler
;
2407 Source
->state
= AL_INITIAL
;
2408 Source
->new_state
= AL_NONE
;
2409 Source
->SourceType
= AL_UNDETERMINED
;
2410 Source
->Offset
= -1.0;
2412 Source
->DirectGain
= 1.0f
;
2413 Source
->DirectGainHF
= 1.0f
;
2414 for(i
= 0;i
< MAX_SENDS
;i
++)
2416 Source
->Send
[i
].Gain
= 1.0f
;
2417 Source
->Send
[i
].GainHF
= 1.0f
;
2420 Source
->NeedsUpdate
= AL_TRUE
;
2422 Source
->Hrtf
.Moving
= AL_FALSE
;
2423 Source
->Hrtf
.Counter
= 0;
2429 * Sets the source's new play state given its current state.
2431 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2433 if(state
== AL_PLAYING
)
2435 ALbufferlistitem
*BufferList
;
2438 /* Check that there is a queue containing at least one valid, non zero
2440 BufferList
= Source
->queue
;
2443 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
2445 BufferList
= BufferList
->next
;
2448 if(Source
->state
!= AL_PLAYING
)
2450 for(j
= 0;j
< MaxChannels
;j
++)
2452 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
2453 Source
->Hrtf
.History
[j
][k
] = 0.0f
;
2454 for(k
= 0;k
< HRIR_LENGTH
;k
++)
2456 Source
->Hrtf
.Values
[j
][k
][0] = 0.0f
;
2457 Source
->Hrtf
.Values
[j
][k
][1] = 0.0f
;
2462 if(Source
->state
!= AL_PAUSED
)
2464 Source
->state
= AL_PLAYING
;
2465 Source
->position
= 0;
2466 Source
->position_fraction
= 0;
2467 Source
->BuffersPlayed
= 0;
2470 Source
->state
= AL_PLAYING
;
2472 // Check if an Offset has been set
2473 if(Source
->Offset
>= 0.0)
2474 ApplyOffset(Source
);
2476 /* If there's nothing to play, or device is disconnected, go right to
2478 if(!BufferList
|| !Context
->Device
->Connected
)
2480 SetSourceState(Source
, Context
, AL_STOPPED
);
2484 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
2486 if(Context
->ActiveSources
[j
] == Source
)
2489 if(j
== Context
->ActiveSourceCount
)
2490 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
2492 else if(state
== AL_PAUSED
)
2494 if(Source
->state
== AL_PLAYING
)
2496 Source
->state
= AL_PAUSED
;
2497 Source
->Hrtf
.Moving
= AL_FALSE
;
2498 Source
->Hrtf
.Counter
= 0;
2501 else if(state
== AL_STOPPED
)
2503 if(Source
->state
!= AL_INITIAL
)
2505 Source
->state
= AL_STOPPED
;
2506 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
2507 Source
->Hrtf
.Moving
= AL_FALSE
;
2508 Source
->Hrtf
.Counter
= 0;
2510 Source
->Offset
= -1.0;
2512 else if(state
== AL_INITIAL
)
2514 if(Source
->state
!= AL_INITIAL
)
2516 Source
->state
= AL_INITIAL
;
2517 Source
->position
= 0;
2518 Source
->position_fraction
= 0;
2519 Source
->BuffersPlayed
= 0;
2520 Source
->Hrtf
.Moving
= AL_FALSE
;
2521 Source
->Hrtf
.Counter
= 0;
2523 Source
->Offset
= -1.0;
2529 * Gets the current read offset for the given Source, in 32.32 fixed-point
2530 * samples. The offset is relative to the start of the queue (not the start of
2531 * the current buffer).
2533 static ALint64
GetSourceOffset(const ALsource
*Source
)
2535 const ALbufferlistitem
*BufferList
;
2539 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2542 /* NOTE: This is the offset into the *current* buffer, so add the length of
2543 * any played buffers */
2544 readPos
= (ALuint64
)Source
->position
<< 32;
2545 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2546 BufferList
= Source
->queue
;
2547 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2549 if(BufferList
->buffer
)
2550 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2551 BufferList
= BufferList
->next
;
2554 return (ALint64
)minu64(readPos
, MAKEU64(0x7fffffff,0xffffffff));
2557 /* GetSourceSecOffset
2559 * Gets the current read offset for the given Source, in seconds. The offset is
2560 * relative to the start of the queue (not the start of the current buffer).
2562 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2564 const ALbufferlistitem
*BufferList
;
2565 const ALbuffer
*Buffer
= NULL
;
2569 BufferList
= Source
->queue
;
2572 if(BufferList
->buffer
)
2574 Buffer
= BufferList
->buffer
;
2577 BufferList
= BufferList
->next
;
2580 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2583 /* NOTE: This is the offset into the *current* buffer, so add the length of
2584 * any played buffers */
2585 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2586 readPos
|= (ALuint64
)Source
->position_fraction
;
2587 BufferList
= Source
->queue
;
2588 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2590 if(BufferList
->buffer
)
2591 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< FRACTIONBITS
;
2592 BufferList
= BufferList
->next
;
2595 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2600 * Gets the current read and write offsets for the given Source, in the
2601 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2602 * the start of the queue (not the start of the current buffer).
2604 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2606 const ALbufferlistitem
*BufferList
;
2607 const ALbuffer
*Buffer
= NULL
;
2608 ALuint readPos
, writePos
;
2609 ALuint totalBufferLen
;
2612 // Find the first valid Buffer in the Queue
2613 BufferList
= Source
->queue
;
2616 if(BufferList
->buffer
)
2618 Buffer
= BufferList
->buffer
;
2621 BufferList
= BufferList
->next
;
2624 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2631 if(updateLen
> 0.0 && updateLen
< 0.015)
2634 /* NOTE: This is the offset into the *current* buffer, so add the length of
2635 * any played buffers */
2636 readPos
= Source
->position
;
2638 BufferList
= Source
->queue
;
2639 for(i
= 0;BufferList
;i
++)
2641 if(BufferList
->buffer
)
2643 if(i
< Source
->BuffersPlayed
)
2644 readPos
+= BufferList
->buffer
->SampleLen
;
2645 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
2647 BufferList
= BufferList
->next
;
2649 if(Source
->state
== AL_PLAYING
)
2650 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2656 readPos
%= totalBufferLen
;
2657 writePos
%= totalBufferLen
;
2661 /* Wrap positions back to 0 */
2662 if(readPos
>= totalBufferLen
)
2664 if(writePos
>= totalBufferLen
)
2671 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2672 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2675 case AL_SAMPLE_OFFSET
:
2676 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2677 offset
[0] = (ALdouble
)readPos
;
2678 offset
[1] = (ALdouble
)writePos
;
2681 case AL_BYTE_OFFSET
:
2682 case AL_BYTE_RW_OFFSETS_SOFT
:
2683 if(Buffer
->OriginalType
== UserFmtIMA4
)
2685 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
2686 ALuint FrameBlockSize
= 65;
2688 /* Round down to nearest ADPCM block */
2689 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2690 if(Source
->state
!= AL_PLAYING
)
2691 offset
[1] = offset
[0];
2694 /* Round up to nearest ADPCM block */
2695 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2696 FrameBlockSize
* BlockSize
);
2701 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2702 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2703 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2712 * Apply the stored playback offset to the Source. This function will update
2713 * the number of buffers "played" given the stored offset.
2715 ALboolean
ApplyOffset(ALsource
*Source
)
2717 const ALbufferlistitem
*BufferList
;
2718 const ALbuffer
*Buffer
;
2719 ALint bufferLen
, totalBufferLen
;
2720 ALint buffersPlayed
;
2723 /* Get sample frame offset */
2724 offset
= GetSampleOffset(Source
);
2731 BufferList
= Source
->queue
;
2734 Buffer
= BufferList
->buffer
;
2735 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2737 if(bufferLen
<= offset
-totalBufferLen
)
2739 /* Offset is past this buffer so increment to the next buffer */
2742 else if(totalBufferLen
<= offset
)
2744 /* Offset is in this buffer */
2745 Source
->BuffersPlayed
= buffersPlayed
;
2747 Source
->position
= offset
- totalBufferLen
;
2748 Source
->position_fraction
= 0;
2752 totalBufferLen
+= bufferLen
;
2754 BufferList
= BufferList
->next
;
2757 /* Offset is out of range of the queue */
2764 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2765 * Second offset supplied by the application). This takes into account the fact
2766 * that the buffer format may have been modifed since.
2768 static ALint
GetSampleOffset(ALsource
*Source
)
2770 const ALbuffer
*Buffer
= NULL
;
2771 const ALbufferlistitem
*BufferList
;
2774 /* Find the first valid Buffer in the Queue */
2775 BufferList
= Source
->queue
;
2778 if(BufferList
->buffer
)
2780 Buffer
= BufferList
->buffer
;
2783 BufferList
= BufferList
->next
;
2788 Source
->Offset
= -1.0;
2792 switch(Source
->OffsetType
)
2794 case AL_BYTE_OFFSET
:
2795 /* Determine the ByteOffset (and ensure it is block aligned) */
2796 Offset
= (ALint
)Source
->Offset
;
2797 if(Buffer
->OriginalType
== UserFmtIMA4
)
2799 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2803 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2806 case AL_SAMPLE_OFFSET
:
2807 Offset
= (ALint
)Source
->Offset
;
2811 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2814 Source
->Offset
= -1.0;
2822 * Destroys all sources in the source map.
2824 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2828 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2830 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2831 Context
->SourceMap
.array
[pos
].value
= NULL
;
2833 while(temp
->queue
!= NULL
)
2835 ALbufferlistitem
*BufferList
= temp
->queue
;
2836 temp
->queue
= BufferList
->next
;
2838 if(BufferList
->buffer
!= NULL
)
2839 DecrementRef(&BufferList
->buffer
->ref
);
2843 for(j
= 0;j
< MAX_SENDS
;++j
)
2845 if(temp
->Send
[j
].Slot
)
2846 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2847 temp
->Send
[j
].Slot
= NULL
;
2850 FreeThunkEntry(temp
->id
);
2851 memset(temp
, 0, sizeof(*temp
));