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 sfMinGain
= AL_MIN_GAIN
,
60 sfMaxGain
= AL_MAX_GAIN
,
61 sfMaxDistance
= AL_MAX_DISTANCE
,
62 sfRolloffFactor
= AL_ROLLOFF_FACTOR
,
63 sfDopplerFactor
= AL_DOPPLER_FACTOR
,
64 sfConeOuterGain
= AL_CONE_OUTER_GAIN
,
65 sfSecOffset
= AL_SEC_OFFSET
,
66 sfSampleOffset
= AL_SAMPLE_OFFSET
,
67 sfByteOffset
= AL_BYTE_OFFSET
,
68 sfConeInnerAngle
= AL_CONE_INNER_ANGLE
,
69 sfConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
70 sfRefDistance
= AL_REFERENCE_DISTANCE
,
72 sfPosition
= AL_POSITION
,
73 sfVelocity
= AL_VELOCITY
,
74 sfDirection
= AL_DIRECTION
,
76 sfSourceRelative
= AL_SOURCE_RELATIVE
,
77 sfLooping
= AL_LOOPING
,
79 sfSourceState
= AL_SOURCE_STATE
,
80 sfBuffersQueued
= AL_BUFFERS_QUEUED
,
81 sfBuffersProcessed
= AL_BUFFERS_PROCESSED
,
82 sfSourceType
= AL_SOURCE_TYPE
,
85 sfConeOuterGainHF
= AL_CONE_OUTER_GAINHF
,
86 sfAirAbsorptionFactor
= AL_AIR_ABSORPTION_FACTOR
,
87 sfRoomRolloffFactor
= AL_ROOM_ROLLOFF_FACTOR
,
88 sfDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
89 sfAuxSendFilterGainAuto
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
90 sfAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
92 /* AL_SOFT_direct_channels */
93 sfDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
95 /* AL_EXT_source_distance_model */
96 sfDistanceModel
= AL_DISTANCE_MODEL
,
98 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
99 sfSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
100 sfByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
102 /* AL_SOFT_source_latency */
103 sfSecOffsetLatencySOFT
= AL_SEC_OFFSET_LATENCY_SOFT
,
106 typedef enum SrcIntProp
{
107 siMaxDistance
= AL_MAX_DISTANCE
,
108 siRolloffFactor
= AL_ROLLOFF_FACTOR
,
109 siRefDistance
= AL_REFERENCE_DISTANCE
,
110 siSourceRelative
= AL_SOURCE_RELATIVE
,
111 siConeInnerAngle
= AL_CONE_INNER_ANGLE
,
112 siConeOuterAngle
= AL_CONE_OUTER_ANGLE
,
113 siLooping
= AL_LOOPING
,
114 siBuffer
= AL_BUFFER
,
115 siSourceState
= AL_SOURCE_STATE
,
116 siBuffersQueued
= AL_BUFFERS_QUEUED
,
117 siBuffersProcessed
= AL_BUFFERS_PROCESSED
,
118 siSourceType
= AL_SOURCE_TYPE
,
119 siSecOffset
= AL_SEC_OFFSET
,
120 siSampleOffset
= AL_SAMPLE_OFFSET
,
121 siByteOffset
= AL_BYTE_OFFSET
,
122 siDopplerFactor
= AL_DOPPLER_FACTOR
,
123 siPosition
= AL_POSITION
,
124 siVelocity
= AL_VELOCITY
,
125 siDirection
= AL_DIRECTION
,
128 siDirectFilterGainHFAuto
= AL_DIRECT_FILTER_GAINHF_AUTO
,
129 siAuxSendFilterGainAutio
= AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
130 siAuxSendFilterGainHFAuto
= AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
131 siDirectFilter
= AL_DIRECT_FILTER
,
132 siAuxSendFilter
= AL_AUXILIARY_SEND_FILTER
,
134 /* AL_SOFT_direct_channels */
135 siDirectChannelsSOFT
= AL_DIRECT_CHANNELS_SOFT
,
137 /* AL_EXT_source_distance_model */
138 siDistanceModel
= AL_DISTANCE_MODEL
,
140 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
141 siSampleRWOffsetsSOFT
= AL_SAMPLE_RW_OFFSETS_SOFT
,
142 siByteRWOffsetsSOFT
= AL_BYTE_RW_OFFSETS_SOFT
,
144 /* AL_SOFT_source_latency */
145 siSampleOffsetLatencySOFT
= AL_SAMPLE_OFFSET_LATENCY_SOFT
,
148 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
);
149 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
);
150 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
);
152 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
);
153 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
);
154 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
);
157 #define RETERR(x) do { \
158 alSetError(Context, (x)); \
162 #define CHECKVAL(x) do { \
164 RETERR(AL_INVALID_VALUE); \
167 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
)
174 CHECKVAL(*values
>= 0.0f
);
176 Source
->Pitch
= *values
;
177 Source
->NeedsUpdate
= AL_TRUE
;
180 case AL_CONE_INNER_ANGLE
:
181 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
183 Source
->InnerAngle
= *values
;
184 Source
->NeedsUpdate
= AL_TRUE
;
187 case AL_CONE_OUTER_ANGLE
:
188 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
190 Source
->OuterAngle
= *values
;
191 Source
->NeedsUpdate
= AL_TRUE
;
195 CHECKVAL(*values
>= 0.0f
);
197 Source
->Gain
= *values
;
198 Source
->NeedsUpdate
= AL_TRUE
;
201 case AL_MAX_DISTANCE
:
202 CHECKVAL(*values
>= 0.0f
);
204 Source
->MaxDistance
= *values
;
205 Source
->NeedsUpdate
= AL_TRUE
;
208 case AL_ROLLOFF_FACTOR
:
209 CHECKVAL(*values
>= 0.0f
);
211 Source
->RollOffFactor
= *values
;
212 Source
->NeedsUpdate
= AL_TRUE
;
215 case AL_REFERENCE_DISTANCE
:
216 CHECKVAL(*values
>= 0.0f
);
218 Source
->RefDistance
= *values
;
219 Source
->NeedsUpdate
= AL_TRUE
;
223 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
225 Source
->MinGain
= *values
;
226 Source
->NeedsUpdate
= AL_TRUE
;
230 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
232 Source
->MaxGain
= *values
;
233 Source
->NeedsUpdate
= AL_TRUE
;
236 case AL_CONE_OUTER_GAIN
:
237 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
239 Source
->OuterGain
= *values
;
240 Source
->NeedsUpdate
= AL_TRUE
;
243 case AL_CONE_OUTER_GAINHF
:
244 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
246 Source
->OuterGainHF
= *values
;
247 Source
->NeedsUpdate
= AL_TRUE
;
250 case AL_AIR_ABSORPTION_FACTOR
:
251 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
253 Source
->AirAbsorptionFactor
= *values
;
254 Source
->NeedsUpdate
= AL_TRUE
;
257 case AL_ROOM_ROLLOFF_FACTOR
:
258 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
260 Source
->RoomRolloffFactor
= *values
;
261 Source
->NeedsUpdate
= AL_TRUE
;
264 case AL_DOPPLER_FACTOR
:
265 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
267 Source
->DopplerFactor
= *values
;
268 Source
->NeedsUpdate
= AL_TRUE
;
272 case AL_SAMPLE_OFFSET
:
274 CHECKVAL(*values
>= 0.0f
);
276 LockContext(Context
);
277 Source
->OffsetType
= prop
;
278 Source
->Offset
= *values
;
280 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
281 !Context
->DeferUpdates
)
283 if(ApplyOffset(Source
) == AL_FALSE
)
285 UnlockContext(Context
);
286 RETERR(AL_INVALID_VALUE
);
289 UnlockContext(Context
);
293 case AL_SEC_OFFSET_LATENCY_SOFT
:
295 RETERR(AL_INVALID_OPERATION
);
299 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
301 LockContext(Context
);
302 Source
->Position
[0] = values
[0];
303 Source
->Position
[1] = values
[1];
304 Source
->Position
[2] = values
[2];
305 UnlockContext(Context
);
306 Source
->NeedsUpdate
= AL_TRUE
;
310 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
312 LockContext(Context
);
313 Source
->Velocity
[0] = values
[0];
314 Source
->Velocity
[1] = values
[1];
315 Source
->Velocity
[2] = values
[2];
316 UnlockContext(Context
);
317 Source
->NeedsUpdate
= AL_TRUE
;
321 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
323 LockContext(Context
);
324 Source
->Orientation
[0] = values
[0];
325 Source
->Orientation
[1] = values
[1];
326 Source
->Orientation
[2] = values
[2];
327 UnlockContext(Context
);
328 Source
->NeedsUpdate
= AL_TRUE
;
332 case sfSampleRWOffsetsSOFT
:
333 case sfByteRWOffsetsSOFT
:
334 RETERR(AL_INVALID_OPERATION
);
337 case sfSourceRelative
:
341 case sfDistanceModel
:
342 case sfDirectFilterGainHFAuto
:
343 case sfAuxSendFilterGainAuto
:
344 case sfAuxSendFilterGainHFAuto
:
345 case sfDirectChannelsSOFT
:
346 ival
= (ALint
)values
[0];
347 return SetSourceiv(Source
, Context
, prop
, &ival
);
350 case sfBuffersQueued
:
351 case sfBuffersProcessed
:
352 ival
= (ALint
)((ALuint
)values
[0]);
353 return SetSourceiv(Source
, Context
, prop
, &ival
);
356 ERR("Unexpected property: 0x%04x\n", prop
);
357 RETERR(AL_INVALID_ENUM
);
360 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
)
362 ALCdevice
*device
= Context
->Device
;
363 ALbuffer
*buffer
= NULL
;
364 ALfilter
*filter
= NULL
;
365 ALeffectslot
*slot
= NULL
;
366 ALbufferlistitem
*oldlist
;
371 case AL_SOURCE_RELATIVE
:
372 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
374 Source
->HeadRelative
= (ALboolean
)*values
;
375 Source
->NeedsUpdate
= AL_TRUE
;
379 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
381 Source
->Looping
= (ALboolean
)*values
;
385 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
387 LockContext(Context
);
388 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
390 UnlockContext(Context
);
391 RETERR(AL_INVALID_OPERATION
);
394 Source
->BuffersInQueue
= 0;
395 Source
->BuffersPlayed
= 0;
399 ALbufferlistitem
*BufferListItem
;
401 /* Source is now Static */
402 Source
->SourceType
= AL_STATIC
;
404 /* Add the selected buffer to a one-item queue */
405 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
406 BufferListItem
->buffer
= buffer
;
407 BufferListItem
->next
= NULL
;
408 BufferListItem
->prev
= NULL
;
409 IncrementRef(&buffer
->ref
);
411 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, BufferListItem
);
412 Source
->BuffersInQueue
= 1;
414 ReadLock(&buffer
->lock
);
415 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
416 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
417 ReadUnlock(&buffer
->lock
);
418 if(buffer
->FmtChannels
== FmtMono
)
419 Source
->Update
= CalcSourceParams
;
421 Source
->Update
= CalcNonAttnSourceParams
;
422 Source
->NeedsUpdate
= AL_TRUE
;
426 /* Source is now Undetermined */
427 Source
->SourceType
= AL_UNDETERMINED
;
428 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, NULL
);
431 /* Delete all elements in the previous queue */
432 while(oldlist
!= NULL
)
434 ALbufferlistitem
*temp
= oldlist
;
435 oldlist
= temp
->next
;
438 DecrementRef(&temp
->buffer
->ref
);
441 UnlockContext(Context
);
446 case siBuffersQueued
:
447 case siBuffersProcessed
:
449 RETERR(AL_INVALID_OPERATION
);
452 case AL_SAMPLE_OFFSET
:
454 CHECKVAL(*values
>= 0);
456 LockContext(Context
);
457 Source
->OffsetType
= prop
;
458 Source
->Offset
= *values
;
460 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
461 !Context
->DeferUpdates
)
463 if(ApplyOffset(Source
) == AL_FALSE
)
465 UnlockContext(Context
);
466 RETERR(AL_INVALID_VALUE
);
469 UnlockContext(Context
);
473 case siSampleRWOffsetsSOFT
:
474 case siByteRWOffsetsSOFT
:
475 case siSampleOffsetLatencySOFT
:
477 RETERR(AL_INVALID_OPERATION
);
480 case AL_DIRECT_FILTER
:
481 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
483 LockContext(Context
);
486 Source
->DirectGain
= 1.0f
;
487 Source
->DirectGainHF
= 1.0f
;
491 Source
->DirectGain
= filter
->Gain
;
492 Source
->DirectGainHF
= filter
->GainHF
;
494 UnlockContext(Context
);
495 Source
->NeedsUpdate
= AL_TRUE
;
498 case AL_DIRECT_FILTER_GAINHF_AUTO
:
499 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
501 Source
->DryGainHFAuto
= *values
;
502 Source
->NeedsUpdate
= AL_TRUE
;
505 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
506 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
508 Source
->WetGainAuto
= *values
;
509 Source
->NeedsUpdate
= AL_TRUE
;
512 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
513 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
515 Source
->WetGainHFAuto
= *values
;
516 Source
->NeedsUpdate
= AL_TRUE
;
519 case AL_DIRECT_CHANNELS_SOFT
:
520 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
522 Source
->DirectChannels
= *values
;
523 Source
->NeedsUpdate
= AL_TRUE
;
526 case AL_DISTANCE_MODEL
:
527 CHECKVAL(*values
== AL_NONE
||
528 *values
== AL_INVERSE_DISTANCE
||
529 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
530 *values
== AL_LINEAR_DISTANCE
||
531 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
532 *values
== AL_EXPONENT_DISTANCE
||
533 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
535 Source
->DistanceModel
= *values
;
536 if(Context
->SourceDistanceModel
)
537 Source
->NeedsUpdate
= AL_TRUE
;
541 case AL_AUXILIARY_SEND_FILTER
:
542 LockContext(Context
);
543 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
544 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
545 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
547 UnlockContext(Context
);
548 RETERR(AL_INVALID_VALUE
);
551 /* Add refcount on the new slot, and release the previous slot */
552 if(slot
) IncrementRef(&slot
->ref
);
553 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
554 if(slot
) DecrementRef(&slot
->ref
);
559 Source
->Send
[values
[1]].Gain
= 1.0f
;
560 Source
->Send
[values
[1]].GainHF
= 1.0f
;
564 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
565 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
567 Source
->NeedsUpdate
= AL_TRUE
;
568 UnlockContext(Context
);
572 case AL_MAX_DISTANCE
:
573 case AL_ROLLOFF_FACTOR
:
574 case AL_CONE_INNER_ANGLE
:
575 case AL_CONE_OUTER_ANGLE
:
576 case AL_REFERENCE_DISTANCE
:
577 case siDopplerFactor
:
578 fvals
[0] = (ALfloat
)*values
;
579 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
584 fvals
[0] = (ALfloat
)values
[0];
585 fvals
[1] = (ALfloat
)values
[1];
586 fvals
[2] = (ALfloat
)values
[2];
587 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
590 ERR("Unexpected property: 0x%04x\n", prop
);
591 RETERR(AL_INVALID_ENUM
);
594 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
)
601 case siSampleRWOffsetsSOFT
:
602 case siByteRWOffsetsSOFT
:
603 case siSampleOffsetLatencySOFT
:
605 RETERR(AL_INVALID_OPERATION
);
609 case AL_SOURCE_RELATIVE
:
611 case AL_SOURCE_STATE
:
613 case AL_SAMPLE_OFFSET
:
615 case siBuffersQueued
:
616 case siBuffersProcessed
:
617 case AL_DIRECT_FILTER_GAINHF_AUTO
:
618 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
619 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
620 case AL_DIRECT_CHANNELS_SOFT
:
621 case AL_DISTANCE_MODEL
:
622 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
624 ivals
[0] = (ALint
)*values
;
625 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
629 case AL_DIRECT_FILTER
:
630 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
632 ivals
[0] = (ALuint
)*values
;
633 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
636 case AL_AUXILIARY_SEND_FILTER
:
637 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
638 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
639 values
[2] <= UINT_MAX
&& values
[2] >= 0);
641 ivals
[0] = (ALuint
)values
[0];
642 ivals
[1] = (ALuint
)values
[1];
643 ivals
[2] = (ALuint
)values
[2];
644 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
647 case AL_MAX_DISTANCE
:
648 case AL_ROLLOFF_FACTOR
:
649 case AL_CONE_INNER_ANGLE
:
650 case AL_CONE_OUTER_ANGLE
:
651 case AL_REFERENCE_DISTANCE
:
653 case siDopplerFactor
:
654 fvals
[0] = (ALfloat
)*values
;
655 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
661 fvals
[0] = (ALfloat
)values
[0];
662 fvals
[1] = (ALfloat
)values
[1];
663 fvals
[2] = (ALfloat
)values
[2];
664 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
667 ERR("Unexpected property: 0x%04x\n", prop
);
668 RETERR(AL_INVALID_ENUM
);
674 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
)
684 *values
= Source
->Gain
;
688 *values
= Source
->Pitch
;
691 case AL_MAX_DISTANCE
:
692 *values
= Source
->MaxDistance
;
695 case AL_ROLLOFF_FACTOR
:
696 *values
= Source
->RollOffFactor
;
699 case AL_REFERENCE_DISTANCE
:
700 *values
= Source
->RefDistance
;
703 case AL_CONE_INNER_ANGLE
:
704 *values
= Source
->InnerAngle
;
707 case AL_CONE_OUTER_ANGLE
:
708 *values
= Source
->OuterAngle
;
712 *values
= Source
->MinGain
;
716 *values
= Source
->MaxGain
;
719 case AL_CONE_OUTER_GAIN
:
720 *values
= Source
->OuterGain
;
724 case AL_SAMPLE_OFFSET
:
726 LockContext(Context
);
727 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
728 Context
->Device
->Frequency
;
729 GetSourceOffsets(Source
, prop
, offsets
, updateLen
);
730 UnlockContext(Context
);
731 *values
= offsets
[0];
734 case AL_CONE_OUTER_GAINHF
:
735 *values
= Source
->OuterGainHF
;
738 case AL_AIR_ABSORPTION_FACTOR
:
739 *values
= Source
->AirAbsorptionFactor
;
742 case AL_ROOM_ROLLOFF_FACTOR
:
743 *values
= Source
->RoomRolloffFactor
;
746 case AL_DOPPLER_FACTOR
:
747 *values
= Source
->DopplerFactor
;
750 case AL_SAMPLE_RW_OFFSETS_SOFT
:
751 case AL_BYTE_RW_OFFSETS_SOFT
:
752 LockContext(Context
);
753 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
754 Context
->Device
->Frequency
;
755 GetSourceOffsets(Source
, prop
, values
, updateLen
);
756 UnlockContext(Context
);
759 case AL_SEC_OFFSET_LATENCY_SOFT
:
760 LockContext(Context
);
761 values
[0] = GetSourceSecOffset(Source
);
762 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
764 UnlockContext(Context
);
768 LockContext(Context
);
769 values
[0] = Source
->Position
[0];
770 values
[1] = Source
->Position
[1];
771 values
[2] = Source
->Position
[2];
772 UnlockContext(Context
);
776 LockContext(Context
);
777 values
[0] = Source
->Velocity
[0];
778 values
[1] = Source
->Velocity
[1];
779 values
[2] = Source
->Velocity
[2];
780 UnlockContext(Context
);
784 LockContext(Context
);
785 values
[0] = Source
->Orientation
[0];
786 values
[1] = Source
->Orientation
[1];
787 values
[2] = Source
->Orientation
[2];
788 UnlockContext(Context
);
791 case AL_SOURCE_RELATIVE
:
794 case AL_SOURCE_STATE
:
795 case AL_BUFFERS_QUEUED
:
796 case AL_BUFFERS_PROCESSED
:
798 case AL_DIRECT_FILTER_GAINHF_AUTO
:
799 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
800 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
801 case AL_DIRECT_CHANNELS_SOFT
:
802 case AL_DISTANCE_MODEL
:
803 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) == AL_NO_ERROR
)
804 *values
= (ALdouble
)ivals
[0];
808 ERR("Unexpected property: 0x%04x\n", prop
);
809 RETERR(AL_INVALID_ENUM
);
812 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
)
814 ALbufferlistitem
*BufferList
;
820 case AL_SOURCE_RELATIVE
:
821 *values
= Source
->HeadRelative
;
825 *values
= Source
->Looping
;
829 LockContext(Context
);
830 BufferList
= Source
->queue
;
831 if(Source
->SourceType
!= AL_STATIC
)
833 ALuint i
= Source
->BuffersPlayed
;
836 BufferList
= BufferList
->next
;
840 *values
= ((BufferList
&& BufferList
->buffer
) ?
841 BufferList
->buffer
->id
: 0);
842 UnlockContext(Context
);
845 case AL_SOURCE_STATE
:
846 *values
= Source
->state
;
849 case AL_BUFFERS_QUEUED
:
850 *values
= Source
->BuffersInQueue
;
853 case AL_BUFFERS_PROCESSED
:
854 LockContext(Context
);
855 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
857 /* Buffers on a looping source are in a perpetual state of
858 * PENDING, so don't report any as PROCESSED */
862 *values
= Source
->BuffersPlayed
;
863 UnlockContext(Context
);
867 *values
= Source
->SourceType
;
870 case AL_DIRECT_FILTER_GAINHF_AUTO
:
871 *values
= Source
->DryGainHFAuto
;
874 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
875 *values
= Source
->WetGainAuto
;
878 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
879 *values
= Source
->WetGainHFAuto
;
882 case AL_DIRECT_CHANNELS_SOFT
:
883 *values
= Source
->DirectChannels
;
886 case AL_DISTANCE_MODEL
:
887 *values
= Source
->DistanceModel
;
890 case AL_MAX_DISTANCE
:
891 case AL_ROLLOFF_FACTOR
:
892 case AL_REFERENCE_DISTANCE
:
893 case AL_CONE_INNER_ANGLE
:
894 case AL_CONE_OUTER_ANGLE
:
896 case AL_SAMPLE_OFFSET
:
898 case AL_DOPPLER_FACTOR
:
899 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
900 *values
= (ALint
)dvals
[0];
903 case AL_SAMPLE_RW_OFFSETS_SOFT
:
904 case AL_BYTE_RW_OFFSETS_SOFT
:
905 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
907 values
[0] = (ALint
)dvals
[0];
908 values
[1] = (ALint
)dvals
[1];
915 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
917 values
[0] = (ALint
)dvals
[0];
918 values
[1] = (ALint
)dvals
[1];
919 values
[2] = (ALint
)dvals
[2];
923 case siSampleOffsetLatencySOFT
:
928 case siAuxSendFilter
:
933 ERR("Unexpected property: 0x%04x\n", prop
);
934 RETERR(AL_INVALID_ENUM
);
937 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
)
945 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
946 LockContext(Context
);
947 values
[0] = GetSourceOffset(Source
);
948 values
[1] = ALCdevice_GetLatency(Context
->Device
);
949 UnlockContext(Context
);
952 case AL_MAX_DISTANCE
:
953 case AL_ROLLOFF_FACTOR
:
954 case AL_REFERENCE_DISTANCE
:
955 case AL_CONE_INNER_ANGLE
:
956 case AL_CONE_OUTER_ANGLE
:
958 case AL_SAMPLE_OFFSET
:
960 case AL_DOPPLER_FACTOR
:
961 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
962 *values
= (ALint64
)dvals
[0];
965 case AL_SAMPLE_RW_OFFSETS_SOFT
:
966 case AL_BYTE_RW_OFFSETS_SOFT
:
967 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
969 values
[0] = (ALint64
)dvals
[0];
970 values
[1] = (ALint64
)dvals
[1];
977 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
979 values
[0] = (ALint64
)dvals
[0];
980 values
[1] = (ALint64
)dvals
[1];
981 values
[2] = (ALint64
)dvals
[2];
985 case AL_SOURCE_RELATIVE
:
988 case AL_SOURCE_STATE
:
989 case AL_BUFFERS_QUEUED
:
990 case AL_BUFFERS_PROCESSED
:
992 case AL_DIRECT_FILTER_GAINHF_AUTO
:
993 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
994 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
995 case AL_DIRECT_CHANNELS_SOFT
:
996 case AL_DISTANCE_MODEL
:
998 case siAuxSendFilter
:
999 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) == AL_NO_ERROR
)
1004 ERR("Unexpected property: 0x%04x\n", prop
);
1005 RETERR(AL_INVALID_ENUM
);
1011 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
1013 ALCcontext
*Context
;
1016 Context
= GetContextRef();
1017 if(!Context
) return;
1023 CHECK_VALUE(Context
, n
>= 0);
1024 for(cur
= 0;cur
< n
;cur
++)
1026 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
1028 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
1029 InitSourceParams(source
);
1031 err
= NewThunkEntry(&source
->id
);
1032 if(err
== AL_NO_ERROR
)
1033 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->id
, source
);
1034 if(err
!= AL_NO_ERROR
)
1036 FreeThunkEntry(source
->id
);
1037 memset(source
, 0, sizeof(ALsource
));
1040 al_throwerr(Context
, err
);
1043 sources
[cur
] = source
->id
;
1049 alDeleteSources(cur
, sources
);
1053 ALCcontext_DecRef(Context
);
1057 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
1059 ALCcontext
*Context
;
1061 Context
= GetContextRef();
1062 if(!Context
) return;
1066 ALbufferlistitem
*BufferList
;
1070 CHECK_VALUE(Context
, n
>= 0);
1072 /* Check that all Sources are valid */
1073 for(i
= 0;i
< n
;i
++)
1075 if(LookupSource(Context
, sources
[i
]) == NULL
)
1076 al_throwerr(Context
, AL_INVALID_NAME
);
1079 for(i
= 0;i
< n
;i
++)
1081 ALsource
**srclist
, **srclistend
;
1083 if((Source
=RemoveSource(Context
, sources
[i
])) == NULL
)
1085 FreeThunkEntry(Source
->id
);
1087 LockContext(Context
);
1088 srclist
= Context
->ActiveSources
;
1089 srclistend
= srclist
+ Context
->ActiveSourceCount
;
1090 while(srclist
!= srclistend
)
1092 if(*srclist
== Source
)
1094 Context
->ActiveSourceCount
--;
1095 *srclist
= *(--srclistend
);
1100 UnlockContext(Context
);
1102 while(Source
->queue
!= NULL
)
1104 BufferList
= Source
->queue
;
1105 Source
->queue
= BufferList
->next
;
1107 if(BufferList
->buffer
!= NULL
)
1108 DecrementRef(&BufferList
->buffer
->ref
);
1112 for(j
= 0;j
< MAX_SENDS
;++j
)
1114 if(Source
->Send
[j
].Slot
)
1115 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
1116 Source
->Send
[j
].Slot
= NULL
;
1119 memset(Source
, 0, sizeof(*Source
));
1125 ALCcontext_DecRef(Context
);
1129 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1131 ALCcontext
*Context
;
1134 Context
= GetContextRef();
1135 if(!Context
) return AL_FALSE
;
1137 result
= (LookupSource(Context
, source
) ? AL_TRUE
: AL_FALSE
);
1139 ALCcontext_DecRef(Context
);
1145 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1147 ALCcontext
*Context
;
1150 Context
= GetContextRef();
1151 if(!Context
) return;
1153 if((Source
=LookupSource(Context
, source
)) == NULL
)
1154 alSetError(Context
, AL_INVALID_NAME
);
1158 case AL_CONE_INNER_ANGLE
:
1159 case AL_CONE_OUTER_ANGLE
:
1161 case AL_MAX_DISTANCE
:
1162 case AL_ROLLOFF_FACTOR
:
1163 case AL_REFERENCE_DISTANCE
:
1166 case AL_CONE_OUTER_GAIN
:
1167 case AL_CONE_OUTER_GAINHF
:
1168 case AL_AIR_ABSORPTION_FACTOR
:
1169 case AL_ROOM_ROLLOFF_FACTOR
:
1170 case AL_DOPPLER_FACTOR
:
1172 case AL_SAMPLE_OFFSET
:
1173 case AL_BYTE_OFFSET
:
1174 SetSourcefv(Source
, Context
, param
, &value
);
1178 alSetError(Context
, AL_INVALID_ENUM
);
1181 ALCcontext_DecRef(Context
);
1184 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1186 ALCcontext
*Context
;
1190 Context
= GetContextRef();
1191 if(!Context
) return;
1193 if((Source
=LookupSource(Context
, source
)) == NULL
)
1194 alSetError(Context
, AL_INVALID_NAME
);
1203 SetSourcefv(Source
, Context
, param
, fvals
);
1207 alSetError(Context
, AL_INVALID_ENUM
);
1210 ALCcontext_DecRef(Context
);
1213 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1215 ALCcontext
*Context
;
1218 Context
= GetContextRef();
1219 if(!Context
) return;
1221 if((Source
=LookupSource(Context
, source
)) == NULL
)
1222 alSetError(Context
, AL_INVALID_NAME
);
1224 alSetError(Context
, AL_INVALID_VALUE
);
1228 case AL_CONE_INNER_ANGLE
:
1229 case AL_CONE_OUTER_ANGLE
:
1231 case AL_MAX_DISTANCE
:
1232 case AL_ROLLOFF_FACTOR
:
1233 case AL_REFERENCE_DISTANCE
:
1236 case AL_CONE_OUTER_GAIN
:
1237 case AL_CONE_OUTER_GAINHF
:
1239 case AL_SAMPLE_OFFSET
:
1240 case AL_BYTE_OFFSET
:
1241 case AL_AIR_ABSORPTION_FACTOR
:
1242 case AL_ROOM_ROLLOFF_FACTOR
:
1247 SetSourcefv(Source
, Context
, param
, values
);
1251 alSetError(Context
, AL_INVALID_ENUM
);
1254 ALCcontext_DecRef(Context
);
1258 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1260 ALCcontext
*Context
;
1264 Context
= GetContextRef();
1265 if(!Context
) return;
1267 if((Source
=LookupSource(Context
, source
)) == NULL
)
1268 alSetError(Context
, AL_INVALID_NAME
);
1272 case AL_CONE_INNER_ANGLE
:
1273 case AL_CONE_OUTER_ANGLE
:
1275 case AL_MAX_DISTANCE
:
1276 case AL_ROLLOFF_FACTOR
:
1277 case AL_REFERENCE_DISTANCE
:
1280 case AL_CONE_OUTER_GAIN
:
1281 case AL_CONE_OUTER_GAINHF
:
1282 case AL_AIR_ABSORPTION_FACTOR
:
1283 case AL_ROOM_ROLLOFF_FACTOR
:
1284 case AL_DOPPLER_FACTOR
:
1286 case AL_SAMPLE_OFFSET
:
1287 case AL_BYTE_OFFSET
:
1288 fval
= (ALfloat
)value
;
1289 SetSourcefv(Source
, Context
, param
, &fval
);
1293 alSetError(Context
, AL_INVALID_ENUM
);
1296 ALCcontext_DecRef(Context
);
1299 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1301 ALCcontext
*Context
;
1305 Context
= GetContextRef();
1306 if(!Context
) return;
1308 if((Source
=LookupSource(Context
, source
)) == NULL
)
1309 alSetError(Context
, AL_INVALID_NAME
);
1315 fvals
[0] = (ALfloat
)value1
;
1316 fvals
[1] = (ALfloat
)value2
;
1317 fvals
[2] = (ALfloat
)value3
;
1318 SetSourcefv(Source
, Context
, param
, fvals
);
1322 alSetError(Context
, AL_INVALID_ENUM
);
1325 ALCcontext_DecRef(Context
);
1328 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1330 ALCcontext
*Context
;
1334 Context
= GetContextRef();
1335 if(!Context
) return;
1337 if((Source
=LookupSource(Context
, source
)) == NULL
)
1338 alSetError(Context
, AL_INVALID_NAME
);
1340 alSetError(Context
, AL_INVALID_VALUE
);
1344 case AL_CONE_INNER_ANGLE
:
1345 case AL_CONE_OUTER_ANGLE
:
1347 case AL_MAX_DISTANCE
:
1348 case AL_ROLLOFF_FACTOR
:
1349 case AL_REFERENCE_DISTANCE
:
1352 case AL_CONE_OUTER_GAIN
:
1353 case AL_CONE_OUTER_GAINHF
:
1355 case AL_SAMPLE_OFFSET
:
1356 case AL_BYTE_OFFSET
:
1357 case AL_AIR_ABSORPTION_FACTOR
:
1358 case AL_ROOM_ROLLOFF_FACTOR
:
1359 fvals
[0] = (ALfloat
)values
[0];
1360 SetSourcefv(Source
, Context
, param
, fvals
);
1363 case AL_SEC_OFFSET_LATENCY_SOFT
:
1364 fvals
[0] = (ALfloat
)values
[0];
1365 fvals
[1] = (ALfloat
)values
[1];
1366 SetSourcefv(Source
, Context
, param
, fvals
);
1372 fvals
[0] = (ALfloat
)values
[0];
1373 fvals
[1] = (ALfloat
)values
[1];
1374 fvals
[2] = (ALfloat
)values
[2];
1375 SetSourcefv(Source
, Context
, param
, fvals
);
1379 alSetError(Context
, AL_INVALID_ENUM
);
1382 ALCcontext_DecRef(Context
);
1386 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1388 ALCcontext
*Context
;
1391 Context
= GetContextRef();
1392 if(!Context
) return;
1394 if((Source
=LookupSource(Context
, source
)) == NULL
)
1395 alSetError(Context
, AL_INVALID_NAME
);
1398 case AL_MAX_DISTANCE
:
1399 case AL_ROLLOFF_FACTOR
:
1400 case AL_CONE_INNER_ANGLE
:
1401 case AL_CONE_OUTER_ANGLE
:
1402 case AL_REFERENCE_DISTANCE
:
1403 case AL_SOURCE_RELATIVE
:
1406 case AL_SOURCE_STATE
:
1408 case AL_SAMPLE_OFFSET
:
1409 case AL_BYTE_OFFSET
:
1410 case AL_DIRECT_FILTER
:
1411 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1412 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1413 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1414 case AL_DIRECT_CHANNELS_SOFT
:
1415 case AL_DISTANCE_MODEL
:
1416 SetSourceiv(Source
, Context
, param
, &value
);
1420 alSetError(Context
, AL_INVALID_ENUM
);
1423 ALCcontext_DecRef(Context
);
1426 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1428 ALCcontext
*Context
;
1432 Context
= GetContextRef();
1433 if(!Context
) return;
1435 if((Source
=LookupSource(Context
, source
)) == NULL
)
1436 alSetError(Context
, AL_INVALID_NAME
);
1442 case AL_AUXILIARY_SEND_FILTER
:
1446 SetSourceiv(Source
, Context
, param
, ivals
);
1450 alSetError(Context
, AL_INVALID_ENUM
);
1453 ALCcontext_DecRef(Context
);
1456 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1458 ALCcontext
*Context
;
1461 Context
= GetContextRef();
1462 if(!Context
) return;
1464 if((Source
=LookupSource(Context
, source
)) == NULL
)
1465 alSetError(Context
, AL_INVALID_NAME
);
1467 alSetError(Context
, AL_INVALID_VALUE
);
1470 case AL_SOURCE_RELATIVE
:
1471 case AL_CONE_INNER_ANGLE
:
1472 case AL_CONE_OUTER_ANGLE
:
1475 case AL_SOURCE_STATE
:
1477 case AL_SAMPLE_OFFSET
:
1478 case AL_BYTE_OFFSET
:
1479 case AL_MAX_DISTANCE
:
1480 case AL_ROLLOFF_FACTOR
:
1481 case AL_REFERENCE_DISTANCE
:
1482 case AL_DIRECT_FILTER
:
1483 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1484 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1485 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1486 case AL_DISTANCE_MODEL
:
1487 case AL_DIRECT_CHANNELS_SOFT
:
1492 case AL_AUXILIARY_SEND_FILTER
:
1493 SetSourceiv(Source
, Context
, param
, values
);
1497 alSetError(Context
, AL_INVALID_ENUM
);
1500 ALCcontext_DecRef(Context
);
1504 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1506 ALCcontext
*Context
;
1509 Context
= GetContextRef();
1510 if(!Context
) return;
1512 if((Source
=LookupSource(Context
, source
)) == NULL
)
1513 alSetError(Context
, AL_INVALID_NAME
);
1516 case AL_MAX_DISTANCE
:
1517 case AL_ROLLOFF_FACTOR
:
1518 case AL_CONE_INNER_ANGLE
:
1519 case AL_CONE_OUTER_ANGLE
:
1520 case AL_REFERENCE_DISTANCE
:
1521 case AL_SOURCE_RELATIVE
:
1523 case AL_SOURCE_STATE
:
1525 case AL_SAMPLE_OFFSET
:
1526 case AL_BYTE_OFFSET
:
1527 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1528 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1529 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1530 case AL_DIRECT_CHANNELS_SOFT
:
1531 case AL_DISTANCE_MODEL
:
1533 case AL_DIRECT_FILTER
:
1534 SetSourcei64v(Source
, Context
, param
, &value
);
1538 alSetError(Context
, AL_INVALID_ENUM
);
1541 ALCcontext_DecRef(Context
);
1544 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1546 ALCcontext
*Context
;
1548 ALint64SOFT i64vals
[3];
1550 Context
= GetContextRef();
1551 if(!Context
) return;
1553 if((Source
=LookupSource(Context
, source
)) == NULL
)
1554 alSetError(Context
, AL_INVALID_NAME
);
1560 case AL_AUXILIARY_SEND_FILTER
:
1561 i64vals
[0] = value1
;
1562 i64vals
[1] = value2
;
1563 i64vals
[2] = value3
;
1564 SetSourcei64v(Source
, Context
, param
, i64vals
);
1568 alSetError(Context
, AL_INVALID_ENUM
);
1571 ALCcontext_DecRef(Context
);
1574 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1576 ALCcontext
*Context
;
1579 Context
= GetContextRef();
1580 if(!Context
) return;
1582 if((Source
=LookupSource(Context
, source
)) == NULL
)
1583 alSetError(Context
, AL_INVALID_NAME
);
1585 alSetError(Context
, AL_INVALID_VALUE
);
1588 case AL_SOURCE_RELATIVE
:
1589 case AL_CONE_INNER_ANGLE
:
1590 case AL_CONE_OUTER_ANGLE
:
1592 case AL_SOURCE_STATE
:
1594 case AL_SAMPLE_OFFSET
:
1595 case AL_BYTE_OFFSET
:
1596 case AL_MAX_DISTANCE
:
1597 case AL_ROLLOFF_FACTOR
:
1598 case AL_REFERENCE_DISTANCE
:
1599 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1600 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1601 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1602 case AL_DISTANCE_MODEL
:
1603 case AL_DIRECT_CHANNELS_SOFT
:
1605 case AL_DIRECT_FILTER
:
1607 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1612 case AL_AUXILIARY_SEND_FILTER
:
1613 SetSourcei64v(Source
, Context
, param
, values
);
1617 alSetError(Context
, AL_INVALID_ENUM
);
1620 ALCcontext_DecRef(Context
);
1624 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1626 ALCcontext
*Context
;
1630 Context
= GetContextRef();
1631 if(!Context
) return;
1633 if((Source
=LookupSource(Context
, source
)) == NULL
)
1634 alSetError(Context
, AL_INVALID_NAME
);
1636 alSetError(Context
, AL_INVALID_VALUE
);
1643 case AL_MAX_DISTANCE
:
1644 case AL_ROLLOFF_FACTOR
:
1645 case AL_CONE_OUTER_GAIN
:
1646 case AL_CONE_OUTER_GAINHF
:
1648 case AL_SAMPLE_OFFSET
:
1649 case AL_BYTE_OFFSET
:
1650 case AL_CONE_INNER_ANGLE
:
1651 case AL_CONE_OUTER_ANGLE
:
1652 case AL_REFERENCE_DISTANCE
:
1653 case AL_AIR_ABSORPTION_FACTOR
:
1654 case AL_ROOM_ROLLOFF_FACTOR
:
1655 case AL_DOPPLER_FACTOR
:
1656 if(GetSourcedv(Source
, Context
, param
, &dval
) == AL_NO_ERROR
)
1657 *value
= (ALfloat
)dval
;
1661 alSetError(Context
, AL_INVALID_ENUM
);
1664 ALCcontext_DecRef(Context
);
1668 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1670 ALCcontext
*Context
;
1674 Context
= GetContextRef();
1675 if(!Context
) return;
1677 if((Source
=LookupSource(Context
, source
)) == NULL
)
1678 alSetError(Context
, AL_INVALID_NAME
);
1679 else if(!(value1
&& value2
&& value3
))
1680 alSetError(Context
, AL_INVALID_VALUE
);
1686 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1688 *value1
= (ALfloat
)dvals
[0];
1689 *value2
= (ALfloat
)dvals
[1];
1690 *value3
= (ALfloat
)dvals
[2];
1695 alSetError(Context
, AL_INVALID_ENUM
);
1698 ALCcontext_DecRef(Context
);
1702 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1704 ALCcontext
*Context
;
1714 case AL_MAX_DISTANCE
:
1715 case AL_ROLLOFF_FACTOR
:
1716 case AL_DOPPLER_FACTOR
:
1717 case AL_CONE_OUTER_GAIN
:
1719 case AL_SAMPLE_OFFSET
:
1720 case AL_BYTE_OFFSET
:
1721 case AL_CONE_INNER_ANGLE
:
1722 case AL_CONE_OUTER_ANGLE
:
1723 case AL_REFERENCE_DISTANCE
:
1724 case AL_CONE_OUTER_GAINHF
:
1725 case AL_AIR_ABSORPTION_FACTOR
:
1726 case AL_ROOM_ROLLOFF_FACTOR
:
1727 alGetSourcef(source
, param
, values
);
1733 alGetSource3f(source
, param
, values
+0, values
+1, values
+2);
1737 Context
= GetContextRef();
1738 if(!Context
) return;
1740 if((Source
=LookupSource(Context
, source
)) == NULL
)
1741 alSetError(Context
, AL_INVALID_NAME
);
1743 alSetError(Context
, AL_INVALID_VALUE
);
1746 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1747 case AL_BYTE_RW_OFFSETS_SOFT
:
1748 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1750 values
[0] = (ALfloat
)dvals
[0];
1751 values
[1] = (ALfloat
)dvals
[1];
1756 alSetError(Context
, AL_INVALID_ENUM
);
1759 ALCcontext_DecRef(Context
);
1763 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1765 ALCcontext
*Context
;
1768 Context
= GetContextRef();
1769 if(!Context
) return;
1771 if((Source
=LookupSource(Context
, source
)) == NULL
)
1772 alSetError(Context
, AL_INVALID_NAME
);
1774 alSetError(Context
, AL_INVALID_VALUE
);
1781 case AL_MAX_DISTANCE
:
1782 case AL_ROLLOFF_FACTOR
:
1783 case AL_CONE_OUTER_GAIN
:
1784 case AL_CONE_OUTER_GAINHF
:
1786 case AL_SAMPLE_OFFSET
:
1787 case AL_BYTE_OFFSET
:
1788 case AL_CONE_INNER_ANGLE
:
1789 case AL_CONE_OUTER_ANGLE
:
1790 case AL_REFERENCE_DISTANCE
:
1791 case AL_AIR_ABSORPTION_FACTOR
:
1792 case AL_ROOM_ROLLOFF_FACTOR
:
1793 case AL_DOPPLER_FACTOR
:
1794 GetSourcedv(Source
, Context
, param
, value
);
1798 alSetError(Context
, AL_INVALID_ENUM
);
1801 ALCcontext_DecRef(Context
);
1804 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1806 ALCcontext
*Context
;
1810 Context
= GetContextRef();
1811 if(!Context
) return;
1813 if((Source
=LookupSource(Context
, source
)) == NULL
)
1814 alSetError(Context
, AL_INVALID_NAME
);
1815 else if(!(value1
&& value2
&& value3
))
1816 alSetError(Context
, AL_INVALID_VALUE
);
1822 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1831 alSetError(Context
, AL_INVALID_ENUM
);
1834 ALCcontext_DecRef(Context
);
1837 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1839 ALCcontext
*Context
;
1842 Context
= GetContextRef();
1843 if(!Context
) return;
1845 if((Source
=LookupSource(Context
, source
)) == NULL
)
1846 alSetError(Context
, AL_INVALID_NAME
);
1848 alSetError(Context
, AL_INVALID_VALUE
);
1855 case AL_MAX_DISTANCE
:
1856 case AL_ROLLOFF_FACTOR
:
1857 case AL_DOPPLER_FACTOR
:
1858 case AL_CONE_OUTER_GAIN
:
1860 case AL_SAMPLE_OFFSET
:
1861 case AL_BYTE_OFFSET
:
1862 case AL_CONE_INNER_ANGLE
:
1863 case AL_CONE_OUTER_ANGLE
:
1864 case AL_REFERENCE_DISTANCE
:
1865 case AL_CONE_OUTER_GAINHF
:
1866 case AL_AIR_ABSORPTION_FACTOR
:
1867 case AL_ROOM_ROLLOFF_FACTOR
:
1869 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1870 case AL_BYTE_RW_OFFSETS_SOFT
:
1871 case AL_SEC_OFFSET_LATENCY_SOFT
:
1876 GetSourcedv(Source
, Context
, param
, values
);
1880 alSetError(Context
, AL_INVALID_ENUM
);
1883 ALCcontext_DecRef(Context
);
1887 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1889 ALCcontext
*Context
;
1892 Context
= GetContextRef();
1893 if(!Context
) return;
1895 if((Source
=LookupSource(Context
, source
)) == NULL
)
1896 alSetError(Context
, AL_INVALID_NAME
);
1898 alSetError(Context
, AL_INVALID_VALUE
);
1901 case AL_MAX_DISTANCE
:
1902 case AL_ROLLOFF_FACTOR
:
1903 case AL_REFERENCE_DISTANCE
:
1904 case AL_SOURCE_RELATIVE
:
1905 case AL_CONE_INNER_ANGLE
:
1906 case AL_CONE_OUTER_ANGLE
:
1909 case AL_SOURCE_STATE
:
1910 case AL_BUFFERS_QUEUED
:
1911 case AL_BUFFERS_PROCESSED
:
1912 case AL_SOURCE_TYPE
:
1914 case AL_SAMPLE_OFFSET
:
1915 case AL_BYTE_OFFSET
:
1916 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1917 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1918 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1919 case AL_DOPPLER_FACTOR
:
1920 case AL_DIRECT_CHANNELS_SOFT
:
1921 case AL_DISTANCE_MODEL
:
1922 GetSourceiv(Source
, Context
, param
, value
);
1926 alSetError(Context
, AL_INVALID_ENUM
);
1929 ALCcontext_DecRef(Context
);
1933 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1935 ALCcontext
*Context
;
1939 Context
= GetContextRef();
1940 if(!Context
) return;
1942 if((Source
=LookupSource(Context
, source
)) == NULL
)
1943 alSetError(Context
, AL_INVALID_NAME
);
1944 else if(!(value1
&& value2
&& value3
))
1945 alSetError(Context
, AL_INVALID_VALUE
);
1951 if(GetSourceiv(Source
, Context
, param
, ivals
) == AL_NO_ERROR
)
1960 alSetError(Context
, AL_INVALID_ENUM
);
1963 ALCcontext_DecRef(Context
);
1967 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1969 ALCcontext
*Context
;
1972 Context
= GetContextRef();
1973 if(!Context
) return;
1975 if((Source
=LookupSource(Context
, source
)) == NULL
)
1976 alSetError(Context
, AL_INVALID_NAME
);
1978 alSetError(Context
, AL_INVALID_VALUE
);
1981 case AL_SOURCE_RELATIVE
:
1982 case AL_CONE_INNER_ANGLE
:
1983 case AL_CONE_OUTER_ANGLE
:
1986 case AL_SOURCE_STATE
:
1987 case AL_BUFFERS_QUEUED
:
1988 case AL_BUFFERS_PROCESSED
:
1990 case AL_SAMPLE_OFFSET
:
1991 case AL_BYTE_OFFSET
:
1992 case AL_MAX_DISTANCE
:
1993 case AL_ROLLOFF_FACTOR
:
1994 case AL_DOPPLER_FACTOR
:
1995 case AL_REFERENCE_DISTANCE
:
1996 case AL_SOURCE_TYPE
:
1997 case AL_DIRECT_FILTER
:
1998 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1999 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
2000 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
2001 case AL_DISTANCE_MODEL
:
2002 case AL_DIRECT_CHANNELS_SOFT
:
2004 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2005 case AL_BYTE_RW_OFFSETS_SOFT
:
2010 GetSourceiv(Source
, Context
, param
, values
);
2014 alSetError(Context
, AL_INVALID_ENUM
);
2017 ALCcontext_DecRef(Context
);
2021 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
2023 ALCcontext
*Context
;
2026 Context
= GetContextRef();
2027 if(!Context
) return;
2029 if((Source
=LookupSource(Context
, source
)) == NULL
)
2030 alSetError(Context
, AL_INVALID_NAME
);
2032 alSetError(Context
, AL_INVALID_VALUE
);
2035 case AL_MAX_DISTANCE
:
2036 case AL_ROLLOFF_FACTOR
:
2037 case AL_REFERENCE_DISTANCE
:
2038 case AL_SOURCE_RELATIVE
:
2039 case AL_CONE_INNER_ANGLE
:
2040 case AL_CONE_OUTER_ANGLE
:
2043 case AL_SOURCE_STATE
:
2044 case AL_BUFFERS_QUEUED
:
2045 case AL_BUFFERS_PROCESSED
:
2046 case AL_SOURCE_TYPE
:
2048 case AL_SAMPLE_OFFSET
:
2049 case AL_BYTE_OFFSET
:
2050 case AL_DIRECT_FILTER_GAINHF_AUTO
:
2051 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
2052 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
2053 case AL_DOPPLER_FACTOR
:
2054 case AL_DIRECT_CHANNELS_SOFT
:
2055 case AL_DISTANCE_MODEL
:
2056 GetSourcei64v(Source
, Context
, param
, value
);
2060 alSetError(Context
, AL_INVALID_ENUM
);
2063 ALCcontext_DecRef(Context
);
2066 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
2068 ALCcontext
*Context
;
2072 Context
= GetContextRef();
2073 if(!Context
) return;
2075 if((Source
=LookupSource(Context
, source
)) == NULL
)
2076 alSetError(Context
, AL_INVALID_NAME
);
2077 else if(!(value1
&& value2
&& value3
))
2078 alSetError(Context
, AL_INVALID_VALUE
);
2084 if(GetSourcei64v(Source
, Context
, param
, i64vals
) == AL_NO_ERROR
)
2086 *value1
= i64vals
[0];
2087 *value2
= i64vals
[1];
2088 *value3
= i64vals
[2];
2093 alSetError(Context
, AL_INVALID_ENUM
);
2096 ALCcontext_DecRef(Context
);
2099 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
2101 ALCcontext
*Context
;
2104 Context
= GetContextRef();
2105 if(!Context
) return;
2107 if((Source
=LookupSource(Context
, source
)) == NULL
)
2108 alSetError(Context
, AL_INVALID_NAME
);
2110 alSetError(Context
, AL_INVALID_VALUE
);
2113 case AL_MAX_DISTANCE
:
2114 case AL_ROLLOFF_FACTOR
:
2115 case AL_REFERENCE_DISTANCE
:
2116 case AL_SOURCE_RELATIVE
:
2117 case AL_CONE_INNER_ANGLE
:
2118 case AL_CONE_OUTER_ANGLE
:
2121 case AL_SOURCE_STATE
:
2122 case AL_BUFFERS_QUEUED
:
2123 case AL_BUFFERS_PROCESSED
:
2124 case AL_SOURCE_TYPE
:
2126 case AL_SAMPLE_OFFSET
:
2127 case AL_BYTE_OFFSET
:
2128 case AL_DIRECT_FILTER_GAINHF_AUTO
:
2129 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
2130 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
2131 case AL_DOPPLER_FACTOR
:
2132 case AL_DIRECT_CHANNELS_SOFT
:
2133 case AL_DISTANCE_MODEL
:
2135 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2136 case AL_BYTE_RW_OFFSETS_SOFT
:
2137 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
2142 GetSourcei64v(Source
, Context
, param
, values
);
2146 alSetError(Context
, AL_INVALID_ENUM
);
2149 ALCcontext_DecRef(Context
);
2153 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
2155 alSourcePlayv(1, &source
);
2157 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
2159 ALCcontext
*Context
;
2163 Context
= GetContextRef();
2164 if(!Context
) return;
2168 CHECK_VALUE(Context
, n
>= 0);
2169 for(i
= 0;i
< n
;i
++)
2171 if(!LookupSource(Context
, sources
[i
]))
2172 al_throwerr(Context
, AL_INVALID_NAME
);
2175 LockContext(Context
);
2176 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
2181 newcount
= Context
->MaxActiveSources
<< 1;
2183 temp
= realloc(Context
->ActiveSources
,
2184 sizeof(*Context
->ActiveSources
) * newcount
);
2187 UnlockContext(Context
);
2188 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
2191 Context
->ActiveSources
= temp
;
2192 Context
->MaxActiveSources
= newcount
;
2195 for(i
= 0;i
< n
;i
++)
2197 Source
= LookupSource(Context
, sources
[i
]);
2198 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
2199 else SetSourceState(Source
, Context
, AL_PLAYING
);
2201 UnlockContext(Context
);
2205 ALCcontext_DecRef(Context
);
2208 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
2210 alSourcePausev(1, &source
);
2212 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
2214 ALCcontext
*Context
;
2218 Context
= GetContextRef();
2219 if(!Context
) return;
2223 CHECK_VALUE(Context
, n
>= 0);
2224 for(i
= 0;i
< n
;i
++)
2226 if(!LookupSource(Context
, sources
[i
]))
2227 al_throwerr(Context
, AL_INVALID_NAME
);
2230 LockContext(Context
);
2231 for(i
= 0;i
< n
;i
++)
2233 Source
= LookupSource(Context
, sources
[i
]);
2234 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
2235 else SetSourceState(Source
, Context
, AL_PAUSED
);
2237 UnlockContext(Context
);
2241 ALCcontext_DecRef(Context
);
2244 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
2246 alSourceStopv(1, &source
);
2248 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
2250 ALCcontext
*Context
;
2254 Context
= GetContextRef();
2255 if(!Context
) return;
2259 CHECK_VALUE(Context
, n
>= 0);
2260 for(i
= 0;i
< n
;i
++)
2262 if(!LookupSource(Context
, sources
[i
]))
2263 al_throwerr(Context
, AL_INVALID_NAME
);
2266 LockContext(Context
);
2267 for(i
= 0;i
< n
;i
++)
2269 Source
= LookupSource(Context
, sources
[i
]);
2270 Source
->new_state
= AL_NONE
;
2271 SetSourceState(Source
, Context
, AL_STOPPED
);
2273 UnlockContext(Context
);
2277 ALCcontext_DecRef(Context
);
2280 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2282 alSourceRewindv(1, &source
);
2284 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2286 ALCcontext
*Context
;
2290 Context
= GetContextRef();
2291 if(!Context
) return;
2295 CHECK_VALUE(Context
, n
>= 0);
2296 for(i
= 0;i
< n
;i
++)
2298 if(!LookupSource(Context
, sources
[i
]))
2299 al_throwerr(Context
, AL_INVALID_NAME
);
2302 LockContext(Context
);
2303 for(i
= 0;i
< n
;i
++)
2305 Source
= LookupSource(Context
, sources
[i
]);
2306 Source
->new_state
= AL_NONE
;
2307 SetSourceState(Source
, Context
, AL_INITIAL
);
2309 UnlockContext(Context
);
2313 ALCcontext_DecRef(Context
);
2317 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei nb
, const ALuint
*buffers
)
2319 ALCcontext
*Context
;
2322 ALbufferlistitem
*BufferListStart
= NULL
;
2323 ALbufferlistitem
*BufferList
;
2324 ALbuffer
*BufferFmt
;
2329 Context
= GetContextRef();
2330 if(!Context
) return;
2334 ALCdevice
*device
= Context
->Device
;
2336 CHECK_VALUE(Context
, nb
>= 0);
2338 if((Source
=LookupSource(Context
, source
)) == NULL
)
2339 al_throwerr(Context
, AL_INVALID_NAME
);
2341 LockContext(Context
);
2342 if(Source
->SourceType
== AL_STATIC
)
2344 UnlockContext(Context
);
2345 /* Can't queue on a Static Source */
2346 al_throwerr(Context
, AL_INVALID_OPERATION
);
2351 /* Check for a valid Buffer, for its frequency and format */
2352 BufferList
= Source
->queue
;
2355 if(BufferList
->buffer
)
2357 BufferFmt
= BufferList
->buffer
;
2360 BufferList
= BufferList
->next
;
2363 for(i
= 0;i
< nb
;i
++)
2365 ALbuffer
*buffer
= NULL
;
2366 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2368 UnlockContext(Context
);
2369 al_throwerr(Context
, AL_INVALID_NAME
);
2372 if(!BufferListStart
)
2374 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2375 BufferListStart
->buffer
= buffer
;
2376 BufferListStart
->next
= NULL
;
2377 BufferListStart
->prev
= NULL
;
2378 BufferList
= BufferListStart
;
2382 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2383 BufferList
->next
->buffer
= buffer
;
2384 BufferList
->next
->next
= NULL
;
2385 BufferList
->next
->prev
= BufferList
;
2386 BufferList
= BufferList
->next
;
2388 if(!buffer
) continue;
2389 IncrementRef(&buffer
->ref
);
2391 ReadLock(&buffer
->lock
);
2392 if(BufferFmt
== NULL
)
2396 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2397 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2398 if(buffer
->FmtChannels
== FmtMono
)
2399 Source
->Update
= CalcSourceParams
;
2401 Source
->Update
= CalcNonAttnSourceParams
;
2403 Source
->NeedsUpdate
= AL_TRUE
;
2405 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2406 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2407 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2409 ReadUnlock(&buffer
->lock
);
2410 UnlockContext(Context
);
2411 al_throwerr(Context
, AL_INVALID_OPERATION
);
2413 ReadUnlock(&buffer
->lock
);
2416 /* Source is now streaming */
2417 Source
->SourceType
= AL_STREAMING
;
2419 if(Source
->queue
== NULL
)
2420 Source
->queue
= BufferListStart
;
2423 /* Append to the end of the queue */
2424 BufferList
= Source
->queue
;
2425 while(BufferList
->next
!= NULL
)
2426 BufferList
= BufferList
->next
;
2428 BufferListStart
->prev
= BufferList
;
2429 BufferList
->next
= BufferListStart
;
2432 Source
->BuffersInQueue
+= nb
;
2434 UnlockContext(Context
);
2438 while(BufferListStart
)
2440 BufferList
= BufferListStart
;
2441 BufferListStart
= BufferList
->next
;
2443 if(BufferList
->buffer
)
2444 DecrementRef(&BufferList
->buffer
->ref
);
2450 ALCcontext_DecRef(Context
);
2453 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint source
, ALsizei nb
, ALuint
*buffers
)
2455 ALCcontext
*Context
;
2458 ALbufferlistitem
*BufferList
;
2463 Context
= GetContextRef();
2464 if(!Context
) return;
2468 CHECK_VALUE(Context
, nb
>= 0);
2470 if((Source
=LookupSource(Context
, source
)) == NULL
)
2471 al_throwerr(Context
, AL_INVALID_NAME
);
2473 LockContext(Context
);
2474 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
||
2475 (ALuint
)nb
> Source
->BuffersPlayed
)
2477 UnlockContext(Context
);
2478 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2479 al_throwerr(Context
, AL_INVALID_VALUE
);
2482 for(i
= 0;i
< nb
;i
++)
2484 BufferList
= Source
->queue
;
2485 Source
->queue
= BufferList
->next
;
2486 Source
->BuffersInQueue
--;
2487 Source
->BuffersPlayed
--;
2489 if(BufferList
->buffer
)
2491 buffers
[i
] = BufferList
->buffer
->id
;
2492 DecrementRef(&BufferList
->buffer
->ref
);
2500 Source
->queue
->prev
= NULL
;
2501 UnlockContext(Context
);
2505 ALCcontext_DecRef(Context
);
2509 static ALvoid
InitSourceParams(ALsource
*Source
)
2513 Source
->InnerAngle
= 360.0f
;
2514 Source
->OuterAngle
= 360.0f
;
2515 Source
->Pitch
= 1.0f
;
2516 Source
->Position
[0] = 0.0f
;
2517 Source
->Position
[1] = 0.0f
;
2518 Source
->Position
[2] = 0.0f
;
2519 Source
->Orientation
[0] = 0.0f
;
2520 Source
->Orientation
[1] = 0.0f
;
2521 Source
->Orientation
[2] = 0.0f
;
2522 Source
->Velocity
[0] = 0.0f
;
2523 Source
->Velocity
[1] = 0.0f
;
2524 Source
->Velocity
[2] = 0.0f
;
2525 Source
->RefDistance
= 1.0f
;
2526 Source
->MaxDistance
= FLT_MAX
;
2527 Source
->RollOffFactor
= 1.0f
;
2528 Source
->Looping
= AL_FALSE
;
2529 Source
->Gain
= 1.0f
;
2530 Source
->MinGain
= 0.0f
;
2531 Source
->MaxGain
= 1.0f
;
2532 Source
->OuterGain
= 0.0f
;
2533 Source
->OuterGainHF
= 1.0f
;
2535 Source
->DryGainHFAuto
= AL_TRUE
;
2536 Source
->WetGainAuto
= AL_TRUE
;
2537 Source
->WetGainHFAuto
= AL_TRUE
;
2538 Source
->AirAbsorptionFactor
= 0.0f
;
2539 Source
->RoomRolloffFactor
= 0.0f
;
2540 Source
->DopplerFactor
= 1.0f
;
2541 Source
->DirectChannels
= AL_FALSE
;
2543 Source
->DistanceModel
= DefaultDistanceModel
;
2545 Source
->Resampler
= DefaultResampler
;
2547 Source
->state
= AL_INITIAL
;
2548 Source
->new_state
= AL_NONE
;
2549 Source
->SourceType
= AL_UNDETERMINED
;
2550 Source
->Offset
= -1.0;
2552 Source
->DirectGain
= 1.0f
;
2553 Source
->DirectGainHF
= 1.0f
;
2554 for(i
= 0;i
< MAX_SENDS
;i
++)
2556 Source
->Send
[i
].Gain
= 1.0f
;
2557 Source
->Send
[i
].GainHF
= 1.0f
;
2560 Source
->NeedsUpdate
= AL_TRUE
;
2562 Source
->Hrtf
.Moving
= AL_FALSE
;
2563 Source
->Hrtf
.Counter
= 0;
2569 * Sets the source's new play state given its current state.
2571 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2573 if(state
== AL_PLAYING
)
2575 ALbufferlistitem
*BufferList
;
2578 /* Check that there is a queue containing at least one valid, non zero
2580 BufferList
= Source
->queue
;
2583 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
2585 BufferList
= BufferList
->next
;
2588 if(Source
->state
!= AL_PLAYING
)
2590 for(j
= 0;j
< MaxChannels
;j
++)
2592 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
2593 Source
->Hrtf
.History
[j
][k
] = 0.0f
;
2594 for(k
= 0;k
< HRIR_LENGTH
;k
++)
2596 Source
->Hrtf
.Values
[j
][k
][0] = 0.0f
;
2597 Source
->Hrtf
.Values
[j
][k
][1] = 0.0f
;
2602 if(Source
->state
!= AL_PAUSED
)
2604 Source
->state
= AL_PLAYING
;
2605 Source
->position
= 0;
2606 Source
->position_fraction
= 0;
2607 Source
->BuffersPlayed
= 0;
2610 Source
->state
= AL_PLAYING
;
2612 // Check if an Offset has been set
2613 if(Source
->Offset
>= 0.0)
2614 ApplyOffset(Source
);
2616 /* If there's nothing to play, or device is disconnected, go right to
2618 if(!BufferList
|| !Context
->Device
->Connected
)
2620 SetSourceState(Source
, Context
, AL_STOPPED
);
2624 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
2626 if(Context
->ActiveSources
[j
] == Source
)
2629 if(j
== Context
->ActiveSourceCount
)
2630 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
2632 else if(state
== AL_PAUSED
)
2634 if(Source
->state
== AL_PLAYING
)
2636 Source
->state
= AL_PAUSED
;
2637 Source
->Hrtf
.Moving
= AL_FALSE
;
2638 Source
->Hrtf
.Counter
= 0;
2641 else if(state
== AL_STOPPED
)
2643 if(Source
->state
!= AL_INITIAL
)
2645 Source
->state
= AL_STOPPED
;
2646 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
2647 Source
->Hrtf
.Moving
= AL_FALSE
;
2648 Source
->Hrtf
.Counter
= 0;
2650 Source
->Offset
= -1.0;
2652 else if(state
== AL_INITIAL
)
2654 if(Source
->state
!= AL_INITIAL
)
2656 Source
->state
= AL_INITIAL
;
2657 Source
->position
= 0;
2658 Source
->position_fraction
= 0;
2659 Source
->BuffersPlayed
= 0;
2660 Source
->Hrtf
.Moving
= AL_FALSE
;
2661 Source
->Hrtf
.Counter
= 0;
2663 Source
->Offset
= -1.0;
2669 * Gets the current read offset for the given Source, in 32.32 fixed-point
2670 * samples. The offset is relative to the start of the queue (not the start of
2671 * the current buffer).
2673 static ALint64
GetSourceOffset(const ALsource
*Source
)
2675 const ALbufferlistitem
*BufferList
;
2679 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2682 /* NOTE: This is the offset into the *current* buffer, so add the length of
2683 * any played buffers */
2684 readPos
= (ALuint64
)Source
->position
<< 32;
2685 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2686 BufferList
= Source
->queue
;
2687 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2689 if(BufferList
->buffer
)
2690 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2691 BufferList
= BufferList
->next
;
2694 return (ALint64
)minu64(readPos
, MAKEU64(0x7fffffff,0xffffffff));
2697 /* GetSourceSecOffset
2699 * Gets the current read offset for the given Source, in seconds. The offset is
2700 * relative to the start of the queue (not the start of the current buffer).
2702 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2704 const ALbufferlistitem
*BufferList
;
2705 const ALbuffer
*Buffer
= NULL
;
2709 BufferList
= Source
->queue
;
2712 if(BufferList
->buffer
)
2714 Buffer
= BufferList
->buffer
;
2717 BufferList
= BufferList
->next
;
2720 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2723 /* NOTE: This is the offset into the *current* buffer, so add the length of
2724 * any played buffers */
2725 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2726 readPos
|= (ALuint64
)Source
->position_fraction
;
2727 BufferList
= Source
->queue
;
2728 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2730 if(BufferList
->buffer
)
2731 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< FRACTIONBITS
;
2732 BufferList
= BufferList
->next
;
2735 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2740 * Gets the current read and write offsets for the given Source, in the
2741 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2742 * the start of the queue (not the start of the current buffer).
2744 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2746 const ALbufferlistitem
*BufferList
;
2747 const ALbuffer
*Buffer
= NULL
;
2748 ALuint readPos
, writePos
;
2749 ALuint totalBufferLen
;
2752 // Find the first valid Buffer in the Queue
2753 BufferList
= Source
->queue
;
2756 if(BufferList
->buffer
)
2758 Buffer
= BufferList
->buffer
;
2761 BufferList
= BufferList
->next
;
2764 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2771 if(updateLen
> 0.0 && updateLen
< 0.015)
2774 /* NOTE: This is the offset into the *current* buffer, so add the length of
2775 * any played buffers */
2776 readPos
= Source
->position
;
2778 BufferList
= Source
->queue
;
2779 for(i
= 0;BufferList
;i
++)
2781 if(BufferList
->buffer
)
2783 if(i
< Source
->BuffersPlayed
)
2784 readPos
+= BufferList
->buffer
->SampleLen
;
2785 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
2787 BufferList
= BufferList
->next
;
2789 if(Source
->state
== AL_PLAYING
)
2790 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2796 readPos
%= totalBufferLen
;
2797 writePos
%= totalBufferLen
;
2801 /* Wrap positions back to 0 */
2802 if(readPos
>= totalBufferLen
)
2804 if(writePos
>= totalBufferLen
)
2811 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2812 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2815 case AL_SAMPLE_OFFSET
:
2816 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2817 offset
[0] = (ALdouble
)readPos
;
2818 offset
[1] = (ALdouble
)writePos
;
2821 case AL_BYTE_OFFSET
:
2822 case AL_BYTE_RW_OFFSETS_SOFT
:
2823 if(Buffer
->OriginalType
== UserFmtIMA4
)
2825 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
2826 ALuint FrameBlockSize
= 65;
2828 /* Round down to nearest ADPCM block */
2829 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2830 if(Source
->state
!= AL_PLAYING
)
2831 offset
[1] = offset
[0];
2834 /* Round up to nearest ADPCM block */
2835 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2836 FrameBlockSize
* BlockSize
);
2841 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2842 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2843 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2852 * Apply the stored playback offset to the Source. This function will update
2853 * the number of buffers "played" given the stored offset.
2855 ALboolean
ApplyOffset(ALsource
*Source
)
2857 const ALbufferlistitem
*BufferList
;
2858 const ALbuffer
*Buffer
;
2859 ALint bufferLen
, totalBufferLen
;
2860 ALint buffersPlayed
;
2863 /* Get sample frame offset */
2864 offset
= GetSampleOffset(Source
);
2871 BufferList
= Source
->queue
;
2874 Buffer
= BufferList
->buffer
;
2875 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2877 if(bufferLen
<= offset
-totalBufferLen
)
2879 /* Offset is past this buffer so increment to the next buffer */
2882 else if(totalBufferLen
<= offset
)
2884 /* Offset is in this buffer */
2885 Source
->BuffersPlayed
= buffersPlayed
;
2887 Source
->position
= offset
- totalBufferLen
;
2888 Source
->position_fraction
= 0;
2892 totalBufferLen
+= bufferLen
;
2894 BufferList
= BufferList
->next
;
2897 /* Offset is out of range of the queue */
2904 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2905 * Second offset supplied by the application). This takes into account the fact
2906 * that the buffer format may have been modifed since.
2908 static ALint
GetSampleOffset(ALsource
*Source
)
2910 const ALbuffer
*Buffer
= NULL
;
2911 const ALbufferlistitem
*BufferList
;
2914 /* Find the first valid Buffer in the Queue */
2915 BufferList
= Source
->queue
;
2918 if(BufferList
->buffer
)
2920 Buffer
= BufferList
->buffer
;
2923 BufferList
= BufferList
->next
;
2928 Source
->Offset
= -1.0;
2932 switch(Source
->OffsetType
)
2934 case AL_BYTE_OFFSET
:
2935 /* Determine the ByteOffset (and ensure it is block aligned) */
2936 Offset
= (ALint
)Source
->Offset
;
2937 if(Buffer
->OriginalType
== UserFmtIMA4
)
2939 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2943 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2946 case AL_SAMPLE_OFFSET
:
2947 Offset
= (ALint
)Source
->Offset
;
2951 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2954 Source
->Offset
= -1.0;
2962 * Destroys all sources in the source map.
2964 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2968 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2970 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2971 Context
->SourceMap
.array
[pos
].value
= NULL
;
2973 while(temp
->queue
!= NULL
)
2975 ALbufferlistitem
*BufferList
= temp
->queue
;
2976 temp
->queue
= BufferList
->next
;
2978 if(BufferList
->buffer
!= NULL
)
2979 DecrementRef(&BufferList
->buffer
->ref
);
2983 for(j
= 0;j
< MAX_SENDS
;++j
)
2985 if(temp
->Send
[j
].Slot
)
2986 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2987 temp
->Send
[j
].Slot
= NULL
;
2990 FreeThunkEntry(temp
->id
);
2991 memset(temp
, 0, sizeof(*temp
));