2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
34 #include "alAuxEffectSlot.h"
37 enum Resampler DefaultResampler
= LinearResampler
;
38 const ALsizei ResamplerPadding
[ResamplerMax
] = {
43 const ALsizei ResamplerPrePadding
[ResamplerMax
] = {
50 static ALvoid
InitSourceParams(ALsource
*Source
);
51 static ALint64
GetSourceOffset(const ALsource
*Source
);
52 static ALdouble
GetSourceSecOffset(const ALsource
*Source
);
53 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offsets
, ALdouble updateLen
);
54 static ALint
GetSampleOffset(ALsource
*Source
);
56 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALfloat
*values
);
57 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint
*values
);
58 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint64SOFT
*values
);
60 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALdouble
*values
);
61 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint
*values
);
62 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint64
*values
);
65 #define RETERR(x) do { \
66 alSetError(Context, (x)); \
70 #define CHECKVAL(x) do { \
72 RETERR(AL_INVALID_VALUE); \
75 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALfloat
*values
)
80 CHECKVAL(*values
>= 0.0f
);
82 Source
->Pitch
= *values
;
83 Source
->NeedsUpdate
= AL_TRUE
;
86 case AL_CONE_INNER_ANGLE
:
87 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
89 Source
->InnerAngle
= *values
;
90 Source
->NeedsUpdate
= AL_TRUE
;
93 case AL_CONE_OUTER_ANGLE
:
94 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
96 Source
->OuterAngle
= *values
;
97 Source
->NeedsUpdate
= AL_TRUE
;
101 CHECKVAL(*values
>= 0.0f
);
103 Source
->Gain
= *values
;
104 Source
->NeedsUpdate
= AL_TRUE
;
107 case AL_MAX_DISTANCE
:
108 CHECKVAL(*values
>= 0.0f
);
110 Source
->MaxDistance
= *values
;
111 Source
->NeedsUpdate
= AL_TRUE
;
114 case AL_ROLLOFF_FACTOR
:
115 CHECKVAL(*values
>= 0.0f
);
117 Source
->RollOffFactor
= *values
;
118 Source
->NeedsUpdate
= AL_TRUE
;
121 case AL_REFERENCE_DISTANCE
:
122 CHECKVAL(*values
>= 0.0f
);
124 Source
->RefDistance
= *values
;
125 Source
->NeedsUpdate
= AL_TRUE
;
129 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
131 Source
->MinGain
= *values
;
132 Source
->NeedsUpdate
= AL_TRUE
;
136 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
138 Source
->MaxGain
= *values
;
139 Source
->NeedsUpdate
= AL_TRUE
;
142 case AL_CONE_OUTER_GAIN
:
143 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
145 Source
->OuterGain
= *values
;
146 Source
->NeedsUpdate
= AL_TRUE
;
149 case AL_CONE_OUTER_GAINHF
:
150 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
152 Source
->OuterGainHF
= *values
;
153 Source
->NeedsUpdate
= AL_TRUE
;
156 case AL_AIR_ABSORPTION_FACTOR
:
157 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
159 Source
->AirAbsorptionFactor
= *values
;
160 Source
->NeedsUpdate
= AL_TRUE
;
163 case AL_ROOM_ROLLOFF_FACTOR
:
164 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
166 Source
->RoomRolloffFactor
= *values
;
167 Source
->NeedsUpdate
= AL_TRUE
;
170 case AL_DOPPLER_FACTOR
:
171 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
173 Source
->DopplerFactor
= *values
;
174 Source
->NeedsUpdate
= AL_TRUE
;
178 case AL_SAMPLE_OFFSET
:
180 CHECKVAL(*values
>= 0.0f
);
182 LockContext(Context
);
183 Source
->OffsetType
= name
;
184 Source
->Offset
= *values
;
186 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
187 !Context
->DeferUpdates
)
189 if(ApplyOffset(Source
) == AL_FALSE
)
191 UnlockContext(Context
);
192 RETERR(AL_INVALID_VALUE
);
195 UnlockContext(Context
);
199 case AL_SEC_OFFSET_LATENCY_SOFT
:
201 RETERR(AL_INVALID_OPERATION
);
205 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
207 LockContext(Context
);
208 Source
->Position
[0] = values
[0];
209 Source
->Position
[1] = values
[1];
210 Source
->Position
[2] = values
[2];
211 UnlockContext(Context
);
212 Source
->NeedsUpdate
= AL_TRUE
;
216 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
218 LockContext(Context
);
219 Source
->Velocity
[0] = values
[0];
220 Source
->Velocity
[1] = values
[1];
221 Source
->Velocity
[2] = values
[2];
222 UnlockContext(Context
);
223 Source
->NeedsUpdate
= AL_TRUE
;
227 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
229 LockContext(Context
);
230 Source
->Orientation
[0] = values
[0];
231 Source
->Orientation
[1] = values
[1];
232 Source
->Orientation
[2] = values
[2];
233 UnlockContext(Context
);
234 Source
->NeedsUpdate
= AL_TRUE
;
238 ERR("Unexpected param: 0x%04x\n", name
);
239 RETERR(AL_INVALID_ENUM
);
245 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint
*values
)
247 ALCdevice
*device
= Context
->Device
;
248 ALbuffer
*buffer
= NULL
;
249 ALfilter
*filter
= NULL
;
250 ALeffectslot
*slot
= NULL
;
251 ALbufferlistitem
*oldlist
;
257 case AL_SOURCE_RELATIVE
:
258 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
260 Source
->HeadRelative
= (ALboolean
)*values
;
261 Source
->NeedsUpdate
= AL_TRUE
;
265 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
267 Source
->Looping
= (ALboolean
)*values
;
271 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
273 LockContext(Context
);
274 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
276 UnlockContext(Context
);
277 RETERR(AL_INVALID_OPERATION
);
280 Source
->BuffersInQueue
= 0;
281 Source
->BuffersPlayed
= 0;
285 ALbufferlistitem
*BufferListItem
;
287 /* Source is now Static */
288 Source
->SourceType
= AL_STATIC
;
290 /* Add the selected buffer to a one-item queue */
291 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
292 BufferListItem
->buffer
= buffer
;
293 BufferListItem
->next
= NULL
;
294 BufferListItem
->prev
= NULL
;
295 IncrementRef(&buffer
->ref
);
297 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, BufferListItem
);
298 Source
->BuffersInQueue
= 1;
300 ReadLock(&buffer
->lock
);
301 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
302 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
303 ReadUnlock(&buffer
->lock
);
304 if(buffer
->FmtChannels
== FmtMono
)
305 Source
->Update
= CalcSourceParams
;
307 Source
->Update
= CalcNonAttnSourceParams
;
308 Source
->NeedsUpdate
= AL_TRUE
;
312 /* Source is now Undetermined */
313 Source
->SourceType
= AL_UNDETERMINED
;
314 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, NULL
);
317 /* Delete all elements in the previous queue */
318 while(oldlist
!= NULL
)
320 ALbufferlistitem
*temp
= oldlist
;
321 oldlist
= temp
->next
;
324 DecrementRef(&temp
->buffer
->ref
);
327 UnlockContext(Context
);
330 case AL_SOURCE_STATE
:
332 RETERR(AL_INVALID_OPERATION
);
335 case AL_SAMPLE_OFFSET
:
337 CHECKVAL(*values
>= 0);
339 LockContext(Context
);
340 Source
->OffsetType
= name
;
341 Source
->Offset
= *values
;
343 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
344 !Context
->DeferUpdates
)
346 if(ApplyOffset(Source
) == AL_FALSE
)
348 UnlockContext(Context
);
349 RETERR(AL_INVALID_VALUE
);
352 UnlockContext(Context
);
355 case AL_DIRECT_FILTER
:
356 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
358 LockContext(Context
);
361 Source
->DirectGain
= 1.0f
;
362 Source
->DirectGainHF
= 1.0f
;
366 Source
->DirectGain
= filter
->Gain
;
367 Source
->DirectGainHF
= filter
->GainHF
;
369 UnlockContext(Context
);
370 Source
->NeedsUpdate
= AL_TRUE
;
373 case AL_DIRECT_FILTER_GAINHF_AUTO
:
374 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
376 Source
->DryGainHFAuto
= *values
;
377 Source
->NeedsUpdate
= AL_TRUE
;
380 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
381 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
383 Source
->WetGainAuto
= *values
;
384 Source
->NeedsUpdate
= AL_TRUE
;
387 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
388 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
390 Source
->WetGainHFAuto
= *values
;
391 Source
->NeedsUpdate
= AL_TRUE
;
394 case AL_DIRECT_CHANNELS_SOFT
:
395 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
397 Source
->DirectChannels
= *values
;
398 Source
->NeedsUpdate
= AL_TRUE
;
401 case AL_DISTANCE_MODEL
:
402 CHECKVAL(*values
== AL_NONE
||
403 *values
== AL_INVERSE_DISTANCE
||
404 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
405 *values
== AL_LINEAR_DISTANCE
||
406 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
407 *values
== AL_EXPONENT_DISTANCE
||
408 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
410 Source
->DistanceModel
= *values
;
411 if(Context
->SourceDistanceModel
)
412 Source
->NeedsUpdate
= AL_TRUE
;
416 case AL_AUXILIARY_SEND_FILTER
:
417 LockContext(Context
);
418 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
419 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
420 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
422 UnlockContext(Context
);
423 RETERR(AL_INVALID_VALUE
);
426 /* Add refcount on the new slot, and release the previous slot */
427 if(slot
) IncrementRef(&slot
->ref
);
428 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
429 if(slot
) DecrementRef(&slot
->ref
);
434 Source
->Send
[values
[1]].Gain
= 1.0f
;
435 Source
->Send
[values
[1]].GainHF
= 1.0f
;
439 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
440 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
442 Source
->NeedsUpdate
= AL_TRUE
;
443 UnlockContext(Context
);
447 case AL_MAX_DISTANCE
:
448 case AL_ROLLOFF_FACTOR
:
449 case AL_CONE_INNER_ANGLE
:
450 case AL_CONE_OUTER_ANGLE
:
451 case AL_REFERENCE_DISTANCE
:
452 fvals
[0] = (ALfloat
)*values
;
453 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
460 fvals
[0] = (ALfloat
)values
[0];
461 fvals
[1] = (ALfloat
)values
[1];
462 fvals
[2] = (ALfloat
)values
[2];
463 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
468 ERR("Unexpected param: 0x%04x\n", name
);
469 RETERR(AL_INVALID_ENUM
);
475 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint64SOFT
*values
)
483 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
485 RETERR(AL_INVALID_OPERATION
);
489 case AL_SOURCE_RELATIVE
:
491 case AL_SOURCE_STATE
:
493 case AL_SAMPLE_OFFSET
:
494 case AL_DIRECT_FILTER_GAINHF_AUTO
:
495 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
496 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
497 case AL_DIRECT_CHANNELS_SOFT
:
498 case AL_DISTANCE_MODEL
:
499 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
501 ivals
[0] = (ALint
)*values
;
502 if((err
=SetSourceiv(Source
, Context
, name
, ivals
)))
508 case AL_DIRECT_FILTER
:
509 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
511 ivals
[0] = (ALuint
)*values
;
512 if((err
=SetSourceiv(Source
, Context
, name
, ivals
)))
517 case AL_AUXILIARY_SEND_FILTER
:
518 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
519 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
520 values
[2] <= UINT_MAX
&& values
[2] >= 0);
522 ivals
[0] = (ALuint
)values
[0];
523 ivals
[1] = (ALuint
)values
[1];
524 ivals
[2] = (ALuint
)values
[2];
525 if((err
=SetSourceiv(Source
, Context
, name
, ivals
)))
530 case AL_MAX_DISTANCE
:
531 case AL_ROLLOFF_FACTOR
:
532 case AL_CONE_INNER_ANGLE
:
533 case AL_CONE_OUTER_ANGLE
:
534 case AL_REFERENCE_DISTANCE
:
536 fvals
[0] = (ALfloat
)*values
;
537 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
545 fvals
[0] = (ALfloat
)values
[0];
546 fvals
[1] = (ALfloat
)values
[1];
547 fvals
[2] = (ALfloat
)values
[2];
548 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
553 ERR("Unexpected param: 0x%04x\n", name
);
554 RETERR(AL_INVALID_ENUM
);
563 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALdouble
*values
)
573 *values
= Source
->Gain
;
577 *values
= Source
->Pitch
;
580 case AL_MAX_DISTANCE
:
581 *values
= Source
->MaxDistance
;
584 case AL_ROLLOFF_FACTOR
:
585 *values
= Source
->RollOffFactor
;
588 case AL_REFERENCE_DISTANCE
:
589 *values
= Source
->RefDistance
;
592 case AL_CONE_INNER_ANGLE
:
593 *values
= Source
->InnerAngle
;
596 case AL_CONE_OUTER_ANGLE
:
597 *values
= Source
->OuterAngle
;
601 *values
= Source
->MinGain
;
605 *values
= Source
->MaxGain
;
608 case AL_CONE_OUTER_GAIN
:
609 *values
= Source
->OuterGain
;
613 case AL_SAMPLE_OFFSET
:
615 LockContext(Context
);
616 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
617 Context
->Device
->Frequency
;
618 GetSourceOffsets(Source
, name
, offsets
, updateLen
);
619 UnlockContext(Context
);
620 *values
= offsets
[0];
623 case AL_CONE_OUTER_GAINHF
:
624 *values
= Source
->OuterGainHF
;
627 case AL_AIR_ABSORPTION_FACTOR
:
628 *values
= Source
->AirAbsorptionFactor
;
631 case AL_ROOM_ROLLOFF_FACTOR
:
632 *values
= Source
->RoomRolloffFactor
;
635 case AL_DOPPLER_FACTOR
:
636 *values
= Source
->DopplerFactor
;
639 case AL_SAMPLE_RW_OFFSETS_SOFT
:
640 case AL_BYTE_RW_OFFSETS_SOFT
:
641 LockContext(Context
);
642 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
643 Context
->Device
->Frequency
;
644 GetSourceOffsets(Source
, name
, values
, updateLen
);
645 UnlockContext(Context
);
648 case AL_SEC_OFFSET_LATENCY_SOFT
:
649 LockContext(Context
);
650 values
[0] = GetSourceSecOffset(Source
);
651 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
653 UnlockContext(Context
);
657 LockContext(Context
);
658 values
[0] = Source
->Position
[0];
659 values
[1] = Source
->Position
[1];
660 values
[2] = Source
->Position
[2];
661 UnlockContext(Context
);
665 LockContext(Context
);
666 values
[0] = Source
->Velocity
[0];
667 values
[1] = Source
->Velocity
[1];
668 values
[2] = Source
->Velocity
[2];
669 UnlockContext(Context
);
673 LockContext(Context
);
674 values
[0] = Source
->Orientation
[0];
675 values
[1] = Source
->Orientation
[1];
676 values
[2] = Source
->Orientation
[2];
677 UnlockContext(Context
);
680 case AL_SOURCE_RELATIVE
:
683 case AL_SOURCE_STATE
:
684 case AL_BUFFERS_QUEUED
:
685 case AL_BUFFERS_PROCESSED
:
687 case AL_DIRECT_FILTER_GAINHF_AUTO
:
688 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
689 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
690 case AL_DIRECT_CHANNELS_SOFT
:
691 case AL_DISTANCE_MODEL
:
692 if((err
=GetSourceiv(Source
, Context
, name
, ivals
)) != AL_NO_ERROR
)
694 *values
= (ALdouble
)ivals
[0];
698 ERR("Unexpected param: 0x%04x\n", name
);
699 RETERR(AL_INVALID_ENUM
);
705 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint
*values
)
707 ALbufferlistitem
*BufferList
;
713 case AL_SOURCE_RELATIVE
:
714 *values
= Source
->HeadRelative
;
718 *values
= Source
->Looping
;
722 LockContext(Context
);
723 BufferList
= Source
->queue
;
724 if(Source
->SourceType
!= AL_STATIC
)
726 ALuint i
= Source
->BuffersPlayed
;
729 BufferList
= BufferList
->next
;
733 *values
= ((BufferList
&& BufferList
->buffer
) ?
734 BufferList
->buffer
->id
: 0);
735 UnlockContext(Context
);
738 case AL_SOURCE_STATE
:
739 *values
= Source
->state
;
742 case AL_BUFFERS_QUEUED
:
743 *values
= Source
->BuffersInQueue
;
746 case AL_BUFFERS_PROCESSED
:
747 LockContext(Context
);
748 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
750 /* Buffers on a looping source are in a perpetual state of
751 * PENDING, so don't report any as PROCESSED */
755 *values
= Source
->BuffersPlayed
;
756 UnlockContext(Context
);
760 *values
= Source
->SourceType
;
763 case AL_DIRECT_FILTER_GAINHF_AUTO
:
764 *values
= Source
->DryGainHFAuto
;
767 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
768 *values
= Source
->WetGainAuto
;
771 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
772 *values
= Source
->WetGainHFAuto
;
775 case AL_DIRECT_CHANNELS_SOFT
:
776 *values
= Source
->DirectChannels
;
779 case AL_DISTANCE_MODEL
:
780 *values
= Source
->DistanceModel
;
783 case AL_MAX_DISTANCE
:
784 case AL_ROLLOFF_FACTOR
:
785 case AL_REFERENCE_DISTANCE
:
786 case AL_CONE_INNER_ANGLE
:
787 case AL_CONE_OUTER_ANGLE
:
789 case AL_SAMPLE_OFFSET
:
791 case AL_DOPPLER_FACTOR
:
792 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
794 *values
= (ALint
)dvals
[0];
797 case AL_SAMPLE_RW_OFFSETS_SOFT
:
798 case AL_BYTE_RW_OFFSETS_SOFT
:
799 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
801 values
[0] = (ALint
)dvals
[0];
802 values
[1] = (ALint
)dvals
[1];
808 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
810 values
[0] = (ALint
)dvals
[0];
811 values
[1] = (ALint
)dvals
[1];
812 values
[2] = (ALint
)dvals
[2];
816 ERR("Unexpected param: 0x%04x\n", name
);
817 RETERR(AL_INVALID_ENUM
);
823 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint64
*values
)
831 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
832 LockContext(Context
);
833 values
[0] = GetSourceOffset(Source
);
834 values
[1] = ALCdevice_GetLatency(Context
->Device
);
835 UnlockContext(Context
);
838 case AL_MAX_DISTANCE
:
839 case AL_ROLLOFF_FACTOR
:
840 case AL_REFERENCE_DISTANCE
:
841 case AL_CONE_INNER_ANGLE
:
842 case AL_CONE_OUTER_ANGLE
:
844 case AL_SAMPLE_OFFSET
:
846 case AL_DOPPLER_FACTOR
:
847 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
849 *values
= (ALint64
)dvals
[0];
852 case AL_SAMPLE_RW_OFFSETS_SOFT
:
853 case AL_BYTE_RW_OFFSETS_SOFT
:
854 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
856 values
[0] = (ALint64
)dvals
[0];
857 values
[1] = (ALint64
)dvals
[1];
863 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
865 values
[0] = (ALint64
)dvals
[0];
866 values
[1] = (ALint64
)dvals
[1];
867 values
[2] = (ALint64
)dvals
[2];
870 case AL_SOURCE_RELATIVE
:
873 case AL_SOURCE_STATE
:
874 case AL_BUFFERS_QUEUED
:
875 case AL_BUFFERS_PROCESSED
:
877 case AL_DIRECT_FILTER_GAINHF_AUTO
:
878 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
879 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
880 case AL_DIRECT_CHANNELS_SOFT
:
881 case AL_DISTANCE_MODEL
:
882 if((err
=GetSourceiv(Source
, Context
, name
, ivals
)) != AL_NO_ERROR
)
888 ERR("Unexpected param: 0x%04x\n", name
);
889 RETERR(AL_INVALID_ENUM
);
898 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
903 Context
= GetContextRef();
910 CHECK_VALUE(Context
, n
>= 0);
911 for(cur
= 0;cur
< n
;cur
++)
913 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
915 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
916 InitSourceParams(source
);
918 err
= NewThunkEntry(&source
->id
);
919 if(err
== AL_NO_ERROR
)
920 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->id
, source
);
921 if(err
!= AL_NO_ERROR
)
923 FreeThunkEntry(source
->id
);
924 memset(source
, 0, sizeof(ALsource
));
927 al_throwerr(Context
, err
);
930 sources
[cur
] = source
->id
;
936 alDeleteSources(cur
, sources
);
940 ALCcontext_DecRef(Context
);
944 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
948 Context
= GetContextRef();
953 ALbufferlistitem
*BufferList
;
957 CHECK_VALUE(Context
, n
>= 0);
959 /* Check that all Sources are valid */
962 if(LookupSource(Context
, sources
[i
]) == NULL
)
963 al_throwerr(Context
, AL_INVALID_NAME
);
968 ALsource
**srclist
, **srclistend
;
970 if((Source
=RemoveSource(Context
, sources
[i
])) == NULL
)
972 FreeThunkEntry(Source
->id
);
974 LockContext(Context
);
975 srclist
= Context
->ActiveSources
;
976 srclistend
= srclist
+ Context
->ActiveSourceCount
;
977 while(srclist
!= srclistend
)
979 if(*srclist
== Source
)
981 Context
->ActiveSourceCount
--;
982 *srclist
= *(--srclistend
);
987 UnlockContext(Context
);
989 while(Source
->queue
!= NULL
)
991 BufferList
= Source
->queue
;
992 Source
->queue
= BufferList
->next
;
994 if(BufferList
->buffer
!= NULL
)
995 DecrementRef(&BufferList
->buffer
->ref
);
999 for(j
= 0;j
< MAX_SENDS
;++j
)
1001 if(Source
->Send
[j
].Slot
)
1002 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
1003 Source
->Send
[j
].Slot
= NULL
;
1006 memset(Source
, 0, sizeof(*Source
));
1012 ALCcontext_DecRef(Context
);
1016 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1018 ALCcontext
*Context
;
1021 Context
= GetContextRef();
1022 if(!Context
) return AL_FALSE
;
1024 result
= (LookupSource(Context
, source
) ? AL_TRUE
: AL_FALSE
);
1026 ALCcontext_DecRef(Context
);
1032 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1034 ALCcontext
*Context
;
1037 Context
= GetContextRef();
1038 if(!Context
) return;
1040 if((Source
=LookupSource(Context
, source
)) == NULL
)
1041 alSetError(Context
, AL_INVALID_NAME
);
1045 case AL_CONE_INNER_ANGLE
:
1046 case AL_CONE_OUTER_ANGLE
:
1048 case AL_MAX_DISTANCE
:
1049 case AL_ROLLOFF_FACTOR
:
1050 case AL_REFERENCE_DISTANCE
:
1053 case AL_CONE_OUTER_GAIN
:
1054 case AL_CONE_OUTER_GAINHF
:
1055 case AL_AIR_ABSORPTION_FACTOR
:
1056 case AL_ROOM_ROLLOFF_FACTOR
:
1057 case AL_DOPPLER_FACTOR
:
1059 case AL_SAMPLE_OFFSET
:
1060 case AL_BYTE_OFFSET
:
1061 SetSourcefv(Source
, Context
, param
, &value
);
1065 alSetError(Context
, AL_INVALID_ENUM
);
1068 ALCcontext_DecRef(Context
);
1071 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1073 ALCcontext
*Context
;
1077 Context
= GetContextRef();
1078 if(!Context
) return;
1080 if((Source
=LookupSource(Context
, source
)) == NULL
)
1081 alSetError(Context
, AL_INVALID_NAME
);
1090 SetSourcefv(Source
, Context
, param
, fvals
);
1094 alSetError(Context
, AL_INVALID_ENUM
);
1097 ALCcontext_DecRef(Context
);
1100 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1102 ALCcontext
*Context
;
1105 Context
= GetContextRef();
1106 if(!Context
) return;
1108 if((Source
=LookupSource(Context
, source
)) == NULL
)
1109 alSetError(Context
, AL_INVALID_NAME
);
1111 alSetError(Context
, AL_INVALID_VALUE
);
1115 case AL_CONE_INNER_ANGLE
:
1116 case AL_CONE_OUTER_ANGLE
:
1118 case AL_MAX_DISTANCE
:
1119 case AL_ROLLOFF_FACTOR
:
1120 case AL_REFERENCE_DISTANCE
:
1123 case AL_CONE_OUTER_GAIN
:
1124 case AL_CONE_OUTER_GAINHF
:
1126 case AL_SAMPLE_OFFSET
:
1127 case AL_BYTE_OFFSET
:
1128 case AL_AIR_ABSORPTION_FACTOR
:
1129 case AL_ROOM_ROLLOFF_FACTOR
:
1134 SetSourcefv(Source
, Context
, param
, values
);
1138 alSetError(Context
, AL_INVALID_ENUM
);
1141 ALCcontext_DecRef(Context
);
1145 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1147 ALCcontext
*Context
;
1151 Context
= GetContextRef();
1152 if(!Context
) return;
1154 if((Source
=LookupSource(Context
, source
)) == NULL
)
1155 alSetError(Context
, AL_INVALID_NAME
);
1159 case AL_CONE_INNER_ANGLE
:
1160 case AL_CONE_OUTER_ANGLE
:
1162 case AL_MAX_DISTANCE
:
1163 case AL_ROLLOFF_FACTOR
:
1164 case AL_REFERENCE_DISTANCE
:
1167 case AL_CONE_OUTER_GAIN
:
1168 case AL_CONE_OUTER_GAINHF
:
1169 case AL_AIR_ABSORPTION_FACTOR
:
1170 case AL_ROOM_ROLLOFF_FACTOR
:
1171 case AL_DOPPLER_FACTOR
:
1173 case AL_SAMPLE_OFFSET
:
1174 case AL_BYTE_OFFSET
:
1175 fval
= (ALfloat
)value
;
1176 SetSourcefv(Source
, Context
, param
, &fval
);
1180 alSetError(Context
, AL_INVALID_ENUM
);
1183 ALCcontext_DecRef(Context
);
1186 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1188 ALCcontext
*Context
;
1192 Context
= GetContextRef();
1193 if(!Context
) return;
1195 if((Source
=LookupSource(Context
, source
)) == NULL
)
1196 alSetError(Context
, AL_INVALID_NAME
);
1202 fvals
[0] = (ALfloat
)value1
;
1203 fvals
[1] = (ALfloat
)value2
;
1204 fvals
[2] = (ALfloat
)value3
;
1205 SetSourcefv(Source
, Context
, param
, fvals
);
1209 alSetError(Context
, AL_INVALID_ENUM
);
1212 ALCcontext_DecRef(Context
);
1215 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1217 ALCcontext
*Context
;
1221 Context
= GetContextRef();
1222 if(!Context
) return;
1224 if((Source
=LookupSource(Context
, source
)) == NULL
)
1225 alSetError(Context
, AL_INVALID_NAME
);
1227 alSetError(Context
, AL_INVALID_VALUE
);
1231 case AL_CONE_INNER_ANGLE
:
1232 case AL_CONE_OUTER_ANGLE
:
1234 case AL_MAX_DISTANCE
:
1235 case AL_ROLLOFF_FACTOR
:
1236 case AL_REFERENCE_DISTANCE
:
1239 case AL_CONE_OUTER_GAIN
:
1240 case AL_CONE_OUTER_GAINHF
:
1242 case AL_SAMPLE_OFFSET
:
1243 case AL_BYTE_OFFSET
:
1244 case AL_AIR_ABSORPTION_FACTOR
:
1245 case AL_ROOM_ROLLOFF_FACTOR
:
1246 fvals
[0] = (ALfloat
)values
[0];
1247 SetSourcefv(Source
, Context
, param
, fvals
);
1250 case AL_SEC_OFFSET_LATENCY_SOFT
:
1251 fvals
[0] = (ALfloat
)values
[0];
1252 fvals
[1] = (ALfloat
)values
[1];
1253 SetSourcefv(Source
, Context
, param
, fvals
);
1259 fvals
[0] = (ALfloat
)values
[0];
1260 fvals
[1] = (ALfloat
)values
[1];
1261 fvals
[2] = (ALfloat
)values
[2];
1262 SetSourcefv(Source
, Context
, param
, fvals
);
1266 alSetError(Context
, AL_INVALID_ENUM
);
1269 ALCcontext_DecRef(Context
);
1273 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1275 ALCcontext
*Context
;
1278 Context
= GetContextRef();
1279 if(!Context
) return;
1281 if((Source
=LookupSource(Context
, source
)) == NULL
)
1282 alSetError(Context
, AL_INVALID_NAME
);
1285 case AL_MAX_DISTANCE
:
1286 case AL_ROLLOFF_FACTOR
:
1287 case AL_CONE_INNER_ANGLE
:
1288 case AL_CONE_OUTER_ANGLE
:
1289 case AL_REFERENCE_DISTANCE
:
1290 case AL_SOURCE_RELATIVE
:
1293 case AL_SOURCE_STATE
:
1295 case AL_SAMPLE_OFFSET
:
1296 case AL_BYTE_OFFSET
:
1297 case AL_DIRECT_FILTER
:
1298 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1299 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1300 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1301 case AL_DIRECT_CHANNELS_SOFT
:
1302 case AL_DISTANCE_MODEL
:
1303 SetSourceiv(Source
, Context
, param
, &value
);
1307 alSetError(Context
, AL_INVALID_ENUM
);
1310 ALCcontext_DecRef(Context
);
1313 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1315 ALCcontext
*Context
;
1319 Context
= GetContextRef();
1320 if(!Context
) return;
1322 if((Source
=LookupSource(Context
, source
)) == NULL
)
1323 alSetError(Context
, AL_INVALID_NAME
);
1329 case AL_AUXILIARY_SEND_FILTER
:
1333 SetSourceiv(Source
, Context
, param
, ivals
);
1337 alSetError(Context
, AL_INVALID_ENUM
);
1340 ALCcontext_DecRef(Context
);
1343 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1345 ALCcontext
*Context
;
1348 Context
= GetContextRef();
1349 if(!Context
) return;
1351 if((Source
=LookupSource(Context
, source
)) == NULL
)
1352 alSetError(Context
, AL_INVALID_NAME
);
1354 alSetError(Context
, AL_INVALID_VALUE
);
1357 case AL_SOURCE_RELATIVE
:
1358 case AL_CONE_INNER_ANGLE
:
1359 case AL_CONE_OUTER_ANGLE
:
1362 case AL_SOURCE_STATE
:
1364 case AL_SAMPLE_OFFSET
:
1365 case AL_BYTE_OFFSET
:
1366 case AL_MAX_DISTANCE
:
1367 case AL_ROLLOFF_FACTOR
:
1368 case AL_REFERENCE_DISTANCE
:
1369 case AL_DIRECT_FILTER
:
1370 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1371 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1372 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1373 case AL_DISTANCE_MODEL
:
1374 case AL_DIRECT_CHANNELS_SOFT
:
1379 case AL_AUXILIARY_SEND_FILTER
:
1380 SetSourceiv(Source
, Context
, param
, values
);
1384 alSetError(Context
, AL_INVALID_ENUM
);
1387 ALCcontext_DecRef(Context
);
1391 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1393 ALCcontext
*Context
;
1396 Context
= GetContextRef();
1397 if(!Context
) return;
1399 if((Source
=LookupSource(Context
, source
)) == NULL
)
1400 alSetError(Context
, AL_INVALID_NAME
);
1403 case AL_MAX_DISTANCE
:
1404 case AL_ROLLOFF_FACTOR
:
1405 case AL_CONE_INNER_ANGLE
:
1406 case AL_CONE_OUTER_ANGLE
:
1407 case AL_REFERENCE_DISTANCE
:
1408 case AL_SOURCE_RELATIVE
:
1410 case AL_SOURCE_STATE
:
1412 case AL_SAMPLE_OFFSET
:
1413 case AL_BYTE_OFFSET
:
1414 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1415 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1416 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1417 case AL_DIRECT_CHANNELS_SOFT
:
1418 case AL_DISTANCE_MODEL
:
1420 case AL_DIRECT_FILTER
:
1421 SetSourcei64v(Source
, Context
, param
, &value
);
1425 alSetError(Context
, AL_INVALID_ENUM
);
1428 ALCcontext_DecRef(Context
);
1431 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1433 ALCcontext
*Context
;
1435 ALint64SOFT i64vals
[3];
1437 Context
= GetContextRef();
1438 if(!Context
) return;
1440 if((Source
=LookupSource(Context
, source
)) == NULL
)
1441 alSetError(Context
, AL_INVALID_NAME
);
1447 case AL_AUXILIARY_SEND_FILTER
:
1448 i64vals
[0] = value1
;
1449 i64vals
[1] = value2
;
1450 i64vals
[2] = value3
;
1451 SetSourcei64v(Source
, Context
, param
, i64vals
);
1455 alSetError(Context
, AL_INVALID_ENUM
);
1458 ALCcontext_DecRef(Context
);
1461 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1463 ALCcontext
*Context
;
1466 Context
= GetContextRef();
1467 if(!Context
) return;
1469 if((Source
=LookupSource(Context
, source
)) == NULL
)
1470 alSetError(Context
, AL_INVALID_NAME
);
1472 alSetError(Context
, AL_INVALID_VALUE
);
1475 case AL_SOURCE_RELATIVE
:
1476 case AL_CONE_INNER_ANGLE
:
1477 case AL_CONE_OUTER_ANGLE
:
1479 case AL_SOURCE_STATE
:
1481 case AL_SAMPLE_OFFSET
:
1482 case AL_BYTE_OFFSET
:
1483 case AL_MAX_DISTANCE
:
1484 case AL_ROLLOFF_FACTOR
:
1485 case AL_REFERENCE_DISTANCE
:
1486 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1487 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1488 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1489 case AL_DISTANCE_MODEL
:
1490 case AL_DIRECT_CHANNELS_SOFT
:
1492 case AL_DIRECT_FILTER
:
1494 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1499 case AL_AUXILIARY_SEND_FILTER
:
1500 SetSourcei64v(Source
, Context
, param
, values
);
1504 alSetError(Context
, AL_INVALID_ENUM
);
1507 ALCcontext_DecRef(Context
);
1511 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1513 ALCcontext
*Context
;
1517 Context
= GetContextRef();
1518 if(!Context
) return;
1520 if((Source
=LookupSource(Context
, source
)) == NULL
)
1521 alSetError(Context
, AL_INVALID_NAME
);
1523 alSetError(Context
, AL_INVALID_VALUE
);
1530 case AL_MAX_DISTANCE
:
1531 case AL_ROLLOFF_FACTOR
:
1532 case AL_CONE_OUTER_GAIN
:
1533 case AL_CONE_OUTER_GAINHF
:
1535 case AL_SAMPLE_OFFSET
:
1536 case AL_BYTE_OFFSET
:
1537 case AL_CONE_INNER_ANGLE
:
1538 case AL_CONE_OUTER_ANGLE
:
1539 case AL_REFERENCE_DISTANCE
:
1540 case AL_AIR_ABSORPTION_FACTOR
:
1541 case AL_ROOM_ROLLOFF_FACTOR
:
1542 case AL_DOPPLER_FACTOR
:
1543 if(GetSourcedv(Source
, Context
, param
, &dval
) == AL_NO_ERROR
)
1544 *value
= (ALfloat
)dval
;
1548 alSetError(Context
, AL_INVALID_ENUM
);
1551 ALCcontext_DecRef(Context
);
1555 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1557 ALCcontext
*Context
;
1561 Context
= GetContextRef();
1562 if(!Context
) return;
1564 if((Source
=LookupSource(Context
, source
)) == NULL
)
1565 alSetError(Context
, AL_INVALID_NAME
);
1566 else if(!(value1
&& value2
&& value3
))
1567 alSetError(Context
, AL_INVALID_VALUE
);
1573 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1575 *value1
= (ALfloat
)dvals
[0];
1576 *value2
= (ALfloat
)dvals
[1];
1577 *value3
= (ALfloat
)dvals
[2];
1582 alSetError(Context
, AL_INVALID_ENUM
);
1585 ALCcontext_DecRef(Context
);
1589 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1591 ALCcontext
*Context
;
1601 case AL_MAX_DISTANCE
:
1602 case AL_ROLLOFF_FACTOR
:
1603 case AL_DOPPLER_FACTOR
:
1604 case AL_CONE_OUTER_GAIN
:
1606 case AL_SAMPLE_OFFSET
:
1607 case AL_BYTE_OFFSET
:
1608 case AL_CONE_INNER_ANGLE
:
1609 case AL_CONE_OUTER_ANGLE
:
1610 case AL_REFERENCE_DISTANCE
:
1611 case AL_CONE_OUTER_GAINHF
:
1612 case AL_AIR_ABSORPTION_FACTOR
:
1613 case AL_ROOM_ROLLOFF_FACTOR
:
1614 alGetSourcef(source
, param
, values
);
1620 alGetSource3f(source
, param
, values
+0, values
+1, values
+2);
1624 Context
= GetContextRef();
1625 if(!Context
) return;
1627 if((Source
=LookupSource(Context
, source
)) == NULL
)
1628 alSetError(Context
, AL_INVALID_NAME
);
1630 alSetError(Context
, AL_INVALID_VALUE
);
1633 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1634 case AL_BYTE_RW_OFFSETS_SOFT
:
1635 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1637 values
[0] = (ALfloat
)dvals
[0];
1638 values
[1] = (ALfloat
)dvals
[1];
1643 alSetError(Context
, AL_INVALID_ENUM
);
1646 ALCcontext_DecRef(Context
);
1650 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1652 ALCcontext
*Context
;
1655 Context
= GetContextRef();
1656 if(!Context
) return;
1658 if((Source
=LookupSource(Context
, source
)) == NULL
)
1659 alSetError(Context
, AL_INVALID_NAME
);
1661 alSetError(Context
, AL_INVALID_VALUE
);
1668 case AL_MAX_DISTANCE
:
1669 case AL_ROLLOFF_FACTOR
:
1670 case AL_CONE_OUTER_GAIN
:
1671 case AL_CONE_OUTER_GAINHF
:
1673 case AL_SAMPLE_OFFSET
:
1674 case AL_BYTE_OFFSET
:
1675 case AL_CONE_INNER_ANGLE
:
1676 case AL_CONE_OUTER_ANGLE
:
1677 case AL_REFERENCE_DISTANCE
:
1678 case AL_AIR_ABSORPTION_FACTOR
:
1679 case AL_ROOM_ROLLOFF_FACTOR
:
1680 case AL_DOPPLER_FACTOR
:
1681 GetSourcedv(Source
, Context
, param
, value
);
1685 alSetError(Context
, AL_INVALID_ENUM
);
1688 ALCcontext_DecRef(Context
);
1691 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1693 ALCcontext
*Context
;
1697 Context
= GetContextRef();
1698 if(!Context
) return;
1700 if((Source
=LookupSource(Context
, source
)) == NULL
)
1701 alSetError(Context
, AL_INVALID_NAME
);
1702 else if(!(value1
&& value2
&& value3
))
1703 alSetError(Context
, AL_INVALID_VALUE
);
1709 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1718 alSetError(Context
, AL_INVALID_ENUM
);
1721 ALCcontext_DecRef(Context
);
1724 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1726 ALCcontext
*Context
;
1729 Context
= GetContextRef();
1730 if(!Context
) return;
1732 if((Source
=LookupSource(Context
, source
)) == NULL
)
1733 alSetError(Context
, AL_INVALID_NAME
);
1735 alSetError(Context
, AL_INVALID_VALUE
);
1742 case AL_MAX_DISTANCE
:
1743 case AL_ROLLOFF_FACTOR
:
1744 case AL_DOPPLER_FACTOR
:
1745 case AL_CONE_OUTER_GAIN
:
1747 case AL_SAMPLE_OFFSET
:
1748 case AL_BYTE_OFFSET
:
1749 case AL_CONE_INNER_ANGLE
:
1750 case AL_CONE_OUTER_ANGLE
:
1751 case AL_REFERENCE_DISTANCE
:
1752 case AL_CONE_OUTER_GAINHF
:
1753 case AL_AIR_ABSORPTION_FACTOR
:
1754 case AL_ROOM_ROLLOFF_FACTOR
:
1756 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1757 case AL_BYTE_RW_OFFSETS_SOFT
:
1758 case AL_SEC_OFFSET_LATENCY_SOFT
:
1763 GetSourcedv(Source
, Context
, param
, values
);
1767 alSetError(Context
, AL_INVALID_ENUM
);
1770 ALCcontext_DecRef(Context
);
1774 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1776 ALCcontext
*Context
;
1779 Context
= GetContextRef();
1780 if(!Context
) return;
1782 if((Source
=LookupSource(Context
, source
)) == NULL
)
1783 alSetError(Context
, AL_INVALID_NAME
);
1785 alSetError(Context
, AL_INVALID_VALUE
);
1788 case AL_MAX_DISTANCE
:
1789 case AL_ROLLOFF_FACTOR
:
1790 case AL_REFERENCE_DISTANCE
:
1791 case AL_SOURCE_RELATIVE
:
1792 case AL_CONE_INNER_ANGLE
:
1793 case AL_CONE_OUTER_ANGLE
:
1796 case AL_SOURCE_STATE
:
1797 case AL_BUFFERS_QUEUED
:
1798 case AL_BUFFERS_PROCESSED
:
1799 case AL_SOURCE_TYPE
:
1801 case AL_SAMPLE_OFFSET
:
1802 case AL_BYTE_OFFSET
:
1803 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1804 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1805 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1806 case AL_DOPPLER_FACTOR
:
1807 case AL_DIRECT_CHANNELS_SOFT
:
1808 case AL_DISTANCE_MODEL
:
1809 GetSourceiv(Source
, Context
, param
, value
);
1813 alSetError(Context
, AL_INVALID_ENUM
);
1816 ALCcontext_DecRef(Context
);
1820 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1822 ALCcontext
*Context
;
1826 Context
= GetContextRef();
1827 if(!Context
) return;
1829 if((Source
=LookupSource(Context
, source
)) == NULL
)
1830 alSetError(Context
, AL_INVALID_NAME
);
1831 else if(!(value1
&& value2
&& value3
))
1832 alSetError(Context
, AL_INVALID_VALUE
);
1838 if(GetSourceiv(Source
, Context
, param
, ivals
) == AL_NO_ERROR
)
1847 alSetError(Context
, AL_INVALID_ENUM
);
1850 ALCcontext_DecRef(Context
);
1854 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1856 ALCcontext
*Context
;
1859 Context
= GetContextRef();
1860 if(!Context
) return;
1862 if((Source
=LookupSource(Context
, source
)) == NULL
)
1863 alSetError(Context
, AL_INVALID_NAME
);
1865 alSetError(Context
, AL_INVALID_VALUE
);
1868 case AL_SOURCE_RELATIVE
:
1869 case AL_CONE_INNER_ANGLE
:
1870 case AL_CONE_OUTER_ANGLE
:
1873 case AL_SOURCE_STATE
:
1874 case AL_BUFFERS_QUEUED
:
1875 case AL_BUFFERS_PROCESSED
:
1877 case AL_SAMPLE_OFFSET
:
1878 case AL_BYTE_OFFSET
:
1879 case AL_MAX_DISTANCE
:
1880 case AL_ROLLOFF_FACTOR
:
1881 case AL_DOPPLER_FACTOR
:
1882 case AL_REFERENCE_DISTANCE
:
1883 case AL_SOURCE_TYPE
:
1884 case AL_DIRECT_FILTER
:
1885 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1886 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1887 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1888 case AL_DISTANCE_MODEL
:
1889 case AL_DIRECT_CHANNELS_SOFT
:
1891 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1892 case AL_BYTE_RW_OFFSETS_SOFT
:
1897 GetSourceiv(Source
, Context
, param
, values
);
1901 alSetError(Context
, AL_INVALID_ENUM
);
1904 ALCcontext_DecRef(Context
);
1908 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
1910 ALCcontext
*Context
;
1913 Context
= GetContextRef();
1914 if(!Context
) return;
1916 if((Source
=LookupSource(Context
, source
)) == NULL
)
1917 alSetError(Context
, AL_INVALID_NAME
);
1919 alSetError(Context
, AL_INVALID_VALUE
);
1922 case AL_MAX_DISTANCE
:
1923 case AL_ROLLOFF_FACTOR
:
1924 case AL_REFERENCE_DISTANCE
:
1925 case AL_SOURCE_RELATIVE
:
1926 case AL_CONE_INNER_ANGLE
:
1927 case AL_CONE_OUTER_ANGLE
:
1930 case AL_SOURCE_STATE
:
1931 case AL_BUFFERS_QUEUED
:
1932 case AL_BUFFERS_PROCESSED
:
1933 case AL_SOURCE_TYPE
:
1935 case AL_SAMPLE_OFFSET
:
1936 case AL_BYTE_OFFSET
:
1937 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1938 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1939 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1940 case AL_DOPPLER_FACTOR
:
1941 case AL_DIRECT_CHANNELS_SOFT
:
1942 case AL_DISTANCE_MODEL
:
1943 GetSourcei64v(Source
, Context
, param
, value
);
1947 alSetError(Context
, AL_INVALID_ENUM
);
1950 ALCcontext_DecRef(Context
);
1953 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
1955 ALCcontext
*Context
;
1959 Context
= GetContextRef();
1960 if(!Context
) return;
1962 if((Source
=LookupSource(Context
, source
)) == NULL
)
1963 alSetError(Context
, AL_INVALID_NAME
);
1964 else if(!(value1
&& value2
&& value3
))
1965 alSetError(Context
, AL_INVALID_VALUE
);
1971 if(GetSourcei64v(Source
, Context
, param
, i64vals
) == AL_NO_ERROR
)
1973 *value1
= i64vals
[0];
1974 *value2
= i64vals
[1];
1975 *value3
= i64vals
[2];
1980 alSetError(Context
, AL_INVALID_ENUM
);
1983 ALCcontext_DecRef(Context
);
1986 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
1988 ALCcontext
*Context
;
1991 Context
= GetContextRef();
1992 if(!Context
) return;
1994 if((Source
=LookupSource(Context
, source
)) == NULL
)
1995 alSetError(Context
, AL_INVALID_NAME
);
1997 alSetError(Context
, AL_INVALID_VALUE
);
2000 case AL_MAX_DISTANCE
:
2001 case AL_ROLLOFF_FACTOR
:
2002 case AL_REFERENCE_DISTANCE
:
2003 case AL_SOURCE_RELATIVE
:
2004 case AL_CONE_INNER_ANGLE
:
2005 case AL_CONE_OUTER_ANGLE
:
2008 case AL_SOURCE_STATE
:
2009 case AL_BUFFERS_QUEUED
:
2010 case AL_BUFFERS_PROCESSED
:
2011 case AL_SOURCE_TYPE
:
2013 case AL_SAMPLE_OFFSET
:
2014 case AL_BYTE_OFFSET
:
2015 case AL_DIRECT_FILTER_GAINHF_AUTO
:
2016 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
2017 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
2018 case AL_DOPPLER_FACTOR
:
2019 case AL_DIRECT_CHANNELS_SOFT
:
2020 case AL_DISTANCE_MODEL
:
2022 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2023 case AL_BYTE_RW_OFFSETS_SOFT
:
2024 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
2029 GetSourcei64v(Source
, Context
, param
, values
);
2033 alSetError(Context
, AL_INVALID_ENUM
);
2036 ALCcontext_DecRef(Context
);
2040 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
2042 alSourcePlayv(1, &source
);
2044 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2046 ALCcontext
*Context
;
2050 Context
= GetContextRef();
2051 if(!Context
) return;
2055 CHECK_VALUE(Context
, n
>= 0);
2056 for(i
= 0;i
< n
;i
++)
2058 if(!LookupSource(Context
, sources
[i
]))
2059 al_throwerr(Context
, AL_INVALID_NAME
);
2062 LockContext(Context
);
2063 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
2068 newcount
= Context
->MaxActiveSources
<< 1;
2070 temp
= realloc(Context
->ActiveSources
,
2071 sizeof(*Context
->ActiveSources
) * newcount
);
2074 UnlockContext(Context
);
2075 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
2078 Context
->ActiveSources
= temp
;
2079 Context
->MaxActiveSources
= newcount
;
2082 for(i
= 0;i
< n
;i
++)
2084 Source
= LookupSource(Context
, sources
[i
]);
2085 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
2086 else SetSourceState(Source
, Context
, AL_PLAYING
);
2088 UnlockContext(Context
);
2092 ALCcontext_DecRef(Context
);
2095 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2097 alSourcePausev(1, &source
);
2099 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2101 ALCcontext
*Context
;
2105 Context
= GetContextRef();
2106 if(!Context
) return;
2110 CHECK_VALUE(Context
, n
>= 0);
2111 for(i
= 0;i
< n
;i
++)
2113 if(!LookupSource(Context
, sources
[i
]))
2114 al_throwerr(Context
, AL_INVALID_NAME
);
2117 LockContext(Context
);
2118 for(i
= 0;i
< n
;i
++)
2120 Source
= LookupSource(Context
, sources
[i
]);
2121 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
2122 else SetSourceState(Source
, Context
, AL_PAUSED
);
2124 UnlockContext(Context
);
2128 ALCcontext_DecRef(Context
);
2131 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2133 alSourceStopv(1, &source
);
2135 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2137 ALCcontext
*Context
;
2141 Context
= GetContextRef();
2142 if(!Context
) return;
2146 CHECK_VALUE(Context
, n
>= 0);
2147 for(i
= 0;i
< n
;i
++)
2149 if(!LookupSource(Context
, sources
[i
]))
2150 al_throwerr(Context
, AL_INVALID_NAME
);
2153 LockContext(Context
);
2154 for(i
= 0;i
< n
;i
++)
2156 Source
= LookupSource(Context
, sources
[i
]);
2157 Source
->new_state
= AL_NONE
;
2158 SetSourceState(Source
, Context
, AL_STOPPED
);
2160 UnlockContext(Context
);
2164 ALCcontext_DecRef(Context
);
2167 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2169 alSourceRewindv(1, &source
);
2171 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2173 ALCcontext
*Context
;
2177 Context
= GetContextRef();
2178 if(!Context
) return;
2182 CHECK_VALUE(Context
, n
>= 0);
2183 for(i
= 0;i
< n
;i
++)
2185 if(!LookupSource(Context
, sources
[i
]))
2186 al_throwerr(Context
, AL_INVALID_NAME
);
2189 LockContext(Context
);
2190 for(i
= 0;i
< n
;i
++)
2192 Source
= LookupSource(Context
, sources
[i
]);
2193 Source
->new_state
= AL_NONE
;
2194 SetSourceState(Source
, Context
, AL_INITIAL
);
2196 UnlockContext(Context
);
2200 ALCcontext_DecRef(Context
);
2204 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei nb
, const ALuint
*buffers
)
2206 ALCcontext
*Context
;
2209 ALbufferlistitem
*BufferListStart
= NULL
;
2210 ALbufferlistitem
*BufferList
;
2211 ALbuffer
*BufferFmt
;
2216 Context
= GetContextRef();
2217 if(!Context
) return;
2221 ALCdevice
*device
= Context
->Device
;
2223 CHECK_VALUE(Context
, nb
>= 0);
2225 if((Source
=LookupSource(Context
, source
)) == NULL
)
2226 al_throwerr(Context
, AL_INVALID_NAME
);
2228 LockContext(Context
);
2229 if(Source
->SourceType
== AL_STATIC
)
2231 UnlockContext(Context
);
2232 /* Can't queue on a Static Source */
2233 al_throwerr(Context
, AL_INVALID_OPERATION
);
2238 /* Check for a valid Buffer, for its frequency and format */
2239 BufferList
= Source
->queue
;
2242 if(BufferList
->buffer
)
2244 BufferFmt
= BufferList
->buffer
;
2247 BufferList
= BufferList
->next
;
2250 for(i
= 0;i
< nb
;i
++)
2252 ALbuffer
*buffer
= NULL
;
2253 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2255 UnlockContext(Context
);
2256 al_throwerr(Context
, AL_INVALID_NAME
);
2259 if(!BufferListStart
)
2261 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2262 BufferListStart
->buffer
= buffer
;
2263 BufferListStart
->next
= NULL
;
2264 BufferListStart
->prev
= NULL
;
2265 BufferList
= BufferListStart
;
2269 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2270 BufferList
->next
->buffer
= buffer
;
2271 BufferList
->next
->next
= NULL
;
2272 BufferList
->next
->prev
= BufferList
;
2273 BufferList
= BufferList
->next
;
2275 if(!buffer
) continue;
2276 IncrementRef(&buffer
->ref
);
2278 ReadLock(&buffer
->lock
);
2279 if(BufferFmt
== NULL
)
2283 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2284 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2285 if(buffer
->FmtChannels
== FmtMono
)
2286 Source
->Update
= CalcSourceParams
;
2288 Source
->Update
= CalcNonAttnSourceParams
;
2290 Source
->NeedsUpdate
= AL_TRUE
;
2292 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2293 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2294 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2296 ReadUnlock(&buffer
->lock
);
2297 UnlockContext(Context
);
2298 al_throwerr(Context
, AL_INVALID_OPERATION
);
2300 ReadUnlock(&buffer
->lock
);
2303 /* Source is now streaming */
2304 Source
->SourceType
= AL_STREAMING
;
2306 if(Source
->queue
== NULL
)
2307 Source
->queue
= BufferListStart
;
2310 /* Append to the end of the queue */
2311 BufferList
= Source
->queue
;
2312 while(BufferList
->next
!= NULL
)
2313 BufferList
= BufferList
->next
;
2315 BufferListStart
->prev
= BufferList
;
2316 BufferList
->next
= BufferListStart
;
2319 Source
->BuffersInQueue
+= nb
;
2321 UnlockContext(Context
);
2325 while(BufferListStart
)
2327 BufferList
= BufferListStart
;
2328 BufferListStart
= BufferList
->next
;
2330 if(BufferList
->buffer
)
2331 DecrementRef(&BufferList
->buffer
->ref
);
2337 ALCcontext_DecRef(Context
);
2340 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint source
, ALsizei nb
, ALuint
*buffers
)
2342 ALCcontext
*Context
;
2345 ALbufferlistitem
*BufferList
;
2350 Context
= GetContextRef();
2351 if(!Context
) return;
2355 CHECK_VALUE(Context
, nb
>= 0);
2357 if((Source
=LookupSource(Context
, source
)) == NULL
)
2358 al_throwerr(Context
, AL_INVALID_NAME
);
2360 LockContext(Context
);
2361 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
||
2362 (ALuint
)nb
> Source
->BuffersPlayed
)
2364 UnlockContext(Context
);
2365 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2366 al_throwerr(Context
, AL_INVALID_VALUE
);
2369 for(i
= 0;i
< nb
;i
++)
2371 BufferList
= Source
->queue
;
2372 Source
->queue
= BufferList
->next
;
2373 Source
->BuffersInQueue
--;
2374 Source
->BuffersPlayed
--;
2376 if(BufferList
->buffer
)
2378 buffers
[i
] = BufferList
->buffer
->id
;
2379 DecrementRef(&BufferList
->buffer
->ref
);
2387 Source
->queue
->prev
= NULL
;
2388 UnlockContext(Context
);
2392 ALCcontext_DecRef(Context
);
2396 static ALvoid
InitSourceParams(ALsource
*Source
)
2400 Source
->InnerAngle
= 360.0f
;
2401 Source
->OuterAngle
= 360.0f
;
2402 Source
->Pitch
= 1.0f
;
2403 Source
->Position
[0] = 0.0f
;
2404 Source
->Position
[1] = 0.0f
;
2405 Source
->Position
[2] = 0.0f
;
2406 Source
->Orientation
[0] = 0.0f
;
2407 Source
->Orientation
[1] = 0.0f
;
2408 Source
->Orientation
[2] = 0.0f
;
2409 Source
->Velocity
[0] = 0.0f
;
2410 Source
->Velocity
[1] = 0.0f
;
2411 Source
->Velocity
[2] = 0.0f
;
2412 Source
->RefDistance
= 1.0f
;
2413 Source
->MaxDistance
= FLT_MAX
;
2414 Source
->RollOffFactor
= 1.0f
;
2415 Source
->Looping
= AL_FALSE
;
2416 Source
->Gain
= 1.0f
;
2417 Source
->MinGain
= 0.0f
;
2418 Source
->MaxGain
= 1.0f
;
2419 Source
->OuterGain
= 0.0f
;
2420 Source
->OuterGainHF
= 1.0f
;
2422 Source
->DryGainHFAuto
= AL_TRUE
;
2423 Source
->WetGainAuto
= AL_TRUE
;
2424 Source
->WetGainHFAuto
= AL_TRUE
;
2425 Source
->AirAbsorptionFactor
= 0.0f
;
2426 Source
->RoomRolloffFactor
= 0.0f
;
2427 Source
->DopplerFactor
= 1.0f
;
2428 Source
->DirectChannels
= AL_FALSE
;
2430 Source
->DistanceModel
= DefaultDistanceModel
;
2432 Source
->Resampler
= DefaultResampler
;
2434 Source
->state
= AL_INITIAL
;
2435 Source
->new_state
= AL_NONE
;
2436 Source
->SourceType
= AL_UNDETERMINED
;
2437 Source
->Offset
= -1.0;
2439 Source
->DirectGain
= 1.0f
;
2440 Source
->DirectGainHF
= 1.0f
;
2441 for(i
= 0;i
< MAX_SENDS
;i
++)
2443 Source
->Send
[i
].Gain
= 1.0f
;
2444 Source
->Send
[i
].GainHF
= 1.0f
;
2447 Source
->NeedsUpdate
= AL_TRUE
;
2449 Source
->Hrtf
.Moving
= AL_FALSE
;
2450 Source
->Hrtf
.Counter
= 0;
2456 * Sets the source's new play state given its current state.
2458 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2460 if(state
== AL_PLAYING
)
2462 ALbufferlistitem
*BufferList
;
2465 /* Check that there is a queue containing at least one valid, non zero
2467 BufferList
= Source
->queue
;
2470 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
2472 BufferList
= BufferList
->next
;
2475 if(Source
->state
!= AL_PLAYING
)
2477 for(j
= 0;j
< MaxChannels
;j
++)
2479 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
2480 Source
->Hrtf
.History
[j
][k
] = 0.0f
;
2481 for(k
= 0;k
< HRIR_LENGTH
;k
++)
2483 Source
->Hrtf
.Values
[j
][k
][0] = 0.0f
;
2484 Source
->Hrtf
.Values
[j
][k
][1] = 0.0f
;
2489 if(Source
->state
!= AL_PAUSED
)
2491 Source
->state
= AL_PLAYING
;
2492 Source
->position
= 0;
2493 Source
->position_fraction
= 0;
2494 Source
->BuffersPlayed
= 0;
2497 Source
->state
= AL_PLAYING
;
2499 // Check if an Offset has been set
2500 if(Source
->Offset
>= 0.0)
2501 ApplyOffset(Source
);
2503 /* If there's nothing to play, or device is disconnected, go right to
2505 if(!BufferList
|| !Context
->Device
->Connected
)
2507 SetSourceState(Source
, Context
, AL_STOPPED
);
2511 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
2513 if(Context
->ActiveSources
[j
] == Source
)
2516 if(j
== Context
->ActiveSourceCount
)
2517 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
2519 else if(state
== AL_PAUSED
)
2521 if(Source
->state
== AL_PLAYING
)
2523 Source
->state
= AL_PAUSED
;
2524 Source
->Hrtf
.Moving
= AL_FALSE
;
2525 Source
->Hrtf
.Counter
= 0;
2528 else if(state
== AL_STOPPED
)
2530 if(Source
->state
!= AL_INITIAL
)
2532 Source
->state
= AL_STOPPED
;
2533 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
2534 Source
->Hrtf
.Moving
= AL_FALSE
;
2535 Source
->Hrtf
.Counter
= 0;
2537 Source
->Offset
= -1.0;
2539 else if(state
== AL_INITIAL
)
2541 if(Source
->state
!= AL_INITIAL
)
2543 Source
->state
= AL_INITIAL
;
2544 Source
->position
= 0;
2545 Source
->position_fraction
= 0;
2546 Source
->BuffersPlayed
= 0;
2547 Source
->Hrtf
.Moving
= AL_FALSE
;
2548 Source
->Hrtf
.Counter
= 0;
2550 Source
->Offset
= -1.0;
2556 * Gets the current read offset for the given Source, in 32.32 fixed-point
2557 * samples. The offset is relative to the start of the queue (not the start of
2558 * the current buffer).
2560 static ALint64
GetSourceOffset(const ALsource
*Source
)
2562 const ALbufferlistitem
*BufferList
;
2566 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2569 /* NOTE: This is the offset into the *current* buffer, so add the length of
2570 * any played buffers */
2571 readPos
= (ALuint64
)Source
->position
<< 32;
2572 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2573 BufferList
= Source
->queue
;
2574 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2576 if(BufferList
->buffer
)
2577 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2578 BufferList
= BufferList
->next
;
2581 return (ALint64
)minu64(readPos
, MAKEU64(0x7fffffff,0xffffffff));
2584 /* GetSourceSecOffset
2586 * Gets the current read offset for the given Source, in seconds. The offset is
2587 * relative to the start of the queue (not the start of the current buffer).
2589 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2591 const ALbufferlistitem
*BufferList
;
2592 const ALbuffer
*Buffer
= NULL
;
2596 BufferList
= Source
->queue
;
2599 if(BufferList
->buffer
)
2601 Buffer
= BufferList
->buffer
;
2604 BufferList
= BufferList
->next
;
2607 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2610 /* NOTE: This is the offset into the *current* buffer, so add the length of
2611 * any played buffers */
2612 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2613 readPos
|= (ALuint64
)Source
->position_fraction
;
2614 BufferList
= Source
->queue
;
2615 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2617 if(BufferList
->buffer
)
2618 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< FRACTIONBITS
;
2619 BufferList
= BufferList
->next
;
2622 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2627 * Gets the current read and write offsets for the given Source, in the
2628 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2629 * the start of the queue (not the start of the current buffer).
2631 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2633 const ALbufferlistitem
*BufferList
;
2634 const ALbuffer
*Buffer
= NULL
;
2635 ALuint readPos
, writePos
;
2636 ALuint totalBufferLen
;
2639 // Find the first valid Buffer in the Queue
2640 BufferList
= Source
->queue
;
2643 if(BufferList
->buffer
)
2645 Buffer
= BufferList
->buffer
;
2648 BufferList
= BufferList
->next
;
2651 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2658 if(updateLen
> 0.0 && updateLen
< 0.015)
2661 /* NOTE: This is the offset into the *current* buffer, so add the length of
2662 * any played buffers */
2663 readPos
= Source
->position
;
2665 BufferList
= Source
->queue
;
2666 for(i
= 0;BufferList
;i
++)
2668 if(BufferList
->buffer
)
2670 if(i
< Source
->BuffersPlayed
)
2671 readPos
+= BufferList
->buffer
->SampleLen
;
2672 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
2674 BufferList
= BufferList
->next
;
2676 if(Source
->state
== AL_PLAYING
)
2677 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2683 readPos
%= totalBufferLen
;
2684 writePos
%= totalBufferLen
;
2688 /* Wrap positions back to 0 */
2689 if(readPos
>= totalBufferLen
)
2691 if(writePos
>= totalBufferLen
)
2698 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2699 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2702 case AL_SAMPLE_OFFSET
:
2703 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2704 offset
[0] = (ALdouble
)readPos
;
2705 offset
[1] = (ALdouble
)writePos
;
2708 case AL_BYTE_OFFSET
:
2709 case AL_BYTE_RW_OFFSETS_SOFT
:
2710 if(Buffer
->OriginalType
== UserFmtIMA4
)
2712 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
2713 ALuint FrameBlockSize
= 65;
2715 /* Round down to nearest ADPCM block */
2716 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2717 if(Source
->state
!= AL_PLAYING
)
2718 offset
[1] = offset
[0];
2721 /* Round up to nearest ADPCM block */
2722 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2723 FrameBlockSize
* BlockSize
);
2728 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2729 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2730 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2739 * Apply the stored playback offset to the Source. This function will update
2740 * the number of buffers "played" given the stored offset.
2742 ALboolean
ApplyOffset(ALsource
*Source
)
2744 const ALbufferlistitem
*BufferList
;
2745 const ALbuffer
*Buffer
;
2746 ALint bufferLen
, totalBufferLen
;
2747 ALint buffersPlayed
;
2750 /* Get sample frame offset */
2751 offset
= GetSampleOffset(Source
);
2758 BufferList
= Source
->queue
;
2761 Buffer
= BufferList
->buffer
;
2762 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2764 if(bufferLen
<= offset
-totalBufferLen
)
2766 /* Offset is past this buffer so increment to the next buffer */
2769 else if(totalBufferLen
<= offset
)
2771 /* Offset is in this buffer */
2772 Source
->BuffersPlayed
= buffersPlayed
;
2774 Source
->position
= offset
- totalBufferLen
;
2775 Source
->position_fraction
= 0;
2779 totalBufferLen
+= bufferLen
;
2781 BufferList
= BufferList
->next
;
2784 /* Offset is out of range of the queue */
2791 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2792 * Second offset supplied by the application). This takes into account the fact
2793 * that the buffer format may have been modifed since.
2795 static ALint
GetSampleOffset(ALsource
*Source
)
2797 const ALbuffer
*Buffer
= NULL
;
2798 const ALbufferlistitem
*BufferList
;
2801 /* Find the first valid Buffer in the Queue */
2802 BufferList
= Source
->queue
;
2805 if(BufferList
->buffer
)
2807 Buffer
= BufferList
->buffer
;
2810 BufferList
= BufferList
->next
;
2815 Source
->Offset
= -1.0;
2819 switch(Source
->OffsetType
)
2821 case AL_BYTE_OFFSET
:
2822 /* Determine the ByteOffset (and ensure it is block aligned) */
2823 Offset
= (ALint
)Source
->Offset
;
2824 if(Buffer
->OriginalType
== UserFmtIMA4
)
2826 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2830 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2833 case AL_SAMPLE_OFFSET
:
2834 Offset
= (ALint
)Source
->Offset
;
2838 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2841 Source
->Offset
= -1.0;
2849 * Destroys all sources in the source map.
2851 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2855 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2857 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2858 Context
->SourceMap
.array
[pos
].value
= NULL
;
2860 while(temp
->queue
!= NULL
)
2862 ALbufferlistitem
*BufferList
= temp
->queue
;
2863 temp
->queue
= BufferList
->next
;
2865 if(BufferList
->buffer
!= NULL
)
2866 DecrementRef(&BufferList
->buffer
->ref
);
2870 for(j
= 0;j
< MAX_SENDS
;++j
)
2872 if(temp
->Send
[j
].Slot
)
2873 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2874 temp
->Send
[j
].Slot
= NULL
;
2877 FreeThunkEntry(temp
->id
);
2878 memset(temp
, 0, sizeof(*temp
));