2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
34 #include "alAuxEffectSlot.h"
37 enum Resampler DefaultResampler
= LinearResampler
;
38 const ALsizei ResamplerPadding
[ResamplerMax
] = {
43 const ALsizei ResamplerPrePadding
[ResamplerMax
] = {
50 static ALvoid
InitSourceParams(ALsource
*Source
);
51 static ALint64
GetSourceOffset(const ALsource
*Source
);
52 static ALdouble
GetSourceSecOffset(const ALsource
*Source
);
53 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offsets
, ALdouble updateLen
);
54 static ALint
GetSampleOffset(ALsource
*Source
);
56 typedef enum SrcFloatProp
{
59 sfvMinGain
= AL_MIN_GAIN
,
60 sfvMaxGain
= AL_MAX_GAIN
,
61 sfvMaxDistance
= AL_MAX_DISTANCE
,
62 sfvRolloffFactor
= AL_ROLLOFF_FACTOR
,
63 sfvDopplerFactor
= AL_DOPPLER_FACTOR
,
64 sfvConeOuterGain
= AL_CONE_OUTER_GAIN
,
65 sfvSecOffset
= AL_SEC_OFFSET
,
66 sfvSampleOffset
= AL_SAMPLE_OFFSET
,
67 sfvByteOffset
= AL_BYTE_OFFSET
,
68 sfvConeInnerAngle
= AL_CONE_INNER_ANGLE
,
69 sfvConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
70 sfvRefDistance
= AL_REFERENCE_DISTANCE
,
72 sfvPosition
= AL_POSITION
,
73 sfvVelocity
= AL_VELOCITY
,
74 sfvDirection
= AL_DIRECTION
,
76 sfvSourceRelative
= AL_SOURCE_RELATIVE
,
77 sfvLooping
= AL_LOOPING
,
78 sfvBuffer
= AL_BUFFER
,
79 sfvSourceState
= AL_SOURCE_STATE
,
80 sfvBuffersQueued
= AL_BUFFERS_QUEUED
,
81 sfvBuffersProcessed
= AL_BUFFERS_PROCESSED
,
82 sfvSourceType
= AL_SOURCE_TYPE
,
83 sfvDistanceModel
= AL_DISTANCE_MODEL
,
86 sfvConeOuterGainHF
= AL_CONE_OUTER_GAINHF
,
87 sfvAirAbsorptionFactor
= AL_AIR_ABSORPTION_FACTOR
,
88 sfvRoomRolloffFactor
= AL_ROOM_ROLLOFF_FACTOR
,
89 sfvDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
90 sfvAuxSendFilterGainAuto
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
91 sfvAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
93 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
94 sfvSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
95 sfvByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
97 /* AL_SOFT_source_latency */
98 sfvSecOffsetLatencySOFT
= AL_SEC_OFFSET_LATENCY_SOFT
,
100 /* AL_SOFT_direct_channels */
101 sfvDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
104 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
);
105 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint
*values
);
106 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint64SOFT
*values
);
108 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
);
109 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint
*values
);
110 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint64
*values
);
113 #define RETERR(x) do { \
114 alSetError(Context, (x)); \
118 #define CHECKVAL(x) do { \
120 RETERR(AL_INVALID_VALUE); \
123 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
)
130 CHECKVAL(*values
>= 0.0f
);
132 Source
->Pitch
= *values
;
133 Source
->NeedsUpdate
= AL_TRUE
;
136 case AL_CONE_INNER_ANGLE
:
137 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
139 Source
->InnerAngle
= *values
;
140 Source
->NeedsUpdate
= AL_TRUE
;
143 case AL_CONE_OUTER_ANGLE
:
144 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
146 Source
->OuterAngle
= *values
;
147 Source
->NeedsUpdate
= AL_TRUE
;
151 CHECKVAL(*values
>= 0.0f
);
153 Source
->Gain
= *values
;
154 Source
->NeedsUpdate
= AL_TRUE
;
157 case AL_MAX_DISTANCE
:
158 CHECKVAL(*values
>= 0.0f
);
160 Source
->MaxDistance
= *values
;
161 Source
->NeedsUpdate
= AL_TRUE
;
164 case AL_ROLLOFF_FACTOR
:
165 CHECKVAL(*values
>= 0.0f
);
167 Source
->RollOffFactor
= *values
;
168 Source
->NeedsUpdate
= AL_TRUE
;
171 case AL_REFERENCE_DISTANCE
:
172 CHECKVAL(*values
>= 0.0f
);
174 Source
->RefDistance
= *values
;
175 Source
->NeedsUpdate
= AL_TRUE
;
179 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
181 Source
->MinGain
= *values
;
182 Source
->NeedsUpdate
= AL_TRUE
;
186 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
188 Source
->MaxGain
= *values
;
189 Source
->NeedsUpdate
= AL_TRUE
;
192 case AL_CONE_OUTER_GAIN
:
193 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
195 Source
->OuterGain
= *values
;
196 Source
->NeedsUpdate
= AL_TRUE
;
199 case AL_CONE_OUTER_GAINHF
:
200 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
202 Source
->OuterGainHF
= *values
;
203 Source
->NeedsUpdate
= AL_TRUE
;
206 case AL_AIR_ABSORPTION_FACTOR
:
207 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
209 Source
->AirAbsorptionFactor
= *values
;
210 Source
->NeedsUpdate
= AL_TRUE
;
213 case AL_ROOM_ROLLOFF_FACTOR
:
214 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
216 Source
->RoomRolloffFactor
= *values
;
217 Source
->NeedsUpdate
= AL_TRUE
;
220 case AL_DOPPLER_FACTOR
:
221 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
223 Source
->DopplerFactor
= *values
;
224 Source
->NeedsUpdate
= AL_TRUE
;
228 case AL_SAMPLE_OFFSET
:
230 CHECKVAL(*values
>= 0.0f
);
232 LockContext(Context
);
233 Source
->OffsetType
= prop
;
234 Source
->Offset
= *values
;
236 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
237 !Context
->DeferUpdates
)
239 if(ApplyOffset(Source
) == AL_FALSE
)
241 UnlockContext(Context
);
242 RETERR(AL_INVALID_VALUE
);
245 UnlockContext(Context
);
249 case AL_SEC_OFFSET_LATENCY_SOFT
:
251 RETERR(AL_INVALID_OPERATION
);
255 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
257 LockContext(Context
);
258 Source
->Position
[0] = values
[0];
259 Source
->Position
[1] = values
[1];
260 Source
->Position
[2] = values
[2];
261 UnlockContext(Context
);
262 Source
->NeedsUpdate
= AL_TRUE
;
266 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
268 LockContext(Context
);
269 Source
->Velocity
[0] = values
[0];
270 Source
->Velocity
[1] = values
[1];
271 Source
->Velocity
[2] = values
[2];
272 UnlockContext(Context
);
273 Source
->NeedsUpdate
= AL_TRUE
;
277 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
279 LockContext(Context
);
280 Source
->Orientation
[0] = values
[0];
281 Source
->Orientation
[1] = values
[1];
282 Source
->Orientation
[2] = values
[2];
283 UnlockContext(Context
);
284 Source
->NeedsUpdate
= AL_TRUE
;
288 case sfvSampleRWOffsetsSOFT
:
289 case sfvByteRWOffsetsSOFT
:
290 RETERR(AL_INVALID_OPERATION
);
293 case sfvSourceRelative
:
297 case sfvDistanceModel
:
298 case sfvDirectFilterGainHFAuto
:
299 case sfvAuxSendFilterGainAuto
:
300 case sfvAuxSendFilterGainHFAuto
:
301 case sfvDirectChannelsSOFT
:
302 ival
= (ALint
)values
[0];
303 return SetSourceiv(Source
, Context
, prop
, &ival
);
306 case sfvBuffersQueued
:
307 case sfvBuffersProcessed
:
308 ival
= (ALint
)((ALuint
)values
[0]);
309 return SetSourceiv(Source
, Context
, prop
, &ival
);
312 ERR("Unexpected property: 0x%04x\n", prop
);
313 RETERR(AL_INVALID_ENUM
);
316 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint
*values
)
318 ALCdevice
*device
= Context
->Device
;
319 ALbuffer
*buffer
= NULL
;
320 ALfilter
*filter
= NULL
;
321 ALeffectslot
*slot
= NULL
;
322 ALbufferlistitem
*oldlist
;
328 case AL_SOURCE_RELATIVE
:
329 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
331 Source
->HeadRelative
= (ALboolean
)*values
;
332 Source
->NeedsUpdate
= AL_TRUE
;
336 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
338 Source
->Looping
= (ALboolean
)*values
;
342 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
344 LockContext(Context
);
345 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
347 UnlockContext(Context
);
348 RETERR(AL_INVALID_OPERATION
);
351 Source
->BuffersInQueue
= 0;
352 Source
->BuffersPlayed
= 0;
356 ALbufferlistitem
*BufferListItem
;
358 /* Source is now Static */
359 Source
->SourceType
= AL_STATIC
;
361 /* Add the selected buffer to a one-item queue */
362 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
363 BufferListItem
->buffer
= buffer
;
364 BufferListItem
->next
= NULL
;
365 BufferListItem
->prev
= NULL
;
366 IncrementRef(&buffer
->ref
);
368 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, BufferListItem
);
369 Source
->BuffersInQueue
= 1;
371 ReadLock(&buffer
->lock
);
372 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
373 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
374 ReadUnlock(&buffer
->lock
);
375 if(buffer
->FmtChannels
== FmtMono
)
376 Source
->Update
= CalcSourceParams
;
378 Source
->Update
= CalcNonAttnSourceParams
;
379 Source
->NeedsUpdate
= AL_TRUE
;
383 /* Source is now Undetermined */
384 Source
->SourceType
= AL_UNDETERMINED
;
385 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, NULL
);
388 /* Delete all elements in the previous queue */
389 while(oldlist
!= NULL
)
391 ALbufferlistitem
*temp
= oldlist
;
392 oldlist
= temp
->next
;
395 DecrementRef(&temp
->buffer
->ref
);
398 UnlockContext(Context
);
401 case AL_SOURCE_STATE
:
403 RETERR(AL_INVALID_OPERATION
);
406 case AL_SAMPLE_OFFSET
:
408 CHECKVAL(*values
>= 0);
410 LockContext(Context
);
411 Source
->OffsetType
= name
;
412 Source
->Offset
= *values
;
414 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
415 !Context
->DeferUpdates
)
417 if(ApplyOffset(Source
) == AL_FALSE
)
419 UnlockContext(Context
);
420 RETERR(AL_INVALID_VALUE
);
423 UnlockContext(Context
);
426 case AL_DIRECT_FILTER
:
427 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
429 LockContext(Context
);
432 Source
->DirectGain
= 1.0f
;
433 Source
->DirectGainHF
= 1.0f
;
437 Source
->DirectGain
= filter
->Gain
;
438 Source
->DirectGainHF
= filter
->GainHF
;
440 UnlockContext(Context
);
441 Source
->NeedsUpdate
= AL_TRUE
;
444 case AL_DIRECT_FILTER_GAINHF_AUTO
:
445 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
447 Source
->DryGainHFAuto
= *values
;
448 Source
->NeedsUpdate
= AL_TRUE
;
451 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
452 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
454 Source
->WetGainAuto
= *values
;
455 Source
->NeedsUpdate
= AL_TRUE
;
458 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
459 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
461 Source
->WetGainHFAuto
= *values
;
462 Source
->NeedsUpdate
= AL_TRUE
;
465 case AL_DIRECT_CHANNELS_SOFT
:
466 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
468 Source
->DirectChannels
= *values
;
469 Source
->NeedsUpdate
= AL_TRUE
;
472 case AL_DISTANCE_MODEL
:
473 CHECKVAL(*values
== AL_NONE
||
474 *values
== AL_INVERSE_DISTANCE
||
475 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
476 *values
== AL_LINEAR_DISTANCE
||
477 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
478 *values
== AL_EXPONENT_DISTANCE
||
479 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
481 Source
->DistanceModel
= *values
;
482 if(Context
->SourceDistanceModel
)
483 Source
->NeedsUpdate
= AL_TRUE
;
487 case AL_AUXILIARY_SEND_FILTER
:
488 LockContext(Context
);
489 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
490 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
491 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
493 UnlockContext(Context
);
494 RETERR(AL_INVALID_VALUE
);
497 /* Add refcount on the new slot, and release the previous slot */
498 if(slot
) IncrementRef(&slot
->ref
);
499 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
500 if(slot
) DecrementRef(&slot
->ref
);
505 Source
->Send
[values
[1]].Gain
= 1.0f
;
506 Source
->Send
[values
[1]].GainHF
= 1.0f
;
510 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
511 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
513 Source
->NeedsUpdate
= AL_TRUE
;
514 UnlockContext(Context
);
518 case AL_MAX_DISTANCE
:
519 case AL_ROLLOFF_FACTOR
:
520 case AL_CONE_INNER_ANGLE
:
521 case AL_CONE_OUTER_ANGLE
:
522 case AL_REFERENCE_DISTANCE
:
523 fvals
[0] = (ALfloat
)*values
;
524 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
531 fvals
[0] = (ALfloat
)values
[0];
532 fvals
[1] = (ALfloat
)values
[1];
533 fvals
[2] = (ALfloat
)values
[2];
534 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
539 ERR("Unexpected param: 0x%04x\n", name
);
540 RETERR(AL_INVALID_ENUM
);
546 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, ALenum name
, const ALint64SOFT
*values
)
554 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
556 RETERR(AL_INVALID_OPERATION
);
560 case AL_SOURCE_RELATIVE
:
562 case AL_SOURCE_STATE
:
564 case AL_SAMPLE_OFFSET
:
565 case AL_DIRECT_FILTER_GAINHF_AUTO
:
566 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
567 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
568 case AL_DIRECT_CHANNELS_SOFT
:
569 case AL_DISTANCE_MODEL
:
570 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
572 ivals
[0] = (ALint
)*values
;
573 if((err
=SetSourceiv(Source
, Context
, name
, ivals
)))
579 case AL_DIRECT_FILTER
:
580 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
582 ivals
[0] = (ALuint
)*values
;
583 if((err
=SetSourceiv(Source
, Context
, name
, ivals
)))
588 case AL_AUXILIARY_SEND_FILTER
:
589 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
590 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
591 values
[2] <= UINT_MAX
&& values
[2] >= 0);
593 ivals
[0] = (ALuint
)values
[0];
594 ivals
[1] = (ALuint
)values
[1];
595 ivals
[2] = (ALuint
)values
[2];
596 if((err
=SetSourceiv(Source
, Context
, name
, ivals
)))
601 case AL_MAX_DISTANCE
:
602 case AL_ROLLOFF_FACTOR
:
603 case AL_CONE_INNER_ANGLE
:
604 case AL_CONE_OUTER_ANGLE
:
605 case AL_REFERENCE_DISTANCE
:
607 fvals
[0] = (ALfloat
)*values
;
608 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
616 fvals
[0] = (ALfloat
)values
[0];
617 fvals
[1] = (ALfloat
)values
[1];
618 fvals
[2] = (ALfloat
)values
[2];
619 if((err
=SetSourcefv(Source
, Context
, name
, fvals
)) != AL_NO_ERROR
)
624 ERR("Unexpected param: 0x%04x\n", name
);
625 RETERR(AL_INVALID_ENUM
);
634 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
)
644 *values
= Source
->Gain
;
648 *values
= Source
->Pitch
;
651 case AL_MAX_DISTANCE
:
652 *values
= Source
->MaxDistance
;
655 case AL_ROLLOFF_FACTOR
:
656 *values
= Source
->RollOffFactor
;
659 case AL_REFERENCE_DISTANCE
:
660 *values
= Source
->RefDistance
;
663 case AL_CONE_INNER_ANGLE
:
664 *values
= Source
->InnerAngle
;
667 case AL_CONE_OUTER_ANGLE
:
668 *values
= Source
->OuterAngle
;
672 *values
= Source
->MinGain
;
676 *values
= Source
->MaxGain
;
679 case AL_CONE_OUTER_GAIN
:
680 *values
= Source
->OuterGain
;
684 case AL_SAMPLE_OFFSET
:
686 LockContext(Context
);
687 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
688 Context
->Device
->Frequency
;
689 GetSourceOffsets(Source
, prop
, offsets
, updateLen
);
690 UnlockContext(Context
);
691 *values
= offsets
[0];
694 case AL_CONE_OUTER_GAINHF
:
695 *values
= Source
->OuterGainHF
;
698 case AL_AIR_ABSORPTION_FACTOR
:
699 *values
= Source
->AirAbsorptionFactor
;
702 case AL_ROOM_ROLLOFF_FACTOR
:
703 *values
= Source
->RoomRolloffFactor
;
706 case AL_DOPPLER_FACTOR
:
707 *values
= Source
->DopplerFactor
;
710 case AL_SAMPLE_RW_OFFSETS_SOFT
:
711 case AL_BYTE_RW_OFFSETS_SOFT
:
712 LockContext(Context
);
713 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
714 Context
->Device
->Frequency
;
715 GetSourceOffsets(Source
, prop
, values
, updateLen
);
716 UnlockContext(Context
);
719 case AL_SEC_OFFSET_LATENCY_SOFT
:
720 LockContext(Context
);
721 values
[0] = GetSourceSecOffset(Source
);
722 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
724 UnlockContext(Context
);
728 LockContext(Context
);
729 values
[0] = Source
->Position
[0];
730 values
[1] = Source
->Position
[1];
731 values
[2] = Source
->Position
[2];
732 UnlockContext(Context
);
736 LockContext(Context
);
737 values
[0] = Source
->Velocity
[0];
738 values
[1] = Source
->Velocity
[1];
739 values
[2] = Source
->Velocity
[2];
740 UnlockContext(Context
);
744 LockContext(Context
);
745 values
[0] = Source
->Orientation
[0];
746 values
[1] = Source
->Orientation
[1];
747 values
[2] = Source
->Orientation
[2];
748 UnlockContext(Context
);
751 case AL_SOURCE_RELATIVE
:
754 case AL_SOURCE_STATE
:
755 case AL_BUFFERS_QUEUED
:
756 case AL_BUFFERS_PROCESSED
:
758 case AL_DIRECT_FILTER_GAINHF_AUTO
:
759 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
760 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
761 case AL_DIRECT_CHANNELS_SOFT
:
762 case AL_DISTANCE_MODEL
:
763 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) == AL_NO_ERROR
)
764 *values
= (ALdouble
)ivals
[0];
768 ERR("Unexpected property: 0x%04x\n", prop
);
769 RETERR(AL_INVALID_ENUM
);
772 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint
*values
)
774 ALbufferlistitem
*BufferList
;
780 case AL_SOURCE_RELATIVE
:
781 *values
= Source
->HeadRelative
;
785 *values
= Source
->Looping
;
789 LockContext(Context
);
790 BufferList
= Source
->queue
;
791 if(Source
->SourceType
!= AL_STATIC
)
793 ALuint i
= Source
->BuffersPlayed
;
796 BufferList
= BufferList
->next
;
800 *values
= ((BufferList
&& BufferList
->buffer
) ?
801 BufferList
->buffer
->id
: 0);
802 UnlockContext(Context
);
805 case AL_SOURCE_STATE
:
806 *values
= Source
->state
;
809 case AL_BUFFERS_QUEUED
:
810 *values
= Source
->BuffersInQueue
;
813 case AL_BUFFERS_PROCESSED
:
814 LockContext(Context
);
815 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
817 /* Buffers on a looping source are in a perpetual state of
818 * PENDING, so don't report any as PROCESSED */
822 *values
= Source
->BuffersPlayed
;
823 UnlockContext(Context
);
827 *values
= Source
->SourceType
;
830 case AL_DIRECT_FILTER_GAINHF_AUTO
:
831 *values
= Source
->DryGainHFAuto
;
834 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
835 *values
= Source
->WetGainAuto
;
838 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
839 *values
= Source
->WetGainHFAuto
;
842 case AL_DIRECT_CHANNELS_SOFT
:
843 *values
= Source
->DirectChannels
;
846 case AL_DISTANCE_MODEL
:
847 *values
= Source
->DistanceModel
;
850 case AL_MAX_DISTANCE
:
851 case AL_ROLLOFF_FACTOR
:
852 case AL_REFERENCE_DISTANCE
:
853 case AL_CONE_INNER_ANGLE
:
854 case AL_CONE_OUTER_ANGLE
:
856 case AL_SAMPLE_OFFSET
:
858 case AL_DOPPLER_FACTOR
:
859 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
861 *values
= (ALint
)dvals
[0];
864 case AL_SAMPLE_RW_OFFSETS_SOFT
:
865 case AL_BYTE_RW_OFFSETS_SOFT
:
866 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
868 values
[0] = (ALint
)dvals
[0];
869 values
[1] = (ALint
)dvals
[1];
875 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
877 values
[0] = (ALint
)dvals
[0];
878 values
[1] = (ALint
)dvals
[1];
879 values
[2] = (ALint
)dvals
[2];
883 ERR("Unexpected param: 0x%04x\n", name
);
884 RETERR(AL_INVALID_ENUM
);
890 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, ALenum name
, ALint64
*values
)
898 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
899 LockContext(Context
);
900 values
[0] = GetSourceOffset(Source
);
901 values
[1] = ALCdevice_GetLatency(Context
->Device
);
902 UnlockContext(Context
);
905 case AL_MAX_DISTANCE
:
906 case AL_ROLLOFF_FACTOR
:
907 case AL_REFERENCE_DISTANCE
:
908 case AL_CONE_INNER_ANGLE
:
909 case AL_CONE_OUTER_ANGLE
:
911 case AL_SAMPLE_OFFSET
:
913 case AL_DOPPLER_FACTOR
:
914 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
916 *values
= (ALint64
)dvals
[0];
919 case AL_SAMPLE_RW_OFFSETS_SOFT
:
920 case AL_BYTE_RW_OFFSETS_SOFT
:
921 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
923 values
[0] = (ALint64
)dvals
[0];
924 values
[1] = (ALint64
)dvals
[1];
930 if((err
=GetSourcedv(Source
, Context
, name
, dvals
)) != AL_NO_ERROR
)
932 values
[0] = (ALint64
)dvals
[0];
933 values
[1] = (ALint64
)dvals
[1];
934 values
[2] = (ALint64
)dvals
[2];
937 case AL_SOURCE_RELATIVE
:
940 case AL_SOURCE_STATE
:
941 case AL_BUFFERS_QUEUED
:
942 case AL_BUFFERS_PROCESSED
:
944 case AL_DIRECT_FILTER_GAINHF_AUTO
:
945 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
946 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
947 case AL_DIRECT_CHANNELS_SOFT
:
948 case AL_DISTANCE_MODEL
:
949 if((err
=GetSourceiv(Source
, Context
, name
, ivals
)) != AL_NO_ERROR
)
955 ERR("Unexpected param: 0x%04x\n", name
);
956 RETERR(AL_INVALID_ENUM
);
965 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
970 Context
= GetContextRef();
977 CHECK_VALUE(Context
, n
>= 0);
978 for(cur
= 0;cur
< n
;cur
++)
980 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
982 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
983 InitSourceParams(source
);
985 err
= NewThunkEntry(&source
->id
);
986 if(err
== AL_NO_ERROR
)
987 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->id
, source
);
988 if(err
!= AL_NO_ERROR
)
990 FreeThunkEntry(source
->id
);
991 memset(source
, 0, sizeof(ALsource
));
994 al_throwerr(Context
, err
);
997 sources
[cur
] = source
->id
;
1003 alDeleteSources(cur
, sources
);
1007 ALCcontext_DecRef(Context
);
1011 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
1013 ALCcontext
*Context
;
1015 Context
= GetContextRef();
1016 if(!Context
) return;
1020 ALbufferlistitem
*BufferList
;
1024 CHECK_VALUE(Context
, n
>= 0);
1026 /* Check that all Sources are valid */
1027 for(i
= 0;i
< n
;i
++)
1029 if(LookupSource(Context
, sources
[i
]) == NULL
)
1030 al_throwerr(Context
, AL_INVALID_NAME
);
1033 for(i
= 0;i
< n
;i
++)
1035 ALsource
**srclist
, **srclistend
;
1037 if((Source
=RemoveSource(Context
, sources
[i
])) == NULL
)
1039 FreeThunkEntry(Source
->id
);
1041 LockContext(Context
);
1042 srclist
= Context
->ActiveSources
;
1043 srclistend
= srclist
+ Context
->ActiveSourceCount
;
1044 while(srclist
!= srclistend
)
1046 if(*srclist
== Source
)
1048 Context
->ActiveSourceCount
--;
1049 *srclist
= *(--srclistend
);
1054 UnlockContext(Context
);
1056 while(Source
->queue
!= NULL
)
1058 BufferList
= Source
->queue
;
1059 Source
->queue
= BufferList
->next
;
1061 if(BufferList
->buffer
!= NULL
)
1062 DecrementRef(&BufferList
->buffer
->ref
);
1066 for(j
= 0;j
< MAX_SENDS
;++j
)
1068 if(Source
->Send
[j
].Slot
)
1069 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
1070 Source
->Send
[j
].Slot
= NULL
;
1073 memset(Source
, 0, sizeof(*Source
));
1079 ALCcontext_DecRef(Context
);
1083 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1085 ALCcontext
*Context
;
1088 Context
= GetContextRef();
1089 if(!Context
) return AL_FALSE
;
1091 result
= (LookupSource(Context
, source
) ? AL_TRUE
: AL_FALSE
);
1093 ALCcontext_DecRef(Context
);
1099 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1101 ALCcontext
*Context
;
1104 Context
= GetContextRef();
1105 if(!Context
) return;
1107 if((Source
=LookupSource(Context
, source
)) == NULL
)
1108 alSetError(Context
, AL_INVALID_NAME
);
1112 case AL_CONE_INNER_ANGLE
:
1113 case AL_CONE_OUTER_ANGLE
:
1115 case AL_MAX_DISTANCE
:
1116 case AL_ROLLOFF_FACTOR
:
1117 case AL_REFERENCE_DISTANCE
:
1120 case AL_CONE_OUTER_GAIN
:
1121 case AL_CONE_OUTER_GAINHF
:
1122 case AL_AIR_ABSORPTION_FACTOR
:
1123 case AL_ROOM_ROLLOFF_FACTOR
:
1124 case AL_DOPPLER_FACTOR
:
1126 case AL_SAMPLE_OFFSET
:
1127 case AL_BYTE_OFFSET
:
1128 SetSourcefv(Source
, Context
, param
, &value
);
1132 alSetError(Context
, AL_INVALID_ENUM
);
1135 ALCcontext_DecRef(Context
);
1138 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1140 ALCcontext
*Context
;
1144 Context
= GetContextRef();
1145 if(!Context
) return;
1147 if((Source
=LookupSource(Context
, source
)) == NULL
)
1148 alSetError(Context
, AL_INVALID_NAME
);
1157 SetSourcefv(Source
, Context
, param
, fvals
);
1161 alSetError(Context
, AL_INVALID_ENUM
);
1164 ALCcontext_DecRef(Context
);
1167 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1169 ALCcontext
*Context
;
1172 Context
= GetContextRef();
1173 if(!Context
) return;
1175 if((Source
=LookupSource(Context
, source
)) == NULL
)
1176 alSetError(Context
, AL_INVALID_NAME
);
1178 alSetError(Context
, AL_INVALID_VALUE
);
1182 case AL_CONE_INNER_ANGLE
:
1183 case AL_CONE_OUTER_ANGLE
:
1185 case AL_MAX_DISTANCE
:
1186 case AL_ROLLOFF_FACTOR
:
1187 case AL_REFERENCE_DISTANCE
:
1190 case AL_CONE_OUTER_GAIN
:
1191 case AL_CONE_OUTER_GAINHF
:
1193 case AL_SAMPLE_OFFSET
:
1194 case AL_BYTE_OFFSET
:
1195 case AL_AIR_ABSORPTION_FACTOR
:
1196 case AL_ROOM_ROLLOFF_FACTOR
:
1201 SetSourcefv(Source
, Context
, param
, values
);
1205 alSetError(Context
, AL_INVALID_ENUM
);
1208 ALCcontext_DecRef(Context
);
1212 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1214 ALCcontext
*Context
;
1218 Context
= GetContextRef();
1219 if(!Context
) return;
1221 if((Source
=LookupSource(Context
, source
)) == NULL
)
1222 alSetError(Context
, AL_INVALID_NAME
);
1226 case AL_CONE_INNER_ANGLE
:
1227 case AL_CONE_OUTER_ANGLE
:
1229 case AL_MAX_DISTANCE
:
1230 case AL_ROLLOFF_FACTOR
:
1231 case AL_REFERENCE_DISTANCE
:
1234 case AL_CONE_OUTER_GAIN
:
1235 case AL_CONE_OUTER_GAINHF
:
1236 case AL_AIR_ABSORPTION_FACTOR
:
1237 case AL_ROOM_ROLLOFF_FACTOR
:
1238 case AL_DOPPLER_FACTOR
:
1240 case AL_SAMPLE_OFFSET
:
1241 case AL_BYTE_OFFSET
:
1242 fval
= (ALfloat
)value
;
1243 SetSourcefv(Source
, Context
, param
, &fval
);
1247 alSetError(Context
, AL_INVALID_ENUM
);
1250 ALCcontext_DecRef(Context
);
1253 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1255 ALCcontext
*Context
;
1259 Context
= GetContextRef();
1260 if(!Context
) return;
1262 if((Source
=LookupSource(Context
, source
)) == NULL
)
1263 alSetError(Context
, AL_INVALID_NAME
);
1269 fvals
[0] = (ALfloat
)value1
;
1270 fvals
[1] = (ALfloat
)value2
;
1271 fvals
[2] = (ALfloat
)value3
;
1272 SetSourcefv(Source
, Context
, param
, fvals
);
1276 alSetError(Context
, AL_INVALID_ENUM
);
1279 ALCcontext_DecRef(Context
);
1282 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1284 ALCcontext
*Context
;
1288 Context
= GetContextRef();
1289 if(!Context
) return;
1291 if((Source
=LookupSource(Context
, source
)) == NULL
)
1292 alSetError(Context
, AL_INVALID_NAME
);
1294 alSetError(Context
, AL_INVALID_VALUE
);
1298 case AL_CONE_INNER_ANGLE
:
1299 case AL_CONE_OUTER_ANGLE
:
1301 case AL_MAX_DISTANCE
:
1302 case AL_ROLLOFF_FACTOR
:
1303 case AL_REFERENCE_DISTANCE
:
1306 case AL_CONE_OUTER_GAIN
:
1307 case AL_CONE_OUTER_GAINHF
:
1309 case AL_SAMPLE_OFFSET
:
1310 case AL_BYTE_OFFSET
:
1311 case AL_AIR_ABSORPTION_FACTOR
:
1312 case AL_ROOM_ROLLOFF_FACTOR
:
1313 fvals
[0] = (ALfloat
)values
[0];
1314 SetSourcefv(Source
, Context
, param
, fvals
);
1317 case AL_SEC_OFFSET_LATENCY_SOFT
:
1318 fvals
[0] = (ALfloat
)values
[0];
1319 fvals
[1] = (ALfloat
)values
[1];
1320 SetSourcefv(Source
, Context
, param
, fvals
);
1326 fvals
[0] = (ALfloat
)values
[0];
1327 fvals
[1] = (ALfloat
)values
[1];
1328 fvals
[2] = (ALfloat
)values
[2];
1329 SetSourcefv(Source
, Context
, param
, fvals
);
1333 alSetError(Context
, AL_INVALID_ENUM
);
1336 ALCcontext_DecRef(Context
);
1340 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1342 ALCcontext
*Context
;
1345 Context
= GetContextRef();
1346 if(!Context
) return;
1348 if((Source
=LookupSource(Context
, source
)) == NULL
)
1349 alSetError(Context
, AL_INVALID_NAME
);
1352 case AL_MAX_DISTANCE
:
1353 case AL_ROLLOFF_FACTOR
:
1354 case AL_CONE_INNER_ANGLE
:
1355 case AL_CONE_OUTER_ANGLE
:
1356 case AL_REFERENCE_DISTANCE
:
1357 case AL_SOURCE_RELATIVE
:
1360 case AL_SOURCE_STATE
:
1362 case AL_SAMPLE_OFFSET
:
1363 case AL_BYTE_OFFSET
:
1364 case AL_DIRECT_FILTER
:
1365 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1366 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1367 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1368 case AL_DIRECT_CHANNELS_SOFT
:
1369 case AL_DISTANCE_MODEL
:
1370 SetSourceiv(Source
, Context
, param
, &value
);
1374 alSetError(Context
, AL_INVALID_ENUM
);
1377 ALCcontext_DecRef(Context
);
1380 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1382 ALCcontext
*Context
;
1386 Context
= GetContextRef();
1387 if(!Context
) return;
1389 if((Source
=LookupSource(Context
, source
)) == NULL
)
1390 alSetError(Context
, AL_INVALID_NAME
);
1396 case AL_AUXILIARY_SEND_FILTER
:
1400 SetSourceiv(Source
, Context
, param
, ivals
);
1404 alSetError(Context
, AL_INVALID_ENUM
);
1407 ALCcontext_DecRef(Context
);
1410 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1412 ALCcontext
*Context
;
1415 Context
= GetContextRef();
1416 if(!Context
) return;
1418 if((Source
=LookupSource(Context
, source
)) == NULL
)
1419 alSetError(Context
, AL_INVALID_NAME
);
1421 alSetError(Context
, AL_INVALID_VALUE
);
1424 case AL_SOURCE_RELATIVE
:
1425 case AL_CONE_INNER_ANGLE
:
1426 case AL_CONE_OUTER_ANGLE
:
1429 case AL_SOURCE_STATE
:
1431 case AL_SAMPLE_OFFSET
:
1432 case AL_BYTE_OFFSET
:
1433 case AL_MAX_DISTANCE
:
1434 case AL_ROLLOFF_FACTOR
:
1435 case AL_REFERENCE_DISTANCE
:
1436 case AL_DIRECT_FILTER
:
1437 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1438 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1439 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1440 case AL_DISTANCE_MODEL
:
1441 case AL_DIRECT_CHANNELS_SOFT
:
1446 case AL_AUXILIARY_SEND_FILTER
:
1447 SetSourceiv(Source
, Context
, param
, values
);
1451 alSetError(Context
, AL_INVALID_ENUM
);
1454 ALCcontext_DecRef(Context
);
1458 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1460 ALCcontext
*Context
;
1463 Context
= GetContextRef();
1464 if(!Context
) return;
1466 if((Source
=LookupSource(Context
, source
)) == NULL
)
1467 alSetError(Context
, AL_INVALID_NAME
);
1470 case AL_MAX_DISTANCE
:
1471 case AL_ROLLOFF_FACTOR
:
1472 case AL_CONE_INNER_ANGLE
:
1473 case AL_CONE_OUTER_ANGLE
:
1474 case AL_REFERENCE_DISTANCE
:
1475 case AL_SOURCE_RELATIVE
:
1477 case AL_SOURCE_STATE
:
1479 case AL_SAMPLE_OFFSET
:
1480 case AL_BYTE_OFFSET
:
1481 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1482 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1483 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1484 case AL_DIRECT_CHANNELS_SOFT
:
1485 case AL_DISTANCE_MODEL
:
1487 case AL_DIRECT_FILTER
:
1488 SetSourcei64v(Source
, Context
, param
, &value
);
1492 alSetError(Context
, AL_INVALID_ENUM
);
1495 ALCcontext_DecRef(Context
);
1498 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1500 ALCcontext
*Context
;
1502 ALint64SOFT i64vals
[3];
1504 Context
= GetContextRef();
1505 if(!Context
) return;
1507 if((Source
=LookupSource(Context
, source
)) == NULL
)
1508 alSetError(Context
, AL_INVALID_NAME
);
1514 case AL_AUXILIARY_SEND_FILTER
:
1515 i64vals
[0] = value1
;
1516 i64vals
[1] = value2
;
1517 i64vals
[2] = value3
;
1518 SetSourcei64v(Source
, Context
, param
, i64vals
);
1522 alSetError(Context
, AL_INVALID_ENUM
);
1525 ALCcontext_DecRef(Context
);
1528 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1530 ALCcontext
*Context
;
1533 Context
= GetContextRef();
1534 if(!Context
) return;
1536 if((Source
=LookupSource(Context
, source
)) == NULL
)
1537 alSetError(Context
, AL_INVALID_NAME
);
1539 alSetError(Context
, AL_INVALID_VALUE
);
1542 case AL_SOURCE_RELATIVE
:
1543 case AL_CONE_INNER_ANGLE
:
1544 case AL_CONE_OUTER_ANGLE
:
1546 case AL_SOURCE_STATE
:
1548 case AL_SAMPLE_OFFSET
:
1549 case AL_BYTE_OFFSET
:
1550 case AL_MAX_DISTANCE
:
1551 case AL_ROLLOFF_FACTOR
:
1552 case AL_REFERENCE_DISTANCE
:
1553 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1554 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1555 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1556 case AL_DISTANCE_MODEL
:
1557 case AL_DIRECT_CHANNELS_SOFT
:
1559 case AL_DIRECT_FILTER
:
1561 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1566 case AL_AUXILIARY_SEND_FILTER
:
1567 SetSourcei64v(Source
, Context
, param
, values
);
1571 alSetError(Context
, AL_INVALID_ENUM
);
1574 ALCcontext_DecRef(Context
);
1578 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1580 ALCcontext
*Context
;
1584 Context
= GetContextRef();
1585 if(!Context
) return;
1587 if((Source
=LookupSource(Context
, source
)) == NULL
)
1588 alSetError(Context
, AL_INVALID_NAME
);
1590 alSetError(Context
, AL_INVALID_VALUE
);
1597 case AL_MAX_DISTANCE
:
1598 case AL_ROLLOFF_FACTOR
:
1599 case AL_CONE_OUTER_GAIN
:
1600 case AL_CONE_OUTER_GAINHF
:
1602 case AL_SAMPLE_OFFSET
:
1603 case AL_BYTE_OFFSET
:
1604 case AL_CONE_INNER_ANGLE
:
1605 case AL_CONE_OUTER_ANGLE
:
1606 case AL_REFERENCE_DISTANCE
:
1607 case AL_AIR_ABSORPTION_FACTOR
:
1608 case AL_ROOM_ROLLOFF_FACTOR
:
1609 case AL_DOPPLER_FACTOR
:
1610 if(GetSourcedv(Source
, Context
, param
, &dval
) == AL_NO_ERROR
)
1611 *value
= (ALfloat
)dval
;
1615 alSetError(Context
, AL_INVALID_ENUM
);
1618 ALCcontext_DecRef(Context
);
1622 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1624 ALCcontext
*Context
;
1628 Context
= GetContextRef();
1629 if(!Context
) return;
1631 if((Source
=LookupSource(Context
, source
)) == NULL
)
1632 alSetError(Context
, AL_INVALID_NAME
);
1633 else if(!(value1
&& value2
&& value3
))
1634 alSetError(Context
, AL_INVALID_VALUE
);
1640 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1642 *value1
= (ALfloat
)dvals
[0];
1643 *value2
= (ALfloat
)dvals
[1];
1644 *value3
= (ALfloat
)dvals
[2];
1649 alSetError(Context
, AL_INVALID_ENUM
);
1652 ALCcontext_DecRef(Context
);
1656 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1658 ALCcontext
*Context
;
1668 case AL_MAX_DISTANCE
:
1669 case AL_ROLLOFF_FACTOR
:
1670 case AL_DOPPLER_FACTOR
:
1671 case AL_CONE_OUTER_GAIN
:
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_CONE_OUTER_GAINHF
:
1679 case AL_AIR_ABSORPTION_FACTOR
:
1680 case AL_ROOM_ROLLOFF_FACTOR
:
1681 alGetSourcef(source
, param
, values
);
1687 alGetSource3f(source
, param
, values
+0, values
+1, values
+2);
1691 Context
= GetContextRef();
1692 if(!Context
) return;
1694 if((Source
=LookupSource(Context
, source
)) == NULL
)
1695 alSetError(Context
, AL_INVALID_NAME
);
1697 alSetError(Context
, AL_INVALID_VALUE
);
1700 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1701 case AL_BYTE_RW_OFFSETS_SOFT
:
1702 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1704 values
[0] = (ALfloat
)dvals
[0];
1705 values
[1] = (ALfloat
)dvals
[1];
1710 alSetError(Context
, AL_INVALID_ENUM
);
1713 ALCcontext_DecRef(Context
);
1717 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1719 ALCcontext
*Context
;
1722 Context
= GetContextRef();
1723 if(!Context
) return;
1725 if((Source
=LookupSource(Context
, source
)) == NULL
)
1726 alSetError(Context
, AL_INVALID_NAME
);
1728 alSetError(Context
, AL_INVALID_VALUE
);
1735 case AL_MAX_DISTANCE
:
1736 case AL_ROLLOFF_FACTOR
:
1737 case AL_CONE_OUTER_GAIN
:
1738 case AL_CONE_OUTER_GAINHF
:
1740 case AL_SAMPLE_OFFSET
:
1741 case AL_BYTE_OFFSET
:
1742 case AL_CONE_INNER_ANGLE
:
1743 case AL_CONE_OUTER_ANGLE
:
1744 case AL_REFERENCE_DISTANCE
:
1745 case AL_AIR_ABSORPTION_FACTOR
:
1746 case AL_ROOM_ROLLOFF_FACTOR
:
1747 case AL_DOPPLER_FACTOR
:
1748 GetSourcedv(Source
, Context
, param
, value
);
1752 alSetError(Context
, AL_INVALID_ENUM
);
1755 ALCcontext_DecRef(Context
);
1758 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1760 ALCcontext
*Context
;
1764 Context
= GetContextRef();
1765 if(!Context
) return;
1767 if((Source
=LookupSource(Context
, source
)) == NULL
)
1768 alSetError(Context
, AL_INVALID_NAME
);
1769 else if(!(value1
&& value2
&& value3
))
1770 alSetError(Context
, AL_INVALID_VALUE
);
1776 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1785 alSetError(Context
, AL_INVALID_ENUM
);
1788 ALCcontext_DecRef(Context
);
1791 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1793 ALCcontext
*Context
;
1796 Context
= GetContextRef();
1797 if(!Context
) return;
1799 if((Source
=LookupSource(Context
, source
)) == NULL
)
1800 alSetError(Context
, AL_INVALID_NAME
);
1802 alSetError(Context
, AL_INVALID_VALUE
);
1809 case AL_MAX_DISTANCE
:
1810 case AL_ROLLOFF_FACTOR
:
1811 case AL_DOPPLER_FACTOR
:
1812 case AL_CONE_OUTER_GAIN
:
1814 case AL_SAMPLE_OFFSET
:
1815 case AL_BYTE_OFFSET
:
1816 case AL_CONE_INNER_ANGLE
:
1817 case AL_CONE_OUTER_ANGLE
:
1818 case AL_REFERENCE_DISTANCE
:
1819 case AL_CONE_OUTER_GAINHF
:
1820 case AL_AIR_ABSORPTION_FACTOR
:
1821 case AL_ROOM_ROLLOFF_FACTOR
:
1823 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1824 case AL_BYTE_RW_OFFSETS_SOFT
:
1825 case AL_SEC_OFFSET_LATENCY_SOFT
:
1830 GetSourcedv(Source
, Context
, param
, values
);
1834 alSetError(Context
, AL_INVALID_ENUM
);
1837 ALCcontext_DecRef(Context
);
1841 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1843 ALCcontext
*Context
;
1846 Context
= GetContextRef();
1847 if(!Context
) return;
1849 if((Source
=LookupSource(Context
, source
)) == NULL
)
1850 alSetError(Context
, AL_INVALID_NAME
);
1852 alSetError(Context
, AL_INVALID_VALUE
);
1855 case AL_MAX_DISTANCE
:
1856 case AL_ROLLOFF_FACTOR
:
1857 case AL_REFERENCE_DISTANCE
:
1858 case AL_SOURCE_RELATIVE
:
1859 case AL_CONE_INNER_ANGLE
:
1860 case AL_CONE_OUTER_ANGLE
:
1863 case AL_SOURCE_STATE
:
1864 case AL_BUFFERS_QUEUED
:
1865 case AL_BUFFERS_PROCESSED
:
1866 case AL_SOURCE_TYPE
:
1868 case AL_SAMPLE_OFFSET
:
1869 case AL_BYTE_OFFSET
:
1870 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1871 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1872 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1873 case AL_DOPPLER_FACTOR
:
1874 case AL_DIRECT_CHANNELS_SOFT
:
1875 case AL_DISTANCE_MODEL
:
1876 GetSourceiv(Source
, Context
, param
, value
);
1880 alSetError(Context
, AL_INVALID_ENUM
);
1883 ALCcontext_DecRef(Context
);
1887 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1889 ALCcontext
*Context
;
1893 Context
= GetContextRef();
1894 if(!Context
) return;
1896 if((Source
=LookupSource(Context
, source
)) == NULL
)
1897 alSetError(Context
, AL_INVALID_NAME
);
1898 else if(!(value1
&& value2
&& value3
))
1899 alSetError(Context
, AL_INVALID_VALUE
);
1905 if(GetSourceiv(Source
, Context
, param
, ivals
) == AL_NO_ERROR
)
1914 alSetError(Context
, AL_INVALID_ENUM
);
1917 ALCcontext_DecRef(Context
);
1921 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1923 ALCcontext
*Context
;
1926 Context
= GetContextRef();
1927 if(!Context
) return;
1929 if((Source
=LookupSource(Context
, source
)) == NULL
)
1930 alSetError(Context
, AL_INVALID_NAME
);
1932 alSetError(Context
, AL_INVALID_VALUE
);
1935 case AL_SOURCE_RELATIVE
:
1936 case AL_CONE_INNER_ANGLE
:
1937 case AL_CONE_OUTER_ANGLE
:
1940 case AL_SOURCE_STATE
:
1941 case AL_BUFFERS_QUEUED
:
1942 case AL_BUFFERS_PROCESSED
:
1944 case AL_SAMPLE_OFFSET
:
1945 case AL_BYTE_OFFSET
:
1946 case AL_MAX_DISTANCE
:
1947 case AL_ROLLOFF_FACTOR
:
1948 case AL_DOPPLER_FACTOR
:
1949 case AL_REFERENCE_DISTANCE
:
1950 case AL_SOURCE_TYPE
:
1951 case AL_DIRECT_FILTER
:
1952 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1953 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1954 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1955 case AL_DISTANCE_MODEL
:
1956 case AL_DIRECT_CHANNELS_SOFT
:
1958 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1959 case AL_BYTE_RW_OFFSETS_SOFT
:
1964 GetSourceiv(Source
, Context
, param
, values
);
1968 alSetError(Context
, AL_INVALID_ENUM
);
1971 ALCcontext_DecRef(Context
);
1975 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
1977 ALCcontext
*Context
;
1980 Context
= GetContextRef();
1981 if(!Context
) return;
1983 if((Source
=LookupSource(Context
, source
)) == NULL
)
1984 alSetError(Context
, AL_INVALID_NAME
);
1986 alSetError(Context
, AL_INVALID_VALUE
);
1989 case AL_MAX_DISTANCE
:
1990 case AL_ROLLOFF_FACTOR
:
1991 case AL_REFERENCE_DISTANCE
:
1992 case AL_SOURCE_RELATIVE
:
1993 case AL_CONE_INNER_ANGLE
:
1994 case AL_CONE_OUTER_ANGLE
:
1997 case AL_SOURCE_STATE
:
1998 case AL_BUFFERS_QUEUED
:
1999 case AL_BUFFERS_PROCESSED
:
2000 case AL_SOURCE_TYPE
:
2002 case AL_SAMPLE_OFFSET
:
2003 case AL_BYTE_OFFSET
:
2004 case AL_DIRECT_FILTER_GAINHF_AUTO
:
2005 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
2006 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
2007 case AL_DOPPLER_FACTOR
:
2008 case AL_DIRECT_CHANNELS_SOFT
:
2009 case AL_DISTANCE_MODEL
:
2010 GetSourcei64v(Source
, Context
, param
, value
);
2014 alSetError(Context
, AL_INVALID_ENUM
);
2017 ALCcontext_DecRef(Context
);
2020 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
2022 ALCcontext
*Context
;
2026 Context
= GetContextRef();
2027 if(!Context
) return;
2029 if((Source
=LookupSource(Context
, source
)) == NULL
)
2030 alSetError(Context
, AL_INVALID_NAME
);
2031 else if(!(value1
&& value2
&& value3
))
2032 alSetError(Context
, AL_INVALID_VALUE
);
2038 if(GetSourcei64v(Source
, Context
, param
, i64vals
) == AL_NO_ERROR
)
2040 *value1
= i64vals
[0];
2041 *value2
= i64vals
[1];
2042 *value3
= i64vals
[2];
2047 alSetError(Context
, AL_INVALID_ENUM
);
2050 ALCcontext_DecRef(Context
);
2053 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
2055 ALCcontext
*Context
;
2058 Context
= GetContextRef();
2059 if(!Context
) return;
2061 if((Source
=LookupSource(Context
, source
)) == NULL
)
2062 alSetError(Context
, AL_INVALID_NAME
);
2064 alSetError(Context
, AL_INVALID_VALUE
);
2067 case AL_MAX_DISTANCE
:
2068 case AL_ROLLOFF_FACTOR
:
2069 case AL_REFERENCE_DISTANCE
:
2070 case AL_SOURCE_RELATIVE
:
2071 case AL_CONE_INNER_ANGLE
:
2072 case AL_CONE_OUTER_ANGLE
:
2075 case AL_SOURCE_STATE
:
2076 case AL_BUFFERS_QUEUED
:
2077 case AL_BUFFERS_PROCESSED
:
2078 case AL_SOURCE_TYPE
:
2080 case AL_SAMPLE_OFFSET
:
2081 case AL_BYTE_OFFSET
:
2082 case AL_DIRECT_FILTER_GAINHF_AUTO
:
2083 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
2084 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
2085 case AL_DOPPLER_FACTOR
:
2086 case AL_DIRECT_CHANNELS_SOFT
:
2087 case AL_DISTANCE_MODEL
:
2089 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2090 case AL_BYTE_RW_OFFSETS_SOFT
:
2091 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
2096 GetSourcei64v(Source
, Context
, param
, values
);
2100 alSetError(Context
, AL_INVALID_ENUM
);
2103 ALCcontext_DecRef(Context
);
2107 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
2109 alSourcePlayv(1, &source
);
2111 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2113 ALCcontext
*Context
;
2117 Context
= GetContextRef();
2118 if(!Context
) return;
2122 CHECK_VALUE(Context
, n
>= 0);
2123 for(i
= 0;i
< n
;i
++)
2125 if(!LookupSource(Context
, sources
[i
]))
2126 al_throwerr(Context
, AL_INVALID_NAME
);
2129 LockContext(Context
);
2130 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
2135 newcount
= Context
->MaxActiveSources
<< 1;
2137 temp
= realloc(Context
->ActiveSources
,
2138 sizeof(*Context
->ActiveSources
) * newcount
);
2141 UnlockContext(Context
);
2142 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
2145 Context
->ActiveSources
= temp
;
2146 Context
->MaxActiveSources
= newcount
;
2149 for(i
= 0;i
< n
;i
++)
2151 Source
= LookupSource(Context
, sources
[i
]);
2152 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
2153 else SetSourceState(Source
, Context
, AL_PLAYING
);
2155 UnlockContext(Context
);
2159 ALCcontext_DecRef(Context
);
2162 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2164 alSourcePausev(1, &source
);
2166 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2168 ALCcontext
*Context
;
2172 Context
= GetContextRef();
2173 if(!Context
) return;
2177 CHECK_VALUE(Context
, n
>= 0);
2178 for(i
= 0;i
< n
;i
++)
2180 if(!LookupSource(Context
, sources
[i
]))
2181 al_throwerr(Context
, AL_INVALID_NAME
);
2184 LockContext(Context
);
2185 for(i
= 0;i
< n
;i
++)
2187 Source
= LookupSource(Context
, sources
[i
]);
2188 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
2189 else SetSourceState(Source
, Context
, AL_PAUSED
);
2191 UnlockContext(Context
);
2195 ALCcontext_DecRef(Context
);
2198 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2200 alSourceStopv(1, &source
);
2202 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2204 ALCcontext
*Context
;
2208 Context
= GetContextRef();
2209 if(!Context
) return;
2213 CHECK_VALUE(Context
, n
>= 0);
2214 for(i
= 0;i
< n
;i
++)
2216 if(!LookupSource(Context
, sources
[i
]))
2217 al_throwerr(Context
, AL_INVALID_NAME
);
2220 LockContext(Context
);
2221 for(i
= 0;i
< n
;i
++)
2223 Source
= LookupSource(Context
, sources
[i
]);
2224 Source
->new_state
= AL_NONE
;
2225 SetSourceState(Source
, Context
, AL_STOPPED
);
2227 UnlockContext(Context
);
2231 ALCcontext_DecRef(Context
);
2234 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2236 alSourceRewindv(1, &source
);
2238 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2240 ALCcontext
*Context
;
2244 Context
= GetContextRef();
2245 if(!Context
) return;
2249 CHECK_VALUE(Context
, n
>= 0);
2250 for(i
= 0;i
< n
;i
++)
2252 if(!LookupSource(Context
, sources
[i
]))
2253 al_throwerr(Context
, AL_INVALID_NAME
);
2256 LockContext(Context
);
2257 for(i
= 0;i
< n
;i
++)
2259 Source
= LookupSource(Context
, sources
[i
]);
2260 Source
->new_state
= AL_NONE
;
2261 SetSourceState(Source
, Context
, AL_INITIAL
);
2263 UnlockContext(Context
);
2267 ALCcontext_DecRef(Context
);
2271 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei nb
, const ALuint
*buffers
)
2273 ALCcontext
*Context
;
2276 ALbufferlistitem
*BufferListStart
= NULL
;
2277 ALbufferlistitem
*BufferList
;
2278 ALbuffer
*BufferFmt
;
2283 Context
= GetContextRef();
2284 if(!Context
) return;
2288 ALCdevice
*device
= Context
->Device
;
2290 CHECK_VALUE(Context
, nb
>= 0);
2292 if((Source
=LookupSource(Context
, source
)) == NULL
)
2293 al_throwerr(Context
, AL_INVALID_NAME
);
2295 LockContext(Context
);
2296 if(Source
->SourceType
== AL_STATIC
)
2298 UnlockContext(Context
);
2299 /* Can't queue on a Static Source */
2300 al_throwerr(Context
, AL_INVALID_OPERATION
);
2305 /* Check for a valid Buffer, for its frequency and format */
2306 BufferList
= Source
->queue
;
2309 if(BufferList
->buffer
)
2311 BufferFmt
= BufferList
->buffer
;
2314 BufferList
= BufferList
->next
;
2317 for(i
= 0;i
< nb
;i
++)
2319 ALbuffer
*buffer
= NULL
;
2320 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2322 UnlockContext(Context
);
2323 al_throwerr(Context
, AL_INVALID_NAME
);
2326 if(!BufferListStart
)
2328 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2329 BufferListStart
->buffer
= buffer
;
2330 BufferListStart
->next
= NULL
;
2331 BufferListStart
->prev
= NULL
;
2332 BufferList
= BufferListStart
;
2336 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2337 BufferList
->next
->buffer
= buffer
;
2338 BufferList
->next
->next
= NULL
;
2339 BufferList
->next
->prev
= BufferList
;
2340 BufferList
= BufferList
->next
;
2342 if(!buffer
) continue;
2343 IncrementRef(&buffer
->ref
);
2345 ReadLock(&buffer
->lock
);
2346 if(BufferFmt
== NULL
)
2350 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2351 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2352 if(buffer
->FmtChannels
== FmtMono
)
2353 Source
->Update
= CalcSourceParams
;
2355 Source
->Update
= CalcNonAttnSourceParams
;
2357 Source
->NeedsUpdate
= AL_TRUE
;
2359 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2360 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2361 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2363 ReadUnlock(&buffer
->lock
);
2364 UnlockContext(Context
);
2365 al_throwerr(Context
, AL_INVALID_OPERATION
);
2367 ReadUnlock(&buffer
->lock
);
2370 /* Source is now streaming */
2371 Source
->SourceType
= AL_STREAMING
;
2373 if(Source
->queue
== NULL
)
2374 Source
->queue
= BufferListStart
;
2377 /* Append to the end of the queue */
2378 BufferList
= Source
->queue
;
2379 while(BufferList
->next
!= NULL
)
2380 BufferList
= BufferList
->next
;
2382 BufferListStart
->prev
= BufferList
;
2383 BufferList
->next
= BufferListStart
;
2386 Source
->BuffersInQueue
+= nb
;
2388 UnlockContext(Context
);
2392 while(BufferListStart
)
2394 BufferList
= BufferListStart
;
2395 BufferListStart
= BufferList
->next
;
2397 if(BufferList
->buffer
)
2398 DecrementRef(&BufferList
->buffer
->ref
);
2404 ALCcontext_DecRef(Context
);
2407 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint source
, ALsizei nb
, ALuint
*buffers
)
2409 ALCcontext
*Context
;
2412 ALbufferlistitem
*BufferList
;
2417 Context
= GetContextRef();
2418 if(!Context
) return;
2422 CHECK_VALUE(Context
, nb
>= 0);
2424 if((Source
=LookupSource(Context
, source
)) == NULL
)
2425 al_throwerr(Context
, AL_INVALID_NAME
);
2427 LockContext(Context
);
2428 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
||
2429 (ALuint
)nb
> Source
->BuffersPlayed
)
2431 UnlockContext(Context
);
2432 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2433 al_throwerr(Context
, AL_INVALID_VALUE
);
2436 for(i
= 0;i
< nb
;i
++)
2438 BufferList
= Source
->queue
;
2439 Source
->queue
= BufferList
->next
;
2440 Source
->BuffersInQueue
--;
2441 Source
->BuffersPlayed
--;
2443 if(BufferList
->buffer
)
2445 buffers
[i
] = BufferList
->buffer
->id
;
2446 DecrementRef(&BufferList
->buffer
->ref
);
2454 Source
->queue
->prev
= NULL
;
2455 UnlockContext(Context
);
2459 ALCcontext_DecRef(Context
);
2463 static ALvoid
InitSourceParams(ALsource
*Source
)
2467 Source
->InnerAngle
= 360.0f
;
2468 Source
->OuterAngle
= 360.0f
;
2469 Source
->Pitch
= 1.0f
;
2470 Source
->Position
[0] = 0.0f
;
2471 Source
->Position
[1] = 0.0f
;
2472 Source
->Position
[2] = 0.0f
;
2473 Source
->Orientation
[0] = 0.0f
;
2474 Source
->Orientation
[1] = 0.0f
;
2475 Source
->Orientation
[2] = 0.0f
;
2476 Source
->Velocity
[0] = 0.0f
;
2477 Source
->Velocity
[1] = 0.0f
;
2478 Source
->Velocity
[2] = 0.0f
;
2479 Source
->RefDistance
= 1.0f
;
2480 Source
->MaxDistance
= FLT_MAX
;
2481 Source
->RollOffFactor
= 1.0f
;
2482 Source
->Looping
= AL_FALSE
;
2483 Source
->Gain
= 1.0f
;
2484 Source
->MinGain
= 0.0f
;
2485 Source
->MaxGain
= 1.0f
;
2486 Source
->OuterGain
= 0.0f
;
2487 Source
->OuterGainHF
= 1.0f
;
2489 Source
->DryGainHFAuto
= AL_TRUE
;
2490 Source
->WetGainAuto
= AL_TRUE
;
2491 Source
->WetGainHFAuto
= AL_TRUE
;
2492 Source
->AirAbsorptionFactor
= 0.0f
;
2493 Source
->RoomRolloffFactor
= 0.0f
;
2494 Source
->DopplerFactor
= 1.0f
;
2495 Source
->DirectChannels
= AL_FALSE
;
2497 Source
->DistanceModel
= DefaultDistanceModel
;
2499 Source
->Resampler
= DefaultResampler
;
2501 Source
->state
= AL_INITIAL
;
2502 Source
->new_state
= AL_NONE
;
2503 Source
->SourceType
= AL_UNDETERMINED
;
2504 Source
->Offset
= -1.0;
2506 Source
->DirectGain
= 1.0f
;
2507 Source
->DirectGainHF
= 1.0f
;
2508 for(i
= 0;i
< MAX_SENDS
;i
++)
2510 Source
->Send
[i
].Gain
= 1.0f
;
2511 Source
->Send
[i
].GainHF
= 1.0f
;
2514 Source
->NeedsUpdate
= AL_TRUE
;
2516 Source
->Hrtf
.Moving
= AL_FALSE
;
2517 Source
->Hrtf
.Counter
= 0;
2523 * Sets the source's new play state given its current state.
2525 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2527 if(state
== AL_PLAYING
)
2529 ALbufferlistitem
*BufferList
;
2532 /* Check that there is a queue containing at least one valid, non zero
2534 BufferList
= Source
->queue
;
2537 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
2539 BufferList
= BufferList
->next
;
2542 if(Source
->state
!= AL_PLAYING
)
2544 for(j
= 0;j
< MaxChannels
;j
++)
2546 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
2547 Source
->Hrtf
.History
[j
][k
] = 0.0f
;
2548 for(k
= 0;k
< HRIR_LENGTH
;k
++)
2550 Source
->Hrtf
.Values
[j
][k
][0] = 0.0f
;
2551 Source
->Hrtf
.Values
[j
][k
][1] = 0.0f
;
2556 if(Source
->state
!= AL_PAUSED
)
2558 Source
->state
= AL_PLAYING
;
2559 Source
->position
= 0;
2560 Source
->position_fraction
= 0;
2561 Source
->BuffersPlayed
= 0;
2564 Source
->state
= AL_PLAYING
;
2566 // Check if an Offset has been set
2567 if(Source
->Offset
>= 0.0)
2568 ApplyOffset(Source
);
2570 /* If there's nothing to play, or device is disconnected, go right to
2572 if(!BufferList
|| !Context
->Device
->Connected
)
2574 SetSourceState(Source
, Context
, AL_STOPPED
);
2578 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
2580 if(Context
->ActiveSources
[j
] == Source
)
2583 if(j
== Context
->ActiveSourceCount
)
2584 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
2586 else if(state
== AL_PAUSED
)
2588 if(Source
->state
== AL_PLAYING
)
2590 Source
->state
= AL_PAUSED
;
2591 Source
->Hrtf
.Moving
= AL_FALSE
;
2592 Source
->Hrtf
.Counter
= 0;
2595 else if(state
== AL_STOPPED
)
2597 if(Source
->state
!= AL_INITIAL
)
2599 Source
->state
= AL_STOPPED
;
2600 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
2601 Source
->Hrtf
.Moving
= AL_FALSE
;
2602 Source
->Hrtf
.Counter
= 0;
2604 Source
->Offset
= -1.0;
2606 else if(state
== AL_INITIAL
)
2608 if(Source
->state
!= AL_INITIAL
)
2610 Source
->state
= AL_INITIAL
;
2611 Source
->position
= 0;
2612 Source
->position_fraction
= 0;
2613 Source
->BuffersPlayed
= 0;
2614 Source
->Hrtf
.Moving
= AL_FALSE
;
2615 Source
->Hrtf
.Counter
= 0;
2617 Source
->Offset
= -1.0;
2623 * Gets the current read offset for the given Source, in 32.32 fixed-point
2624 * samples. The offset is relative to the start of the queue (not the start of
2625 * the current buffer).
2627 static ALint64
GetSourceOffset(const ALsource
*Source
)
2629 const ALbufferlistitem
*BufferList
;
2633 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2636 /* NOTE: This is the offset into the *current* buffer, so add the length of
2637 * any played buffers */
2638 readPos
= (ALuint64
)Source
->position
<< 32;
2639 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2640 BufferList
= Source
->queue
;
2641 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2643 if(BufferList
->buffer
)
2644 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2645 BufferList
= BufferList
->next
;
2648 return (ALint64
)minu64(readPos
, MAKEU64(0x7fffffff,0xffffffff));
2651 /* GetSourceSecOffset
2653 * Gets the current read offset for the given Source, in seconds. The offset is
2654 * relative to the start of the queue (not the start of the current buffer).
2656 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2658 const ALbufferlistitem
*BufferList
;
2659 const ALbuffer
*Buffer
= NULL
;
2663 BufferList
= Source
->queue
;
2666 if(BufferList
->buffer
)
2668 Buffer
= BufferList
->buffer
;
2671 BufferList
= BufferList
->next
;
2674 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2677 /* NOTE: This is the offset into the *current* buffer, so add the length of
2678 * any played buffers */
2679 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2680 readPos
|= (ALuint64
)Source
->position_fraction
;
2681 BufferList
= Source
->queue
;
2682 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2684 if(BufferList
->buffer
)
2685 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< FRACTIONBITS
;
2686 BufferList
= BufferList
->next
;
2689 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2694 * Gets the current read and write offsets for the given Source, in the
2695 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2696 * the start of the queue (not the start of the current buffer).
2698 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2700 const ALbufferlistitem
*BufferList
;
2701 const ALbuffer
*Buffer
= NULL
;
2702 ALuint readPos
, writePos
;
2703 ALuint totalBufferLen
;
2706 // Find the first valid Buffer in the Queue
2707 BufferList
= Source
->queue
;
2710 if(BufferList
->buffer
)
2712 Buffer
= BufferList
->buffer
;
2715 BufferList
= BufferList
->next
;
2718 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2725 if(updateLen
> 0.0 && updateLen
< 0.015)
2728 /* NOTE: This is the offset into the *current* buffer, so add the length of
2729 * any played buffers */
2730 readPos
= Source
->position
;
2732 BufferList
= Source
->queue
;
2733 for(i
= 0;BufferList
;i
++)
2735 if(BufferList
->buffer
)
2737 if(i
< Source
->BuffersPlayed
)
2738 readPos
+= BufferList
->buffer
->SampleLen
;
2739 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
2741 BufferList
= BufferList
->next
;
2743 if(Source
->state
== AL_PLAYING
)
2744 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2750 readPos
%= totalBufferLen
;
2751 writePos
%= totalBufferLen
;
2755 /* Wrap positions back to 0 */
2756 if(readPos
>= totalBufferLen
)
2758 if(writePos
>= totalBufferLen
)
2765 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2766 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2769 case AL_SAMPLE_OFFSET
:
2770 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2771 offset
[0] = (ALdouble
)readPos
;
2772 offset
[1] = (ALdouble
)writePos
;
2775 case AL_BYTE_OFFSET
:
2776 case AL_BYTE_RW_OFFSETS_SOFT
:
2777 if(Buffer
->OriginalType
== UserFmtIMA4
)
2779 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
2780 ALuint FrameBlockSize
= 65;
2782 /* Round down to nearest ADPCM block */
2783 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2784 if(Source
->state
!= AL_PLAYING
)
2785 offset
[1] = offset
[0];
2788 /* Round up to nearest ADPCM block */
2789 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2790 FrameBlockSize
* BlockSize
);
2795 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2796 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2797 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2806 * Apply the stored playback offset to the Source. This function will update
2807 * the number of buffers "played" given the stored offset.
2809 ALboolean
ApplyOffset(ALsource
*Source
)
2811 const ALbufferlistitem
*BufferList
;
2812 const ALbuffer
*Buffer
;
2813 ALint bufferLen
, totalBufferLen
;
2814 ALint buffersPlayed
;
2817 /* Get sample frame offset */
2818 offset
= GetSampleOffset(Source
);
2825 BufferList
= Source
->queue
;
2828 Buffer
= BufferList
->buffer
;
2829 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2831 if(bufferLen
<= offset
-totalBufferLen
)
2833 /* Offset is past this buffer so increment to the next buffer */
2836 else if(totalBufferLen
<= offset
)
2838 /* Offset is in this buffer */
2839 Source
->BuffersPlayed
= buffersPlayed
;
2841 Source
->position
= offset
- totalBufferLen
;
2842 Source
->position_fraction
= 0;
2846 totalBufferLen
+= bufferLen
;
2848 BufferList
= BufferList
->next
;
2851 /* Offset is out of range of the queue */
2858 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2859 * Second offset supplied by the application). This takes into account the fact
2860 * that the buffer format may have been modifed since.
2862 static ALint
GetSampleOffset(ALsource
*Source
)
2864 const ALbuffer
*Buffer
= NULL
;
2865 const ALbufferlistitem
*BufferList
;
2868 /* Find the first valid Buffer in the Queue */
2869 BufferList
= Source
->queue
;
2872 if(BufferList
->buffer
)
2874 Buffer
= BufferList
->buffer
;
2877 BufferList
= BufferList
->next
;
2882 Source
->Offset
= -1.0;
2886 switch(Source
->OffsetType
)
2888 case AL_BYTE_OFFSET
:
2889 /* Determine the ByteOffset (and ensure it is block aligned) */
2890 Offset
= (ALint
)Source
->Offset
;
2891 if(Buffer
->OriginalType
== UserFmtIMA4
)
2893 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2897 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2900 case AL_SAMPLE_OFFSET
:
2901 Offset
= (ALint
)Source
->Offset
;
2905 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2908 Source
->Offset
= -1.0;
2916 * Destroys all sources in the source map.
2918 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2922 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2924 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2925 Context
->SourceMap
.array
[pos
].value
= NULL
;
2927 while(temp
->queue
!= NULL
)
2929 ALbufferlistitem
*BufferList
= temp
->queue
;
2930 temp
->queue
= BufferList
->next
;
2932 if(BufferList
->buffer
!= NULL
)
2933 DecrementRef(&BufferList
->buffer
->ref
);
2937 for(j
= 0;j
< MAX_SENDS
;++j
)
2939 if(temp
->Send
[j
].Slot
)
2940 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2941 temp
->Send
[j
].Slot
= NULL
;
2944 FreeThunkEntry(temp
->id
);
2945 memset(temp
, 0, sizeof(*temp
));