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
33 #include "alAuxEffectSlot.h"
36 enum Resampler DefaultResampler
= LinearResampler
;
37 const ALsizei ResamplerPadding
[ResamplerMax
] = {
42 const ALsizei ResamplerPrePadding
[ResamplerMax
] = {
49 static ALvoid
InitSourceParams(ALsource
*Source
);
50 static ALint64
GetSourceOffset(ALsource
*Source
);
51 static ALvoid
GetSourceOffsets(ALsource
*Source
, ALenum name
, ALdouble
*offsets
, ALdouble updateLen
);
52 static ALint
GetSampleOffset(ALsource
*Source
);
55 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
, ALuint
*sources
)
60 Context
= GetContextRef();
67 CHECK_VALUE(Context
, n
>= 0);
68 for(cur
= 0;cur
< n
;cur
++)
70 ALsource
*source
= al_calloc(16, sizeof(ALsource
));
72 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
73 InitSourceParams(source
);
75 err
= NewThunkEntry(&source
->id
);
76 if(err
== AL_NO_ERROR
)
77 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->id
, source
);
78 if(err
!= AL_NO_ERROR
)
80 FreeThunkEntry(source
->id
);
81 memset(source
, 0, sizeof(ALsource
));
84 al_throwerr(Context
, err
);
87 sources
[cur
] = source
->id
;
93 alDeleteSources(cur
, sources
);
97 ALCcontext_DecRef(Context
);
101 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
105 Context
= GetContextRef();
110 ALbufferlistitem
*BufferList
;
114 CHECK_VALUE(Context
, n
>= 0);
116 /* Check that all Sources are valid */
119 if(LookupSource(Context
, sources
[i
]) == NULL
)
120 al_throwerr(Context
, AL_INVALID_NAME
);
125 ALsource
**srclist
, **srclistend
;
127 if((Source
=RemoveSource(Context
, sources
[i
])) == NULL
)
129 FreeThunkEntry(Source
->id
);
131 LockContext(Context
);
132 srclist
= Context
->ActiveSources
;
133 srclistend
= srclist
+ Context
->ActiveSourceCount
;
134 while(srclist
!= srclistend
)
136 if(*srclist
== Source
)
138 Context
->ActiveSourceCount
--;
139 *srclist
= *(--srclistend
);
144 UnlockContext(Context
);
146 while(Source
->queue
!= NULL
)
148 BufferList
= Source
->queue
;
149 Source
->queue
= BufferList
->next
;
151 if(BufferList
->buffer
!= NULL
)
152 DecrementRef(&BufferList
->buffer
->ref
);
156 for(j
= 0;j
< MAX_SENDS
;++j
)
158 if(Source
->Send
[j
].Slot
)
159 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
160 Source
->Send
[j
].Slot
= NULL
;
163 memset(Source
, 0, sizeof(*Source
));
169 ALCcontext_DecRef(Context
);
173 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
178 Context
= GetContextRef();
179 if(!Context
) return AL_FALSE
;
181 result
= (LookupSource(Context
, source
) ? AL_TRUE
: AL_FALSE
);
183 ALCcontext_DecRef(Context
);
189 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum param
, ALfloat value
)
194 Context
= GetContextRef();
199 if((Source
=LookupSource(Context
, source
)) == NULL
)
200 al_throwerr(Context
, AL_INVALID_NAME
);
204 CHECK_VALUE(Context
, value
>= 0.0f
);
206 Source
->Pitch
= value
;
207 Source
->NeedsUpdate
= AL_TRUE
;
210 case AL_CONE_INNER_ANGLE
:
211 CHECK_VALUE(Context
, value
>= 0.0f
&& value
<= 360.0f
);
213 Source
->InnerAngle
= value
;
214 Source
->NeedsUpdate
= AL_TRUE
;
217 case AL_CONE_OUTER_ANGLE
:
218 CHECK_VALUE(Context
, value
>= 0.0f
&& value
<= 360.0f
);
220 Source
->OuterAngle
= value
;
221 Source
->NeedsUpdate
= AL_TRUE
;
225 CHECK_VALUE(Context
, value
>= 0.0f
);
227 Source
->Gain
= value
;
228 Source
->NeedsUpdate
= AL_TRUE
;
231 case AL_MAX_DISTANCE
:
232 CHECK_VALUE(Context
, value
>= 0.0f
);
234 Source
->MaxDistance
= value
;
235 Source
->NeedsUpdate
= AL_TRUE
;
238 case AL_ROLLOFF_FACTOR
:
239 CHECK_VALUE(Context
, value
>= 0.0f
);
241 Source
->RollOffFactor
= value
;
242 Source
->NeedsUpdate
= AL_TRUE
;
245 case AL_REFERENCE_DISTANCE
:
246 CHECK_VALUE(Context
, value
>= 0.0f
);
248 Source
->RefDistance
= value
;
249 Source
->NeedsUpdate
= AL_TRUE
;
253 CHECK_VALUE(Context
, value
>= 0.0f
&& value
<= 1.0f
);
255 Source
->MinGain
= value
;
256 Source
->NeedsUpdate
= AL_TRUE
;
260 CHECK_VALUE(Context
, value
>= 0.0f
&& value
<= 1.0f
);
262 Source
->MaxGain
= value
;
263 Source
->NeedsUpdate
= AL_TRUE
;
266 case AL_CONE_OUTER_GAIN
:
267 CHECK_VALUE(Context
, value
>= 0.0f
&& value
<= 1.0f
);
269 Source
->OuterGain
= value
;
270 Source
->NeedsUpdate
= AL_TRUE
;
273 case AL_CONE_OUTER_GAINHF
:
274 CHECK_VALUE(Context
, value
>= 0.0f
&& value
<= 1.0f
);
276 Source
->OuterGainHF
= value
;
277 Source
->NeedsUpdate
= AL_TRUE
;
280 case AL_AIR_ABSORPTION_FACTOR
:
281 CHECK_VALUE(Context
, value
>= 0.0f
&& value
<= 10.0f
);
283 Source
->AirAbsorptionFactor
= value
;
284 Source
->NeedsUpdate
= AL_TRUE
;
287 case AL_ROOM_ROLLOFF_FACTOR
:
288 CHECK_VALUE(Context
, value
>= 0.0f
&& value
<= 10.0f
);
290 Source
->RoomRolloffFactor
= value
;
291 Source
->NeedsUpdate
= AL_TRUE
;
294 case AL_DOPPLER_FACTOR
:
295 CHECK_VALUE(Context
, value
>= 0.0f
&& value
<= 1.0f
);
297 Source
->DopplerFactor
= value
;
298 Source
->NeedsUpdate
= AL_TRUE
;
302 case AL_SAMPLE_OFFSET
:
304 CHECK_VALUE(Context
, value
>= 0.0f
);
306 LockContext(Context
);
307 Source
->OffsetType
= param
;
308 Source
->Offset
= value
;
310 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
311 !Context
->DeferUpdates
)
313 if(ApplyOffset(Source
) == AL_FALSE
)
315 UnlockContext(Context
);
316 al_throwerr(Context
, AL_INVALID_VALUE
);
319 UnlockContext(Context
);
323 al_throwerr(Context
, AL_INVALID_ENUM
);
328 ALCcontext_DecRef(Context
);
332 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
337 Context
= GetContextRef();
342 if((Source
=LookupSource(Context
, source
)) == NULL
)
343 al_throwerr(Context
, AL_INVALID_NAME
);
347 CHECK_VALUE(Context
, isfinite(value1
) && isfinite(value2
) && isfinite(value3
));
349 LockContext(Context
);
350 Source
->Position
[0] = value1
;
351 Source
->Position
[1] = value2
;
352 Source
->Position
[2] = value3
;
353 UnlockContext(Context
);
354 Source
->NeedsUpdate
= AL_TRUE
;
358 CHECK_VALUE(Context
, isfinite(value1
) && isfinite(value2
) && isfinite(value3
));
360 LockContext(Context
);
361 Source
->Velocity
[0] = value1
;
362 Source
->Velocity
[1] = value2
;
363 Source
->Velocity
[2] = value3
;
364 UnlockContext(Context
);
365 Source
->NeedsUpdate
= AL_TRUE
;
369 CHECK_VALUE(Context
, isfinite(value1
) && isfinite(value2
) && isfinite(value3
));
371 LockContext(Context
);
372 Source
->Orientation
[0] = value1
;
373 Source
->Orientation
[1] = value2
;
374 Source
->Orientation
[2] = value3
;
375 UnlockContext(Context
);
376 Source
->NeedsUpdate
= AL_TRUE
;
380 al_throwerr(Context
, AL_INVALID_ENUM
);
385 ALCcontext_DecRef(Context
);
389 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum param
, const ALfloat
*values
)
398 case AL_CONE_INNER_ANGLE
:
399 case AL_CONE_OUTER_ANGLE
:
401 case AL_MAX_DISTANCE
:
402 case AL_ROLLOFF_FACTOR
:
403 case AL_REFERENCE_DISTANCE
:
406 case AL_CONE_OUTER_GAIN
:
407 case AL_CONE_OUTER_GAINHF
:
409 case AL_SAMPLE_OFFSET
:
411 case AL_AIR_ABSORPTION_FACTOR
:
412 case AL_ROOM_ROLLOFF_FACTOR
:
413 alSourcef(source
, param
, values
[0]);
419 alSource3f(source
, param
, values
[0], values
[1], values
[2]);
424 Context
= GetContextRef();
429 if(LookupSource(Context
, source
) == NULL
)
430 al_throwerr(Context
, AL_INVALID_NAME
);
431 CHECK_VALUE(Context
, values
);
436 al_throwerr(Context
, AL_INVALID_ENUM
);
441 ALCcontext_DecRef(Context
);
445 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
, ALenum param
, ALint value
)
452 case AL_MAX_DISTANCE
:
453 case AL_ROLLOFF_FACTOR
:
454 case AL_CONE_INNER_ANGLE
:
455 case AL_CONE_OUTER_ANGLE
:
456 case AL_REFERENCE_DISTANCE
:
457 alSourcef(source
, param
, (ALfloat
)value
);
461 Context
= GetContextRef();
466 ALCdevice
*device
= Context
->Device
;
467 ALbuffer
*buffer
= NULL
;
468 ALfilter
*filter
= NULL
;
469 ALbufferlistitem
*oldlist
;
471 if((Source
=LookupSource(Context
, source
)) == NULL
)
472 al_throwerr(Context
, AL_INVALID_NAME
);
475 case AL_SOURCE_RELATIVE
:
476 CHECK_VALUE(Context
, value
== AL_FALSE
|| value
== AL_TRUE
);
478 Source
->HeadRelative
= (ALboolean
)value
;
479 Source
->NeedsUpdate
= AL_TRUE
;
483 CHECK_VALUE(Context
, value
== AL_FALSE
|| value
== AL_TRUE
);
485 Source
->Looping
= (ALboolean
)value
;
489 CHECK_VALUE(Context
, value
== 0 ||
490 (buffer
=LookupBuffer(device
, value
)) != NULL
);
492 LockContext(Context
);
493 if(!(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
))
495 UnlockContext(Context
);
496 al_throwerr(Context
, AL_INVALID_OPERATION
);
499 Source
->BuffersInQueue
= 0;
500 Source
->BuffersPlayed
= 0;
504 ALbufferlistitem
*BufferListItem
;
506 /* Source is now Static */
507 Source
->SourceType
= AL_STATIC
;
509 /* Add the selected buffer to a one-item queue */
510 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
511 BufferListItem
->buffer
= buffer
;
512 BufferListItem
->next
= NULL
;
513 BufferListItem
->prev
= NULL
;
514 IncrementRef(&buffer
->ref
);
516 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, BufferListItem
);
517 Source
->BuffersInQueue
= 1;
519 ReadLock(&buffer
->lock
);
520 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
521 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
522 ReadUnlock(&buffer
->lock
);
523 if(buffer
->FmtChannels
== FmtMono
)
524 Source
->Update
= CalcSourceParams
;
526 Source
->Update
= CalcNonAttnSourceParams
;
527 Source
->NeedsUpdate
= AL_TRUE
;
531 /* Source is now Undetermined */
532 Source
->SourceType
= AL_UNDETERMINED
;
533 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, NULL
);
536 /* Delete all elements in the previous queue */
537 while(oldlist
!= NULL
)
539 ALbufferlistitem
*temp
= oldlist
;
540 oldlist
= temp
->next
;
543 DecrementRef(&temp
->buffer
->ref
);
546 UnlockContext(Context
);
549 case AL_SOURCE_STATE
:
551 al_throwerr(Context
, AL_INVALID_OPERATION
);
554 case AL_SAMPLE_OFFSET
:
556 CHECK_VALUE(Context
, value
>= 0);
558 LockContext(Context
);
559 Source
->OffsetType
= param
;
560 Source
->Offset
= value
;
562 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
563 !Context
->DeferUpdates
)
565 if(ApplyOffset(Source
) == AL_FALSE
)
567 UnlockContext(Context
);
568 al_throwerr(Context
, AL_INVALID_VALUE
);
571 UnlockContext(Context
);
574 case AL_DIRECT_FILTER
:
575 CHECK_VALUE(Context
, value
== 0 ||
576 (filter
=LookupFilter(device
, value
)) != NULL
);
578 LockContext(Context
);
581 Source
->DirectGain
= 1.0f
;
582 Source
->DirectGainHF
= 1.0f
;
586 Source
->DirectGain
= filter
->Gain
;
587 Source
->DirectGainHF
= filter
->GainHF
;
589 UnlockContext(Context
);
590 Source
->NeedsUpdate
= AL_TRUE
;
593 case AL_DIRECT_FILTER_GAINHF_AUTO
:
594 CHECK_VALUE(Context
, value
== AL_FALSE
|| value
== AL_TRUE
);
596 Source
->DryGainHFAuto
= value
;
597 Source
->NeedsUpdate
= AL_TRUE
;
600 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
601 CHECK_VALUE(Context
, value
== AL_FALSE
|| value
== AL_TRUE
);
603 Source
->WetGainAuto
= value
;
604 Source
->NeedsUpdate
= AL_TRUE
;
607 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
608 CHECK_VALUE(Context
, value
== AL_FALSE
|| value
== AL_TRUE
);
610 Source
->WetGainHFAuto
= value
;
611 Source
->NeedsUpdate
= AL_TRUE
;
614 case AL_DIRECT_CHANNELS_SOFT
:
615 CHECK_VALUE(Context
, value
== AL_FALSE
|| value
== AL_TRUE
);
617 Source
->DirectChannels
= value
;
618 Source
->NeedsUpdate
= AL_TRUE
;
621 case AL_DISTANCE_MODEL
:
622 CHECK_VALUE(Context
, value
== AL_NONE
||
623 value
== AL_INVERSE_DISTANCE
||
624 value
== AL_INVERSE_DISTANCE_CLAMPED
||
625 value
== AL_LINEAR_DISTANCE
||
626 value
== AL_LINEAR_DISTANCE_CLAMPED
||
627 value
== AL_EXPONENT_DISTANCE
||
628 value
== AL_EXPONENT_DISTANCE_CLAMPED
);
630 Source
->DistanceModel
= value
;
631 if(Context
->SourceDistanceModel
)
632 Source
->NeedsUpdate
= AL_TRUE
;
636 al_throwerr(Context
, AL_INVALID_ENUM
);
641 ALCcontext_DecRef(Context
);
645 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum param
, ALint value1
, ALint value2
, ALint value3
)
655 alSource3f(source
, param
, (ALfloat
)value1
, (ALfloat
)value2
, (ALfloat
)value3
);
659 Context
= GetContextRef();
664 ALCdevice
*device
= Context
->Device
;
665 ALeffectslot
*slot
= NULL
;
666 ALfilter
*filter
= NULL
;
668 if((Source
=LookupSource(Context
, source
)) == NULL
)
669 al_throwerr(Context
, AL_INVALID_NAME
);
672 case AL_AUXILIARY_SEND_FILTER
:
673 LockContext(Context
);
674 if(!((ALuint
)value2
< device
->NumAuxSends
&&
675 (value1
== 0 || (slot
=LookupEffectSlot(Context
, value1
)) != NULL
) &&
676 (value3
== 0 || (filter
=LookupFilter(device
, value3
)) != NULL
)))
678 UnlockContext(Context
);
679 al_throwerr(Context
, AL_INVALID_VALUE
);
682 /* Add refcount on the new slot, and release the previous slot */
683 if(slot
) IncrementRef(&slot
->ref
);
684 slot
= ExchangePtr((XchgPtr
*)&Source
->Send
[value2
].Slot
, slot
);
685 if(slot
) DecrementRef(&slot
->ref
);
690 Source
->Send
[value2
].Gain
= 1.0f
;
691 Source
->Send
[value2
].GainHF
= 1.0f
;
695 Source
->Send
[value2
].Gain
= filter
->Gain
;
696 Source
->Send
[value2
].GainHF
= filter
->GainHF
;
698 Source
->NeedsUpdate
= AL_TRUE
;
699 UnlockContext(Context
);
703 al_throwerr(Context
, AL_INVALID_ENUM
);
708 ALCcontext_DecRef(Context
);
712 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum param
, const ALint
*values
)
720 case AL_SOURCE_RELATIVE
:
721 case AL_CONE_INNER_ANGLE
:
722 case AL_CONE_OUTER_ANGLE
:
725 case AL_SOURCE_STATE
:
727 case AL_SAMPLE_OFFSET
:
729 case AL_MAX_DISTANCE
:
730 case AL_ROLLOFF_FACTOR
:
731 case AL_REFERENCE_DISTANCE
:
732 case AL_DIRECT_FILTER
:
733 case AL_DIRECT_FILTER_GAINHF_AUTO
:
734 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
735 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
736 case AL_DISTANCE_MODEL
:
737 case AL_DIRECT_CHANNELS_SOFT
:
738 alSourcei(source
, param
, values
[0]);
744 case AL_AUXILIARY_SEND_FILTER
:
745 alSource3i(source
, param
, values
[0], values
[1], values
[2]);
750 Context
= GetContextRef();
755 if(LookupSource(Context
, source
) == NULL
)
756 al_throwerr(Context
, AL_INVALID_NAME
);
757 CHECK_VALUE(Context
, values
);
761 al_throwerr(Context
, AL_INVALID_ENUM
);
766 ALCcontext_DecRef(Context
);
770 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum param
, ALfloat
*value
)
777 Context
= GetContextRef();
782 if((Source
=LookupSource(Context
, source
)) == NULL
)
783 al_throwerr(Context
, AL_INVALID_NAME
);
784 CHECK_VALUE(Context
, value
);
788 *value
= Source
->Pitch
;
792 *value
= Source
->Gain
;
796 *value
= Source
->MinGain
;
800 *value
= Source
->MaxGain
;
803 case AL_MAX_DISTANCE
:
804 *value
= Source
->MaxDistance
;
807 case AL_ROLLOFF_FACTOR
:
808 *value
= Source
->RollOffFactor
;
811 case AL_CONE_OUTER_GAIN
:
812 *value
= Source
->OuterGain
;
815 case AL_CONE_OUTER_GAINHF
:
816 *value
= Source
->OuterGainHF
;
820 case AL_SAMPLE_OFFSET
:
822 LockContext(Context
);
823 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
824 Context
->Device
->Frequency
;
825 GetSourceOffsets(Source
, param
, offsets
, updateLen
);
826 UnlockContext(Context
);
827 *value
= (ALfloat
)offsets
[0];
830 case AL_CONE_INNER_ANGLE
:
831 *value
= Source
->InnerAngle
;
834 case AL_CONE_OUTER_ANGLE
:
835 *value
= Source
->OuterAngle
;
838 case AL_REFERENCE_DISTANCE
:
839 *value
= Source
->RefDistance
;
842 case AL_AIR_ABSORPTION_FACTOR
:
843 *value
= Source
->AirAbsorptionFactor
;
846 case AL_ROOM_ROLLOFF_FACTOR
:
847 *value
= Source
->RoomRolloffFactor
;
850 case AL_DOPPLER_FACTOR
:
851 *value
= Source
->DopplerFactor
;
855 al_throwerr(Context
, AL_INVALID_ENUM
);
860 ALCcontext_DecRef(Context
);
864 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
869 Context
= GetContextRef();
874 if((Source
=LookupSource(Context
, source
)) == NULL
)
875 al_throwerr(Context
, AL_INVALID_NAME
);
876 CHECK_VALUE(Context
, value1
&& value2
&& value3
);
880 LockContext(Context
);
881 *value1
= Source
->Position
[0];
882 *value2
= Source
->Position
[1];
883 *value3
= Source
->Position
[2];
884 UnlockContext(Context
);
888 LockContext(Context
);
889 *value1
= Source
->Velocity
[0];
890 *value2
= Source
->Velocity
[1];
891 *value3
= Source
->Velocity
[2];
892 UnlockContext(Context
);
896 LockContext(Context
);
897 *value1
= Source
->Orientation
[0];
898 *value2
= Source
->Orientation
[1];
899 *value3
= Source
->Orientation
[2];
900 UnlockContext(Context
);
904 al_throwerr(Context
, AL_INVALID_ENUM
);
909 ALCcontext_DecRef(Context
);
913 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum param
, ALfloat
*values
)
926 case AL_MAX_DISTANCE
:
927 case AL_ROLLOFF_FACTOR
:
928 case AL_DOPPLER_FACTOR
:
929 case AL_CONE_OUTER_GAIN
:
931 case AL_SAMPLE_OFFSET
:
933 case AL_CONE_INNER_ANGLE
:
934 case AL_CONE_OUTER_ANGLE
:
935 case AL_REFERENCE_DISTANCE
:
936 case AL_CONE_OUTER_GAINHF
:
937 case AL_AIR_ABSORPTION_FACTOR
:
938 case AL_ROOM_ROLLOFF_FACTOR
:
939 alGetSourcef(source
, param
, values
);
945 alGetSource3f(source
, param
, values
+0, values
+1, values
+2);
949 Context
= GetContextRef();
954 if((Source
=LookupSource(Context
, source
)) == NULL
)
955 al_throwerr(Context
, AL_INVALID_NAME
);
956 CHECK_VALUE(Context
, values
);
959 case AL_SAMPLE_RW_OFFSETS_SOFT
:
960 case AL_BYTE_RW_OFFSETS_SOFT
:
961 LockContext(Context
);
962 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
963 Context
->Device
->Frequency
;
964 GetSourceOffsets(Source
, param
, offsets
, updateLen
);
965 UnlockContext(Context
);
966 values
[0] = (ALfloat
)offsets
[0];
967 values
[1] = (ALfloat
)offsets
[1];
971 al_throwerr(Context
, AL_INVALID_ENUM
);
976 ALCcontext_DecRef(Context
);
980 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum param
, ALint
*value
)
982 ALbufferlistitem
*BufferList
;
988 Context
= GetContextRef();
993 if((Source
=LookupSource(Context
, source
)) == NULL
)
994 al_throwerr(Context
, AL_INVALID_NAME
);
995 CHECK_VALUE(Context
, value
);
998 case AL_MAX_DISTANCE
:
999 *value
= (ALint
)Source
->MaxDistance
;
1002 case AL_ROLLOFF_FACTOR
:
1003 *value
= (ALint
)Source
->RollOffFactor
;
1006 case AL_REFERENCE_DISTANCE
:
1007 *value
= (ALint
)Source
->RefDistance
;
1010 case AL_SOURCE_RELATIVE
:
1011 *value
= Source
->HeadRelative
;
1014 case AL_CONE_INNER_ANGLE
:
1015 *value
= (ALint
)Source
->InnerAngle
;
1018 case AL_CONE_OUTER_ANGLE
:
1019 *value
= (ALint
)Source
->OuterAngle
;
1023 *value
= Source
->Looping
;
1027 LockContext(Context
);
1028 BufferList
= Source
->queue
;
1029 if(Source
->SourceType
!= AL_STATIC
)
1031 ALuint i
= Source
->BuffersPlayed
;
1034 BufferList
= BufferList
->next
;
1038 *value
= ((BufferList
&& BufferList
->buffer
) ?
1039 BufferList
->buffer
->id
: 0);
1040 UnlockContext(Context
);
1043 case AL_SOURCE_STATE
:
1044 *value
= Source
->state
;
1047 case AL_BUFFERS_QUEUED
:
1048 *value
= Source
->BuffersInQueue
;
1051 case AL_BUFFERS_PROCESSED
:
1052 LockContext(Context
);
1053 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
)
1055 /* Buffers on a looping source are in a perpetual state of
1056 * PENDING, so don't report any as PROCESSED */
1060 *value
= Source
->BuffersPlayed
;
1061 UnlockContext(Context
);
1064 case AL_SOURCE_TYPE
:
1065 *value
= Source
->SourceType
;
1069 case AL_SAMPLE_OFFSET
:
1070 case AL_BYTE_OFFSET
:
1071 LockContext(Context
);
1072 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
1073 Context
->Device
->Frequency
;
1074 GetSourceOffsets(Source
, param
, offsets
, updateLen
);
1075 UnlockContext(Context
);
1076 *value
= (ALint
)offsets
[0];
1079 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1080 *value
= Source
->DryGainHFAuto
;
1083 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1084 *value
= Source
->WetGainAuto
;
1087 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1088 *value
= Source
->WetGainHFAuto
;
1091 case AL_DOPPLER_FACTOR
:
1092 *value
= (ALint
)Source
->DopplerFactor
;
1095 case AL_DIRECT_CHANNELS_SOFT
:
1096 *value
= Source
->DirectChannels
;
1099 case AL_DISTANCE_MODEL
:
1100 *value
= Source
->DistanceModel
;
1104 al_throwerr(Context
, AL_INVALID_ENUM
);
1109 ALCcontext_DecRef(Context
);
1113 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
1115 ALCcontext
*Context
;
1118 Context
= GetContextRef();
1119 if(!Context
) return;
1123 if((Source
=LookupSource(Context
, source
)) == NULL
)
1124 al_throwerr(Context
, AL_INVALID_NAME
);
1125 CHECK_VALUE(Context
, value1
&& value2
&& value3
);
1129 LockContext(Context
);
1130 *value1
= (ALint
)Source
->Position
[0];
1131 *value2
= (ALint
)Source
->Position
[1];
1132 *value3
= (ALint
)Source
->Position
[2];
1133 UnlockContext(Context
);
1137 LockContext(Context
);
1138 *value1
= (ALint
)Source
->Velocity
[0];
1139 *value2
= (ALint
)Source
->Velocity
[1];
1140 *value3
= (ALint
)Source
->Velocity
[2];
1141 UnlockContext(Context
);
1145 LockContext(Context
);
1146 *value1
= (ALint
)Source
->Orientation
[0];
1147 *value2
= (ALint
)Source
->Orientation
[1];
1148 *value3
= (ALint
)Source
->Orientation
[2];
1149 UnlockContext(Context
);
1153 al_throwerr(Context
, AL_INVALID_ENUM
);
1158 ALCcontext_DecRef(Context
);
1162 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum param
, ALint
*values
)
1164 ALCcontext
*Context
;
1166 ALdouble offsets
[2];
1171 case AL_SOURCE_RELATIVE
:
1172 case AL_CONE_INNER_ANGLE
:
1173 case AL_CONE_OUTER_ANGLE
:
1176 case AL_SOURCE_STATE
:
1177 case AL_BUFFERS_QUEUED
:
1178 case AL_BUFFERS_PROCESSED
:
1180 case AL_SAMPLE_OFFSET
:
1181 case AL_BYTE_OFFSET
:
1182 case AL_MAX_DISTANCE
:
1183 case AL_ROLLOFF_FACTOR
:
1184 case AL_DOPPLER_FACTOR
:
1185 case AL_REFERENCE_DISTANCE
:
1186 case AL_SOURCE_TYPE
:
1187 case AL_DIRECT_FILTER
:
1188 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1189 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1190 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1191 case AL_DISTANCE_MODEL
:
1192 case AL_DIRECT_CHANNELS_SOFT
:
1193 alGetSourcei(source
, param
, values
);
1199 alGetSource3i(source
, param
, values
+0, values
+1, values
+2);
1203 Context
= GetContextRef();
1204 if(!Context
) return;
1208 if((Source
=LookupSource(Context
, source
)) == NULL
)
1209 al_throwerr(Context
, AL_INVALID_NAME
);
1210 CHECK_VALUE(Context
, values
);
1213 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1214 case AL_BYTE_RW_OFFSETS_SOFT
:
1215 LockContext(Context
);
1216 updateLen
= (ALdouble
)Context
->Device
->UpdateSize
/
1217 Context
->Device
->Frequency
;
1218 GetSourceOffsets(Source
, param
, offsets
, updateLen
);
1219 UnlockContext(Context
);
1220 values
[0] = (ALint
)offsets
[0];
1221 values
[1] = (ALint
)offsets
[1];
1225 al_throwerr(Context
, AL_INVALID_ENUM
);
1230 ALCcontext_DecRef(Context
);
1234 AL_API
void AL_APIENTRY
alGetSourcei64SOFT(ALuint source
, ALenum param
, ALint64
*values
)
1236 ALCcontext
*Context
;
1239 Context
= GetContextRef();
1240 if(!Context
) return;
1244 if((Source
=LookupSource(Context
, source
)) == NULL
)
1245 al_throwerr(Context
, AL_INVALID_NAME
);
1246 CHECK_VALUE(Context
, values
);
1250 al_throwerr(Context
, AL_INVALID_ENUM
);
1255 ALCcontext_DecRef(Context
);
1258 AL_API
void AL_APIENTRY
alGetSourcei64vSOFT(ALuint source
, ALenum param
, ALint64
*values
)
1260 ALCcontext
*Context
;
1263 Context
= GetContextRef();
1264 if(!Context
) return;
1268 if((Source
=LookupSource(Context
, source
)) == NULL
)
1269 al_throwerr(Context
, AL_INVALID_NAME
);
1270 CHECK_VALUE(Context
, values
);
1273 case AL_SAMPLE_OFFSET_LATENCY_SOFT
:
1274 LockContext(Context
);
1275 values
[0] = GetSourceOffset(Source
);
1276 values
[1] = ALCdevice_GetLatency(Context
->Device
);
1277 UnlockContext(Context
);
1281 al_throwerr(Context
, AL_INVALID_ENUM
);
1286 ALCcontext_DecRef(Context
);
1290 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
1292 alSourcePlayv(1, &source
);
1294 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
1296 ALCcontext
*Context
;
1300 Context
= GetContextRef();
1301 if(!Context
) return;
1305 CHECK_VALUE(Context
, n
>= 0);
1306 for(i
= 0;i
< n
;i
++)
1308 if(!LookupSource(Context
, sources
[i
]))
1309 al_throwerr(Context
, AL_INVALID_NAME
);
1312 LockContext(Context
);
1313 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
1318 newcount
= Context
->MaxActiveSources
<< 1;
1320 temp
= realloc(Context
->ActiveSources
,
1321 sizeof(*Context
->ActiveSources
) * newcount
);
1324 UnlockContext(Context
);
1325 al_throwerr(Context
, AL_OUT_OF_MEMORY
);
1328 Context
->ActiveSources
= temp
;
1329 Context
->MaxActiveSources
= newcount
;
1332 for(i
= 0;i
< n
;i
++)
1334 Source
= LookupSource(Context
, sources
[i
]);
1335 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
1336 else SetSourceState(Source
, Context
, AL_PLAYING
);
1338 UnlockContext(Context
);
1342 ALCcontext_DecRef(Context
);
1345 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
1347 alSourcePausev(1, &source
);
1349 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1351 ALCcontext
*Context
;
1355 Context
= GetContextRef();
1356 if(!Context
) return;
1360 CHECK_VALUE(Context
, n
>= 0);
1361 for(i
= 0;i
< n
;i
++)
1363 if(!LookupSource(Context
, sources
[i
]))
1364 al_throwerr(Context
, AL_INVALID_NAME
);
1367 LockContext(Context
);
1368 for(i
= 0;i
< n
;i
++)
1370 Source
= LookupSource(Context
, sources
[i
]);
1371 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
1372 else SetSourceState(Source
, Context
, AL_PAUSED
);
1374 UnlockContext(Context
);
1378 ALCcontext_DecRef(Context
);
1381 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
1383 alSourceStopv(1, &source
);
1385 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1387 ALCcontext
*Context
;
1391 Context
= GetContextRef();
1392 if(!Context
) return;
1396 CHECK_VALUE(Context
, n
>= 0);
1397 for(i
= 0;i
< n
;i
++)
1399 if(!LookupSource(Context
, sources
[i
]))
1400 al_throwerr(Context
, AL_INVALID_NAME
);
1403 LockContext(Context
);
1404 for(i
= 0;i
< n
;i
++)
1406 Source
= LookupSource(Context
, sources
[i
]);
1407 Source
->new_state
= AL_NONE
;
1408 SetSourceState(Source
, Context
, AL_STOPPED
);
1410 UnlockContext(Context
);
1414 ALCcontext_DecRef(Context
);
1417 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
1419 alSourceRewindv(1, &source
);
1421 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1423 ALCcontext
*Context
;
1427 Context
= GetContextRef();
1428 if(!Context
) return;
1432 CHECK_VALUE(Context
, n
>= 0);
1433 for(i
= 0;i
< n
;i
++)
1435 if(!LookupSource(Context
, sources
[i
]))
1436 al_throwerr(Context
, AL_INVALID_NAME
);
1439 LockContext(Context
);
1440 for(i
= 0;i
< n
;i
++)
1442 Source
= LookupSource(Context
, sources
[i
]);
1443 Source
->new_state
= AL_NONE
;
1444 SetSourceState(Source
, Context
, AL_INITIAL
);
1446 UnlockContext(Context
);
1450 ALCcontext_DecRef(Context
);
1454 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei nb
, const ALuint
*buffers
)
1456 ALCcontext
*Context
;
1459 ALbufferlistitem
*BufferListStart
= NULL
;
1460 ALbufferlistitem
*BufferList
;
1461 ALbuffer
*BufferFmt
;
1466 Context
= GetContextRef();
1467 if(!Context
) return;
1471 ALCdevice
*device
= Context
->Device
;
1473 CHECK_VALUE(Context
, nb
>= 0);
1475 if((Source
=LookupSource(Context
, source
)) == NULL
)
1476 al_throwerr(Context
, AL_INVALID_NAME
);
1478 LockContext(Context
);
1479 if(Source
->SourceType
== AL_STATIC
)
1481 UnlockContext(Context
);
1482 /* Can't queue on a Static Source */
1483 al_throwerr(Context
, AL_INVALID_OPERATION
);
1488 /* Check for a valid Buffer, for its frequency and format */
1489 BufferList
= Source
->queue
;
1492 if(BufferList
->buffer
)
1494 BufferFmt
= BufferList
->buffer
;
1497 BufferList
= BufferList
->next
;
1500 for(i
= 0;i
< nb
;i
++)
1502 ALbuffer
*buffer
= NULL
;
1503 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
1505 UnlockContext(Context
);
1506 al_throwerr(Context
, AL_INVALID_NAME
);
1509 if(!BufferListStart
)
1511 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
1512 BufferListStart
->buffer
= buffer
;
1513 BufferListStart
->next
= NULL
;
1514 BufferListStart
->prev
= NULL
;
1515 BufferList
= BufferListStart
;
1519 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1520 BufferList
->next
->buffer
= buffer
;
1521 BufferList
->next
->next
= NULL
;
1522 BufferList
->next
->prev
= BufferList
;
1523 BufferList
= BufferList
->next
;
1525 if(!buffer
) continue;
1526 IncrementRef(&buffer
->ref
);
1528 ReadLock(&buffer
->lock
);
1529 if(BufferFmt
== NULL
)
1533 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
1534 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
1535 if(buffer
->FmtChannels
== FmtMono
)
1536 Source
->Update
= CalcSourceParams
;
1538 Source
->Update
= CalcNonAttnSourceParams
;
1540 Source
->NeedsUpdate
= AL_TRUE
;
1542 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
1543 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
1544 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
1546 ReadUnlock(&buffer
->lock
);
1547 UnlockContext(Context
);
1548 al_throwerr(Context
, AL_INVALID_OPERATION
);
1550 ReadUnlock(&buffer
->lock
);
1553 /* Source is now streaming */
1554 Source
->SourceType
= AL_STREAMING
;
1556 if(Source
->queue
== NULL
)
1557 Source
->queue
= BufferListStart
;
1560 /* Append to the end of the queue */
1561 BufferList
= Source
->queue
;
1562 while(BufferList
->next
!= NULL
)
1563 BufferList
= BufferList
->next
;
1565 BufferListStart
->prev
= BufferList
;
1566 BufferList
->next
= BufferListStart
;
1569 Source
->BuffersInQueue
+= nb
;
1571 UnlockContext(Context
);
1575 while(BufferListStart
)
1577 BufferList
= BufferListStart
;
1578 BufferListStart
= BufferList
->next
;
1580 if(BufferList
->buffer
)
1581 DecrementRef(&BufferList
->buffer
->ref
);
1587 ALCcontext_DecRef(Context
);
1590 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers(ALuint source
, ALsizei nb
, ALuint
*buffers
)
1592 ALCcontext
*Context
;
1595 ALbufferlistitem
*BufferList
;
1600 Context
= GetContextRef();
1601 if(!Context
) return;
1605 CHECK_VALUE(Context
, nb
>= 0);
1607 if((Source
=LookupSource(Context
, source
)) == NULL
)
1608 al_throwerr(Context
, AL_INVALID_NAME
);
1610 LockContext(Context
);
1611 if(Source
->Looping
|| Source
->SourceType
!= AL_STREAMING
||
1612 (ALuint
)nb
> Source
->BuffersPlayed
)
1614 UnlockContext(Context
);
1615 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
1616 al_throwerr(Context
, AL_INVALID_VALUE
);
1619 for(i
= 0;i
< nb
;i
++)
1621 BufferList
= Source
->queue
;
1622 Source
->queue
= BufferList
->next
;
1623 Source
->BuffersInQueue
--;
1624 Source
->BuffersPlayed
--;
1626 if(BufferList
->buffer
)
1628 buffers
[i
] = BufferList
->buffer
->id
;
1629 DecrementRef(&BufferList
->buffer
->ref
);
1637 Source
->queue
->prev
= NULL
;
1638 UnlockContext(Context
);
1642 ALCcontext_DecRef(Context
);
1646 static ALvoid
InitSourceParams(ALsource
*Source
)
1650 Source
->InnerAngle
= 360.0f
;
1651 Source
->OuterAngle
= 360.0f
;
1652 Source
->Pitch
= 1.0f
;
1653 Source
->Position
[0] = 0.0f
;
1654 Source
->Position
[1] = 0.0f
;
1655 Source
->Position
[2] = 0.0f
;
1656 Source
->Orientation
[0] = 0.0f
;
1657 Source
->Orientation
[1] = 0.0f
;
1658 Source
->Orientation
[2] = 0.0f
;
1659 Source
->Velocity
[0] = 0.0f
;
1660 Source
->Velocity
[1] = 0.0f
;
1661 Source
->Velocity
[2] = 0.0f
;
1662 Source
->RefDistance
= 1.0f
;
1663 Source
->MaxDistance
= FLT_MAX
;
1664 Source
->RollOffFactor
= 1.0f
;
1665 Source
->Looping
= AL_FALSE
;
1666 Source
->Gain
= 1.0f
;
1667 Source
->MinGain
= 0.0f
;
1668 Source
->MaxGain
= 1.0f
;
1669 Source
->OuterGain
= 0.0f
;
1670 Source
->OuterGainHF
= 1.0f
;
1672 Source
->DryGainHFAuto
= AL_TRUE
;
1673 Source
->WetGainAuto
= AL_TRUE
;
1674 Source
->WetGainHFAuto
= AL_TRUE
;
1675 Source
->AirAbsorptionFactor
= 0.0f
;
1676 Source
->RoomRolloffFactor
= 0.0f
;
1677 Source
->DopplerFactor
= 1.0f
;
1678 Source
->DirectChannels
= AL_FALSE
;
1680 Source
->DistanceModel
= DefaultDistanceModel
;
1682 Source
->Resampler
= DefaultResampler
;
1684 Source
->state
= AL_INITIAL
;
1685 Source
->new_state
= AL_NONE
;
1686 Source
->SourceType
= AL_UNDETERMINED
;
1687 Source
->Offset
= -1.0;
1689 Source
->DirectGain
= 1.0f
;
1690 Source
->DirectGainHF
= 1.0f
;
1691 for(i
= 0;i
< MAX_SENDS
;i
++)
1693 Source
->Send
[i
].Gain
= 1.0f
;
1694 Source
->Send
[i
].GainHF
= 1.0f
;
1697 Source
->NeedsUpdate
= AL_TRUE
;
1699 Source
->Hrtf
.Moving
= AL_FALSE
;
1700 Source
->Hrtf
.Counter
= 0;
1706 * Sets the source's new play state given its current state.
1708 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
1710 if(state
== AL_PLAYING
)
1712 ALbufferlistitem
*BufferList
;
1715 /* Check that there is a queue containing at least one valid, non zero
1717 BufferList
= Source
->queue
;
1720 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
1722 BufferList
= BufferList
->next
;
1725 if(Source
->state
!= AL_PLAYING
)
1727 for(j
= 0;j
< MaxChannels
;j
++)
1729 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
1730 Source
->Hrtf
.History
[j
][k
] = 0.0f
;
1731 for(k
= 0;k
< HRIR_LENGTH
;k
++)
1733 Source
->Hrtf
.Values
[j
][k
][0] = 0.0f
;
1734 Source
->Hrtf
.Values
[j
][k
][1] = 0.0f
;
1739 if(Source
->state
!= AL_PAUSED
)
1741 Source
->state
= AL_PLAYING
;
1742 Source
->position
= 0;
1743 Source
->position_fraction
= 0;
1744 Source
->BuffersPlayed
= 0;
1747 Source
->state
= AL_PLAYING
;
1749 // Check if an Offset has been set
1750 if(Source
->Offset
>= 0.0)
1751 ApplyOffset(Source
);
1753 /* If there's nothing to play, or device is disconnected, go right to
1755 if(!BufferList
|| !Context
->Device
->Connected
)
1757 SetSourceState(Source
, Context
, AL_STOPPED
);
1761 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
1763 if(Context
->ActiveSources
[j
] == Source
)
1766 if(j
== Context
->ActiveSourceCount
)
1767 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
1769 else if(state
== AL_PAUSED
)
1771 if(Source
->state
== AL_PLAYING
)
1773 Source
->state
= AL_PAUSED
;
1774 Source
->Hrtf
.Moving
= AL_FALSE
;
1775 Source
->Hrtf
.Counter
= 0;
1778 else if(state
== AL_STOPPED
)
1780 if(Source
->state
!= AL_INITIAL
)
1782 Source
->state
= AL_STOPPED
;
1783 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1784 Source
->Hrtf
.Moving
= AL_FALSE
;
1785 Source
->Hrtf
.Counter
= 0;
1787 Source
->Offset
= -1.0;
1789 else if(state
== AL_INITIAL
)
1791 if(Source
->state
!= AL_INITIAL
)
1793 Source
->state
= AL_INITIAL
;
1794 Source
->position
= 0;
1795 Source
->position_fraction
= 0;
1796 Source
->BuffersPlayed
= 0;
1797 Source
->Hrtf
.Moving
= AL_FALSE
;
1798 Source
->Hrtf
.Counter
= 0;
1800 Source
->Offset
= -1.0;
1806 * Gets the current read offset for the given Source, in 32.32 fixed-point
1807 * samples. The offset is relative to the start of the queue (not the start of
1808 * the current buffer).
1810 static ALint64
GetSourceOffset(ALsource
*Source
)
1812 const ALbufferlistitem
*BufferList
;
1816 if(Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
)
1819 /* NOTE: This is the offset into the *current* buffer, so add the length of
1820 * any played buffers */
1821 readPos
= (ALuint64
)Source
->position
<< 32;
1822 readPos
|= (ALuint64
)Source
->position_fraction
<< (32-FRACTIONBITS
);
1823 BufferList
= Source
->queue
;
1824 for(i
= 0;i
< Source
->BuffersPlayed
&& BufferList
;i
++)
1826 if(BufferList
->buffer
)
1827 readPos
+= (ALuint64
)BufferList
->buffer
->SampleLen
<< 32;
1828 BufferList
= BufferList
->next
;
1831 return (ALint64
)minu64(readPos
, MAKEU64(0x7fffffff,0xffffffff));
1836 * Gets the current read and write offsets for the given Source, in the
1837 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
1838 * the start of the queue (not the start of the current buffer).
1840 static ALvoid
GetSourceOffsets(ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
1842 const ALbufferlistitem
*BufferList
;
1843 const ALbuffer
*Buffer
= NULL
;
1844 ALuint readPos
, writePos
;
1845 ALuint totalBufferLen
;
1848 // Find the first valid Buffer in the Queue
1849 BufferList
= Source
->queue
;
1852 if(BufferList
->buffer
)
1854 Buffer
= BufferList
->buffer
;
1857 BufferList
= BufferList
->next
;
1860 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
1867 if(updateLen
> 0.0 && updateLen
< 0.015)
1870 /* NOTE: This is the offset into the *current* buffer, so add the length of
1871 * any played buffers */
1872 readPos
= Source
->position
;
1874 BufferList
= Source
->queue
;
1875 for(i
= 0;BufferList
;i
++)
1877 if(BufferList
->buffer
)
1879 if(i
< Source
->BuffersPlayed
)
1880 readPos
+= BufferList
->buffer
->SampleLen
;
1881 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
1883 BufferList
= BufferList
->next
;
1885 if(Source
->state
== AL_PLAYING
)
1886 writePos
= readPos
+ (ALuint
)(updateLen
*Buffer
->Frequency
);
1892 readPos
%= totalBufferLen
;
1893 writePos
%= totalBufferLen
;
1897 /* Wrap positions back to 0 */
1898 if(readPos
>= totalBufferLen
)
1900 if(writePos
>= totalBufferLen
)
1907 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
1908 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
1911 case AL_SAMPLE_OFFSET
:
1912 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1913 offset
[0] = (ALdouble
)readPos
;
1914 offset
[1] = (ALdouble
)writePos
;
1917 case AL_BYTE_OFFSET
:
1918 case AL_BYTE_RW_OFFSETS_SOFT
:
1919 if(Buffer
->OriginalType
== UserFmtIMA4
)
1921 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
1922 ALuint FrameBlockSize
= 65;
1924 /* Round down to nearest ADPCM block */
1925 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
1926 if(Source
->state
!= AL_PLAYING
)
1927 offset
[1] = offset
[0];
1930 /* Round up to nearest ADPCM block */
1931 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
1932 FrameBlockSize
* BlockSize
);
1937 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
1938 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
1939 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
1948 * Apply the stored playback offset to the Source. This function will update
1949 * the number of buffers "played" given the stored offset.
1951 ALboolean
ApplyOffset(ALsource
*Source
)
1953 const ALbufferlistitem
*BufferList
;
1954 const ALbuffer
*Buffer
;
1955 ALint bufferLen
, totalBufferLen
;
1956 ALint buffersPlayed
;
1959 /* Get sample frame offset */
1960 offset
= GetSampleOffset(Source
);
1967 BufferList
= Source
->queue
;
1970 Buffer
= BufferList
->buffer
;
1971 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
1973 if(bufferLen
<= offset
-totalBufferLen
)
1975 /* Offset is past this buffer so increment to the next buffer */
1978 else if(totalBufferLen
<= offset
)
1980 /* Offset is in this buffer */
1981 Source
->BuffersPlayed
= buffersPlayed
;
1983 Source
->position
= offset
- totalBufferLen
;
1984 Source
->position_fraction
= 0;
1988 totalBufferLen
+= bufferLen
;
1990 BufferList
= BufferList
->next
;
1993 /* Offset is out of range of the queue */
2000 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2001 * Second offset supplied by the application). This takes into account the fact
2002 * that the buffer format may have been modifed since.
2004 static ALint
GetSampleOffset(ALsource
*Source
)
2006 const ALbuffer
*Buffer
= NULL
;
2007 const ALbufferlistitem
*BufferList
;
2010 /* Find the first valid Buffer in the Queue */
2011 BufferList
= Source
->queue
;
2014 if(BufferList
->buffer
)
2016 Buffer
= BufferList
->buffer
;
2019 BufferList
= BufferList
->next
;
2024 Source
->Offset
= -1.0;
2028 switch(Source
->OffsetType
)
2030 case AL_BYTE_OFFSET
:
2031 /* Determine the ByteOffset (and ensure it is block aligned) */
2032 Offset
= (ALint
)Source
->Offset
;
2033 if(Buffer
->OriginalType
== UserFmtIMA4
)
2035 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2039 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2042 case AL_SAMPLE_OFFSET
:
2043 Offset
= (ALint
)Source
->Offset
;
2047 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2050 Source
->Offset
= -1.0;
2058 * Destroys all sources in the source map.
2060 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2064 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2066 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2067 Context
->SourceMap
.array
[pos
].value
= NULL
;
2069 while(temp
->queue
!= NULL
)
2071 ALbufferlistitem
*BufferList
= temp
->queue
;
2072 temp
->queue
= BufferList
->next
;
2074 if(BufferList
->buffer
!= NULL
)
2075 DecrementRef(&BufferList
->buffer
->ref
);
2079 for(j
= 0;j
< MAX_SENDS
;++j
)
2081 if(temp
->Send
[j
].Slot
)
2082 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2083 temp
->Send
[j
].Slot
= NULL
;
2086 FreeThunkEntry(temp
->id
);
2087 memset(temp
, 0, sizeof(*temp
));