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
);
156 static ALint
FloatValsByProp(ALenum prop
)
158 if(prop
!= (ALenum
)((SrcFloatProp
)prop
))
160 switch((SrcFloatProp
)prop
)
167 case sfRolloffFactor
:
168 case sfDopplerFactor
:
169 case sfConeOuterGain
:
173 case sfConeInnerAngle
:
174 case sfConeOuterAngle
:
176 case sfConeOuterGainHF
:
177 case sfAirAbsorptionFactor
:
178 case sfRoomRolloffFactor
:
179 case sfDirectFilterGainHFAuto
:
180 case sfAuxSendFilterGainAuto
:
181 case sfAuxSendFilterGainHFAuto
:
182 case sfDirectChannelsSOFT
:
183 case sfDistanceModel
:
184 case sfSourceRelative
:
188 case sfBuffersQueued
:
189 case sfBuffersProcessed
:
193 case sfSampleRWOffsetsSOFT
:
194 case sfByteRWOffsetsSOFT
:
202 case sfSecOffsetLatencySOFT
:
203 break; /* Double only */
207 static ALint
DoubleValsByProp(ALenum prop
)
209 if(prop
!= (ALenum
)((SrcFloatProp
)prop
))
211 switch((SrcFloatProp
)prop
)
218 case sfRolloffFactor
:
219 case sfDopplerFactor
:
220 case sfConeOuterGain
:
224 case sfConeInnerAngle
:
225 case sfConeOuterAngle
:
227 case sfConeOuterGainHF
:
228 case sfAirAbsorptionFactor
:
229 case sfRoomRolloffFactor
:
230 case sfDirectFilterGainHFAuto
:
231 case sfAuxSendFilterGainAuto
:
232 case sfAuxSendFilterGainHFAuto
:
233 case sfDirectChannelsSOFT
:
234 case sfDistanceModel
:
235 case sfSourceRelative
:
239 case sfBuffersQueued
:
240 case sfBuffersProcessed
:
244 case sfSampleRWOffsetsSOFT
:
245 case sfByteRWOffsetsSOFT
:
246 case sfSecOffsetLatencySOFT
:
257 static ALint
IntValsByProp(ALenum prop
)
259 if(prop
!= (ALenum
)((SrcIntProp
)prop
))
261 switch((SrcIntProp
)prop
)
264 case siRolloffFactor
:
266 case siSourceRelative
:
267 case siConeInnerAngle
:
268 case siConeOuterAngle
:
272 case siBuffersQueued
:
273 case siBuffersProcessed
:
278 case siDopplerFactor
:
279 case siDirectFilterGainHFAuto
:
280 case siAuxSendFilterGainAutio
:
281 case siAuxSendFilterGainHFAuto
:
283 case siDirectChannelsSOFT
:
284 case siDistanceModel
:
287 case siSampleRWOffsetsSOFT
:
288 case siByteRWOffsetsSOFT
:
294 case siAuxSendFilter
:
297 case siSampleOffsetLatencySOFT
:
298 break; /* i64 only */
302 static ALint
Int64ValsByProp(ALenum prop
)
304 if(prop
!= (ALenum
)((SrcIntProp
)prop
))
306 switch((SrcIntProp
)prop
)
309 case siRolloffFactor
:
311 case siSourceRelative
:
312 case siConeInnerAngle
:
313 case siConeOuterAngle
:
317 case siBuffersQueued
:
318 case siBuffersProcessed
:
323 case siDopplerFactor
:
324 case siDirectFilterGainHFAuto
:
325 case siAuxSendFilterGainAutio
:
326 case siAuxSendFilterGainHFAuto
:
328 case siDirectChannelsSOFT
:
329 case siDistanceModel
:
332 case siSampleRWOffsetsSOFT
:
333 case siByteRWOffsetsSOFT
:
334 case siSampleOffsetLatencySOFT
:
340 case siAuxSendFilter
:
347 #define RETERR(x) do { \
348 alSetError(Context, (x)); \
352 #define CHECKVAL(x) do { \
354 RETERR(AL_INVALID_VALUE); \
357 static ALenum
SetSourcefv(ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, const ALfloat
*values
)
364 CHECKVAL(*values
>= 0.0f
);
366 Source
->Pitch
= *values
;
367 Source
->NeedsUpdate
= AL_TRUE
;
370 case AL_CONE_INNER_ANGLE
:
371 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
373 Source
->InnerAngle
= *values
;
374 Source
->NeedsUpdate
= AL_TRUE
;
377 case AL_CONE_OUTER_ANGLE
:
378 CHECKVAL(*values
>= 0.0f
&& *values
<= 360.0f
);
380 Source
->OuterAngle
= *values
;
381 Source
->NeedsUpdate
= AL_TRUE
;
385 CHECKVAL(*values
>= 0.0f
);
387 Source
->Gain
= *values
;
388 Source
->NeedsUpdate
= AL_TRUE
;
391 case AL_MAX_DISTANCE
:
392 CHECKVAL(*values
>= 0.0f
);
394 Source
->MaxDistance
= *values
;
395 Source
->NeedsUpdate
= AL_TRUE
;
398 case AL_ROLLOFF_FACTOR
:
399 CHECKVAL(*values
>= 0.0f
);
401 Source
->RollOffFactor
= *values
;
402 Source
->NeedsUpdate
= AL_TRUE
;
405 case AL_REFERENCE_DISTANCE
:
406 CHECKVAL(*values
>= 0.0f
);
408 Source
->RefDistance
= *values
;
409 Source
->NeedsUpdate
= AL_TRUE
;
413 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
415 Source
->MinGain
= *values
;
416 Source
->NeedsUpdate
= AL_TRUE
;
420 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
422 Source
->MaxGain
= *values
;
423 Source
->NeedsUpdate
= AL_TRUE
;
426 case AL_CONE_OUTER_GAIN
:
427 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
429 Source
->OuterGain
= *values
;
430 Source
->NeedsUpdate
= AL_TRUE
;
433 case AL_CONE_OUTER_GAINHF
:
434 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
436 Source
->OuterGainHF
= *values
;
437 Source
->NeedsUpdate
= AL_TRUE
;
440 case AL_AIR_ABSORPTION_FACTOR
:
441 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
443 Source
->AirAbsorptionFactor
= *values
;
444 Source
->NeedsUpdate
= AL_TRUE
;
447 case AL_ROOM_ROLLOFF_FACTOR
:
448 CHECKVAL(*values
>= 0.0f
&& *values
<= 10.0f
);
450 Source
->RoomRolloffFactor
= *values
;
451 Source
->NeedsUpdate
= AL_TRUE
;
454 case AL_DOPPLER_FACTOR
:
455 CHECKVAL(*values
>= 0.0f
&& *values
<= 1.0f
);
457 Source
->DopplerFactor
= *values
;
458 Source
->NeedsUpdate
= AL_TRUE
;
462 case AL_SAMPLE_OFFSET
:
464 CHECKVAL(*values
>= 0.0f
);
466 LockContext(Context
);
467 Source
->OffsetType
= prop
;
468 Source
->Offset
= *values
;
470 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
471 !Context
->DeferUpdates
)
473 if(ApplyOffset(Source
) == AL_FALSE
)
475 UnlockContext(Context
);
476 RETERR(AL_INVALID_VALUE
);
479 UnlockContext(Context
);
483 case AL_SEC_OFFSET_LATENCY_SOFT
:
485 RETERR(AL_INVALID_OPERATION
);
489 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
491 LockContext(Context
);
492 Source
->Position
[0] = values
[0];
493 Source
->Position
[1] = values
[1];
494 Source
->Position
[2] = values
[2];
495 UnlockContext(Context
);
496 Source
->NeedsUpdate
= AL_TRUE
;
500 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
502 LockContext(Context
);
503 Source
->Velocity
[0] = values
[0];
504 Source
->Velocity
[1] = values
[1];
505 Source
->Velocity
[2] = values
[2];
506 UnlockContext(Context
);
507 Source
->NeedsUpdate
= AL_TRUE
;
511 CHECKVAL(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]));
513 LockContext(Context
);
514 Source
->Orientation
[0] = values
[0];
515 Source
->Orientation
[1] = values
[1];
516 Source
->Orientation
[2] = values
[2];
517 UnlockContext(Context
);
518 Source
->NeedsUpdate
= AL_TRUE
;
522 case sfSampleRWOffsetsSOFT
:
523 case sfByteRWOffsetsSOFT
:
524 RETERR(AL_INVALID_OPERATION
);
527 case sfSourceRelative
:
531 case sfDistanceModel
:
532 case sfDirectFilterGainHFAuto
:
533 case sfAuxSendFilterGainAuto
:
534 case sfAuxSendFilterGainHFAuto
:
535 case sfDirectChannelsSOFT
:
536 ival
= (ALint
)values
[0];
537 return SetSourceiv(Source
, Context
, prop
, &ival
);
540 case sfBuffersQueued
:
541 case sfBuffersProcessed
:
542 ival
= (ALint
)((ALuint
)values
[0]);
543 return SetSourceiv(Source
, Context
, prop
, &ival
);
546 ERR("Unexpected property: 0x%04x\n", prop
);
547 RETERR(AL_INVALID_ENUM
);
550 static ALenum
SetSourceiv(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint
*values
)
552 ALCdevice
*device
= Context
->Device
;
553 ALbuffer
*buffer
= NULL
;
554 ALfilter
*filter
= NULL
;
555 ALeffectslot
*slot
= NULL
;
556 ALbufferlistitem
*oldlist
;
561 case AL_SOURCE_RELATIVE
:
562 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
564 Source
->HeadRelative
= (ALboolean
)*values
;
565 Source
->NeedsUpdate
= AL_TRUE
;
569 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
571 Source
->Looping
= (ALboolean
)*values
;
575 CHECKVAL(*values
== 0 || (buffer
=LookupBuffer(device
, *values
)) != NULL
);
577 LockContext(Context
);
578 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
580 UnlockContext(Context
);
581 RETERR(AL_INVALID_OPERATION
);
584 Source
->BuffersInQueue
= 0;
585 Source
->BuffersPlayed
= 0;
589 ALbufferlistitem
*BufferListItem
;
591 /* Source is now Static */
592 Source
->SourceType
= AL_STATIC
;
594 /* Add the selected buffer to a one-item queue */
595 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
596 BufferListItem
->buffer
= buffer
;
597 BufferListItem
->next
= NULL
;
598 BufferListItem
->prev
= NULL
;
599 IncrementRef(&buffer
->ref
);
601 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, BufferListItem
);
602 Source
->BuffersInQueue
= 1;
604 ReadLock(&buffer
->lock
);
605 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
606 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
607 ReadUnlock(&buffer
->lock
);
608 if(buffer
->FmtChannels
== FmtMono
)
609 Source
->Update
= CalcSourceParams
;
611 Source
->Update
= CalcNonAttnSourceParams
;
612 Source
->NeedsUpdate
= AL_TRUE
;
616 /* Source is now Undetermined */
617 Source
->SourceType
= AL_UNDETERMINED
;
618 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, NULL
);
621 /* Delete all elements in the previous queue */
622 while(oldlist
!= NULL
)
624 ALbufferlistitem
*temp
= oldlist
;
625 oldlist
= temp
->next
;
628 DecrementRef(&temp
->buffer
->ref
);
631 UnlockContext(Context
);
636 case siBuffersQueued
:
637 case siBuffersProcessed
:
639 RETERR(AL_INVALID_OPERATION
);
642 case AL_SAMPLE_OFFSET
:
644 CHECKVAL(*values
>= 0);
646 LockContext(Context
);
647 Source
->OffsetType
= prop
;
648 Source
->Offset
= *values
;
650 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
651 !Context
->DeferUpdates
)
653 if(ApplyOffset(Source
) == AL_FALSE
)
655 UnlockContext(Context
);
656 RETERR(AL_INVALID_VALUE
);
659 UnlockContext(Context
);
663 case siSampleRWOffsetsSOFT
:
664 case siByteRWOffsetsSOFT
:
666 RETERR(AL_INVALID_OPERATION
);
669 case AL_DIRECT_FILTER
:
670 CHECKVAL(*values
== 0 || (filter
=LookupFilter(device
, *values
)) != NULL
);
672 LockContext(Context
);
675 Source
->DirectGain
= 1.0f
;
676 Source
->DirectGainHF
= 1.0f
;
680 Source
->DirectGain
= filter
->Gain
;
681 Source
->DirectGainHF
= filter
->GainHF
;
683 UnlockContext(Context
);
684 Source
->NeedsUpdate
= AL_TRUE
;
687 case AL_DIRECT_FILTER_GAINHF_AUTO
:
688 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
690 Source
->DryGainHFAuto
= *values
;
691 Source
->NeedsUpdate
= AL_TRUE
;
694 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
695 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
697 Source
->WetGainAuto
= *values
;
698 Source
->NeedsUpdate
= AL_TRUE
;
701 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
702 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
704 Source
->WetGainHFAuto
= *values
;
705 Source
->NeedsUpdate
= AL_TRUE
;
708 case AL_DIRECT_CHANNELS_SOFT
:
709 CHECKVAL(*values
== AL_FALSE
|| *values
== AL_TRUE
);
711 Source
->DirectChannels
= *values
;
712 Source
->NeedsUpdate
= AL_TRUE
;
715 case AL_DISTANCE_MODEL
:
716 CHECKVAL(*values
== AL_NONE
||
717 *values
== AL_INVERSE_DISTANCE
||
718 *values
== AL_INVERSE_DISTANCE_CLAMPED
||
719 *values
== AL_LINEAR_DISTANCE
||
720 *values
== AL_LINEAR_DISTANCE_CLAMPED
||
721 *values
== AL_EXPONENT_DISTANCE
||
722 *values
== AL_EXPONENT_DISTANCE_CLAMPED
);
724 Source
->DistanceModel
= *values
;
725 if(Context
->SourceDistanceModel
)
726 Source
->NeedsUpdate
= AL_TRUE
;
730 case AL_AUXILIARY_SEND_FILTER
:
731 LockContext(Context
);
732 if(!((ALuint
)values
[1] < device
->NumAuxSends
&&
733 (values
[0] == 0 || (slot
=LookupEffectSlot(Context
, values
[0])) != NULL
) &&
734 (values
[2] == 0 || (filter
=LookupFilter(device
, values
[2])) != NULL
)))
736 UnlockContext(Context
);
737 RETERR(AL_INVALID_VALUE
);
740 /* Add refcount on the new slot, and release the previous slot */
741 if(slot
) IncrementRef(&slot
->ref
);
742 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[values
[1]].Slot
, slot
);
743 if(slot
) DecrementRef(&slot
->ref
);
748 Source
->Send
[values
[1]].Gain
= 1.0f
;
749 Source
->Send
[values
[1]].GainHF
= 1.0f
;
753 Source
->Send
[values
[1]].Gain
= filter
->Gain
;
754 Source
->Send
[values
[1]].GainHF
= filter
->GainHF
;
756 Source
->NeedsUpdate
= AL_TRUE
;
757 UnlockContext(Context
);
761 case AL_MAX_DISTANCE
:
762 case AL_ROLLOFF_FACTOR
:
763 case AL_CONE_INNER_ANGLE
:
764 case AL_CONE_OUTER_ANGLE
:
765 case AL_REFERENCE_DISTANCE
:
766 case siDopplerFactor
:
767 fvals
[0] = (ALfloat
)*values
;
768 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
773 fvals
[0] = (ALfloat
)values
[0];
774 fvals
[1] = (ALfloat
)values
[1];
775 fvals
[2] = (ALfloat
)values
[2];
776 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
778 case siSampleOffsetLatencySOFT
:
783 ERR("Unexpected property: 0x%04x\n", prop
);
784 RETERR(AL_INVALID_ENUM
);
787 static ALenum
SetSourcei64v(ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, const ALint64SOFT
*values
)
794 case siSampleRWOffsetsSOFT
:
795 case siByteRWOffsetsSOFT
:
796 case siSampleOffsetLatencySOFT
:
798 RETERR(AL_INVALID_OPERATION
);
802 case AL_SOURCE_RELATIVE
:
804 case AL_SOURCE_STATE
:
806 case AL_SAMPLE_OFFSET
:
808 case siBuffersQueued
:
809 case siBuffersProcessed
:
810 case AL_DIRECT_FILTER_GAINHF_AUTO
:
811 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
812 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
813 case AL_DIRECT_CHANNELS_SOFT
:
814 case AL_DISTANCE_MODEL
:
815 CHECKVAL(*values
<= INT_MAX
&& *values
>= INT_MIN
);
817 ivals
[0] = (ALint
)*values
;
818 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
822 case AL_DIRECT_FILTER
:
823 CHECKVAL(*values
<= UINT_MAX
&& *values
>= 0);
825 ivals
[0] = (ALuint
)*values
;
826 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
829 case AL_AUXILIARY_SEND_FILTER
:
830 CHECKVAL(values
[0] <= UINT_MAX
&& values
[0] >= 0 &&
831 values
[1] <= UINT_MAX
&& values
[1] >= 0 &&
832 values
[2] <= UINT_MAX
&& values
[2] >= 0);
834 ivals
[0] = (ALuint
)values
[0];
835 ivals
[1] = (ALuint
)values
[1];
836 ivals
[2] = (ALuint
)values
[2];
837 return SetSourceiv(Source
, Context
, (int)prop
, ivals
);
840 case AL_MAX_DISTANCE
:
841 case AL_ROLLOFF_FACTOR
:
842 case AL_CONE_INNER_ANGLE
:
843 case AL_CONE_OUTER_ANGLE
:
844 case AL_REFERENCE_DISTANCE
:
846 case siDopplerFactor
:
847 fvals
[0] = (ALfloat
)*values
;
848 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
854 fvals
[0] = (ALfloat
)values
[0];
855 fvals
[1] = (ALfloat
)values
[1];
856 fvals
[2] = (ALfloat
)values
[2];
857 return SetSourcefv(Source
, Context
, (int)prop
, fvals
);
860 ERR("Unexpected property: 0x%04x\n", prop
);
861 RETERR(AL_INVALID_ENUM
);
867 static ALenum
GetSourcedv(const ALsource
*Source
, ALCcontext
*Context
, SrcFloatProp prop
, ALdouble
*values
)
877 *values
= Source
->Gain
;
881 *values
= Source
->Pitch
;
884 case AL_MAX_DISTANCE
:
885 *values
= Source
->MaxDistance
;
888 case AL_ROLLOFF_FACTOR
:
889 *values
= Source
->RollOffFactor
;
892 case AL_REFERENCE_DISTANCE
:
893 *values
= Source
->RefDistance
;
896 case AL_CONE_INNER_ANGLE
:
897 *values
= Source
->InnerAngle
;
900 case AL_CONE_OUTER_ANGLE
:
901 *values
= Source
->OuterAngle
;
905 *values
= Source
->MinGain
;
909 *values
= Source
->MaxGain
;
912 case AL_CONE_OUTER_GAIN
:
913 *values
= Source
->OuterGain
;
917 case AL_SAMPLE_OFFSET
:
919 LockContext(Context
);
920 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
921 Context
->Device
->Frequency
;
922 GetSourceOffsets(Source
, prop
, offsets
, updateLen
);
923 UnlockContext(Context
);
924 *values
= offsets
[0];
927 case AL_CONE_OUTER_GAINHF
:
928 *values
= Source
->OuterGainHF
;
931 case AL_AIR_ABSORPTION_FACTOR
:
932 *values
= Source
->AirAbsorptionFactor
;
935 case AL_ROOM_ROLLOFF_FACTOR
:
936 *values
= Source
->RoomRolloffFactor
;
939 case AL_DOPPLER_FACTOR
:
940 *values
= Source
->DopplerFactor
;
943 case AL_SAMPLE_RW_OFFSETS_SOFT
:
944 case AL_BYTE_RW_OFFSETS_SOFT
:
945 LockContext(Context
);
946 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
947 Context
->Device
->Frequency
;
948 GetSourceOffsets(Source
, prop
, values
, updateLen
);
949 UnlockContext(Context
);
952 case AL_SEC_OFFSET_LATENCY_SOFT
:
953 LockContext(Context
);
954 values
[0] = GetSourceSecOffset(Source
);
955 values
[1] = (ALdouble
)ALCdevice_GetLatency(Context
->Device
) /
957 UnlockContext(Context
);
961 LockContext(Context
);
962 values
[0] = Source
->Position
[0];
963 values
[1] = Source
->Position
[1];
964 values
[2] = Source
->Position
[2];
965 UnlockContext(Context
);
969 LockContext(Context
);
970 values
[0] = Source
->Velocity
[0];
971 values
[1] = Source
->Velocity
[1];
972 values
[2] = Source
->Velocity
[2];
973 UnlockContext(Context
);
977 LockContext(Context
);
978 values
[0] = Source
->Orientation
[0];
979 values
[1] = Source
->Orientation
[1];
980 values
[2] = Source
->Orientation
[2];
981 UnlockContext(Context
);
984 case AL_SOURCE_RELATIVE
:
987 case AL_SOURCE_STATE
:
988 case AL_BUFFERS_QUEUED
:
989 case AL_BUFFERS_PROCESSED
:
991 case AL_DIRECT_FILTER_GAINHF_AUTO
:
992 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
993 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
994 case AL_DIRECT_CHANNELS_SOFT
:
995 case AL_DISTANCE_MODEL
:
996 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) == AL_NO_ERROR
)
997 *values
= (ALdouble
)ivals
[0];
1001 ERR("Unexpected property: 0x%04x\n", prop
);
1002 RETERR(AL_INVALID_ENUM
);
1005 static ALenum
GetSourceiv(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint
*values
)
1007 ALbufferlistitem
*BufferList
;
1013 case AL_SOURCE_RELATIVE
:
1014 *values
= Source
->HeadRelative
;
1018 *values
= Source
->Looping
;
1022 LockContext(Context
);
1023 BufferList
= Source
->queue
;
1024 if(Source
->SourceType
!= AL_STATIC
)
1026 ALuint i
= Source
->BuffersPlayed
;
1029 BufferList
= BufferList
->next
;
1033 *values
= ((BufferList
&& BufferList
->buffer
) ?
1034 BufferList
->buffer
->id
: 0);
1035 UnlockContext(Context
);
1038 case AL_SOURCE_STATE
:
1039 *values
= Source
->state
;
1042 case AL_BUFFERS_QUEUED
:
1043 *values
= Source
->BuffersInQueue
;
1046 case AL_BUFFERS_PROCESSED
:
1047 LockContext(Context
);
1048 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
1050 /* Buffers on a looping source are in a perpetual state of
1051 * PENDING, so don't report any as PROCESSED */
1055 *values
= Source
->BuffersPlayed
;
1056 UnlockContext(Context
);
1059 case AL_SOURCE_TYPE
:
1060 *values
= Source
->SourceType
;
1063 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1064 *values
= Source
->DryGainHFAuto
;
1067 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1068 *values
= Source
->WetGainAuto
;
1071 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1072 *values
= Source
->WetGainHFAuto
;
1075 case AL_DIRECT_CHANNELS_SOFT
:
1076 *values
= Source
->DirectChannels
;
1079 case AL_DISTANCE_MODEL
:
1080 *values
= Source
->DistanceModel
;
1083 case AL_MAX_DISTANCE
:
1084 case AL_ROLLOFF_FACTOR
:
1085 case AL_REFERENCE_DISTANCE
:
1086 case AL_CONE_INNER_ANGLE
:
1087 case AL_CONE_OUTER_ANGLE
:
1089 case AL_SAMPLE_OFFSET
:
1090 case AL_BYTE_OFFSET
:
1091 case AL_DOPPLER_FACTOR
:
1092 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
1093 *values
= (ALint
)dvals
[0];
1096 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1097 case AL_BYTE_RW_OFFSETS_SOFT
:
1098 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
1100 values
[0] = (ALint
)dvals
[0];
1101 values
[1] = (ALint
)dvals
[1];
1108 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
1110 values
[0] = (ALint
)dvals
[0];
1111 values
[1] = (ALint
)dvals
[1];
1112 values
[2] = (ALint
)dvals
[2];
1116 case siSampleOffsetLatencySOFT
:
1120 case siDirectFilter
:
1121 case siAuxSendFilter
:
1126 ERR("Unexpected property: 0x%04x\n", prop
);
1127 RETERR(AL_INVALID_ENUM
);
1130 static ALenum
GetSourcei64v(const ALsource
*Source
, ALCcontext
*Context
, SrcIntProp prop
, ALint64
*values
)
1138 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1139 LockContext(Context
);
1140 values
[0] = GetSourceOffset(Source
);
1141 values
[1] = ALCdevice_GetLatency(Context
->Device
);
1142 UnlockContext(Context
);
1145 case AL_MAX_DISTANCE
:
1146 case AL_ROLLOFF_FACTOR
:
1147 case AL_REFERENCE_DISTANCE
:
1148 case AL_CONE_INNER_ANGLE
:
1149 case AL_CONE_OUTER_ANGLE
:
1151 case AL_SAMPLE_OFFSET
:
1152 case AL_BYTE_OFFSET
:
1153 case AL_DOPPLER_FACTOR
:
1154 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
1155 *values
= (ALint64
)dvals
[0];
1158 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1159 case AL_BYTE_RW_OFFSETS_SOFT
:
1160 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
1162 values
[0] = (ALint64
)dvals
[0];
1163 values
[1] = (ALint64
)dvals
[1];
1170 if((err
=GetSourcedv(Source
, Context
, (int)prop
, dvals
)) == AL_NO_ERROR
)
1172 values
[0] = (ALint64
)dvals
[0];
1173 values
[1] = (ALint64
)dvals
[1];
1174 values
[2] = (ALint64
)dvals
[2];
1178 case AL_SOURCE_RELATIVE
:
1180 case AL_SOURCE_STATE
:
1181 case AL_BUFFERS_QUEUED
:
1182 case AL_BUFFERS_PROCESSED
:
1183 case AL_SOURCE_TYPE
:
1184 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1185 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1186 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1187 case AL_DIRECT_CHANNELS_SOFT
:
1188 case AL_DISTANCE_MODEL
:
1189 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) == AL_NO_ERROR
)
1194 case siDirectFilter
:
1195 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) == AL_NO_ERROR
)
1196 *values
= ((ALuint
*)ivals
)[0];
1199 case siAuxSendFilter
:
1200 if((err
=GetSourceiv(Source
, Context
, (int)prop
, ivals
)) == AL_NO_ERROR
)
1202 values
[0] = ((ALuint
*)ivals
)[0];
1203 values
[1] = ((ALuint
*)ivals
)[1];
1204 values
[2] = ((ALuint
*)ivals
)[2];
1209 ERR("Unexpected property: 0x%04x\n", prop
);
1210 RETERR(AL_INVALID_ENUM
);
1216 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
1218 ALCcontext
*Context
;
1221 Context
= GetContextRef();
1222 if(!Context
) return;
1228 CHECK_VALUE(Context
, n
>= 0);
1229 for(cur
= 0;cur
< n
;cur
++)
1231 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
1233 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
1234 InitSourceParams(source
);
1236 err
= NewThunkEntry(&source
->id
);
1237 if(err
== AL_NO_ERROR
)
1238 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->id
, source
);
1239 if(err
!= AL_NO_ERROR
)
1241 FreeThunkEntry(source
->id
);
1242 memset(source
, 0, sizeof(ALsource
));
1245 al_throwerr(Context
, err
);
1248 sources
[cur
] = source
->id
;
1254 alDeleteSources(cur
, sources
);
1258 ALCcontext_DecRef(Context
);
1262 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
1264 ALCcontext
*Context
;
1266 Context
= GetContextRef();
1267 if(!Context
) return;
1271 ALbufferlistitem
*BufferList
;
1275 CHECK_VALUE(Context
, n
>= 0);
1277 /* Check that all Sources are valid */
1278 for(i
= 0;i
< n
;i
++)
1280 if(LookupSource(Context
, sources
[i
]) == NULL
)
1281 al_throwerr(Context
, AL_INVALID_NAME
);
1284 for(i
= 0;i
< n
;i
++)
1286 ALsource
**srclist
, **srclistend
;
1288 if((Source
=RemoveSource(Context
, sources
[i
])) == NULL
)
1290 FreeThunkEntry(Source
->id
);
1292 LockContext(Context
);
1293 srclist
= Context
->ActiveSources
;
1294 srclistend
= srclist
+ Context
->ActiveSourceCount
;
1295 while(srclist
!= srclistend
)
1297 if(*srclist
== Source
)
1299 Context
->ActiveSourceCount
--;
1300 *srclist
= *(--srclistend
);
1305 UnlockContext(Context
);
1307 while(Source
->queue
!= NULL
)
1309 BufferList
= Source
->queue
;
1310 Source
->queue
= BufferList
->next
;
1312 if(BufferList
->buffer
!= NULL
)
1313 DecrementRef(&BufferList
->buffer
->ref
);
1317 for(j
= 0;j
< MAX_SENDS
;++j
)
1319 if(Source
->Send
[j
].Slot
)
1320 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
1321 Source
->Send
[j
].Slot
= NULL
;
1324 memset(Source
, 0, sizeof(*Source
));
1330 ALCcontext_DecRef(Context
);
1334 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
1336 ALCcontext
*Context
;
1339 Context
= GetContextRef();
1340 if(!Context
) return AL_FALSE
;
1342 result
= (LookupSource(Context
, source
) ? AL_TRUE
: AL_FALSE
);
1344 ALCcontext_DecRef(Context
);
1350 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
1352 ALCcontext
*Context
;
1355 Context
= GetContextRef();
1356 if(!Context
) return;
1358 if((Source
=LookupSource(Context
, source
)) == NULL
)
1359 alSetError(Context
, AL_INVALID_NAME
);
1360 else if(!(FloatValsByProp(param
) == 1))
1361 alSetError(Context
, AL_INVALID_ENUM
);
1363 SetSourcefv(Source
, Context
, param
, &value
);
1365 ALCcontext_DecRef(Context
);
1368 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
1370 ALCcontext
*Context
;
1373 Context
= GetContextRef();
1374 if(!Context
) return;
1376 if((Source
=LookupSource(Context
, source
)) == NULL
)
1377 alSetError(Context
, AL_INVALID_NAME
);
1378 else if(!(FloatValsByProp(param
) == 3))
1379 alSetError(Context
, AL_INVALID_ENUM
);
1382 ALfloat fvals
[3] = { value1
, value2
, value3
};
1383 SetSourcefv(Source
, Context
, param
, fvals
);
1386 ALCcontext_DecRef(Context
);
1389 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
1391 ALCcontext
*Context
;
1394 Context
= GetContextRef();
1395 if(!Context
) return;
1397 if((Source
=LookupSource(Context
, source
)) == NULL
)
1398 alSetError(Context
, AL_INVALID_NAME
);
1400 alSetError(Context
, AL_INVALID_VALUE
);
1401 else if(!(FloatValsByProp(param
) > 0))
1402 alSetError(Context
, AL_INVALID_ENUM
);
1404 SetSourcefv(Source
, Context
, param
, values
);
1406 ALCcontext_DecRef(Context
);
1410 AL_API ALvoid AL_APIENTRY
alSourcedSOFT(ALuint source
, ALenum param
, ALdouble value
)
1412 ALCcontext
*Context
;
1415 Context
= GetContextRef();
1416 if(!Context
) return;
1418 if((Source
=LookupSource(Context
, source
)) == NULL
)
1419 alSetError(Context
, AL_INVALID_NAME
);
1420 else if(!(DoubleValsByProp(param
) == 1))
1421 alSetError(Context
, AL_INVALID_ENUM
);
1424 ALfloat fval
= (ALfloat
)value
;
1425 SetSourcefv(Source
, Context
, param
, &fval
);
1428 ALCcontext_DecRef(Context
);
1431 AL_API ALvoid AL_APIENTRY
alSource3dSOFT(ALuint source
, ALenum param
, ALdouble value1
, ALdouble value2
, ALdouble value3
)
1433 ALCcontext
*Context
;
1436 Context
= GetContextRef();
1437 if(!Context
) return;
1439 if((Source
=LookupSource(Context
, source
)) == NULL
)
1440 alSetError(Context
, AL_INVALID_NAME
);
1441 else if(!(DoubleValsByProp(param
) == 3))
1442 alSetError(Context
, AL_INVALID_ENUM
);
1445 ALfloat fvals
[3] = { (ALfloat
)value1
, (ALfloat
)value2
, (ALfloat
)value3
};
1446 SetSourcefv(Source
, Context
, param
, fvals
);
1449 ALCcontext_DecRef(Context
);
1452 AL_API ALvoid AL_APIENTRY
alSourcedvSOFT(ALuint source
, ALenum param
, const ALdouble
*values
)
1454 ALCcontext
*Context
;
1458 Context
= GetContextRef();
1459 if(!Context
) return;
1461 if((Source
=LookupSource(Context
, source
)) == NULL
)
1462 alSetError(Context
, AL_INVALID_NAME
);
1464 alSetError(Context
, AL_INVALID_VALUE
);
1465 else if(!((count
=DoubleValsByProp(param
)) > 0 && count
<= 3))
1466 alSetError(Context
, AL_INVALID_ENUM
);
1472 for(i
= 0;i
< count
;i
++)
1473 fvals
[i
] = (ALfloat
)values
[i
];
1474 SetSourcefv(Source
, Context
, param
, fvals
);
1477 ALCcontext_DecRef(Context
);
1481 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
1483 ALCcontext
*Context
;
1486 Context
= GetContextRef();
1487 if(!Context
) return;
1489 if((Source
=LookupSource(Context
, source
)) == NULL
)
1490 alSetError(Context
, AL_INVALID_NAME
);
1491 else if(!(IntValsByProp(param
) == 1))
1492 alSetError(Context
, AL_INVALID_ENUM
);
1494 SetSourceiv(Source
, Context
, param
, &value
);
1496 ALCcontext_DecRef(Context
);
1499 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
1501 ALCcontext
*Context
;
1504 Context
= GetContextRef();
1505 if(!Context
) return;
1507 if((Source
=LookupSource(Context
, source
)) == NULL
)
1508 alSetError(Context
, AL_INVALID_NAME
);
1509 else if(!(IntValsByProp(param
) == 3))
1510 alSetError(Context
, AL_INVALID_ENUM
);
1513 ALint ivals
[3] = { value1
, value2
, value3
};
1514 SetSourceiv(Source
, Context
, param
, ivals
);
1517 ALCcontext_DecRef(Context
);
1520 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
1522 ALCcontext
*Context
;
1525 Context
= GetContextRef();
1526 if(!Context
) return;
1528 if((Source
=LookupSource(Context
, source
)) == NULL
)
1529 alSetError(Context
, AL_INVALID_NAME
);
1531 alSetError(Context
, AL_INVALID_VALUE
);
1532 else if(!(IntValsByProp(param
) > 0))
1533 alSetError(Context
, AL_INVALID_ENUM
);
1535 SetSourceiv(Source
, Context
, param
, values
);
1537 ALCcontext_DecRef(Context
);
1541 AL_API ALvoid AL_APIENTRY
alSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT value
)
1543 ALCcontext
*Context
;
1546 Context
= GetContextRef();
1547 if(!Context
) return;
1549 if((Source
=LookupSource(Context
, source
)) == NULL
)
1550 alSetError(Context
, AL_INVALID_NAME
);
1551 else if(!(Int64ValsByProp(param
) == 1))
1552 alSetError(Context
, AL_INVALID_ENUM
);
1554 SetSourcei64v(Source
, Context
, param
, &value
);
1556 ALCcontext_DecRef(Context
);
1559 AL_API
void AL_APIENTRY
alSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT value1
, ALint64SOFT value2
, ALint64SOFT value3
)
1561 ALCcontext
*Context
;
1564 Context
= GetContextRef();
1565 if(!Context
) return;
1567 if((Source
=LookupSource(Context
, source
)) == NULL
)
1568 alSetError(Context
, AL_INVALID_NAME
);
1569 else if(!(Int64ValsByProp(param
) == 3))
1570 alSetError(Context
, AL_INVALID_ENUM
);
1573 ALint64SOFT i64vals
[3] = { value1
, value2
, value3
};
1574 SetSourcei64v(Source
, Context
, param
, i64vals
);
1577 ALCcontext_DecRef(Context
);
1580 AL_API
void AL_APIENTRY
alSourcei64vSOFT(ALuint source
, ALenum param
, const ALint64SOFT
*values
)
1582 ALCcontext
*Context
;
1585 Context
= GetContextRef();
1586 if(!Context
) return;
1588 if((Source
=LookupSource(Context
, source
)) == NULL
)
1589 alSetError(Context
, AL_INVALID_NAME
);
1591 alSetError(Context
, AL_INVALID_VALUE
);
1592 else if(!(Int64ValsByProp(param
) > 0))
1593 alSetError(Context
, AL_INVALID_ENUM
);
1595 SetSourcei64v(Source
, Context
, param
, values
);
1597 ALCcontext_DecRef(Context
);
1601 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
1603 ALCcontext
*Context
;
1606 Context
= GetContextRef();
1607 if(!Context
) return;
1609 if((Source
=LookupSource(Context
, source
)) == NULL
)
1610 alSetError(Context
, AL_INVALID_NAME
);
1612 alSetError(Context
, AL_INVALID_VALUE
);
1613 else if(!(FloatValsByProp(param
) == 1))
1614 alSetError(Context
, AL_INVALID_ENUM
);
1618 if(GetSourcedv(Source
, Context
, param
, &dval
) == AL_NO_ERROR
)
1619 *value
= (ALfloat
)dval
;
1622 ALCcontext_DecRef(Context
);
1626 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
1628 ALCcontext
*Context
;
1631 Context
= GetContextRef();
1632 if(!Context
) return;
1634 if((Source
=LookupSource(Context
, source
)) == NULL
)
1635 alSetError(Context
, AL_INVALID_NAME
);
1636 else if(!(value1
&& value2
&& value3
))
1637 alSetError(Context
, AL_INVALID_VALUE
);
1638 else if(!(FloatValsByProp(param
) == 3))
1639 alSetError(Context
, AL_INVALID_ENUM
);
1643 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1645 *value1
= (ALfloat
)dvals
[0];
1646 *value2
= (ALfloat
)dvals
[1];
1647 *value3
= (ALfloat
)dvals
[2];
1651 ALCcontext_DecRef(Context
);
1655 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
1657 ALCcontext
*Context
;
1661 Context
= GetContextRef();
1662 if(!Context
) return;
1664 if((Source
=LookupSource(Context
, source
)) == NULL
)
1665 alSetError(Context
, AL_INVALID_NAME
);
1667 alSetError(Context
, AL_INVALID_VALUE
);
1668 else if(!((count
=FloatValsByProp(param
)) > 0 && count
<= 3))
1669 alSetError(Context
, AL_INVALID_ENUM
);
1673 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1676 for(i
= 0;i
< count
;i
++)
1677 values
[i
] = (ALfloat
)dvals
[i
];
1681 ALCcontext_DecRef(Context
);
1685 AL_API
void AL_APIENTRY
alGetSourcedSOFT(ALuint source
, ALenum param
, ALdouble
*value
)
1687 ALCcontext
*Context
;
1690 Context
= GetContextRef();
1691 if(!Context
) return;
1693 if((Source
=LookupSource(Context
, source
)) == NULL
)
1694 alSetError(Context
, AL_INVALID_NAME
);
1696 alSetError(Context
, AL_INVALID_VALUE
);
1697 else if(!(DoubleValsByProp(param
) == 1))
1698 alSetError(Context
, AL_INVALID_ENUM
);
1700 GetSourcedv(Source
, Context
, param
, value
);
1702 ALCcontext_DecRef(Context
);
1705 AL_API
void AL_APIENTRY
alGetSource3dSOFT(ALuint source
, ALenum param
, ALdouble
*value1
, ALdouble
*value2
, ALdouble
*value3
)
1707 ALCcontext
*Context
;
1710 Context
= GetContextRef();
1711 if(!Context
) return;
1713 if((Source
=LookupSource(Context
, source
)) == NULL
)
1714 alSetError(Context
, AL_INVALID_NAME
);
1715 else if(!(value1
&& value2
&& value3
))
1716 alSetError(Context
, AL_INVALID_VALUE
);
1717 else if(!(DoubleValsByProp(param
) == 3))
1718 alSetError(Context
, AL_INVALID_ENUM
);
1722 if(GetSourcedv(Source
, Context
, param
, dvals
) == AL_NO_ERROR
)
1730 ALCcontext_DecRef(Context
);
1733 AL_API
void AL_APIENTRY
alGetSourcedvSOFT(ALuint source
, ALenum param
, ALdouble
*values
)
1735 ALCcontext
*Context
;
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
);
1745 else if(!(DoubleValsByProp(param
) > 0))
1746 alSetError(Context
, AL_INVALID_ENUM
);
1748 GetSourcedv(Source
, Context
, param
, values
);
1750 ALCcontext_DecRef(Context
);
1754 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
1756 ALCcontext
*Context
;
1759 Context
= GetContextRef();
1760 if(!Context
) return;
1762 if((Source
=LookupSource(Context
, source
)) == NULL
)
1763 alSetError(Context
, AL_INVALID_NAME
);
1765 alSetError(Context
, AL_INVALID_VALUE
);
1766 else if(!(IntValsByProp(param
) == 1))
1767 alSetError(Context
, AL_INVALID_ENUM
);
1769 GetSourceiv(Source
, Context
, param
, value
);
1771 ALCcontext_DecRef(Context
);
1775 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1777 ALCcontext
*Context
;
1780 Context
= GetContextRef();
1781 if(!Context
) return;
1783 if((Source
=LookupSource(Context
, source
)) == NULL
)
1784 alSetError(Context
, AL_INVALID_NAME
);
1785 else if(!(value1
&& value2
&& value3
))
1786 alSetError(Context
, AL_INVALID_VALUE
);
1787 else if(!(IntValsByProp(param
) == 3))
1788 alSetError(Context
, AL_INVALID_ENUM
);
1792 if(GetSourceiv(Source
, Context
, param
, ivals
) == AL_NO_ERROR
)
1800 ALCcontext_DecRef(Context
);
1804 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1806 ALCcontext
*Context
;
1809 Context
= GetContextRef();
1810 if(!Context
) return;
1812 if((Source
=LookupSource(Context
, source
)) == NULL
)
1813 alSetError(Context
, AL_INVALID_NAME
);
1815 alSetError(Context
, AL_INVALID_VALUE
);
1816 else if(!(IntValsByProp(param
) > 0))
1817 alSetError(Context
, AL_INVALID_ENUM
);
1819 GetSourceiv(Source
, Context
, param
, values
);
1821 ALCcontext_DecRef(Context
);
1825 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value
)
1827 ALCcontext
*Context
;
1830 Context
= GetContextRef();
1831 if(!Context
) return;
1833 if((Source
=LookupSource(Context
, source
)) == NULL
)
1834 alSetError(Context
, AL_INVALID_NAME
);
1836 alSetError(Context
, AL_INVALID_VALUE
);
1837 else if(!(Int64ValsByProp(param
) == 1))
1838 alSetError(Context
, AL_INVALID_ENUM
);
1840 GetSourcei64v(Source
, Context
, param
, value
);
1842 ALCcontext_DecRef(Context
);
1845 AL_API
void AL_APIENTRY
alGetSource3i64SOFT(ALuint source
, ALenum param
, ALint64SOFT
*value1
, ALint64SOFT
*value2
, ALint64SOFT
*value3
)
1847 ALCcontext
*Context
;
1850 Context
= GetContextRef();
1851 if(!Context
) return;
1853 if((Source
=LookupSource(Context
, source
)) == NULL
)
1854 alSetError(Context
, AL_INVALID_NAME
);
1855 else if(!(value1
&& value2
&& value3
))
1856 alSetError(Context
, AL_INVALID_VALUE
);
1857 else if(!(Int64ValsByProp(param
) == 3))
1858 alSetError(Context
, AL_INVALID_ENUM
);
1862 if(GetSourcei64v(Source
, Context
, param
, i64vals
) == AL_NO_ERROR
)
1864 *value1
= i64vals
[0];
1865 *value2
= i64vals
[1];
1866 *value3
= i64vals
[2];
1870 ALCcontext_DecRef(Context
);
1873 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64SOFT
*values
)
1875 ALCcontext
*Context
;
1878 Context
= GetContextRef();
1879 if(!Context
) return;
1881 if((Source
=LookupSource(Context
, source
)) == NULL
)
1882 alSetError(Context
, AL_INVALID_NAME
);
1884 alSetError(Context
, AL_INVALID_VALUE
);
1885 else if(!(Int64ValsByProp(param
) > 0))
1886 alSetError(Context
, AL_INVALID_ENUM
);
1888 GetSourcei64v(Source
, Context
, param
, values
);
1890 ALCcontext_DecRef(Context
);
1894 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
1896 alSourcePlayv(1, &source
);
1898 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
1900 ALCcontext
*Context
;
1904 Context
= GetContextRef();
1905 if(!Context
) return;
1909 CHECK_VALUE(Context
, n
>= 0);
1910 for(i
= 0;i
< n
;i
++)
1912 if(!LookupSource(Context
, sources
[i
]))
1913 al_throwerr(Context
, AL_INVALID_NAME
);
1916 LockContext(Context
);
1917 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
1922 newcount
= Context
->MaxActiveSources
<< 1;
1924 temp
= realloc(Context
->ActiveSources
,
1925 sizeof(*Context
->ActiveSources
) * newcount
);
1928 UnlockContext(Context
);
1929 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
1932 Context
->ActiveSources
= temp
;
1933 Context
->MaxActiveSources
= newcount
;
1936 for(i
= 0;i
< n
;i
++)
1938 Source
= LookupSource(Context
, sources
[i
]);
1939 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
1940 else SetSourceState(Source
, Context
, AL_PLAYING
);
1942 UnlockContext(Context
);
1946 ALCcontext_DecRef(Context
);
1949 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
1951 alSourcePausev(1, &source
);
1953 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1955 ALCcontext
*Context
;
1959 Context
= GetContextRef();
1960 if(!Context
) return;
1964 CHECK_VALUE(Context
, n
>= 0);
1965 for(i
= 0;i
< n
;i
++)
1967 if(!LookupSource(Context
, sources
[i
]))
1968 al_throwerr(Context
, AL_INVALID_NAME
);
1971 LockContext(Context
);
1972 for(i
= 0;i
< n
;i
++)
1974 Source
= LookupSource(Context
, sources
[i
]);
1975 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
1976 else SetSourceState(Source
, Context
, AL_PAUSED
);
1978 UnlockContext(Context
);
1982 ALCcontext_DecRef(Context
);
1985 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
1987 alSourceStopv(1, &source
);
1989 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1991 ALCcontext
*Context
;
1995 Context
= GetContextRef();
1996 if(!Context
) return;
2000 CHECK_VALUE(Context
, n
>= 0);
2001 for(i
= 0;i
< n
;i
++)
2003 if(!LookupSource(Context
, sources
[i
]))
2004 al_throwerr(Context
, AL_INVALID_NAME
);
2007 LockContext(Context
);
2008 for(i
= 0;i
< n
;i
++)
2010 Source
= LookupSource(Context
, sources
[i
]);
2011 Source
->new_state
= AL_NONE
;
2012 SetSourceState(Source
, Context
, AL_STOPPED
);
2014 UnlockContext(Context
);
2018 ALCcontext_DecRef(Context
);
2021 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
2023 alSourceRewindv(1, &source
);
2025 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
2027 ALCcontext
*Context
;
2031 Context
= GetContextRef();
2032 if(!Context
) return;
2036 CHECK_VALUE(Context
, n
>= 0);
2037 for(i
= 0;i
< n
;i
++)
2039 if(!LookupSource(Context
, sources
[i
]))
2040 al_throwerr(Context
, AL_INVALID_NAME
);
2043 LockContext(Context
);
2044 for(i
= 0;i
< n
;i
++)
2046 Source
= LookupSource(Context
, sources
[i
]);
2047 Source
->new_state
= AL_NONE
;
2048 SetSourceState(Source
, Context
, AL_INITIAL
);
2050 UnlockContext(Context
);
2054 ALCcontext_DecRef(Context
);
2058 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei nb
, const ALuint
*buffers
)
2060 ALCcontext
*Context
;
2063 ALbufferlistitem
*BufferListStart
= NULL
;
2064 ALbufferlistitem
*BufferList
;
2065 ALbuffer
*BufferFmt
;
2070 Context
= GetContextRef();
2071 if(!Context
) return;
2075 ALCdevice
*device
= Context
->Device
;
2077 CHECK_VALUE(Context
, nb
>= 0);
2079 if((Source
=LookupSource(Context
, source
)) == NULL
)
2080 al_throwerr(Context
, AL_INVALID_NAME
);
2082 LockContext(Context
);
2083 if(Source
->SourceType
== AL_STATIC
)
2085 UnlockContext(Context
);
2086 /* Can't queue on a Static Source */
2087 al_throwerr(Context
, AL_INVALID_OPERATION
);
2092 /* Check for a valid Buffer, for its frequency and format */
2093 BufferList
= Source
->queue
;
2096 if(BufferList
->buffer
)
2098 BufferFmt
= BufferList
->buffer
;
2101 BufferList
= BufferList
->next
;
2104 for(i
= 0;i
< nb
;i
++)
2106 ALbuffer
*buffer
= NULL
;
2107 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
2109 UnlockContext(Context
);
2110 al_throwerr(Context
, AL_INVALID_NAME
);
2113 if(!BufferListStart
)
2115 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
2116 BufferListStart
->buffer
= buffer
;
2117 BufferListStart
->next
= NULL
;
2118 BufferListStart
->prev
= NULL
;
2119 BufferList
= BufferListStart
;
2123 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
2124 BufferList
->next
->buffer
= buffer
;
2125 BufferList
->next
->next
= NULL
;
2126 BufferList
->next
->prev
= BufferList
;
2127 BufferList
= BufferList
->next
;
2129 if(!buffer
) continue;
2130 IncrementRef(&buffer
->ref
);
2132 ReadLock(&buffer
->lock
);
2133 if(BufferFmt
== NULL
)
2137 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
2138 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
2139 if(buffer
->FmtChannels
== FmtMono
)
2140 Source
->Update
= CalcSourceParams
;
2142 Source
->Update
= CalcNonAttnSourceParams
;
2144 Source
->NeedsUpdate
= AL_TRUE
;
2146 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
2147 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
2148 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
2150 ReadUnlock(&buffer
->lock
);
2151 UnlockContext(Context
);
2152 al_throwerr(Context
, AL_INVALID_OPERATION
);
2154 ReadUnlock(&buffer
->lock
);
2157 /* Source is now streaming */
2158 Source
->SourceType
= AL_STREAMING
;
2160 if(Source
->queue
== NULL
)
2161 Source
->queue
= BufferListStart
;
2164 /* Append to the end of the queue */
2165 BufferList
= Source
->queue
;
2166 while(BufferList
->next
!= NULL
)
2167 BufferList
= BufferList
->next
;
2169 BufferListStart
->prev
= BufferList
;
2170 BufferList
->next
= BufferListStart
;
2173 Source
->BuffersInQueue
+= nb
;
2175 UnlockContext(Context
);
2179 while(BufferListStart
)
2181 BufferList
= BufferListStart
;
2182 BufferListStart
= BufferList
->next
;
2184 if(BufferList
->buffer
)
2185 DecrementRef(&BufferList
->buffer
->ref
);
2191 ALCcontext_DecRef(Context
);
2194 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint source
, ALsizei nb
, ALuint
*buffers
)
2196 ALCcontext
*Context
;
2199 ALbufferlistitem
*BufferList
;
2204 Context
= GetContextRef();
2205 if(!Context
) return;
2209 CHECK_VALUE(Context
, nb
>= 0);
2211 if((Source
=LookupSource(Context
, source
)) == NULL
)
2212 al_throwerr(Context
, AL_INVALID_NAME
);
2214 LockContext(Context
);
2215 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
||
2216 (ALuint
)nb
> Source
->BuffersPlayed
)
2218 UnlockContext(Context
);
2219 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2220 al_throwerr(Context
, AL_INVALID_VALUE
);
2223 for(i
= 0;i
< nb
;i
++)
2225 BufferList
= Source
->queue
;
2226 Source
->queue
= BufferList
->next
;
2227 Source
->BuffersInQueue
--;
2228 Source
->BuffersPlayed
--;
2230 if(BufferList
->buffer
)
2232 buffers
[i
] = BufferList
->buffer
->id
;
2233 DecrementRef(&BufferList
->buffer
->ref
);
2241 Source
->queue
->prev
= NULL
;
2242 UnlockContext(Context
);
2246 ALCcontext_DecRef(Context
);
2250 static ALvoid
InitSourceParams(ALsource
*Source
)
2254 Source
->InnerAngle
= 360.0f
;
2255 Source
->OuterAngle
= 360.0f
;
2256 Source
->Pitch
= 1.0f
;
2257 Source
->Position
[0] = 0.0f
;
2258 Source
->Position
[1] = 0.0f
;
2259 Source
->Position
[2] = 0.0f
;
2260 Source
->Orientation
[0] = 0.0f
;
2261 Source
->Orientation
[1] = 0.0f
;
2262 Source
->Orientation
[2] = 0.0f
;
2263 Source
->Velocity
[0] = 0.0f
;
2264 Source
->Velocity
[1] = 0.0f
;
2265 Source
->Velocity
[2] = 0.0f
;
2266 Source
->RefDistance
= 1.0f
;
2267 Source
->MaxDistance
= FLT_MAX
;
2268 Source
->RollOffFactor
= 1.0f
;
2269 Source
->Looping
= AL_FALSE
;
2270 Source
->Gain
= 1.0f
;
2271 Source
->MinGain
= 0.0f
;
2272 Source
->MaxGain
= 1.0f
;
2273 Source
->OuterGain
= 0.0f
;
2274 Source
->OuterGainHF
= 1.0f
;
2276 Source
->DryGainHFAuto
= AL_TRUE
;
2277 Source
->WetGainAuto
= AL_TRUE
;
2278 Source
->WetGainHFAuto
= AL_TRUE
;
2279 Source
->AirAbsorptionFactor
= 0.0f
;
2280 Source
->RoomRolloffFactor
= 0.0f
;
2281 Source
->DopplerFactor
= 1.0f
;
2282 Source
->DirectChannels
= AL_FALSE
;
2284 Source
->DistanceModel
= DefaultDistanceModel
;
2286 Source
->Resampler
= DefaultResampler
;
2288 Source
->state
= AL_INITIAL
;
2289 Source
->new_state
= AL_NONE
;
2290 Source
->SourceType
= AL_UNDETERMINED
;
2291 Source
->Offset
= -1.0;
2293 Source
->DirectGain
= 1.0f
;
2294 Source
->DirectGainHF
= 1.0f
;
2295 for(i
= 0;i
< MAX_SENDS
;i
++)
2297 Source
->Send
[i
].Gain
= 1.0f
;
2298 Source
->Send
[i
].GainHF
= 1.0f
;
2301 Source
->NeedsUpdate
= AL_TRUE
;
2303 Source
->Hrtf
.Moving
= AL_FALSE
;
2304 Source
->Hrtf
.Counter
= 0;
2310 * Sets the source's new play state given its current state.
2312 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
2314 if(state
== AL_PLAYING
)
2316 ALbufferlistitem
*BufferList
;
2319 /* Check that there is a queue containing at least one valid, non zero
2321 BufferList
= Source
->queue
;
2324 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
2326 BufferList
= BufferList
->next
;
2329 if(Source
->state
!= AL_PLAYING
)
2331 for(j
= 0;j
< MaxChannels
;j
++)
2333 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
2334 Source
->Hrtf
.History
[j
][k
] = 0.0f
;
2335 for(k
= 0;k
< HRIR_LENGTH
;k
++)
2337 Source
->Hrtf
.Values
[j
][k
][0] = 0.0f
;
2338 Source
->Hrtf
.Values
[j
][k
][1] = 0.0f
;
2343 if(Source
->state
!= AL_PAUSED
)
2345 Source
->state
= AL_PLAYING
;
2346 Source
->position
= 0;
2347 Source
->position_fraction
= 0;
2348 Source
->BuffersPlayed
= 0;
2351 Source
->state
= AL_PLAYING
;
2353 // Check if an Offset has been set
2354 if(Source
->Offset
>= 0.0)
2355 ApplyOffset(Source
);
2357 /* If there's nothing to play, or device is disconnected, go right to
2359 if(!BufferList
|| !Context
->Device
->Connected
)
2361 SetSourceState(Source
, Context
, AL_STOPPED
);
2365 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
2367 if(Context
->ActiveSources
[j
] == Source
)
2370 if(j
== Context
->ActiveSourceCount
)
2371 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
2373 else if(state
== AL_PAUSED
)
2375 if(Source
->state
== AL_PLAYING
)
2377 Source
->state
= AL_PAUSED
;
2378 Source
->Hrtf
.Moving
= AL_FALSE
;
2379 Source
->Hrtf
.Counter
= 0;
2382 else if(state
== AL_STOPPED
)
2384 if(Source
->state
!= AL_INITIAL
)
2386 Source
->state
= AL_STOPPED
;
2387 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
2388 Source
->Hrtf
.Moving
= AL_FALSE
;
2389 Source
->Hrtf
.Counter
= 0;
2391 Source
->Offset
= -1.0;
2393 else if(state
== AL_INITIAL
)
2395 if(Source
->state
!= AL_INITIAL
)
2397 Source
->state
= AL_INITIAL
;
2398 Source
->position
= 0;
2399 Source
->position_fraction
= 0;
2400 Source
->BuffersPlayed
= 0;
2401 Source
->Hrtf
.Moving
= AL_FALSE
;
2402 Source
->Hrtf
.Counter
= 0;
2404 Source
->Offset
= -1.0;
2410 * Gets the current read offset for the given Source, in 32.32 fixed-point
2411 * samples. The offset is relative to the start of the queue (not the start of
2412 * the current buffer).
2414 static ALint64
GetSourceOffset(const ALsource
*Source
)
2416 const ALbufferlistitem
*BufferList
;
2420 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
2423 /* NOTE: This is the offset into the *current* buffer, so add the length of
2424 * any played buffers */
2425 readPos
= (ALuint64
)Source
->position
<< 32;
2426 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
2427 BufferList
= Source
->queue
;
2428 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2430 if(BufferList
->buffer
)
2431 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
2432 BufferList
= BufferList
->next
;
2435 return (ALint64
)minu64(readPos
, MAKEU64(0x7fffffff,0xffffffff));
2438 /* GetSourceSecOffset
2440 * Gets the current read offset for the given Source, in seconds. The offset is
2441 * relative to the start of the queue (not the start of the current buffer).
2443 static ALdouble
GetSourceSecOffset(const ALsource
*Source
)
2445 const ALbufferlistitem
*BufferList
;
2446 const ALbuffer
*Buffer
= NULL
;
2450 BufferList
= Source
->queue
;
2453 if(BufferList
->buffer
)
2455 Buffer
= BufferList
->buffer
;
2458 BufferList
= BufferList
->next
;
2461 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2464 /* NOTE: This is the offset into the *current* buffer, so add the length of
2465 * any played buffers */
2466 readPos
= (ALuint64
)Source
->position
<< FRACTIONBITS
;
2467 readPos
|= (ALuint64
)Source
->position_fraction
;
2468 BufferList
= Source
->queue
;
2469 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
2471 if(BufferList
->buffer
)
2472 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< FRACTIONBITS
;
2473 BufferList
= BufferList
->next
;
2476 return (ALdouble
)readPos
/ (ALdouble
)FRACTIONONE
/ (ALdouble
)Buffer
->Frequency
;
2481 * Gets the current read and write offsets for the given Source, in the
2482 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2483 * the start of the queue (not the start of the current buffer).
2485 static ALvoid
GetSourceOffsets(const ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
2487 const ALbufferlistitem
*BufferList
;
2488 const ALbuffer
*Buffer
= NULL
;
2489 ALuint readPos
, writePos
;
2490 ALuint totalBufferLen
;
2493 // Find the first valid Buffer in the Queue
2494 BufferList
= Source
->queue
;
2497 if(BufferList
->buffer
)
2499 Buffer
= BufferList
->buffer
;
2502 BufferList
= BufferList
->next
;
2505 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
2512 if(updateLen
> 0.0 && updateLen
< 0.015)
2515 /* NOTE: This is the offset into the *current* buffer, so add the length of
2516 * any played buffers */
2517 readPos
= Source
->position
;
2519 BufferList
= Source
->queue
;
2520 for(i
= 0;BufferList
;i
++)
2522 if(BufferList
->buffer
)
2524 if(i
< Source
->BuffersPlayed
)
2525 readPos
+= BufferList
->buffer
->SampleLen
;
2526 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
2528 BufferList
= BufferList
->next
;
2530 if(Source
->state
== AL_PLAYING
)
2531 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
2537 readPos
%= totalBufferLen
;
2538 writePos
%= totalBufferLen
;
2542 /* Wrap positions back to 0 */
2543 if(readPos
>= totalBufferLen
)
2545 if(writePos
>= totalBufferLen
)
2552 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2553 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2556 case AL_SAMPLE_OFFSET
:
2557 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2558 offset
[0] = (ALdouble
)readPos
;
2559 offset
[1] = (ALdouble
)writePos
;
2562 case AL_BYTE_OFFSET
:
2563 case AL_BYTE_RW_OFFSETS_SOFT
:
2564 if(Buffer
->OriginalType
== UserFmtIMA4
)
2566 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
2567 ALuint FrameBlockSize
= 65;
2569 /* Round down to nearest ADPCM block */
2570 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2571 if(Source
->state
!= AL_PLAYING
)
2572 offset
[1] = offset
[0];
2575 /* Round up to nearest ADPCM block */
2576 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2577 FrameBlockSize
* BlockSize
);
2582 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2583 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2584 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2593 * Apply the stored playback offset to the Source. This function will update
2594 * the number of buffers "played" given the stored offset.
2596 ALboolean
ApplyOffset(ALsource
*Source
)
2598 const ALbufferlistitem
*BufferList
;
2599 const ALbuffer
*Buffer
;
2600 ALint bufferLen
, totalBufferLen
;
2601 ALint buffersPlayed
;
2604 /* Get sample frame offset */
2605 offset
= GetSampleOffset(Source
);
2612 BufferList
= Source
->queue
;
2615 Buffer
= BufferList
->buffer
;
2616 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2618 if(bufferLen
<= offset
-totalBufferLen
)
2620 /* Offset is past this buffer so increment to the next buffer */
2623 else if(totalBufferLen
<= offset
)
2625 /* Offset is in this buffer */
2626 Source
->BuffersPlayed
= buffersPlayed
;
2628 Source
->position
= offset
- totalBufferLen
;
2629 Source
->position_fraction
= 0;
2633 totalBufferLen
+= bufferLen
;
2635 BufferList
= BufferList
->next
;
2638 /* Offset is out of range of the queue */
2645 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2646 * Second offset supplied by the application). This takes into account the fact
2647 * that the buffer format may have been modifed since.
2649 static ALint
GetSampleOffset(ALsource
*Source
)
2651 const ALbuffer
*Buffer
= NULL
;
2652 const ALbufferlistitem
*BufferList
;
2655 /* Find the first valid Buffer in the Queue */
2656 BufferList
= Source
->queue
;
2659 if(BufferList
->buffer
)
2661 Buffer
= BufferList
->buffer
;
2664 BufferList
= BufferList
->next
;
2669 Source
->Offset
= -1.0;
2673 switch(Source
->OffsetType
)
2675 case AL_BYTE_OFFSET
:
2676 /* Determine the ByteOffset (and ensure it is block aligned) */
2677 Offset
= (ALint
)Source
->Offset
;
2678 if(Buffer
->OriginalType
== UserFmtIMA4
)
2680 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2684 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2687 case AL_SAMPLE_OFFSET
:
2688 Offset
= (ALint
)Source
->Offset
;
2692 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2695 Source
->Offset
= -1.0;
2703 * Destroys all sources in the source map.
2705 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2709 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2711 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2712 Context
->SourceMap
.array
[pos
].value
= NULL
;
2714 while(temp
->queue
!= NULL
)
2716 ALbufferlistitem
*BufferList
= temp
->queue
;
2717 temp
->queue
= BufferList
->next
;
2719 if(BufferList
->buffer
!= NULL
)
2720 DecrementRef(&BufferList
->buffer
->ref
);
2724 for(j
= 0;j
< MAX_SENDS
;++j
)
2726 if(temp
->Send
[j
].Slot
)
2727 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2728 temp
->Send
[j
].Slot
= NULL
;
2731 FreeThunkEntry(temp
->id
);
2732 memset(temp
, 0, sizeof(*temp
));