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 typedef enum SrcIntProp
{
105 sivMaxDistance
= AL_MAX_DISTANCE
,
106 sivRolloffFactor
= AL_ROLLOFF_FACTOR
,
107 sivRefDistance
= AL_REFERENCE_DISTANCE
,
108 sivSourceRelative
= AL_SOURCE_RELATIVE
,
109 sivConeInnerAngle
= AL_CONE_INNER_ANGLE
,
110 sivConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
111 sivLooping
= AL_LOOPING
,
112 sivBuffer
= AL_BUFFER
,
113 sivSourceState
= AL_SOURCE_STATE
,
114 sivBuffersQueued
= AL_BUFFERS_QUEUED
,
115 sivBuffersProcessed
= AL_BUFFERS_PROCESSED
,
116 sivSourceType
= AL_SOURCE_TYPE
,
117 sivSecOffset
= AL_SEC_OFFSET
,
118 sivSampleOffset
= AL_SAMPLE_OFFSET
,
119 sivByteOffset
= AL_BYTE_OFFSET
,
120 sivDopplerFactor
= AL_DOPPLER_FACTOR
,
121 sivPosition
= AL_POSITION
,
122 sivVelocity
= AL_VELOCITY
,
123 sivDirection
= AL_DIRECTION
,
126 sivDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
127 sivAuxSendFilterGainAutio
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
128 sivAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
129 sivDirectFilter
= AL_DIRECT_FILTER
,
130 sivAuxSendFilter
= AL_AUXILIARY_SEND_FILTER
,
132 /* AL_SOFT_direct_channels */
133 sivDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
135 /* AL_EXT_source_distance_model */
136 sivDistanceModel
= AL_DISTANCE_MODEL
,
138 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
139 sivSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
140 sivByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
142 /* AL_SOFT_source_latency */
143 sivSampleOffsetLatencySOFT
= AL_SAMPLE_OFFSET_LATENCY_SOFT
,
146 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
);
147 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
);
148 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
);
150 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
);
151 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
);
152 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
);
155 #define RETERR(x) do { \
156 alSetError(Context, (x)); \
160 #define CHECKVAL(x) do { \
162 RETERR(AL_INVALID_VALUE); \
165 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
)
172 CHECKVAL(*values
>= 0.0f
);
174 Source
->Pitch
= *values
;
175 Source
->NeedsUpdate
= AL_TRUE
;
178 case AL_CONE_INNER_ANGLE
:
179 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
181 Source
->InnerAngle
= *values
;
182 Source
->NeedsUpdate
= AL_TRUE
;
185 case AL_CONE_OUTER_ANGLE
:
186 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
188 Source
->OuterAngle
= *values
;
189 Source
->NeedsUpdate
= AL_TRUE
;
193 CHECKVAL(*values
>= 0.0f
);
195 Source
->Gain
= *values
;
196 Source
->NeedsUpdate
= AL_TRUE
;
199 case AL_MAX_DISTANCE
:
200 CHECKVAL(*values
>= 0.0f
);
202 Source
->MaxDistance
= *values
;
203 Source
->NeedsUpdate
= AL_TRUE
;
206 case AL_ROLLOFF_FACTOR
:
207 CHECKVAL(*values
>= 0.0f
);
209 Source
->RollOffFactor
= *values
;
210 Source
->NeedsUpdate
= AL_TRUE
;
213 case AL_REFERENCE_DISTANCE
:
214 CHECKVAL(*values
>= 0.0f
);
216 Source
->RefDistance
= *values
;
217 Source
->NeedsUpdate
= AL_TRUE
;
221 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
223 Source
->MinGain
= *values
;
224 Source
->NeedsUpdate
= AL_TRUE
;
228 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
230 Source
->MaxGain
= *values
;
231 Source
->NeedsUpdate
= AL_TRUE
;
234 case AL_CONE_OUTER_GAIN
:
235 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
237 Source
->OuterGain
= *values
;
238 Source
->NeedsUpdate
= AL_TRUE
;
241 case AL_CONE_OUTER_GAINHF
:
242 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
244 Source
->OuterGainHF
= *values
;
245 Source
->NeedsUpdate
= AL_TRUE
;
248 case AL_AIR_ABSORPTION_FACTOR
:
249 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
251 Source
->AirAbsorptionFactor
= *values
;
252 Source
->NeedsUpdate
= AL_TRUE
;
255 case AL_ROOM_ROLLOFF_FACTOR
:
256 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
258 Source
->RoomRolloffFactor
= *values
;
259 Source
->NeedsUpdate
= AL_TRUE
;
262 case AL_DOPPLER_FACTOR
:
263 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
265 Source
->DopplerFactor
= *values
;
266 Source
->NeedsUpdate
= AL_TRUE
;
270 case AL_SAMPLE_OFFSET
:
272 CHECKVAL(*values
>= 0.0f
);
274 LockContext(Context
);
275 Source
->OffsetType
= prop
;
276 Source
->Offset
= *values
;
278 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
279 !Context
->DeferUpdates
)
281 if(ApplyOffset(Source
) == AL_FALSE
)
283 UnlockContext(Context
);
284 RETERR(AL_INVALID_VALUE
);
287 UnlockContext(Context
);
291 case AL_SEC_OFFSET_LATENCY_SOFT
:
293 RETERR(AL_INVALID_OPERATION
);
297 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
299 LockContext(Context
);
300 Source
->Position
[0] = values
[0];
301 Source
->Position
[1] = values
[1];
302 Source
->Position
[2] = values
[2];
303 UnlockContext(Context
);
304 Source
->NeedsUpdate
= AL_TRUE
;
308 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
310 LockContext(Context
);
311 Source
->Velocity
[0] = values
[0];
312 Source
->Velocity
[1] = values
[1];
313 Source
->Velocity
[2] = values
[2];
314 UnlockContext(Context
);
315 Source
->NeedsUpdate
= AL_TRUE
;
319 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
321 LockContext(Context
);
322 Source
->Orientation
[0] = values
[0];
323 Source
->Orientation
[1] = values
[1];
324 Source
->Orientation
[2] = values
[2];
325 UnlockContext(Context
);
326 Source
->NeedsUpdate
= AL_TRUE
;
330 case sfvSampleRWOffsetsSOFT
:
331 case sfvByteRWOffsetsSOFT
:
332 RETERR(AL_INVALID_OPERATION
);
335 case sfvSourceRelative
:
339 case sfvDistanceModel
:
340 case sfvDirectFilterGainHFAuto
:
341 case sfvAuxSendFilterGainAuto
:
342 case sfvAuxSendFilterGainHFAuto
:
343 case sfvDirectChannelsSOFT
:
344 ival
= (ALint
)values
[0];
345 return SetSourceiv(Source
, Context
, prop
, &ival
);
348 case sfvBuffersQueued
:
349 case sfvBuffersProcessed
:
350 ival
= (ALint
)((ALuint
)values
[0]);
351 return SetSourceiv(Source
, Context
, prop
, &ival
);
354 ERR("Unexpected property: 0x%04x\n", prop
);
355 RETERR(AL_INVALID_ENUM
);
358 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
)
360 ALCdevice
*device
= Context
->Device
;
361 ALbuffer
*buffer
= NULL
;
362 ALfilter
*filter
= NULL
;
363 ALeffectslot
*slot
= NULL
;
364 ALbufferlistitem
*oldlist
;
369 case AL_SOURCE_RELATIVE
:
370 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
372 Source
->HeadRelative
= (ALboolean
)*values
;
373 Source
->NeedsUpdate
= AL_TRUE
;
377 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
379 Source
->Looping
= (ALboolean
)*values
;
383 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
385 LockContext(Context
);
386 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
388 UnlockContext(Context
);
389 RETERR(AL_INVALID_OPERATION
);
392 Source
->BuffersInQueue
= 0;
393 Source
->BuffersPlayed
= 0;
397 ALbufferlistitem
*BufferListItem
;
399 /* Source is now Static */
400 Source
->SourceType
= AL_STATIC
;
402 /* Add the selected buffer to a one-item queue */
403 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
404 BufferListItem
->buffer
= buffer
;
405 BufferListItem
->next
= NULL
;
406 BufferListItem
->prev
= NULL
;
407 IncrementRef(&buffer
->ref
);
409 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, BufferListItem
);
410 Source
->BuffersInQueue
= 1;
412 ReadLock(&buffer
->lock
);
413 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
414 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
415 ReadUnlock(&buffer
->lock
);
416 if(buffer
->FmtChannels
== FmtMono
)
417 Source
->Update
= CalcSourceParams
;
419 Source
->Update
= CalcNonAttnSourceParams
;
420 Source
->NeedsUpdate
= AL_TRUE
;
424 /* Source is now Undetermined */
425 Source
->SourceType
= AL_UNDETERMINED
;
426 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, NULL
);
429 /* Delete all elements in the previous queue */
430 while(oldlist
!= NULL
)
432 ALbufferlistitem
*temp
= oldlist
;
433 oldlist
= temp
->next
;
436 DecrementRef(&temp
->buffer
->ref
);
439 UnlockContext(Context
);
444 case sivBuffersQueued
:
445 case sivBuffersProcessed
:
447 RETERR(AL_INVALID_OPERATION
);
450 case AL_SAMPLE_OFFSET
:
452 CHECKVAL(*values
>= 0);
454 LockContext(Context
);
455 Source
->OffsetType
= prop
;
456 Source
->Offset
= *values
;
458 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
459 !Context
->DeferUpdates
)
461 if(ApplyOffset(Source
) == AL_FALSE
)
463 UnlockContext(Context
);
464 RETERR(AL_INVALID_VALUE
);
467 UnlockContext(Context
);
471 case sivSampleRWOffsetsSOFT
:
472 case sivByteRWOffsetsSOFT
:
473 case sivSampleOffsetLatencySOFT
:
475 RETERR(AL_INVALID_OPERATION
);
478 case AL_DIRECT_FILTER
:
479 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
481 LockContext(Context
);
484 Source
->DirectGain
= 1.0f
;
485 Source
->DirectGainHF
= 1.0f
;
489 Source
->DirectGain
= filter
->Gain
;
490 Source
->DirectGainHF
= filter
->GainHF
;
492 UnlockContext(Context
);
493 Source
->NeedsUpdate
= AL_TRUE
;
496 case AL_DIRECT_FILTER_GAINHF_AUTO
:
497 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
499 Source
->DryGainHFAuto
= *values
;
500 Source
->NeedsUpdate
= AL_TRUE
;
503 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
504 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
506 Source
->WetGainAuto
= *values
;
507 Source
->NeedsUpdate
= AL_TRUE
;
510 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
511 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
513 Source
->WetGainHFAuto
= *values
;
514 Source
->NeedsUpdate
= AL_TRUE
;
517 case AL_DIRECT_CHANNELS_SOFT
:
518 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
520 Source
->DirectChannels
= *values
;
521 Source
->NeedsUpdate
= AL_TRUE
;
524 case AL_DISTANCE_MODEL
:
525 CHECKVAL(*values
== AL_NONE
||
526 *values
== AL_INVERSE_DISTANCE
||
527 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
528 *values
== AL_LINEAR_DISTANCE
||
529 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
530 *values
== AL_EXPONENT_DISTANCE
||
531 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
533 Source
->DistanceModel
= *values
;
534 if(Context
->SourceDistanceModel
)
535 Source
->NeedsUpdate
= AL_TRUE
;
539 case AL_AUXILIARY_SEND_FILTER
:
540 LockContext(Context
);
541 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
542 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
543 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
545 UnlockContext(Context
);
546 RETERR(AL_INVALID_VALUE
);
549 /* Add refcount on the new slot, and release the previous slot */
550 if(slot
) IncrementRef(&slot
->ref
);
551 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
552 if(slot
) DecrementRef(&slot
->ref
);
557 Source
->Send
[values
[1]].Gain
= 1.0f
;
558 Source
->Send
[values
[1]].GainHF
= 1.0f
;
562 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
563 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
565 Source
->NeedsUpdate
= AL_TRUE
;
566 UnlockContext(Context
);
570 case AL_MAX_DISTANCE
:
571 case AL_ROLLOFF_FACTOR
:
572 case AL_CONE_INNER_ANGLE
:
573 case AL_CONE_OUTER_ANGLE
:
574 case AL_REFERENCE_DISTANCE
:
575 case sivDopplerFactor
:
576 fvals
[0] = (ALfloat
)*values
;
577 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
582 fvals
[0] = (ALfloat
)values
[0];
583 fvals
[1] = (ALfloat
)values
[1];
584 fvals
[2] = (ALfloat
)values
[2];
585 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
588 ERR("Unexpected property: 0x%04x\n", prop
);
589 RETERR(AL_INVALID_ENUM
);
592 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
)
599 case sivSampleRWOffsetsSOFT
:
600 case sivByteRWOffsetsSOFT
:
601 case sivSampleOffsetLatencySOFT
:
603 RETERR(AL_INVALID_OPERATION
);
607 case AL_SOURCE_RELATIVE
:
609 case AL_SOURCE_STATE
:
611 case AL_SAMPLE_OFFSET
:
613 case sivBuffersQueued
:
614 case sivBuffersProcessed
:
615 case AL_DIRECT_FILTER_GAINHF_AUTO
:
616 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
617 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
618 case AL_DIRECT_CHANNELS_SOFT
:
619 case AL_DISTANCE_MODEL
:
620 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
622 ivals
[0] = (ALint
)*values
;
623 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
627 case AL_DIRECT_FILTER
:
628 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
630 ivals
[0] = (ALuint
)*values
;
631 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
634 case AL_AUXILIARY_SEND_FILTER
:
635 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
636 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
637 values
[2] <= UINT_MAX
&& values
[2] >= 0);
639 ivals
[0] = (ALuint
)values
[0];
640 ivals
[1] = (ALuint
)values
[1];
641 ivals
[2] = (ALuint
)values
[2];
642 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
645 case AL_MAX_DISTANCE
:
646 case AL_ROLLOFF_FACTOR
:
647 case AL_CONE_INNER_ANGLE
:
648 case AL_CONE_OUTER_ANGLE
:
649 case AL_REFERENCE_DISTANCE
:
651 case sivDopplerFactor
:
652 fvals
[0] = (ALfloat
)*values
;
653 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
659 fvals
[0] = (ALfloat
)values
[0];
660 fvals
[1] = (ALfloat
)values
[1];
661 fvals
[2] = (ALfloat
)values
[2];
662 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
665 ERR("Unexpected property: 0x%04x\n", prop
);
666 RETERR(AL_INVALID_ENUM
);
672 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
)
682 *values
= Source
->Gain
;
686 *values
= Source
->Pitch
;
689 case AL_MAX_DISTANCE
:
690 *values
= Source
->MaxDistance
;
693 case AL_ROLLOFF_FACTOR
:
694 *values
= Source
->RollOffFactor
;
697 case AL_REFERENCE_DISTANCE
:
698 *values
= Source
->RefDistance
;
701 case AL_CONE_INNER_ANGLE
:
702 *values
= Source
->InnerAngle
;
705 case AL_CONE_OUTER_ANGLE
:
706 *values
= Source
->OuterAngle
;
710 *values
= Source
->MinGain
;
714 *values
= Source
->MaxGain
;
717 case AL_CONE_OUTER_GAIN
:
718 *values
= Source
->OuterGain
;
722 case AL_SAMPLE_OFFSET
:
724 LockContext(Context
);
725 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
726 Context
->Device
->Frequency
;
727 GetSourceOffsets(Source
, prop
, offsets
, updateLen
);
728 UnlockContext(Context
);
729 *values
= offsets
[0];
732 case AL_CONE_OUTER_GAINHF
:
733 *values
= Source
->OuterGainHF
;
736 case AL_AIR_ABSORPTION_FACTOR
:
737 *values
= Source
->AirAbsorptionFactor
;
740 case AL_ROOM_ROLLOFF_FACTOR
:
741 *values
= Source
->RoomRolloffFactor
;
744 case AL_DOPPLER_FACTOR
:
745 *values
= Source
->DopplerFactor
;
748 case AL_SAMPLE_RW_OFFSETS_SOFT
:
749 case AL_BYTE_RW_OFFSETS_SOFT
:
750 LockContext(Context
);
751 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
752 Context
->Device
->Frequency
;
753 GetSourceOffsets(Source
, prop
, values
, updateLen
);
754 UnlockContext(Context
);
757 case AL_SEC_OFFSET_LATENCY_SOFT
:
758 LockContext(Context
);
759 values
[0] = GetSourceSecOffset(Source
);
760 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
762 UnlockContext(Context
);
766 LockContext(Context
);
767 values
[0] = Source
->Position
[0];
768 values
[1] = Source
->Position
[1];
769 values
[2] = Source
->Position
[2];
770 UnlockContext(Context
);
774 LockContext(Context
);
775 values
[0] = Source
->Velocity
[0];
776 values
[1] = Source
->Velocity
[1];
777 values
[2] = Source
->Velocity
[2];
778 UnlockContext(Context
);
782 LockContext(Context
);
783 values
[0] = Source
->Orientation
[0];
784 values
[1] = Source
->Orientation
[1];
785 values
[2] = Source
->Orientation
[2];
786 UnlockContext(Context
);
789 case AL_SOURCE_RELATIVE
:
792 case AL_SOURCE_STATE
:
793 case AL_BUFFERS_QUEUED
:
794 case AL_BUFFERS_PROCESSED
:
796 case AL_DIRECT_FILTER_GAINHF_AUTO
:
797 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
798 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
799 case AL_DIRECT_CHANNELS_SOFT
:
800 case AL_DISTANCE_MODEL
:
801 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) == AL_NO_ERROR
)
802 *values
= (ALdouble
)ivals
[0];
806 ERR("Unexpected property: 0x%04x\n", prop
);
807 RETERR(AL_INVALID_ENUM
);
810 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
)
812 ALbufferlistitem
*BufferList
;
818 case AL_SOURCE_RELATIVE
:
819 *values
= Source
->HeadRelative
;
823 *values
= Source
->Looping
;
827 LockContext(Context
);
828 BufferList
= Source
->queue
;
829 if(Source
->SourceType
!= AL_STATIC
)
831 ALuint i
= Source
->BuffersPlayed
;
834 BufferList
= BufferList
->next
;
838 *values
= ((BufferList
&& BufferList
->buffer
) ?
839 BufferList
->buffer
->id
: 0);
840 UnlockContext(Context
);
843 case AL_SOURCE_STATE
:
844 *values
= Source
->state
;
847 case AL_BUFFERS_QUEUED
:
848 *values
= Source
->BuffersInQueue
;
851 case AL_BUFFERS_PROCESSED
:
852 LockContext(Context
);
853 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
855 /* Buffers on a looping source are in a perpetual state of
856 * PENDING, so don't report any as PROCESSED */
860 *values
= Source
->BuffersPlayed
;
861 UnlockContext(Context
);
865 *values
= Source
->SourceType
;
868 case AL_DIRECT_FILTER_GAINHF_AUTO
:
869 *values
= Source
->DryGainHFAuto
;
872 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
873 *values
= Source
->WetGainAuto
;
876 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
877 *values
= Source
->WetGainHFAuto
;
880 case AL_DIRECT_CHANNELS_SOFT
:
881 *values
= Source
->DirectChannels
;
884 case AL_DISTANCE_MODEL
:
885 *values
= Source
->DistanceModel
;
888 case AL_MAX_DISTANCE
:
889 case AL_ROLLOFF_FACTOR
:
890 case AL_REFERENCE_DISTANCE
:
891 case AL_CONE_INNER_ANGLE
:
892 case AL_CONE_OUTER_ANGLE
:
894 case AL_SAMPLE_OFFSET
:
896 case AL_DOPPLER_FACTOR
:
897 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
898 *values
= (ALint
)dvals
[0];
901 case AL_SAMPLE_RW_OFFSETS_SOFT
:
902 case AL_BYTE_RW_OFFSETS_SOFT
:
903 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
905 values
[0] = (ALint
)dvals
[0];
906 values
[1] = (ALint
)dvals
[1];
913 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
915 values
[0] = (ALint
)dvals
[0];
916 values
[1] = (ALint
)dvals
[1];
917 values
[2] = (ALint
)dvals
[2];
921 case sivSampleOffsetLatencySOFT
:
925 case sivDirectFilter
:
926 case sivAuxSendFilter
:
931 ERR("Unexpected property: 0x%04x\n", prop
);
932 RETERR(AL_INVALID_ENUM
);
935 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
)
943 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
944 LockContext(Context
);
945 values
[0] = GetSourceOffset(Source
);
946 values
[1] = ALCdevice_GetLatency(Context
->Device
);
947 UnlockContext(Context
);
950 case AL_MAX_DISTANCE
:
951 case AL_ROLLOFF_FACTOR
:
952 case AL_REFERENCE_DISTANCE
:
953 case AL_CONE_INNER_ANGLE
:
954 case AL_CONE_OUTER_ANGLE
:
956 case AL_SAMPLE_OFFSET
:
958 case AL_DOPPLER_FACTOR
:
959 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
960 *values
= (ALint64
)dvals
[0];
963 case AL_SAMPLE_RW_OFFSETS_SOFT
:
964 case AL_BYTE_RW_OFFSETS_SOFT
:
965 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
967 values
[0] = (ALint64
)dvals
[0];
968 values
[1] = (ALint64
)dvals
[1];
975 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
977 values
[0] = (ALint64
)dvals
[0];
978 values
[1] = (ALint64
)dvals
[1];
979 values
[2] = (ALint64
)dvals
[2];
983 case AL_SOURCE_RELATIVE
:
986 case AL_SOURCE_STATE
:
987 case AL_BUFFERS_QUEUED
:
988 case AL_BUFFERS_PROCESSED
:
990 case AL_DIRECT_FILTER_GAINHF_AUTO
:
991 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
992 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
993 case AL_DIRECT_CHANNELS_SOFT
:
994 case AL_DISTANCE_MODEL
:
995 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) == AL_NO_ERROR
)
1000 case sivDirectFilter
:
1001 case sivAuxSendFilter
:
1005 ERR("Unexpected property: 0x%04x\n", prop
);
1006 RETERR(AL_INVALID_ENUM
);
1012 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
1014 ALCcontext
*Context
;
1017 Context
= GetContextRef();
1018 if(!Context
) return;
1024 CHECK_VALUE(Context
, n
>= 0);
1025 for(cur
= 0;cur
< n
;cur
++)
1027 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
1029 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
1030 InitSourceParams(source
);
1032 err
= NewThunkEntry(&source
->id
);
1033 if(err
== AL_NO_ERROR
)
1034 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->id
, source
);
1035 if(err
!= AL_NO_ERROR
)
1037 FreeThunkEntry(source
->id
);
1038 memset(source
, 0, sizeof(ALsource
));
1041 al_throwerr(Context
, err
);
1044 sources
[cur
] = source
->id
;
1050 alDeleteSources(cur
, sources
);
1054 ALCcontext_DecRef(Context
);
1058 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
1060 ALCcontext
*Context
;
1062 Context
= GetContextRef();
1063 if(!Context
) return;
1067 ALbufferlistitem
*BufferList
;
1071 CHECK_VALUE(Context
, n
>= 0);
1073 /* Check that all Sources are valid */
1074 for(i
= 0;i
< n
;i
++)
1076 if(LookupSource(Context
, sources
[i
]) == NULL
)
1077 al_throwerr(Context
, AL_INVALID_NAME
);
1080 for(i
= 0;i
< n
;i
++)
1082 ALsource
**srclist
, **srclistend
;
1084 if((Source
=RemoveSource(Context
, sources
[i
])) == NULL
)
1086 FreeThunkEntry(Source
->id
);
1088 LockContext(Context
);
1089 srclist
= Context
->ActiveSources
;
1090 srclistend
= srclist
+ Context
->ActiveSourceCount
;
1091 while(srclist
!= srclistend
)
1093 if(*srclist
== Source
)
1095 Context
->ActiveSourceCount
--;
1096 *srclist
= *(--srclistend
);
1101 UnlockContext(Context
);
1103 while(Source
->queue
!= NULL
)
1105 BufferList
= Source
->queue
;
1106 Source
->queue
= BufferList
->next
;
1108 if(BufferList
->buffer
!= NULL
)
1109 DecrementRef(&BufferList
->buffer
->ref
);
1113 for(j
= 0;j
< MAX_SENDS
;++j
)
1115 if(Source
->Send
[j
].Slot
)
1116 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
1117 Source
->Send
[j
].Slot
= NULL
;
1120 memset(Source
, 0, sizeof(*Source
));
1126 ALCcontext_DecRef(Context
);
1130 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1132 ALCcontext
*Context
;
1135 Context
= GetContextRef();
1136 if(!Context
) return AL_FALSE
;
1138 result
= (LookupSource(Context
, source
) ? AL_TRUE
: AL_FALSE
);
1140 ALCcontext_DecRef(Context
);
1146 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1148 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 SetSourcefv(Source
, Context
, param
, &value
);
1179 alSetError(Context
, AL_INVALID_ENUM
);
1182 ALCcontext_DecRef(Context
);
1185 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1187 ALCcontext
*Context
;
1191 Context
= GetContextRef();
1192 if(!Context
) return;
1194 if((Source
=LookupSource(Context
, source
)) == NULL
)
1195 alSetError(Context
, AL_INVALID_NAME
);
1204 SetSourcefv(Source
, Context
, param
, fvals
);
1208 alSetError(Context
, AL_INVALID_ENUM
);
1211 ALCcontext_DecRef(Context
);
1214 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1216 ALCcontext
*Context
;
1219 Context
= GetContextRef();
1220 if(!Context
) return;
1222 if((Source
=LookupSource(Context
, source
)) == NULL
)
1223 alSetError(Context
, AL_INVALID_NAME
);
1225 alSetError(Context
, AL_INVALID_VALUE
);
1229 case AL_CONE_INNER_ANGLE
:
1230 case AL_CONE_OUTER_ANGLE
:
1232 case AL_MAX_DISTANCE
:
1233 case AL_ROLLOFF_FACTOR
:
1234 case AL_REFERENCE_DISTANCE
:
1237 case AL_CONE_OUTER_GAIN
:
1238 case AL_CONE_OUTER_GAINHF
:
1240 case AL_SAMPLE_OFFSET
:
1241 case AL_BYTE_OFFSET
:
1242 case AL_AIR_ABSORPTION_FACTOR
:
1243 case AL_ROOM_ROLLOFF_FACTOR
:
1248 SetSourcefv(Source
, Context
, param
, values
);
1252 alSetError(Context
, AL_INVALID_ENUM
);
1255 ALCcontext_DecRef(Context
);
1259 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1261 ALCcontext
*Context
;
1265 Context
= GetContextRef();
1266 if(!Context
) return;
1268 if((Source
=LookupSource(Context
, source
)) == NULL
)
1269 alSetError(Context
, AL_INVALID_NAME
);
1273 case AL_CONE_INNER_ANGLE
:
1274 case AL_CONE_OUTER_ANGLE
:
1276 case AL_MAX_DISTANCE
:
1277 case AL_ROLLOFF_FACTOR
:
1278 case AL_REFERENCE_DISTANCE
:
1281 case AL_CONE_OUTER_GAIN
:
1282 case AL_CONE_OUTER_GAINHF
:
1283 case AL_AIR_ABSORPTION_FACTOR
:
1284 case AL_ROOM_ROLLOFF_FACTOR
:
1285 case AL_DOPPLER_FACTOR
:
1287 case AL_SAMPLE_OFFSET
:
1288 case AL_BYTE_OFFSET
:
1289 fval
= (ALfloat
)value
;
1290 SetSourcefv(Source
, Context
, param
, &fval
);
1294 alSetError(Context
, AL_INVALID_ENUM
);
1297 ALCcontext_DecRef(Context
);
1300 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1302 ALCcontext
*Context
;
1306 Context
= GetContextRef();
1307 if(!Context
) return;
1309 if((Source
=LookupSource(Context
, source
)) == NULL
)
1310 alSetError(Context
, AL_INVALID_NAME
);
1316 fvals
[0] = (ALfloat
)value1
;
1317 fvals
[1] = (ALfloat
)value2
;
1318 fvals
[2] = (ALfloat
)value3
;
1319 SetSourcefv(Source
, Context
, param
, fvals
);
1323 alSetError(Context
, AL_INVALID_ENUM
);
1326 ALCcontext_DecRef(Context
);
1329 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1331 ALCcontext
*Context
;
1335 Context
= GetContextRef();
1336 if(!Context
) return;
1338 if((Source
=LookupSource(Context
, source
)) == NULL
)
1339 alSetError(Context
, AL_INVALID_NAME
);
1341 alSetError(Context
, AL_INVALID_VALUE
);
1345 case AL_CONE_INNER_ANGLE
:
1346 case AL_CONE_OUTER_ANGLE
:
1348 case AL_MAX_DISTANCE
:
1349 case AL_ROLLOFF_FACTOR
:
1350 case AL_REFERENCE_DISTANCE
:
1353 case AL_CONE_OUTER_GAIN
:
1354 case AL_CONE_OUTER_GAINHF
:
1356 case AL_SAMPLE_OFFSET
:
1357 case AL_BYTE_OFFSET
:
1358 case AL_AIR_ABSORPTION_FACTOR
:
1359 case AL_ROOM_ROLLOFF_FACTOR
:
1360 fvals
[0] = (ALfloat
)values
[0];
1361 SetSourcefv(Source
, Context
, param
, fvals
);
1364 case AL_SEC_OFFSET_LATENCY_SOFT
:
1365 fvals
[0] = (ALfloat
)values
[0];
1366 fvals
[1] = (ALfloat
)values
[1];
1367 SetSourcefv(Source
, Context
, param
, fvals
);
1373 fvals
[0] = (ALfloat
)values
[0];
1374 fvals
[1] = (ALfloat
)values
[1];
1375 fvals
[2] = (ALfloat
)values
[2];
1376 SetSourcefv(Source
, Context
, param
, fvals
);
1380 alSetError(Context
, AL_INVALID_ENUM
);
1383 ALCcontext_DecRef(Context
);
1387 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1389 ALCcontext
*Context
;
1392 Context
= GetContextRef();
1393 if(!Context
) return;
1395 if((Source
=LookupSource(Context
, source
)) == NULL
)
1396 alSetError(Context
, AL_INVALID_NAME
);
1399 case AL_MAX_DISTANCE
:
1400 case AL_ROLLOFF_FACTOR
:
1401 case AL_CONE_INNER_ANGLE
:
1402 case AL_CONE_OUTER_ANGLE
:
1403 case AL_REFERENCE_DISTANCE
:
1404 case AL_SOURCE_RELATIVE
:
1407 case AL_SOURCE_STATE
:
1409 case AL_SAMPLE_OFFSET
:
1410 case AL_BYTE_OFFSET
:
1411 case AL_DIRECT_FILTER
:
1412 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1413 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1414 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1415 case AL_DIRECT_CHANNELS_SOFT
:
1416 case AL_DISTANCE_MODEL
:
1417 SetSourceiv(Source
, Context
, param
, &value
);
1421 alSetError(Context
, AL_INVALID_ENUM
);
1424 ALCcontext_DecRef(Context
);
1427 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1429 ALCcontext
*Context
;
1433 Context
= GetContextRef();
1434 if(!Context
) return;
1436 if((Source
=LookupSource(Context
, source
)) == NULL
)
1437 alSetError(Context
, AL_INVALID_NAME
);
1443 case AL_AUXILIARY_SEND_FILTER
:
1447 SetSourceiv(Source
, Context
, param
, ivals
);
1451 alSetError(Context
, AL_INVALID_ENUM
);
1454 ALCcontext_DecRef(Context
);
1457 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1459 ALCcontext
*Context
;
1462 Context
= GetContextRef();
1463 if(!Context
) return;
1465 if((Source
=LookupSource(Context
, source
)) == NULL
)
1466 alSetError(Context
, AL_INVALID_NAME
);
1468 alSetError(Context
, AL_INVALID_VALUE
);
1471 case AL_SOURCE_RELATIVE
:
1472 case AL_CONE_INNER_ANGLE
:
1473 case AL_CONE_OUTER_ANGLE
:
1476 case AL_SOURCE_STATE
:
1478 case AL_SAMPLE_OFFSET
:
1479 case AL_BYTE_OFFSET
:
1480 case AL_MAX_DISTANCE
:
1481 case AL_ROLLOFF_FACTOR
:
1482 case AL_REFERENCE_DISTANCE
:
1483 case AL_DIRECT_FILTER
:
1484 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1485 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1486 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1487 case AL_DISTANCE_MODEL
:
1488 case AL_DIRECT_CHANNELS_SOFT
:
1493 case AL_AUXILIARY_SEND_FILTER
:
1494 SetSourceiv(Source
, Context
, param
, values
);
1498 alSetError(Context
, AL_INVALID_ENUM
);
1501 ALCcontext_DecRef(Context
);
1505 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1507 ALCcontext
*Context
;
1510 Context
= GetContextRef();
1511 if(!Context
) return;
1513 if((Source
=LookupSource(Context
, source
)) == NULL
)
1514 alSetError(Context
, AL_INVALID_NAME
);
1517 case AL_MAX_DISTANCE
:
1518 case AL_ROLLOFF_FACTOR
:
1519 case AL_CONE_INNER_ANGLE
:
1520 case AL_CONE_OUTER_ANGLE
:
1521 case AL_REFERENCE_DISTANCE
:
1522 case AL_SOURCE_RELATIVE
:
1524 case AL_SOURCE_STATE
:
1526 case AL_SAMPLE_OFFSET
:
1527 case AL_BYTE_OFFSET
:
1528 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1529 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1530 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1531 case AL_DIRECT_CHANNELS_SOFT
:
1532 case AL_DISTANCE_MODEL
:
1534 case AL_DIRECT_FILTER
:
1535 SetSourcei64v(Source
, Context
, param
, &value
);
1539 alSetError(Context
, AL_INVALID_ENUM
);
1542 ALCcontext_DecRef(Context
);
1545 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1547 ALCcontext
*Context
;
1549 ALint64SOFT i64vals
[3];
1551 Context
= GetContextRef();
1552 if(!Context
) return;
1554 if((Source
=LookupSource(Context
, source
)) == NULL
)
1555 alSetError(Context
, AL_INVALID_NAME
);
1561 case AL_AUXILIARY_SEND_FILTER
:
1562 i64vals
[0] = value1
;
1563 i64vals
[1] = value2
;
1564 i64vals
[2] = value3
;
1565 SetSourcei64v(Source
, Context
, param
, i64vals
);
1569 alSetError(Context
, AL_INVALID_ENUM
);
1572 ALCcontext_DecRef(Context
);
1575 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1577 ALCcontext
*Context
;
1580 Context
= GetContextRef();
1581 if(!Context
) return;
1583 if((Source
=LookupSource(Context
, source
)) == NULL
)
1584 alSetError(Context
, AL_INVALID_NAME
);
1586 alSetError(Context
, AL_INVALID_VALUE
);
1589 case AL_SOURCE_RELATIVE
:
1590 case AL_CONE_INNER_ANGLE
:
1591 case AL_CONE_OUTER_ANGLE
:
1593 case AL_SOURCE_STATE
:
1595 case AL_SAMPLE_OFFSET
:
1596 case AL_BYTE_OFFSET
:
1597 case AL_MAX_DISTANCE
:
1598 case AL_ROLLOFF_FACTOR
:
1599 case AL_REFERENCE_DISTANCE
:
1600 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1601 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1602 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1603 case AL_DISTANCE_MODEL
:
1604 case AL_DIRECT_CHANNELS_SOFT
:
1606 case AL_DIRECT_FILTER
:
1608 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1613 case AL_AUXILIARY_SEND_FILTER
:
1614 SetSourcei64v(Source
, Context
, param
, values
);
1618 alSetError(Context
, AL_INVALID_ENUM
);
1621 ALCcontext_DecRef(Context
);
1625 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1627 ALCcontext
*Context
;
1631 Context
= GetContextRef();
1632 if(!Context
) return;
1634 if((Source
=LookupSource(Context
, source
)) == NULL
)
1635 alSetError(Context
, AL_INVALID_NAME
);
1637 alSetError(Context
, AL_INVALID_VALUE
);
1644 case AL_MAX_DISTANCE
:
1645 case AL_ROLLOFF_FACTOR
:
1646 case AL_CONE_OUTER_GAIN
:
1647 case AL_CONE_OUTER_GAINHF
:
1649 case AL_SAMPLE_OFFSET
:
1650 case AL_BYTE_OFFSET
:
1651 case AL_CONE_INNER_ANGLE
:
1652 case AL_CONE_OUTER_ANGLE
:
1653 case AL_REFERENCE_DISTANCE
:
1654 case AL_AIR_ABSORPTION_FACTOR
:
1655 case AL_ROOM_ROLLOFF_FACTOR
:
1656 case AL_DOPPLER_FACTOR
:
1657 if(GetSourcedv(Source
, Context
, param
, &dval
) == AL_NO_ERROR
)
1658 *value
= (ALfloat
)dval
;
1662 alSetError(Context
, AL_INVALID_ENUM
);
1665 ALCcontext_DecRef(Context
);
1669 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1671 ALCcontext
*Context
;
1675 Context
= GetContextRef();
1676 if(!Context
) return;
1678 if((Source
=LookupSource(Context
, source
)) == NULL
)
1679 alSetError(Context
, AL_INVALID_NAME
);
1680 else if(!(value1
&& value2
&& value3
))
1681 alSetError(Context
, AL_INVALID_VALUE
);
1687 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1689 *value1
= (ALfloat
)dvals
[0];
1690 *value2
= (ALfloat
)dvals
[1];
1691 *value3
= (ALfloat
)dvals
[2];
1696 alSetError(Context
, AL_INVALID_ENUM
);
1699 ALCcontext_DecRef(Context
);
1703 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1705 ALCcontext
*Context
;
1715 case AL_MAX_DISTANCE
:
1716 case AL_ROLLOFF_FACTOR
:
1717 case AL_DOPPLER_FACTOR
:
1718 case AL_CONE_OUTER_GAIN
:
1720 case AL_SAMPLE_OFFSET
:
1721 case AL_BYTE_OFFSET
:
1722 case AL_CONE_INNER_ANGLE
:
1723 case AL_CONE_OUTER_ANGLE
:
1724 case AL_REFERENCE_DISTANCE
:
1725 case AL_CONE_OUTER_GAINHF
:
1726 case AL_AIR_ABSORPTION_FACTOR
:
1727 case AL_ROOM_ROLLOFF_FACTOR
:
1728 alGetSourcef(source
, param
, values
);
1734 alGetSource3f(source
, param
, values
+0, values
+1, values
+2);
1738 Context
= GetContextRef();
1739 if(!Context
) return;
1741 if((Source
=LookupSource(Context
, source
)) == NULL
)
1742 alSetError(Context
, AL_INVALID_NAME
);
1744 alSetError(Context
, AL_INVALID_VALUE
);
1747 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1748 case AL_BYTE_RW_OFFSETS_SOFT
:
1749 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1751 values
[0] = (ALfloat
)dvals
[0];
1752 values
[1] = (ALfloat
)dvals
[1];
1757 alSetError(Context
, AL_INVALID_ENUM
);
1760 ALCcontext_DecRef(Context
);
1764 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1766 ALCcontext
*Context
;
1769 Context
= GetContextRef();
1770 if(!Context
) return;
1772 if((Source
=LookupSource(Context
, source
)) == NULL
)
1773 alSetError(Context
, AL_INVALID_NAME
);
1775 alSetError(Context
, AL_INVALID_VALUE
);
1782 case AL_MAX_DISTANCE
:
1783 case AL_ROLLOFF_FACTOR
:
1784 case AL_CONE_OUTER_GAIN
:
1785 case AL_CONE_OUTER_GAINHF
:
1787 case AL_SAMPLE_OFFSET
:
1788 case AL_BYTE_OFFSET
:
1789 case AL_CONE_INNER_ANGLE
:
1790 case AL_CONE_OUTER_ANGLE
:
1791 case AL_REFERENCE_DISTANCE
:
1792 case AL_AIR_ABSORPTION_FACTOR
:
1793 case AL_ROOM_ROLLOFF_FACTOR
:
1794 case AL_DOPPLER_FACTOR
:
1795 GetSourcedv(Source
, Context
, param
, value
);
1799 alSetError(Context
, AL_INVALID_ENUM
);
1802 ALCcontext_DecRef(Context
);
1805 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1807 ALCcontext
*Context
;
1811 Context
= GetContextRef();
1812 if(!Context
) return;
1814 if((Source
=LookupSource(Context
, source
)) == NULL
)
1815 alSetError(Context
, AL_INVALID_NAME
);
1816 else if(!(value1
&& value2
&& value3
))
1817 alSetError(Context
, AL_INVALID_VALUE
);
1823 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1832 alSetError(Context
, AL_INVALID_ENUM
);
1835 ALCcontext_DecRef(Context
);
1838 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1840 ALCcontext
*Context
;
1843 Context
= GetContextRef();
1844 if(!Context
) return;
1846 if((Source
=LookupSource(Context
, source
)) == NULL
)
1847 alSetError(Context
, AL_INVALID_NAME
);
1849 alSetError(Context
, AL_INVALID_VALUE
);
1856 case AL_MAX_DISTANCE
:
1857 case AL_ROLLOFF_FACTOR
:
1858 case AL_DOPPLER_FACTOR
:
1859 case AL_CONE_OUTER_GAIN
:
1861 case AL_SAMPLE_OFFSET
:
1862 case AL_BYTE_OFFSET
:
1863 case AL_CONE_INNER_ANGLE
:
1864 case AL_CONE_OUTER_ANGLE
:
1865 case AL_REFERENCE_DISTANCE
:
1866 case AL_CONE_OUTER_GAINHF
:
1867 case AL_AIR_ABSORPTION_FACTOR
:
1868 case AL_ROOM_ROLLOFF_FACTOR
:
1870 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1871 case AL_BYTE_RW_OFFSETS_SOFT
:
1872 case AL_SEC_OFFSET_LATENCY_SOFT
:
1877 GetSourcedv(Source
, Context
, param
, values
);
1881 alSetError(Context
, AL_INVALID_ENUM
);
1884 ALCcontext_DecRef(Context
);
1888 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1890 ALCcontext
*Context
;
1893 Context
= GetContextRef();
1894 if(!Context
) return;
1896 if((Source
=LookupSource(Context
, source
)) == NULL
)
1897 alSetError(Context
, AL_INVALID_NAME
);
1899 alSetError(Context
, AL_INVALID_VALUE
);
1902 case AL_MAX_DISTANCE
:
1903 case AL_ROLLOFF_FACTOR
:
1904 case AL_REFERENCE_DISTANCE
:
1905 case AL_SOURCE_RELATIVE
:
1906 case AL_CONE_INNER_ANGLE
:
1907 case AL_CONE_OUTER_ANGLE
:
1910 case AL_SOURCE_STATE
:
1911 case AL_BUFFERS_QUEUED
:
1912 case AL_BUFFERS_PROCESSED
:
1913 case AL_SOURCE_TYPE
:
1915 case AL_SAMPLE_OFFSET
:
1916 case AL_BYTE_OFFSET
:
1917 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1918 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1919 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1920 case AL_DOPPLER_FACTOR
:
1921 case AL_DIRECT_CHANNELS_SOFT
:
1922 case AL_DISTANCE_MODEL
:
1923 GetSourceiv(Source
, Context
, param
, value
);
1927 alSetError(Context
, AL_INVALID_ENUM
);
1930 ALCcontext_DecRef(Context
);
1934 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1936 ALCcontext
*Context
;
1940 Context
= GetContextRef();
1941 if(!Context
) return;
1943 if((Source
=LookupSource(Context
, source
)) == NULL
)
1944 alSetError(Context
, AL_INVALID_NAME
);
1945 else if(!(value1
&& value2
&& value3
))
1946 alSetError(Context
, AL_INVALID_VALUE
);
1952 if(GetSourceiv(Source
, Context
, param
, ivals
) == AL_NO_ERROR
)
1961 alSetError(Context
, AL_INVALID_ENUM
);
1964 ALCcontext_DecRef(Context
);
1968 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1970 ALCcontext
*Context
;
1973 Context
= GetContextRef();
1974 if(!Context
) return;
1976 if((Source
=LookupSource(Context
, source
)) == NULL
)
1977 alSetError(Context
, AL_INVALID_NAME
);
1979 alSetError(Context
, AL_INVALID_VALUE
);
1982 case AL_SOURCE_RELATIVE
:
1983 case AL_CONE_INNER_ANGLE
:
1984 case AL_CONE_OUTER_ANGLE
:
1987 case AL_SOURCE_STATE
:
1988 case AL_BUFFERS_QUEUED
:
1989 case AL_BUFFERS_PROCESSED
:
1991 case AL_SAMPLE_OFFSET
:
1992 case AL_BYTE_OFFSET
:
1993 case AL_MAX_DISTANCE
:
1994 case AL_ROLLOFF_FACTOR
:
1995 case AL_DOPPLER_FACTOR
:
1996 case AL_REFERENCE_DISTANCE
:
1997 case AL_SOURCE_TYPE
:
1998 case AL_DIRECT_FILTER
:
1999 case AL_DIRECT_FILTER_GAINHF_AUTO
:
2000 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
2001 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
2002 case AL_DISTANCE_MODEL
:
2003 case AL_DIRECT_CHANNELS_SOFT
:
2005 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2006 case AL_BYTE_RW_OFFSETS_SOFT
:
2011 GetSourceiv(Source
, Context
, param
, values
);
2015 alSetError(Context
, AL_INVALID_ENUM
);
2018 ALCcontext_DecRef(Context
);
2022 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
2024 ALCcontext
*Context
;
2027 Context
= GetContextRef();
2028 if(!Context
) return;
2030 if((Source
=LookupSource(Context
, source
)) == NULL
)
2031 alSetError(Context
, AL_INVALID_NAME
);
2033 alSetError(Context
, AL_INVALID_VALUE
);
2036 case AL_MAX_DISTANCE
:
2037 case AL_ROLLOFF_FACTOR
:
2038 case AL_REFERENCE_DISTANCE
:
2039 case AL_SOURCE_RELATIVE
:
2040 case AL_CONE_INNER_ANGLE
:
2041 case AL_CONE_OUTER_ANGLE
:
2044 case AL_SOURCE_STATE
:
2045 case AL_BUFFERS_QUEUED
:
2046 case AL_BUFFERS_PROCESSED
:
2047 case AL_SOURCE_TYPE
:
2049 case AL_SAMPLE_OFFSET
:
2050 case AL_BYTE_OFFSET
:
2051 case AL_DIRECT_FILTER_GAINHF_AUTO
:
2052 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
2053 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
2054 case AL_DOPPLER_FACTOR
:
2055 case AL_DIRECT_CHANNELS_SOFT
:
2056 case AL_DISTANCE_MODEL
:
2057 GetSourcei64v(Source
, Context
, param
, value
);
2061 alSetError(Context
, AL_INVALID_ENUM
);
2064 ALCcontext_DecRef(Context
);
2067 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
2069 ALCcontext
*Context
;
2073 Context
= GetContextRef();
2074 if(!Context
) return;
2076 if((Source
=LookupSource(Context
, source
)) == NULL
)
2077 alSetError(Context
, AL_INVALID_NAME
);
2078 else if(!(value1
&& value2
&& value3
))
2079 alSetError(Context
, AL_INVALID_VALUE
);
2085 if(GetSourcei64v(Source
, Context
, param
, i64vals
) == AL_NO_ERROR
)
2087 *value1
= i64vals
[0];
2088 *value2
= i64vals
[1];
2089 *value3
= i64vals
[2];
2094 alSetError(Context
, AL_INVALID_ENUM
);
2097 ALCcontext_DecRef(Context
);
2100 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
2102 ALCcontext
*Context
;
2105 Context
= GetContextRef();
2106 if(!Context
) return;
2108 if((Source
=LookupSource(Context
, source
)) == NULL
)
2109 alSetError(Context
, AL_INVALID_NAME
);
2111 alSetError(Context
, AL_INVALID_VALUE
);
2114 case AL_MAX_DISTANCE
:
2115 case AL_ROLLOFF_FACTOR
:
2116 case AL_REFERENCE_DISTANCE
:
2117 case AL_SOURCE_RELATIVE
:
2118 case AL_CONE_INNER_ANGLE
:
2119 case AL_CONE_OUTER_ANGLE
:
2122 case AL_SOURCE_STATE
:
2123 case AL_BUFFERS_QUEUED
:
2124 case AL_BUFFERS_PROCESSED
:
2125 case AL_SOURCE_TYPE
:
2127 case AL_SAMPLE_OFFSET
:
2128 case AL_BYTE_OFFSET
:
2129 case AL_DIRECT_FILTER_GAINHF_AUTO
:
2130 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
2131 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
2132 case AL_DOPPLER_FACTOR
:
2133 case AL_DIRECT_CHANNELS_SOFT
:
2134 case AL_DISTANCE_MODEL
:
2136 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2137 case AL_BYTE_RW_OFFSETS_SOFT
:
2138 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
2143 GetSourcei64v(Source
, Context
, param
, values
);
2147 alSetError(Context
, AL_INVALID_ENUM
);
2150 ALCcontext_DecRef(Context
);
2154 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
2156 alSourcePlayv(1, &source
);
2158 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2160 ALCcontext
*Context
;
2164 Context
= GetContextRef();
2165 if(!Context
) return;
2169 CHECK_VALUE(Context
, n
>= 0);
2170 for(i
= 0;i
< n
;i
++)
2172 if(!LookupSource(Context
, sources
[i
]))
2173 al_throwerr(Context
, AL_INVALID_NAME
);
2176 LockContext(Context
);
2177 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
2182 newcount
= Context
->MaxActiveSources
<< 1;
2184 temp
= realloc(Context
->ActiveSources
,
2185 sizeof(*Context
->ActiveSources
) * newcount
);
2188 UnlockContext(Context
);
2189 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
2192 Context
->ActiveSources
= temp
;
2193 Context
->MaxActiveSources
= newcount
;
2196 for(i
= 0;i
< n
;i
++)
2198 Source
= LookupSource(Context
, sources
[i
]);
2199 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
2200 else SetSourceState(Source
, Context
, AL_PLAYING
);
2202 UnlockContext(Context
);
2206 ALCcontext_DecRef(Context
);
2209 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2211 alSourcePausev(1, &source
);
2213 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2215 ALCcontext
*Context
;
2219 Context
= GetContextRef();
2220 if(!Context
) return;
2224 CHECK_VALUE(Context
, n
>= 0);
2225 for(i
= 0;i
< n
;i
++)
2227 if(!LookupSource(Context
, sources
[i
]))
2228 al_throwerr(Context
, AL_INVALID_NAME
);
2231 LockContext(Context
);
2232 for(i
= 0;i
< n
;i
++)
2234 Source
= LookupSource(Context
, sources
[i
]);
2235 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
2236 else SetSourceState(Source
, Context
, AL_PAUSED
);
2238 UnlockContext(Context
);
2242 ALCcontext_DecRef(Context
);
2245 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2247 alSourceStopv(1, &source
);
2249 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2251 ALCcontext
*Context
;
2255 Context
= GetContextRef();
2256 if(!Context
) return;
2260 CHECK_VALUE(Context
, n
>= 0);
2261 for(i
= 0;i
< n
;i
++)
2263 if(!LookupSource(Context
, sources
[i
]))
2264 al_throwerr(Context
, AL_INVALID_NAME
);
2267 LockContext(Context
);
2268 for(i
= 0;i
< n
;i
++)
2270 Source
= LookupSource(Context
, sources
[i
]);
2271 Source
->new_state
= AL_NONE
;
2272 SetSourceState(Source
, Context
, AL_STOPPED
);
2274 UnlockContext(Context
);
2278 ALCcontext_DecRef(Context
);
2281 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2283 alSourceRewindv(1, &source
);
2285 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2287 ALCcontext
*Context
;
2291 Context
= GetContextRef();
2292 if(!Context
) return;
2296 CHECK_VALUE(Context
, n
>= 0);
2297 for(i
= 0;i
< n
;i
++)
2299 if(!LookupSource(Context
, sources
[i
]))
2300 al_throwerr(Context
, AL_INVALID_NAME
);
2303 LockContext(Context
);
2304 for(i
= 0;i
< n
;i
++)
2306 Source
= LookupSource(Context
, sources
[i
]);
2307 Source
->new_state
= AL_NONE
;
2308 SetSourceState(Source
, Context
, AL_INITIAL
);
2310 UnlockContext(Context
);
2314 ALCcontext_DecRef(Context
);
2318 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei nb
, const ALuint
*buffers
)
2320 ALCcontext
*Context
;
2323 ALbufferlistitem
*BufferListStart
= NULL
;
2324 ALbufferlistitem
*BufferList
;
2325 ALbuffer
*BufferFmt
;
2330 Context
= GetContextRef();
2331 if(!Context
) return;
2335 ALCdevice
*device
= Context
->Device
;
2337 CHECK_VALUE(Context
, nb
>= 0);
2339 if((Source
=LookupSource(Context
, source
)) == NULL
)
2340 al_throwerr(Context
, AL_INVALID_NAME
);
2342 LockContext(Context
);
2343 if(Source
->SourceType
== AL_STATIC
)
2345 UnlockContext(Context
);
2346 /* Can't queue on a Static Source */
2347 al_throwerr(Context
, AL_INVALID_OPERATION
);
2352 /* Check for a valid Buffer, for its frequency and format */
2353 BufferList
= Source
->queue
;
2356 if(BufferList
->buffer
)
2358 BufferFmt
= BufferList
->buffer
;
2361 BufferList
= BufferList
->next
;
2364 for(i
= 0;i
< nb
;i
++)
2366 ALbuffer
*buffer
= NULL
;
2367 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2369 UnlockContext(Context
);
2370 al_throwerr(Context
, AL_INVALID_NAME
);
2373 if(!BufferListStart
)
2375 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2376 BufferListStart
->buffer
= buffer
;
2377 BufferListStart
->next
= NULL
;
2378 BufferListStart
->prev
= NULL
;
2379 BufferList
= BufferListStart
;
2383 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2384 BufferList
->next
->buffer
= buffer
;
2385 BufferList
->next
->next
= NULL
;
2386 BufferList
->next
->prev
= BufferList
;
2387 BufferList
= BufferList
->next
;
2389 if(!buffer
) continue;
2390 IncrementRef(&buffer
->ref
);
2392 ReadLock(&buffer
->lock
);
2393 if(BufferFmt
== NULL
)
2397 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2398 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2399 if(buffer
->FmtChannels
== FmtMono
)
2400 Source
->Update
= CalcSourceParams
;
2402 Source
->Update
= CalcNonAttnSourceParams
;
2404 Source
->NeedsUpdate
= AL_TRUE
;
2406 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2407 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2408 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2410 ReadUnlock(&buffer
->lock
);
2411 UnlockContext(Context
);
2412 al_throwerr(Context
, AL_INVALID_OPERATION
);
2414 ReadUnlock(&buffer
->lock
);
2417 /* Source is now streaming */
2418 Source
->SourceType
= AL_STREAMING
;
2420 if(Source
->queue
== NULL
)
2421 Source
->queue
= BufferListStart
;
2424 /* Append to the end of the queue */
2425 BufferList
= Source
->queue
;
2426 while(BufferList
->next
!= NULL
)
2427 BufferList
= BufferList
->next
;
2429 BufferListStart
->prev
= BufferList
;
2430 BufferList
->next
= BufferListStart
;
2433 Source
->BuffersInQueue
+= nb
;
2435 UnlockContext(Context
);
2439 while(BufferListStart
)
2441 BufferList
= BufferListStart
;
2442 BufferListStart
= BufferList
->next
;
2444 if(BufferList
->buffer
)
2445 DecrementRef(&BufferList
->buffer
->ref
);
2451 ALCcontext_DecRef(Context
);
2454 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint source
, ALsizei nb
, ALuint
*buffers
)
2456 ALCcontext
*Context
;
2459 ALbufferlistitem
*BufferList
;
2464 Context
= GetContextRef();
2465 if(!Context
) return;
2469 CHECK_VALUE(Context
, nb
>= 0);
2471 if((Source
=LookupSource(Context
, source
)) == NULL
)
2472 al_throwerr(Context
, AL_INVALID_NAME
);
2474 LockContext(Context
);
2475 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
||
2476 (ALuint
)nb
> Source
->BuffersPlayed
)
2478 UnlockContext(Context
);
2479 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2480 al_throwerr(Context
, AL_INVALID_VALUE
);
2483 for(i
= 0;i
< nb
;i
++)
2485 BufferList
= Source
->queue
;
2486 Source
->queue
= BufferList
->next
;
2487 Source
->BuffersInQueue
--;
2488 Source
->BuffersPlayed
--;
2490 if(BufferList
->buffer
)
2492 buffers
[i
] = BufferList
->buffer
->id
;
2493 DecrementRef(&BufferList
->buffer
->ref
);
2501 Source
->queue
->prev
= NULL
;
2502 UnlockContext(Context
);
2506 ALCcontext_DecRef(Context
);
2510 static ALvoid
InitSourceParams(ALsource
*Source
)
2514 Source
->InnerAngle
= 360.0f
;
2515 Source
->OuterAngle
= 360.0f
;
2516 Source
->Pitch
= 1.0f
;
2517 Source
->Position
[0] = 0.0f
;
2518 Source
->Position
[1] = 0.0f
;
2519 Source
->Position
[2] = 0.0f
;
2520 Source
->Orientation
[0] = 0.0f
;
2521 Source
->Orientation
[1] = 0.0f
;
2522 Source
->Orientation
[2] = 0.0f
;
2523 Source
->Velocity
[0] = 0.0f
;
2524 Source
->Velocity
[1] = 0.0f
;
2525 Source
->Velocity
[2] = 0.0f
;
2526 Source
->RefDistance
= 1.0f
;
2527 Source
->MaxDistance
= FLT_MAX
;
2528 Source
->RollOffFactor
= 1.0f
;
2529 Source
->Looping
= AL_FALSE
;
2530 Source
->Gain
= 1.0f
;
2531 Source
->MinGain
= 0.0f
;
2532 Source
->MaxGain
= 1.0f
;
2533 Source
->OuterGain
= 0.0f
;
2534 Source
->OuterGainHF
= 1.0f
;
2536 Source
->DryGainHFAuto
= AL_TRUE
;
2537 Source
->WetGainAuto
= AL_TRUE
;
2538 Source
->WetGainHFAuto
= AL_TRUE
;
2539 Source
->AirAbsorptionFactor
= 0.0f
;
2540 Source
->RoomRolloffFactor
= 0.0f
;
2541 Source
->DopplerFactor
= 1.0f
;
2542 Source
->DirectChannels
= AL_FALSE
;
2544 Source
->DistanceModel
= DefaultDistanceModel
;
2546 Source
->Resampler
= DefaultResampler
;
2548 Source
->state
= AL_INITIAL
;
2549 Source
->new_state
= AL_NONE
;
2550 Source
->SourceType
= AL_UNDETERMINED
;
2551 Source
->Offset
= -1.0;
2553 Source
->DirectGain
= 1.0f
;
2554 Source
->DirectGainHF
= 1.0f
;
2555 for(i
= 0;i
< MAX_SENDS
;i
++)
2557 Source
->Send
[i
].Gain
= 1.0f
;
2558 Source
->Send
[i
].GainHF
= 1.0f
;
2561 Source
->NeedsUpdate
= AL_TRUE
;
2563 Source
->Hrtf
.Moving
= AL_FALSE
;
2564 Source
->Hrtf
.Counter
= 0;
2570 * Sets the source's new play state given its current state.
2572 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2574 if(state
== AL_PLAYING
)
2576 ALbufferlistitem
*BufferList
;
2579 /* Check that there is a queue containing at least one valid, non zero
2581 BufferList
= Source
->queue
;
2584 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
2586 BufferList
= BufferList
->next
;
2589 if(Source
->state
!= AL_PLAYING
)
2591 for(j
= 0;j
< MaxChannels
;j
++)
2593 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
2594 Source
->Hrtf
.History
[j
][k
] = 0.0f
;
2595 for(k
= 0;k
< HRIR_LENGTH
;k
++)
2597 Source
->Hrtf
.Values
[j
][k
][0] = 0.0f
;
2598 Source
->Hrtf
.Values
[j
][k
][1] = 0.0f
;
2603 if(Source
->state
!= AL_PAUSED
)
2605 Source
->state
= AL_PLAYING
;
2606 Source
->position
= 0;
2607 Source
->position_fraction
= 0;
2608 Source
->BuffersPlayed
= 0;
2611 Source
->state
= AL_PLAYING
;
2613 // Check if an Offset has been set
2614 if(Source
->Offset
>= 0.0)
2615 ApplyOffset(Source
);
2617 /* If there's nothing to play, or device is disconnected, go right to
2619 if(!BufferList
|| !Context
->Device
->Connected
)
2621 SetSourceState(Source
, Context
, AL_STOPPED
);
2625 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
2627 if(Context
->ActiveSources
[j
] == Source
)
2630 if(j
== Context
->ActiveSourceCount
)
2631 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
2633 else if(state
== AL_PAUSED
)
2635 if(Source
->state
== AL_PLAYING
)
2637 Source
->state
= AL_PAUSED
;
2638 Source
->Hrtf
.Moving
= AL_FALSE
;
2639 Source
->Hrtf
.Counter
= 0;
2642 else if(state
== AL_STOPPED
)
2644 if(Source
->state
!= AL_INITIAL
)
2646 Source
->state
= AL_STOPPED
;
2647 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
2648 Source
->Hrtf
.Moving
= AL_FALSE
;
2649 Source
->Hrtf
.Counter
= 0;
2651 Source
->Offset
= -1.0;
2653 else if(state
== AL_INITIAL
)
2655 if(Source
->state
!= AL_INITIAL
)
2657 Source
->state
= AL_INITIAL
;
2658 Source
->position
= 0;
2659 Source
->position_fraction
= 0;
2660 Source
->BuffersPlayed
= 0;
2661 Source
->Hrtf
.Moving
= AL_FALSE
;
2662 Source
->Hrtf
.Counter
= 0;
2664 Source
->Offset
= -1.0;
2670 * Gets the current read offset for the given Source, in 32.32 fixed-point
2671 * samples. The offset is relative to the start of the queue (not the start of
2672 * the current buffer).
2674 static ALint64
GetSourceOffset(const ALsource
*Source
)
2676 const ALbufferlistitem
*BufferList
;
2680 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2683 /* NOTE: This is the offset into the *current* buffer, so add the length of
2684 * any played buffers */
2685 readPos
= (ALuint64
)Source
->position
<< 32;
2686 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2687 BufferList
= Source
->queue
;
2688 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2690 if(BufferList
->buffer
)
2691 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2692 BufferList
= BufferList
->next
;
2695 return (ALint64
)minu64(readPos
, MAKEU64(0x7fffffff,0xffffffff));
2698 /* GetSourceSecOffset
2700 * Gets the current read offset for the given Source, in seconds. The offset is
2701 * relative to the start of the queue (not the start of the current buffer).
2703 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2705 const ALbufferlistitem
*BufferList
;
2706 const ALbuffer
*Buffer
= NULL
;
2710 BufferList
= Source
->queue
;
2713 if(BufferList
->buffer
)
2715 Buffer
= BufferList
->buffer
;
2718 BufferList
= BufferList
->next
;
2721 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2724 /* NOTE: This is the offset into the *current* buffer, so add the length of
2725 * any played buffers */
2726 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2727 readPos
|= (ALuint64
)Source
->position_fraction
;
2728 BufferList
= Source
->queue
;
2729 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2731 if(BufferList
->buffer
)
2732 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< FRACTIONBITS
;
2733 BufferList
= BufferList
->next
;
2736 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2741 * Gets the current read and write offsets for the given Source, in the
2742 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2743 * the start of the queue (not the start of the current buffer).
2745 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2747 const ALbufferlistitem
*BufferList
;
2748 const ALbuffer
*Buffer
= NULL
;
2749 ALuint readPos
, writePos
;
2750 ALuint totalBufferLen
;
2753 // Find the first valid Buffer in the Queue
2754 BufferList
= Source
->queue
;
2757 if(BufferList
->buffer
)
2759 Buffer
= BufferList
->buffer
;
2762 BufferList
= BufferList
->next
;
2765 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2772 if(updateLen
> 0.0 && updateLen
< 0.015)
2775 /* NOTE: This is the offset into the *current* buffer, so add the length of
2776 * any played buffers */
2777 readPos
= Source
->position
;
2779 BufferList
= Source
->queue
;
2780 for(i
= 0;BufferList
;i
++)
2782 if(BufferList
->buffer
)
2784 if(i
< Source
->BuffersPlayed
)
2785 readPos
+= BufferList
->buffer
->SampleLen
;
2786 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
2788 BufferList
= BufferList
->next
;
2790 if(Source
->state
== AL_PLAYING
)
2791 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2797 readPos
%= totalBufferLen
;
2798 writePos
%= totalBufferLen
;
2802 /* Wrap positions back to 0 */
2803 if(readPos
>= totalBufferLen
)
2805 if(writePos
>= totalBufferLen
)
2812 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2813 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2816 case AL_SAMPLE_OFFSET
:
2817 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2818 offset
[0] = (ALdouble
)readPos
;
2819 offset
[1] = (ALdouble
)writePos
;
2822 case AL_BYTE_OFFSET
:
2823 case AL_BYTE_RW_OFFSETS_SOFT
:
2824 if(Buffer
->OriginalType
== UserFmtIMA4
)
2826 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
2827 ALuint FrameBlockSize
= 65;
2829 /* Round down to nearest ADPCM block */
2830 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2831 if(Source
->state
!= AL_PLAYING
)
2832 offset
[1] = offset
[0];
2835 /* Round up to nearest ADPCM block */
2836 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2837 FrameBlockSize
* BlockSize
);
2842 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2843 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2844 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2853 * Apply the stored playback offset to the Source. This function will update
2854 * the number of buffers "played" given the stored offset.
2856 ALboolean
ApplyOffset(ALsource
*Source
)
2858 const ALbufferlistitem
*BufferList
;
2859 const ALbuffer
*Buffer
;
2860 ALint bufferLen
, totalBufferLen
;
2861 ALint buffersPlayed
;
2864 /* Get sample frame offset */
2865 offset
= GetSampleOffset(Source
);
2872 BufferList
= Source
->queue
;
2875 Buffer
= BufferList
->buffer
;
2876 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2878 if(bufferLen
<= offset
-totalBufferLen
)
2880 /* Offset is past this buffer so increment to the next buffer */
2883 else if(totalBufferLen
<= offset
)
2885 /* Offset is in this buffer */
2886 Source
->BuffersPlayed
= buffersPlayed
;
2888 Source
->position
= offset
- totalBufferLen
;
2889 Source
->position_fraction
= 0;
2893 totalBufferLen
+= bufferLen
;
2895 BufferList
= BufferList
->next
;
2898 /* Offset is out of range of the queue */
2905 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2906 * Second offset supplied by the application). This takes into account the fact
2907 * that the buffer format may have been modifed since.
2909 static ALint
GetSampleOffset(ALsource
*Source
)
2911 const ALbuffer
*Buffer
= NULL
;
2912 const ALbufferlistitem
*BufferList
;
2915 /* Find the first valid Buffer in the Queue */
2916 BufferList
= Source
->queue
;
2919 if(BufferList
->buffer
)
2921 Buffer
= BufferList
->buffer
;
2924 BufferList
= BufferList
->next
;
2929 Source
->Offset
= -1.0;
2933 switch(Source
->OffsetType
)
2935 case AL_BYTE_OFFSET
:
2936 /* Determine the ByteOffset (and ensure it is block aligned) */
2937 Offset
= (ALint
)Source
->Offset
;
2938 if(Buffer
->OriginalType
== UserFmtIMA4
)
2940 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2944 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2947 case AL_SAMPLE_OFFSET
:
2948 Offset
= (ALint
)Source
->Offset
;
2952 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2955 Source
->Offset
= -1.0;
2963 * Destroys all sources in the source map.
2965 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2969 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2971 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2972 Context
->SourceMap
.array
[pos
].value
= NULL
;
2974 while(temp
->queue
!= NULL
)
2976 ALbufferlistitem
*BufferList
= temp
->queue
;
2977 temp
->queue
= BufferList
->next
;
2979 if(BufferList
->buffer
!= NULL
)
2980 DecrementRef(&BufferList
->buffer
->ref
);
2984 for(j
= 0;j
< MAX_SENDS
;++j
)
2986 if(temp
->Send
[j
].Slot
)
2987 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2988 temp
->Send
[j
].Slot
= NULL
;
2991 FreeThunkEntry(temp
->id
);
2992 memset(temp
, 0, sizeof(*temp
));