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
)
560 case AL_MAX_DISTANCE
:
561 *values
= Source
->MaxDistance
;
564 case AL_ROLLOFF_FACTOR
:
565 *values
= Source
->RollOffFactor
;
568 case AL_REFERENCE_DISTANCE
:
569 *values
= Source
->RefDistance
;
572 case AL_CONE_INNER_ANGLE
:
573 *values
= Source
->InnerAngle
;
576 case AL_CONE_OUTER_ANGLE
:
577 *values
= Source
->OuterAngle
;
581 case AL_SAMPLE_OFFSET
:
583 LockContext(Context
);
584 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
585 Context
->Device
->Frequency
;
586 GetSourceOffsets(Source
, name
, offsets
, updateLen
);
587 UnlockContext(Context
);
588 *values
= offsets
[0];
591 case AL_CONE_OUTER_GAINHF
:
592 *values
= Source
->OuterGainHF
;
595 case AL_AIR_ABSORPTION_FACTOR
:
596 *values
= Source
->AirAbsorptionFactor
;
599 case AL_ROOM_ROLLOFF_FACTOR
:
600 *values
= Source
->RoomRolloffFactor
;
603 case AL_DOPPLER_FACTOR
:
604 *values
= Source
->DopplerFactor
;
607 case AL_SAMPLE_RW_OFFSETS_SOFT
:
608 case AL_BYTE_RW_OFFSETS_SOFT
:
609 LockContext(Context
);
610 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
611 Context
->Device
->Frequency
;
612 GetSourceOffsets(Source
, name
, values
, updateLen
);
613 UnlockContext(Context
);
616 case AL_SEC_OFFSET_LATENCY_SOFT
:
617 LockContext(Context
);
618 values
[0] = GetSourceSecOffset(Source
);
619 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
621 UnlockContext(Context
);
625 LockContext(Context
);
626 values
[0] = Source
->Position
[0];
627 values
[1] = Source
->Position
[1];
628 values
[2] = Source
->Position
[2];
629 UnlockContext(Context
);
633 LockContext(Context
);
634 values
[0] = Source
->Velocity
[0];
635 values
[1] = Source
->Velocity
[1];
636 values
[2] = Source
->Velocity
[2];
637 UnlockContext(Context
);
641 LockContext(Context
);
642 values
[0] = Source
->Orientation
[0];
643 values
[1] = Source
->Orientation
[1];
644 values
[2] = Source
->Orientation
[2];
645 UnlockContext(Context
);
648 case AL_SOURCE_RELATIVE
:
651 case AL_SOURCE_STATE
:
652 case AL_BUFFERS_QUEUED
:
653 case AL_BUFFERS_PROCESSED
:
655 case AL_DIRECT_FILTER_GAINHF_AUTO
:
656 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
657 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
658 case AL_DIRECT_CHANNELS_SOFT
:
659 case AL_DISTANCE_MODEL
:
660 if((err
=GetSourceiv(Source
, Context
, name
, ivals
)) != AL_NO_ERROR
)
662 *values
= (ALdouble
)ivals
[0];
666 RETERR(AL_INVALID_ENUM
);
672 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint
*values
)
674 ALbufferlistitem
*BufferList
;
680 case AL_SOURCE_RELATIVE
:
681 *values
= Source
->HeadRelative
;
685 *values
= Source
->Looping
;
689 LockContext(Context
);
690 BufferList
= Source
->queue
;
691 if(Source
->SourceType
!= AL_STATIC
)
693 ALuint i
= Source
->BuffersPlayed
;
696 BufferList
= BufferList
->next
;
700 *values
= ((BufferList
&& BufferList
->buffer
) ?
701 BufferList
->buffer
->id
: 0);
702 UnlockContext(Context
);
705 case AL_SOURCE_STATE
:
706 *values
= Source
->state
;
709 case AL_BUFFERS_QUEUED
:
710 *values
= Source
->BuffersInQueue
;
713 case AL_BUFFERS_PROCESSED
:
714 LockContext(Context
);
715 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
717 /* Buffers on a looping source are in a perpetual state of
718 * PENDING, so don't report any as PROCESSED */
722 *values
= Source
->BuffersPlayed
;
723 UnlockContext(Context
);
727 *values
= Source
->SourceType
;
730 case AL_DIRECT_FILTER_GAINHF_AUTO
:
731 *values
= Source
->DryGainHFAuto
;
734 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
735 *values
= Source
->WetGainAuto
;
738 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
739 *values
= Source
->WetGainHFAuto
;
742 case AL_DIRECT_CHANNELS_SOFT
:
743 *values
= Source
->DirectChannels
;
746 case AL_DISTANCE_MODEL
:
747 *values
= Source
->DistanceModel
;
750 case AL_MAX_DISTANCE
:
751 case AL_ROLLOFF_FACTOR
:
752 case AL_REFERENCE_DISTANCE
:
753 case AL_CONE_INNER_ANGLE
:
754 case AL_CONE_OUTER_ANGLE
:
756 case AL_SAMPLE_OFFSET
:
758 case AL_DOPPLER_FACTOR
:
759 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
761 *values
= (ALint
)dvals
[0];
764 case AL_SAMPLE_RW_OFFSETS_SOFT
:
765 case AL_BYTE_RW_OFFSETS_SOFT
:
766 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
768 values
[0] = (ALint
)dvals
[0];
769 values
[1] = (ALint
)dvals
[0];
775 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
777 values
[0] = (ALint
)dvals
[0];
778 values
[1] = (ALint
)dvals
[1];
779 values
[2] = (ALint
)dvals
[2];
783 RETERR(AL_INVALID_ENUM
);
789 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint64
*values
)
797 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
798 LockContext(Context
);
799 values
[0] = GetSourceOffset(Source
);
800 values
[1] = ALCdevice_GetLatency(Context
->Device
);
801 UnlockContext(Context
);
804 case AL_MAX_DISTANCE
:
805 case AL_ROLLOFF_FACTOR
:
806 case AL_REFERENCE_DISTANCE
:
807 case AL_CONE_INNER_ANGLE
:
808 case AL_CONE_OUTER_ANGLE
:
810 case AL_SAMPLE_OFFSET
:
812 case AL_DOPPLER_FACTOR
:
813 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
815 *values
= (ALint64
)dvals
[0];
818 case AL_SAMPLE_RW_OFFSETS_SOFT
:
819 case AL_BYTE_RW_OFFSETS_SOFT
:
820 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
822 values
[0] = (ALint64
)dvals
[0];
823 values
[1] = (ALint64
)dvals
[0];
829 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
831 values
[0] = (ALint64
)dvals
[0];
832 values
[1] = (ALint64
)dvals
[1];
833 values
[2] = (ALint64
)dvals
[2];
836 case AL_SOURCE_RELATIVE
:
839 case AL_SOURCE_STATE
:
840 case AL_BUFFERS_QUEUED
:
841 case AL_BUFFERS_PROCESSED
:
843 case AL_DIRECT_FILTER_GAINHF_AUTO
:
844 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
845 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
846 case AL_DIRECT_CHANNELS_SOFT
:
847 case AL_DISTANCE_MODEL
:
848 if((err
=GetSourceiv(Source
, Context
, name
, ivals
)) != AL_NO_ERROR
)
854 RETERR(AL_INVALID_ENUM
);
863 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
868 Context
= GetContextRef();
875 CHECK_VALUE(Context
, n
>= 0);
876 for(cur
= 0;cur
< n
;cur
++)
878 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
880 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
881 InitSourceParams(source
);
883 err
= NewThunkEntry(&source
->id
);
884 if(err
== AL_NO_ERROR
)
885 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->id
, source
);
886 if(err
!= AL_NO_ERROR
)
888 FreeThunkEntry(source
->id
);
889 memset(source
, 0, sizeof(ALsource
));
892 al_throwerr(Context
, err
);
895 sources
[cur
] = source
->id
;
901 alDeleteSources(cur
, sources
);
905 ALCcontext_DecRef(Context
);
909 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
913 Context
= GetContextRef();
918 ALbufferlistitem
*BufferList
;
922 CHECK_VALUE(Context
, n
>= 0);
924 /* Check that all Sources are valid */
927 if(LookupSource(Context
, sources
[i
]) == NULL
)
928 al_throwerr(Context
, AL_INVALID_NAME
);
933 ALsource
**srclist
, **srclistend
;
935 if((Source
=RemoveSource(Context
, sources
[i
])) == NULL
)
937 FreeThunkEntry(Source
->id
);
939 LockContext(Context
);
940 srclist
= Context
->ActiveSources
;
941 srclistend
= srclist
+ Context
->ActiveSourceCount
;
942 while(srclist
!= srclistend
)
944 if(*srclist
== Source
)
946 Context
->ActiveSourceCount
--;
947 *srclist
= *(--srclistend
);
952 UnlockContext(Context
);
954 while(Source
->queue
!= NULL
)
956 BufferList
= Source
->queue
;
957 Source
->queue
= BufferList
->next
;
959 if(BufferList
->buffer
!= NULL
)
960 DecrementRef(&BufferList
->buffer
->ref
);
964 for(j
= 0;j
< MAX_SENDS
;++j
)
966 if(Source
->Send
[j
].Slot
)
967 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
968 Source
->Send
[j
].Slot
= NULL
;
971 memset(Source
, 0, sizeof(*Source
));
977 ALCcontext_DecRef(Context
);
981 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
986 Context
= GetContextRef();
987 if(!Context
) return AL_FALSE
;
989 result
= (LookupSource(Context
, source
) ? AL_TRUE
: AL_FALSE
);
991 ALCcontext_DecRef(Context
);
997 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1002 Context
= GetContextRef();
1003 if(!Context
) return;
1005 if((Source
=LookupSource(Context
, source
)) == NULL
)
1006 alSetError(Context
, AL_INVALID_NAME
);
1010 case AL_CONE_INNER_ANGLE
:
1011 case AL_CONE_OUTER_ANGLE
:
1013 case AL_MAX_DISTANCE
:
1014 case AL_ROLLOFF_FACTOR
:
1015 case AL_REFERENCE_DISTANCE
:
1018 case AL_CONE_OUTER_GAIN
:
1019 case AL_CONE_OUTER_GAINHF
:
1020 case AL_AIR_ABSORPTION_FACTOR
:
1021 case AL_ROOM_ROLLOFF_FACTOR
:
1022 case AL_DOPPLER_FACTOR
:
1024 case AL_SAMPLE_OFFSET
:
1025 case AL_BYTE_OFFSET
:
1026 SetSourcefv(Source
, Context
, param
, &value
);
1030 alSetError(Context
, AL_INVALID_ENUM
);
1033 ALCcontext_DecRef(Context
);
1036 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1038 ALCcontext
*Context
;
1042 Context
= GetContextRef();
1043 if(!Context
) return;
1045 if((Source
=LookupSource(Context
, source
)) == NULL
)
1046 alSetError(Context
, AL_INVALID_NAME
);
1055 SetSourcefv(Source
, Context
, param
, fvals
);
1059 alSetError(Context
, AL_INVALID_ENUM
);
1062 ALCcontext_DecRef(Context
);
1065 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1067 ALCcontext
*Context
;
1070 Context
= GetContextRef();
1071 if(!Context
) return;
1073 if((Source
=LookupSource(Context
, source
)) == NULL
)
1074 alSetError(Context
, AL_INVALID_NAME
);
1076 alSetError(Context
, AL_INVALID_VALUE
);
1080 case AL_CONE_INNER_ANGLE
:
1081 case AL_CONE_OUTER_ANGLE
:
1083 case AL_MAX_DISTANCE
:
1084 case AL_ROLLOFF_FACTOR
:
1085 case AL_REFERENCE_DISTANCE
:
1088 case AL_CONE_OUTER_GAIN
:
1089 case AL_CONE_OUTER_GAINHF
:
1091 case AL_SAMPLE_OFFSET
:
1092 case AL_BYTE_OFFSET
:
1093 case AL_AIR_ABSORPTION_FACTOR
:
1094 case AL_ROOM_ROLLOFF_FACTOR
:
1099 SetSourcefv(Source
, Context
, param
, values
);
1103 alSetError(Context
, AL_INVALID_ENUM
);
1106 ALCcontext_DecRef(Context
);
1110 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1112 ALCcontext
*Context
;
1116 Context
= GetContextRef();
1117 if(!Context
) return;
1119 if((Source
=LookupSource(Context
, source
)) == NULL
)
1120 alSetError(Context
, AL_INVALID_NAME
);
1124 case AL_CONE_INNER_ANGLE
:
1125 case AL_CONE_OUTER_ANGLE
:
1127 case AL_MAX_DISTANCE
:
1128 case AL_ROLLOFF_FACTOR
:
1129 case AL_REFERENCE_DISTANCE
:
1132 case AL_CONE_OUTER_GAIN
:
1133 case AL_CONE_OUTER_GAINHF
:
1134 case AL_AIR_ABSORPTION_FACTOR
:
1135 case AL_ROOM_ROLLOFF_FACTOR
:
1136 case AL_DOPPLER_FACTOR
:
1138 case AL_SAMPLE_OFFSET
:
1139 case AL_BYTE_OFFSET
:
1141 SetSourcefv(Source
, Context
, param
, &fval
);
1145 alSetError(Context
, AL_INVALID_ENUM
);
1148 ALCcontext_DecRef(Context
);
1151 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1153 ALCcontext
*Context
;
1157 Context
= GetContextRef();
1158 if(!Context
) return;
1160 if((Source
=LookupSource(Context
, source
)) == NULL
)
1161 alSetError(Context
, AL_INVALID_NAME
);
1170 SetSourcefv(Source
, Context
, param
, fvals
);
1174 alSetError(Context
, AL_INVALID_ENUM
);
1177 ALCcontext_DecRef(Context
);
1180 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1182 ALCcontext
*Context
;
1186 Context
= GetContextRef();
1187 if(!Context
) return;
1189 if((Source
=LookupSource(Context
, source
)) == NULL
)
1190 alSetError(Context
, AL_INVALID_NAME
);
1192 alSetError(Context
, AL_INVALID_VALUE
);
1196 case AL_CONE_INNER_ANGLE
:
1197 case AL_CONE_OUTER_ANGLE
:
1199 case AL_MAX_DISTANCE
:
1200 case AL_ROLLOFF_FACTOR
:
1201 case AL_REFERENCE_DISTANCE
:
1204 case AL_CONE_OUTER_GAIN
:
1205 case AL_CONE_OUTER_GAINHF
:
1207 case AL_SAMPLE_OFFSET
:
1208 case AL_BYTE_OFFSET
:
1209 case AL_AIR_ABSORPTION_FACTOR
:
1210 case AL_ROOM_ROLLOFF_FACTOR
:
1211 fvals
[0] = values
[0];
1212 SetSourcefv(Source
, Context
, param
, fvals
);
1218 fvals
[0] = values
[0];
1219 fvals
[1] = values
[1];
1220 fvals
[2] = values
[2];
1221 SetSourcefv(Source
, Context
, param
, fvals
);
1225 alSetError(Context
, AL_INVALID_ENUM
);
1228 ALCcontext_DecRef(Context
);
1232 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1234 ALCcontext
*Context
;
1237 Context
= GetContextRef();
1238 if(!Context
) return;
1240 if((Source
=LookupSource(Context
, source
)) == NULL
)
1241 alSetError(Context
, AL_INVALID_NAME
);
1244 case AL_MAX_DISTANCE
:
1245 case AL_ROLLOFF_FACTOR
:
1246 case AL_CONE_INNER_ANGLE
:
1247 case AL_CONE_OUTER_ANGLE
:
1248 case AL_REFERENCE_DISTANCE
:
1249 case AL_SOURCE_RELATIVE
:
1252 case AL_SOURCE_STATE
:
1254 case AL_SAMPLE_OFFSET
:
1255 case AL_BYTE_OFFSET
:
1256 case AL_DIRECT_FILTER
:
1257 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1258 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1259 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1260 case AL_DIRECT_CHANNELS_SOFT
:
1261 case AL_DISTANCE_MODEL
:
1262 SetSourceiv(Source
, Context
, param
, &value
);
1266 alSetError(Context
, AL_INVALID_ENUM
);
1269 ALCcontext_DecRef(Context
);
1272 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1274 ALCcontext
*Context
;
1278 Context
= GetContextRef();
1279 if(!Context
) return;
1281 if((Source
=LookupSource(Context
, source
)) == NULL
)
1282 alSetError(Context
, AL_INVALID_NAME
);
1288 case AL_AUXILIARY_SEND_FILTER
:
1292 SetSourceiv(Source
, Context
, param
, ivals
);
1296 alSetError(Context
, AL_INVALID_ENUM
);
1299 ALCcontext_DecRef(Context
);
1302 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1304 ALCcontext
*Context
;
1307 Context
= GetContextRef();
1308 if(!Context
) return;
1310 if((Source
=LookupSource(Context
, source
)) == NULL
)
1311 alSetError(Context
, AL_INVALID_NAME
);
1313 alSetError(Context
, AL_INVALID_VALUE
);
1316 case AL_SOURCE_RELATIVE
:
1317 case AL_CONE_INNER_ANGLE
:
1318 case AL_CONE_OUTER_ANGLE
:
1321 case AL_SOURCE_STATE
:
1323 case AL_SAMPLE_OFFSET
:
1324 case AL_BYTE_OFFSET
:
1325 case AL_MAX_DISTANCE
:
1326 case AL_ROLLOFF_FACTOR
:
1327 case AL_REFERENCE_DISTANCE
:
1328 case AL_DIRECT_FILTER
:
1329 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1330 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1331 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1332 case AL_DISTANCE_MODEL
:
1333 case AL_DIRECT_CHANNELS_SOFT
:
1338 case AL_AUXILIARY_SEND_FILTER
:
1339 SetSourceiv(Source
, Context
, param
, values
);
1343 alSetError(Context
, AL_INVALID_ENUM
);
1346 ALCcontext_DecRef(Context
);
1350 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1352 ALCcontext
*Context
;
1355 Context
= GetContextRef();
1356 if(!Context
) return;
1358 if((Source
=LookupSource(Context
, source
)) == NULL
)
1359 alSetError(Context
, AL_INVALID_NAME
);
1362 case AL_MAX_DISTANCE
:
1363 case AL_ROLLOFF_FACTOR
:
1364 case AL_CONE_INNER_ANGLE
:
1365 case AL_CONE_OUTER_ANGLE
:
1366 case AL_REFERENCE_DISTANCE
:
1367 case AL_SOURCE_RELATIVE
:
1369 case AL_SOURCE_STATE
:
1371 case AL_SAMPLE_OFFSET
:
1372 case AL_BYTE_OFFSET
:
1373 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1374 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1375 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1376 case AL_DIRECT_CHANNELS_SOFT
:
1377 case AL_DISTANCE_MODEL
:
1379 case AL_DIRECT_FILTER
:
1380 SetSourcei64v(Source
, Context
, param
, &value
);
1384 alSetError(Context
, AL_INVALID_ENUM
);
1387 ALCcontext_DecRef(Context
);
1390 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1392 ALCcontext
*Context
;
1394 ALint64SOFT i64vals
[3];
1396 Context
= GetContextRef();
1397 if(!Context
) return;
1399 if((Source
=LookupSource(Context
, source
)) == NULL
)
1400 alSetError(Context
, AL_INVALID_NAME
);
1406 case AL_AUXILIARY_SEND_FILTER
:
1407 i64vals
[0] = value1
;
1408 i64vals
[1] = value2
;
1409 i64vals
[2] = value3
;
1410 SetSourcei64v(Source
, Context
, param
, i64vals
);
1414 alSetError(Context
, AL_INVALID_ENUM
);
1417 ALCcontext_DecRef(Context
);
1420 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1422 ALCcontext
*Context
;
1425 Context
= GetContextRef();
1426 if(!Context
) return;
1428 if((Source
=LookupSource(Context
, source
)) == NULL
)
1429 alSetError(Context
, AL_INVALID_NAME
);
1431 alSetError(Context
, AL_INVALID_VALUE
);
1434 case AL_SOURCE_RELATIVE
:
1435 case AL_CONE_INNER_ANGLE
:
1436 case AL_CONE_OUTER_ANGLE
:
1438 case AL_SOURCE_STATE
:
1440 case AL_SAMPLE_OFFSET
:
1441 case AL_BYTE_OFFSET
:
1442 case AL_MAX_DISTANCE
:
1443 case AL_ROLLOFF_FACTOR
:
1444 case AL_REFERENCE_DISTANCE
:
1445 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1446 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1447 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1448 case AL_DISTANCE_MODEL
:
1449 case AL_DIRECT_CHANNELS_SOFT
:
1451 case AL_DIRECT_FILTER
:
1456 case AL_AUXILIARY_SEND_FILTER
:
1457 SetSourcei64v(Source
, Context
, param
, values
);
1461 alSetError(Context
, AL_INVALID_ENUM
);
1464 ALCcontext_DecRef(Context
);
1468 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1470 ALCcontext
*Context
;
1474 Context
= GetContextRef();
1475 if(!Context
) return;
1477 if((Source
=LookupSource(Context
, source
)) == NULL
)
1478 alSetError(Context
, AL_INVALID_NAME
);
1480 alSetError(Context
, AL_INVALID_VALUE
);
1487 case AL_MAX_DISTANCE
:
1488 case AL_ROLLOFF_FACTOR
:
1489 case AL_CONE_OUTER_GAIN
:
1490 case AL_CONE_OUTER_GAINHF
:
1492 case AL_SAMPLE_OFFSET
:
1493 case AL_BYTE_OFFSET
:
1494 case AL_CONE_INNER_ANGLE
:
1495 case AL_CONE_OUTER_ANGLE
:
1496 case AL_REFERENCE_DISTANCE
:
1497 case AL_AIR_ABSORPTION_FACTOR
:
1498 case AL_ROOM_ROLLOFF_FACTOR
:
1499 case AL_DOPPLER_FACTOR
:
1500 if(GetSourcedv(Source
, Context
, param
, &dval
) == AL_NO_ERROR
)
1501 *value
= (ALfloat
)dval
;
1505 alSetError(Context
, AL_INVALID_ENUM
);
1508 ALCcontext_DecRef(Context
);
1512 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1514 ALCcontext
*Context
;
1518 Context
= GetContextRef();
1519 if(!Context
) return;
1521 if((Source
=LookupSource(Context
, source
)) == NULL
)
1522 alSetError(Context
, AL_INVALID_NAME
);
1523 else if(!(value1
&& value2
&& value3
))
1524 alSetError(Context
, AL_INVALID_VALUE
);
1530 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1532 *value1
= (ALfloat
)dvals
[0];
1533 *value2
= (ALfloat
)dvals
[1];
1534 *value3
= (ALfloat
)dvals
[2];
1539 alSetError(Context
, AL_INVALID_ENUM
);
1542 ALCcontext_DecRef(Context
);
1546 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1548 ALCcontext
*Context
;
1558 case AL_MAX_DISTANCE
:
1559 case AL_ROLLOFF_FACTOR
:
1560 case AL_DOPPLER_FACTOR
:
1561 case AL_CONE_OUTER_GAIN
:
1563 case AL_SAMPLE_OFFSET
:
1564 case AL_BYTE_OFFSET
:
1565 case AL_CONE_INNER_ANGLE
:
1566 case AL_CONE_OUTER_ANGLE
:
1567 case AL_REFERENCE_DISTANCE
:
1568 case AL_CONE_OUTER_GAINHF
:
1569 case AL_AIR_ABSORPTION_FACTOR
:
1570 case AL_ROOM_ROLLOFF_FACTOR
:
1571 alGetSourcef(source
, param
, values
);
1577 alGetSource3f(source
, param
, values
+0, values
+1, values
+2);
1581 Context
= GetContextRef();
1582 if(!Context
) return;
1584 if((Source
=LookupSource(Context
, source
)) == NULL
)
1585 alSetError(Context
, AL_INVALID_NAME
);
1587 alSetError(Context
, AL_INVALID_VALUE
);
1590 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1591 case AL_BYTE_RW_OFFSETS_SOFT
:
1592 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1594 values
[0] = (ALfloat
)dvals
[0];
1595 values
[1] = (ALfloat
)dvals
[1];
1600 alSetError(Context
, AL_INVALID_ENUM
);
1603 ALCcontext_DecRef(Context
);
1607 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1609 ALCcontext
*Context
;
1612 Context
= GetContextRef();
1613 if(!Context
) return;
1615 if((Source
=LookupSource(Context
, source
)) == NULL
)
1616 alSetError(Context
, AL_INVALID_NAME
);
1618 alSetError(Context
, AL_INVALID_VALUE
);
1625 case AL_MAX_DISTANCE
:
1626 case AL_ROLLOFF_FACTOR
:
1627 case AL_CONE_OUTER_GAIN
:
1628 case AL_CONE_OUTER_GAINHF
:
1630 case AL_SAMPLE_OFFSET
:
1631 case AL_BYTE_OFFSET
:
1632 case AL_CONE_INNER_ANGLE
:
1633 case AL_CONE_OUTER_ANGLE
:
1634 case AL_REFERENCE_DISTANCE
:
1635 case AL_AIR_ABSORPTION_FACTOR
:
1636 case AL_ROOM_ROLLOFF_FACTOR
:
1637 case AL_DOPPLER_FACTOR
:
1638 GetSourcedv(Source
, Context
, param
, value
);
1642 alSetError(Context
, AL_INVALID_ENUM
);
1645 ALCcontext_DecRef(Context
);
1648 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1650 ALCcontext
*Context
;
1654 Context
= GetContextRef();
1655 if(!Context
) return;
1657 if((Source
=LookupSource(Context
, source
)) == NULL
)
1658 alSetError(Context
, AL_INVALID_NAME
);
1659 else if(!(value1
&& value2
&& value3
))
1660 alSetError(Context
, AL_INVALID_VALUE
);
1666 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1675 alSetError(Context
, AL_INVALID_ENUM
);
1678 ALCcontext_DecRef(Context
);
1681 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1683 ALCcontext
*Context
;
1686 Context
= GetContextRef();
1687 if(!Context
) return;
1689 if((Source
=LookupSource(Context
, source
)) == NULL
)
1690 alSetError(Context
, AL_INVALID_NAME
);
1692 alSetError(Context
, AL_INVALID_VALUE
);
1699 case AL_MAX_DISTANCE
:
1700 case AL_ROLLOFF_FACTOR
:
1701 case AL_DOPPLER_FACTOR
:
1702 case AL_CONE_OUTER_GAIN
:
1704 case AL_SAMPLE_OFFSET
:
1705 case AL_BYTE_OFFSET
:
1706 case AL_CONE_INNER_ANGLE
:
1707 case AL_CONE_OUTER_ANGLE
:
1708 case AL_REFERENCE_DISTANCE
:
1709 case AL_CONE_OUTER_GAINHF
:
1710 case AL_AIR_ABSORPTION_FACTOR
:
1711 case AL_ROOM_ROLLOFF_FACTOR
:
1713 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1714 case AL_BYTE_RW_OFFSETS_SOFT
:
1715 case AL_SEC_OFFSET_LATENCY_SOFT
:
1720 GetSourcedv(Source
, Context
, param
, values
);
1724 alSetError(Context
, AL_INVALID_ENUM
);
1727 ALCcontext_DecRef(Context
);
1731 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1733 ALCcontext
*Context
;
1736 Context
= GetContextRef();
1737 if(!Context
) return;
1739 if((Source
=LookupSource(Context
, source
)) == NULL
)
1740 alSetError(Context
, AL_INVALID_NAME
);
1742 alSetError(Context
, AL_INVALID_VALUE
);
1745 case AL_MAX_DISTANCE
:
1746 case AL_ROLLOFF_FACTOR
:
1747 case AL_REFERENCE_DISTANCE
:
1748 case AL_SOURCE_RELATIVE
:
1749 case AL_CONE_INNER_ANGLE
:
1750 case AL_CONE_OUTER_ANGLE
:
1753 case AL_SOURCE_STATE
:
1754 case AL_BUFFERS_QUEUED
:
1755 case AL_BUFFERS_PROCESSED
:
1756 case AL_SOURCE_TYPE
:
1758 case AL_SAMPLE_OFFSET
:
1759 case AL_BYTE_OFFSET
:
1760 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1761 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1762 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1763 case AL_DOPPLER_FACTOR
:
1764 case AL_DIRECT_CHANNELS_SOFT
:
1765 case AL_DISTANCE_MODEL
:
1766 GetSourceiv(Source
, Context
, param
, value
);
1770 alSetError(Context
, AL_INVALID_ENUM
);
1773 ALCcontext_DecRef(Context
);
1777 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1779 ALCcontext
*Context
;
1783 Context
= GetContextRef();
1784 if(!Context
) return;
1786 if((Source
=LookupSource(Context
, source
)) == NULL
)
1787 alSetError(Context
, AL_INVALID_NAME
);
1788 else if(!(value1
&& value2
&& value3
))
1789 alSetError(Context
, AL_INVALID_VALUE
);
1795 if(GetSourceiv(Source
, Context
, param
, ivals
) == AL_NO_ERROR
)
1804 alSetError(Context
, AL_INVALID_ENUM
);
1807 ALCcontext_DecRef(Context
);
1811 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1813 ALCcontext
*Context
;
1816 Context
= GetContextRef();
1817 if(!Context
) return;
1819 if((Source
=LookupSource(Context
, source
)) == NULL
)
1820 alSetError(Context
, AL_INVALID_NAME
);
1822 alSetError(Context
, AL_INVALID_VALUE
);
1825 case AL_SOURCE_RELATIVE
:
1826 case AL_CONE_INNER_ANGLE
:
1827 case AL_CONE_OUTER_ANGLE
:
1830 case AL_SOURCE_STATE
:
1831 case AL_BUFFERS_QUEUED
:
1832 case AL_BUFFERS_PROCESSED
:
1834 case AL_SAMPLE_OFFSET
:
1835 case AL_BYTE_OFFSET
:
1836 case AL_MAX_DISTANCE
:
1837 case AL_ROLLOFF_FACTOR
:
1838 case AL_DOPPLER_FACTOR
:
1839 case AL_REFERENCE_DISTANCE
:
1840 case AL_SOURCE_TYPE
:
1841 case AL_DIRECT_FILTER
:
1842 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1843 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1844 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1845 case AL_DISTANCE_MODEL
:
1846 case AL_DIRECT_CHANNELS_SOFT
:
1848 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1849 case AL_BYTE_RW_OFFSETS_SOFT
:
1854 GetSourceiv(Source
, Context
, param
, values
);
1858 alSetError(Context
, AL_INVALID_ENUM
);
1861 ALCcontext_DecRef(Context
);
1865 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
1867 ALCcontext
*Context
;
1870 Context
= GetContextRef();
1871 if(!Context
) return;
1873 if((Source
=LookupSource(Context
, source
)) == NULL
)
1874 alSetError(Context
, AL_INVALID_NAME
);
1876 alSetError(Context
, AL_INVALID_VALUE
);
1879 case AL_MAX_DISTANCE
:
1880 case AL_ROLLOFF_FACTOR
:
1881 case AL_REFERENCE_DISTANCE
:
1882 case AL_SOURCE_RELATIVE
:
1883 case AL_CONE_INNER_ANGLE
:
1884 case AL_CONE_OUTER_ANGLE
:
1887 case AL_SOURCE_STATE
:
1888 case AL_BUFFERS_QUEUED
:
1889 case AL_BUFFERS_PROCESSED
:
1890 case AL_SOURCE_TYPE
:
1892 case AL_SAMPLE_OFFSET
:
1893 case AL_BYTE_OFFSET
:
1894 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1895 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1896 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1897 case AL_DOPPLER_FACTOR
:
1898 case AL_DIRECT_CHANNELS_SOFT
:
1899 case AL_DISTANCE_MODEL
:
1900 GetSourcei64v(Source
, Context
, param
, value
);
1904 alSetError(Context
, AL_INVALID_ENUM
);
1907 ALCcontext_DecRef(Context
);
1910 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
1912 ALCcontext
*Context
;
1916 Context
= GetContextRef();
1917 if(!Context
) return;
1919 if((Source
=LookupSource(Context
, source
)) == NULL
)
1920 alSetError(Context
, AL_INVALID_NAME
);
1921 else if(!(value1
&& value2
&& value3
))
1922 alSetError(Context
, AL_INVALID_VALUE
);
1928 if(GetSourcei64v(Source
, Context
, param
, i64vals
) == AL_NO_ERROR
)
1930 *value1
= i64vals
[0];
1931 *value2
= i64vals
[1];
1932 *value3
= i64vals
[2];
1937 alSetError(Context
, AL_INVALID_ENUM
);
1940 ALCcontext_DecRef(Context
);
1943 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
1945 ALCcontext
*Context
;
1948 Context
= GetContextRef();
1949 if(!Context
) return;
1951 if((Source
=LookupSource(Context
, source
)) == NULL
)
1952 alSetError(Context
, AL_INVALID_NAME
);
1954 alSetError(Context
, AL_INVALID_VALUE
);
1957 case AL_MAX_DISTANCE
:
1958 case AL_ROLLOFF_FACTOR
:
1959 case AL_REFERENCE_DISTANCE
:
1960 case AL_SOURCE_RELATIVE
:
1961 case AL_CONE_INNER_ANGLE
:
1962 case AL_CONE_OUTER_ANGLE
:
1965 case AL_SOURCE_STATE
:
1966 case AL_BUFFERS_QUEUED
:
1967 case AL_BUFFERS_PROCESSED
:
1968 case AL_SOURCE_TYPE
:
1970 case AL_SAMPLE_OFFSET
:
1971 case AL_BYTE_OFFSET
:
1972 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1973 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1974 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1975 case AL_DOPPLER_FACTOR
:
1976 case AL_DIRECT_CHANNELS_SOFT
:
1977 case AL_DISTANCE_MODEL
:
1979 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1980 case AL_BYTE_RW_OFFSETS_SOFT
:
1981 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1986 GetSourcei64v(Source
, Context
, param
, values
);
1990 alSetError(Context
, AL_INVALID_ENUM
);
1993 ALCcontext_DecRef(Context
);
1997 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
1999 alSourcePlayv(1, &source
);
2001 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2003 ALCcontext
*Context
;
2007 Context
= GetContextRef();
2008 if(!Context
) return;
2012 CHECK_VALUE(Context
, n
>= 0);
2013 for(i
= 0;i
< n
;i
++)
2015 if(!LookupSource(Context
, sources
[i
]))
2016 al_throwerr(Context
, AL_INVALID_NAME
);
2019 LockContext(Context
);
2020 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
2025 newcount
= Context
->MaxActiveSources
<< 1;
2027 temp
= realloc(Context
->ActiveSources
,
2028 sizeof(*Context
->ActiveSources
) * newcount
);
2031 UnlockContext(Context
);
2032 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
2035 Context
->ActiveSources
= temp
;
2036 Context
->MaxActiveSources
= newcount
;
2039 for(i
= 0;i
< n
;i
++)
2041 Source
= LookupSource(Context
, sources
[i
]);
2042 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
2043 else SetSourceState(Source
, Context
, AL_PLAYING
);
2045 UnlockContext(Context
);
2049 ALCcontext_DecRef(Context
);
2052 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2054 alSourcePausev(1, &source
);
2056 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2058 ALCcontext
*Context
;
2062 Context
= GetContextRef();
2063 if(!Context
) return;
2067 CHECK_VALUE(Context
, n
>= 0);
2068 for(i
= 0;i
< n
;i
++)
2070 if(!LookupSource(Context
, sources
[i
]))
2071 al_throwerr(Context
, AL_INVALID_NAME
);
2074 LockContext(Context
);
2075 for(i
= 0;i
< n
;i
++)
2077 Source
= LookupSource(Context
, sources
[i
]);
2078 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
2079 else SetSourceState(Source
, Context
, AL_PAUSED
);
2081 UnlockContext(Context
);
2085 ALCcontext_DecRef(Context
);
2088 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2090 alSourceStopv(1, &source
);
2092 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2094 ALCcontext
*Context
;
2098 Context
= GetContextRef();
2099 if(!Context
) return;
2103 CHECK_VALUE(Context
, n
>= 0);
2104 for(i
= 0;i
< n
;i
++)
2106 if(!LookupSource(Context
, sources
[i
]))
2107 al_throwerr(Context
, AL_INVALID_NAME
);
2110 LockContext(Context
);
2111 for(i
= 0;i
< n
;i
++)
2113 Source
= LookupSource(Context
, sources
[i
]);
2114 Source
->new_state
= AL_NONE
;
2115 SetSourceState(Source
, Context
, AL_STOPPED
);
2117 UnlockContext(Context
);
2121 ALCcontext_DecRef(Context
);
2124 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2126 alSourceRewindv(1, &source
);
2128 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2130 ALCcontext
*Context
;
2134 Context
= GetContextRef();
2135 if(!Context
) return;
2139 CHECK_VALUE(Context
, n
>= 0);
2140 for(i
= 0;i
< n
;i
++)
2142 if(!LookupSource(Context
, sources
[i
]))
2143 al_throwerr(Context
, AL_INVALID_NAME
);
2146 LockContext(Context
);
2147 for(i
= 0;i
< n
;i
++)
2149 Source
= LookupSource(Context
, sources
[i
]);
2150 Source
->new_state
= AL_NONE
;
2151 SetSourceState(Source
, Context
, AL_INITIAL
);
2153 UnlockContext(Context
);
2157 ALCcontext_DecRef(Context
);
2161 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei nb
, const ALuint
*buffers
)
2163 ALCcontext
*Context
;
2166 ALbufferlistitem
*BufferListStart
= NULL
;
2167 ALbufferlistitem
*BufferList
;
2168 ALbuffer
*BufferFmt
;
2173 Context
= GetContextRef();
2174 if(!Context
) return;
2178 ALCdevice
*device
= Context
->Device
;
2180 CHECK_VALUE(Context
, nb
>= 0);
2182 if((Source
=LookupSource(Context
, source
)) == NULL
)
2183 al_throwerr(Context
, AL_INVALID_NAME
);
2185 LockContext(Context
);
2186 if(Source
->SourceType
== AL_STATIC
)
2188 UnlockContext(Context
);
2189 /* Can't queue on a Static Source */
2190 al_throwerr(Context
, AL_INVALID_OPERATION
);
2195 /* Check for a valid Buffer, for its frequency and format */
2196 BufferList
= Source
->queue
;
2199 if(BufferList
->buffer
)
2201 BufferFmt
= BufferList
->buffer
;
2204 BufferList
= BufferList
->next
;
2207 for(i
= 0;i
< nb
;i
++)
2209 ALbuffer
*buffer
= NULL
;
2210 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2212 UnlockContext(Context
);
2213 al_throwerr(Context
, AL_INVALID_NAME
);
2216 if(!BufferListStart
)
2218 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2219 BufferListStart
->buffer
= buffer
;
2220 BufferListStart
->next
= NULL
;
2221 BufferListStart
->prev
= NULL
;
2222 BufferList
= BufferListStart
;
2226 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2227 BufferList
->next
->buffer
= buffer
;
2228 BufferList
->next
->next
= NULL
;
2229 BufferList
->next
->prev
= BufferList
;
2230 BufferList
= BufferList
->next
;
2232 if(!buffer
) continue;
2233 IncrementRef(&buffer
->ref
);
2235 ReadLock(&buffer
->lock
);
2236 if(BufferFmt
== NULL
)
2240 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2241 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2242 if(buffer
->FmtChannels
== FmtMono
)
2243 Source
->Update
= CalcSourceParams
;
2245 Source
->Update
= CalcNonAttnSourceParams
;
2247 Source
->NeedsUpdate
= AL_TRUE
;
2249 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2250 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2251 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2253 ReadUnlock(&buffer
->lock
);
2254 UnlockContext(Context
);
2255 al_throwerr(Context
, AL_INVALID_OPERATION
);
2257 ReadUnlock(&buffer
->lock
);
2260 /* Source is now streaming */
2261 Source
->SourceType
= AL_STREAMING
;
2263 if(Source
->queue
== NULL
)
2264 Source
->queue
= BufferListStart
;
2267 /* Append to the end of the queue */
2268 BufferList
= Source
->queue
;
2269 while(BufferList
->next
!= NULL
)
2270 BufferList
= BufferList
->next
;
2272 BufferListStart
->prev
= BufferList
;
2273 BufferList
->next
= BufferListStart
;
2276 Source
->BuffersInQueue
+= nb
;
2278 UnlockContext(Context
);
2282 while(BufferListStart
)
2284 BufferList
= BufferListStart
;
2285 BufferListStart
= BufferList
->next
;
2287 if(BufferList
->buffer
)
2288 DecrementRef(&BufferList
->buffer
->ref
);
2294 ALCcontext_DecRef(Context
);
2297 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint source
, ALsizei nb
, ALuint
*buffers
)
2299 ALCcontext
*Context
;
2302 ALbufferlistitem
*BufferList
;
2307 Context
= GetContextRef();
2308 if(!Context
) return;
2312 CHECK_VALUE(Context
, nb
>= 0);
2314 if((Source
=LookupSource(Context
, source
)) == NULL
)
2315 al_throwerr(Context
, AL_INVALID_NAME
);
2317 LockContext(Context
);
2318 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
||
2319 (ALuint
)nb
> Source
->BuffersPlayed
)
2321 UnlockContext(Context
);
2322 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2323 al_throwerr(Context
, AL_INVALID_VALUE
);
2326 for(i
= 0;i
< nb
;i
++)
2328 BufferList
= Source
->queue
;
2329 Source
->queue
= BufferList
->next
;
2330 Source
->BuffersInQueue
--;
2331 Source
->BuffersPlayed
--;
2333 if(BufferList
->buffer
)
2335 buffers
[i
] = BufferList
->buffer
->id
;
2336 DecrementRef(&BufferList
->buffer
->ref
);
2344 Source
->queue
->prev
= NULL
;
2345 UnlockContext(Context
);
2349 ALCcontext_DecRef(Context
);
2353 static ALvoid
InitSourceParams(ALsource
*Source
)
2357 Source
->InnerAngle
= 360.0f
;
2358 Source
->OuterAngle
= 360.0f
;
2359 Source
->Pitch
= 1.0f
;
2360 Source
->Position
[0] = 0.0f
;
2361 Source
->Position
[1] = 0.0f
;
2362 Source
->Position
[2] = 0.0f
;
2363 Source
->Orientation
[0] = 0.0f
;
2364 Source
->Orientation
[1] = 0.0f
;
2365 Source
->Orientation
[2] = 0.0f
;
2366 Source
->Velocity
[0] = 0.0f
;
2367 Source
->Velocity
[1] = 0.0f
;
2368 Source
->Velocity
[2] = 0.0f
;
2369 Source
->RefDistance
= 1.0f
;
2370 Source
->MaxDistance
= FLT_MAX
;
2371 Source
->RollOffFactor
= 1.0f
;
2372 Source
->Looping
= AL_FALSE
;
2373 Source
->Gain
= 1.0f
;
2374 Source
->MinGain
= 0.0f
;
2375 Source
->MaxGain
= 1.0f
;
2376 Source
->OuterGain
= 0.0f
;
2377 Source
->OuterGainHF
= 1.0f
;
2379 Source
->DryGainHFAuto
= AL_TRUE
;
2380 Source
->WetGainAuto
= AL_TRUE
;
2381 Source
->WetGainHFAuto
= AL_TRUE
;
2382 Source
->AirAbsorptionFactor
= 0.0f
;
2383 Source
->RoomRolloffFactor
= 0.0f
;
2384 Source
->DopplerFactor
= 1.0f
;
2385 Source
->DirectChannels
= AL_FALSE
;
2387 Source
->DistanceModel
= DefaultDistanceModel
;
2389 Source
->Resampler
= DefaultResampler
;
2391 Source
->state
= AL_INITIAL
;
2392 Source
->new_state
= AL_NONE
;
2393 Source
->SourceType
= AL_UNDETERMINED
;
2394 Source
->Offset
= -1.0;
2396 Source
->DirectGain
= 1.0f
;
2397 Source
->DirectGainHF
= 1.0f
;
2398 for(i
= 0;i
< MAX_SENDS
;i
++)
2400 Source
->Send
[i
].Gain
= 1.0f
;
2401 Source
->Send
[i
].GainHF
= 1.0f
;
2404 Source
->NeedsUpdate
= AL_TRUE
;
2406 Source
->Hrtf
.Moving
= AL_FALSE
;
2407 Source
->Hrtf
.Counter
= 0;
2413 * Sets the source's new play state given its current state.
2415 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2417 if(state
== AL_PLAYING
)
2419 ALbufferlistitem
*BufferList
;
2422 /* Check that there is a queue containing at least one valid, non zero
2424 BufferList
= Source
->queue
;
2427 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
2429 BufferList
= BufferList
->next
;
2432 if(Source
->state
!= AL_PLAYING
)
2434 for(j
= 0;j
< MaxChannels
;j
++)
2436 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
2437 Source
->Hrtf
.History
[j
][k
] = 0.0f
;
2438 for(k
= 0;k
< HRIR_LENGTH
;k
++)
2440 Source
->Hrtf
.Values
[j
][k
][0] = 0.0f
;
2441 Source
->Hrtf
.Values
[j
][k
][1] = 0.0f
;
2446 if(Source
->state
!= AL_PAUSED
)
2448 Source
->state
= AL_PLAYING
;
2449 Source
->position
= 0;
2450 Source
->position_fraction
= 0;
2451 Source
->BuffersPlayed
= 0;
2454 Source
->state
= AL_PLAYING
;
2456 // Check if an Offset has been set
2457 if(Source
->Offset
>= 0.0)
2458 ApplyOffset(Source
);
2460 /* If there's nothing to play, or device is disconnected, go right to
2462 if(!BufferList
|| !Context
->Device
->Connected
)
2464 SetSourceState(Source
, Context
, AL_STOPPED
);
2468 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
2470 if(Context
->ActiveSources
[j
] == Source
)
2473 if(j
== Context
->ActiveSourceCount
)
2474 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
2476 else if(state
== AL_PAUSED
)
2478 if(Source
->state
== AL_PLAYING
)
2480 Source
->state
= AL_PAUSED
;
2481 Source
->Hrtf
.Moving
= AL_FALSE
;
2482 Source
->Hrtf
.Counter
= 0;
2485 else if(state
== AL_STOPPED
)
2487 if(Source
->state
!= AL_INITIAL
)
2489 Source
->state
= AL_STOPPED
;
2490 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
2491 Source
->Hrtf
.Moving
= AL_FALSE
;
2492 Source
->Hrtf
.Counter
= 0;
2494 Source
->Offset
= -1.0;
2496 else if(state
== AL_INITIAL
)
2498 if(Source
->state
!= AL_INITIAL
)
2500 Source
->state
= AL_INITIAL
;
2501 Source
->position
= 0;
2502 Source
->position_fraction
= 0;
2503 Source
->BuffersPlayed
= 0;
2504 Source
->Hrtf
.Moving
= AL_FALSE
;
2505 Source
->Hrtf
.Counter
= 0;
2507 Source
->Offset
= -1.0;
2513 * Gets the current read offset for the given Source, in 32.32 fixed-point
2514 * samples. The offset is relative to the start of the queue (not the start of
2515 * the current buffer).
2517 static ALint64
GetSourceOffset(const ALsource
*Source
)
2519 const ALbufferlistitem
*BufferList
;
2523 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2526 /* NOTE: This is the offset into the *current* buffer, so add the length of
2527 * any played buffers */
2528 readPos
= (ALuint64
)Source
->position
<< 32;
2529 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2530 BufferList
= Source
->queue
;
2531 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2533 if(BufferList
->buffer
)
2534 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2535 BufferList
= BufferList
->next
;
2538 return (ALint64
)minu64(readPos
, MAKEU64(0x7fffffff,0xffffffff));
2541 /* GetSourceSecOffset
2543 * Gets the current read offset for the given Source, in seconds. The offset is
2544 * relative to the start of the queue (not the start of the current buffer).
2546 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2548 const ALbufferlistitem
*BufferList
;
2549 const ALbuffer
*Buffer
= NULL
;
2553 BufferList
= Source
->queue
;
2556 if(BufferList
->buffer
)
2558 Buffer
= BufferList
->buffer
;
2561 BufferList
= BufferList
->next
;
2564 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2567 /* NOTE: This is the offset into the *current* buffer, so add the length of
2568 * any played buffers */
2569 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2570 readPos
|= (ALuint64
)Source
->position_fraction
;
2571 BufferList
= Source
->queue
;
2572 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2574 if(BufferList
->buffer
)
2575 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< FRACTIONBITS
;
2576 BufferList
= BufferList
->next
;
2579 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2584 * Gets the current read and write offsets for the given Source, in the
2585 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2586 * the start of the queue (not the start of the current buffer).
2588 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2590 const ALbufferlistitem
*BufferList
;
2591 const ALbuffer
*Buffer
= NULL
;
2592 ALuint readPos
, writePos
;
2593 ALuint totalBufferLen
;
2596 // Find the first valid Buffer in the Queue
2597 BufferList
= Source
->queue
;
2600 if(BufferList
->buffer
)
2602 Buffer
= BufferList
->buffer
;
2605 BufferList
= BufferList
->next
;
2608 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2615 if(updateLen
> 0.0 && updateLen
< 0.015)
2618 /* NOTE: This is the offset into the *current* buffer, so add the length of
2619 * any played buffers */
2620 readPos
= Source
->position
;
2622 BufferList
= Source
->queue
;
2623 for(i
= 0;BufferList
;i
++)
2625 if(BufferList
->buffer
)
2627 if(i
< Source
->BuffersPlayed
)
2628 readPos
+= BufferList
->buffer
->SampleLen
;
2629 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
2631 BufferList
= BufferList
->next
;
2633 if(Source
->state
== AL_PLAYING
)
2634 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2640 readPos
%= totalBufferLen
;
2641 writePos
%= totalBufferLen
;
2645 /* Wrap positions back to 0 */
2646 if(readPos
>= totalBufferLen
)
2648 if(writePos
>= totalBufferLen
)
2655 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2656 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2659 case AL_SAMPLE_OFFSET
:
2660 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2661 offset
[0] = (ALdouble
)readPos
;
2662 offset
[1] = (ALdouble
)writePos
;
2665 case AL_BYTE_OFFSET
:
2666 case AL_BYTE_RW_OFFSETS_SOFT
:
2667 if(Buffer
->OriginalType
== UserFmtIMA4
)
2669 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
2670 ALuint FrameBlockSize
= 65;
2672 /* Round down to nearest ADPCM block */
2673 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2674 if(Source
->state
!= AL_PLAYING
)
2675 offset
[1] = offset
[0];
2678 /* Round up to nearest ADPCM block */
2679 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2680 FrameBlockSize
* BlockSize
);
2685 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2686 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2687 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2696 * Apply the stored playback offset to the Source. This function will update
2697 * the number of buffers "played" given the stored offset.
2699 ALboolean
ApplyOffset(ALsource
*Source
)
2701 const ALbufferlistitem
*BufferList
;
2702 const ALbuffer
*Buffer
;
2703 ALint bufferLen
, totalBufferLen
;
2704 ALint buffersPlayed
;
2707 /* Get sample frame offset */
2708 offset
= GetSampleOffset(Source
);
2715 BufferList
= Source
->queue
;
2718 Buffer
= BufferList
->buffer
;
2719 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2721 if(bufferLen
<= offset
-totalBufferLen
)
2723 /* Offset is past this buffer so increment to the next buffer */
2726 else if(totalBufferLen
<= offset
)
2728 /* Offset is in this buffer */
2729 Source
->BuffersPlayed
= buffersPlayed
;
2731 Source
->position
= offset
- totalBufferLen
;
2732 Source
->position_fraction
= 0;
2736 totalBufferLen
+= bufferLen
;
2738 BufferList
= BufferList
->next
;
2741 /* Offset is out of range of the queue */
2748 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2749 * Second offset supplied by the application). This takes into account the fact
2750 * that the buffer format may have been modifed since.
2752 static ALint
GetSampleOffset(ALsource
*Source
)
2754 const ALbuffer
*Buffer
= NULL
;
2755 const ALbufferlistitem
*BufferList
;
2758 /* Find the first valid Buffer in the Queue */
2759 BufferList
= Source
->queue
;
2762 if(BufferList
->buffer
)
2764 Buffer
= BufferList
->buffer
;
2767 BufferList
= BufferList
->next
;
2772 Source
->Offset
= -1.0;
2776 switch(Source
->OffsetType
)
2778 case AL_BYTE_OFFSET
:
2779 /* Determine the ByteOffset (and ensure it is block aligned) */
2780 Offset
= (ALint
)Source
->Offset
;
2781 if(Buffer
->OriginalType
== UserFmtIMA4
)
2783 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2787 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2790 case AL_SAMPLE_OFFSET
:
2791 Offset
= (ALint
)Source
->Offset
;
2795 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2798 Source
->Offset
= -1.0;
2806 * Destroys all sources in the source map.
2808 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2812 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2814 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2815 Context
->SourceMap
.array
[pos
].value
= NULL
;
2817 while(temp
->queue
!= NULL
)
2819 ALbufferlistitem
*BufferList
= temp
->queue
;
2820 temp
->queue
= BufferList
->next
;
2822 if(BufferList
->buffer
!= NULL
)
2823 DecrementRef(&BufferList
->buffer
->ref
);
2827 for(j
= 0;j
< MAX_SENDS
;++j
)
2829 if(temp
->Send
[j
].Slot
)
2830 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2831 temp
->Send
[j
].Slot
= NULL
;
2834 FreeThunkEntry(temp
->id
);
2835 memset(temp
, 0, sizeof(*temp
));