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
= RESAMPLER_DEFAULT
;
37 const ALsizei ResamplerPadding
[RESAMPLER_MAX
] = {
42 const ALsizei ResamplerPrePadding
[RESAMPLER_MAX
] = {
49 static ALvoid
InitSourceParams(ALsource
*Source
);
50 static ALvoid
GetSourceOffset(ALsource
*Source
, ALenum eName
, ALdouble
*Offsets
, ALdouble updateLen
);
51 static ALint
GetSampleOffset(ALsource
*Source
);
54 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
,ALuint
*sources
)
59 Context
= GetContextRef();
62 Device
= Context
->Device
;
63 if(n
< 0 || IsBadWritePtr((void*)sources
, n
* sizeof(ALuint
)))
64 alSetError(Context
, AL_INVALID_VALUE
);
70 // Add additional sources to the list
74 ALsource
*source
= calloc(1, sizeof(ALsource
));
77 alSetError(Context
, AL_OUT_OF_MEMORY
);
78 alDeleteSources(i
, sources
);
81 InitSourceParams(source
);
83 err
= NewThunkEntry(&source
->source
);
84 if(err
== AL_NO_ERROR
)
85 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->source
, source
);
86 if(err
!= AL_NO_ERROR
)
88 FreeThunkEntry(source
->source
);
89 memset(source
, 0, sizeof(ALsource
));
92 alSetError(Context
, err
);
93 alDeleteSources(i
, sources
);
97 sources
[i
++] = source
->source
;
101 ALCcontext_DecRef(Context
);
105 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
110 ALbufferlistitem
*BufferList
;
112 Context
= GetContextRef();
116 alSetError(Context
, AL_INVALID_VALUE
);
119 // Check that all Sources are valid (and can therefore be deleted)
122 if(LookupSource(Context
, sources
[i
]) == NULL
)
124 alSetError(Context
, AL_INVALID_NAME
);
130 // All Sources are valid, and can be deleted
133 ALsource
**srclist
, **srclistend
;
135 // Remove Source from list of Sources
136 if((Source
=RemoveSource(Context
, sources
[i
])) == NULL
)
139 FreeThunkEntry(Source
->source
);
141 LockContext(Context
);
142 srclist
= Context
->ActiveSources
;
143 srclistend
= srclist
+ Context
->ActiveSourceCount
;
144 while(srclist
!= srclistend
)
146 if(*srclist
== Source
)
148 Context
->ActiveSourceCount
--;
149 *srclist
= *(--srclistend
);
154 UnlockContext(Context
);
156 // For each buffer in the source's queue...
157 while(Source
->queue
!= NULL
)
159 BufferList
= Source
->queue
;
160 Source
->queue
= BufferList
->next
;
162 if(BufferList
->buffer
!= NULL
)
163 DecrementRef(&BufferList
->buffer
->ref
);
167 for(j
= 0;j
< MAX_SENDS
;++j
)
169 if(Source
->Send
[j
].Slot
)
170 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
171 Source
->Send
[j
].Slot
= NULL
;
174 memset(Source
,0,sizeof(ALsource
));
179 ALCcontext_DecRef(Context
);
183 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
188 Context
= GetContextRef();
189 if(!Context
) return AL_FALSE
;
191 result
= (LookupSource(Context
, source
) ? AL_TRUE
: AL_FALSE
);
193 ALCcontext_DecRef(Context
);
199 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
201 ALCcontext
*pContext
;
204 pContext
= GetContextRef();
205 if(!pContext
) return;
207 if((Source
=LookupSource(pContext
, source
)) != NULL
)
214 Source
->flPitch
= flValue
;
215 Source
->NeedsUpdate
= AL_TRUE
;
218 alSetError(pContext
, AL_INVALID_VALUE
);
221 case AL_CONE_INNER_ANGLE
:
222 if(flValue
>= 0.0f
&& flValue
<= 360.0f
)
224 Source
->flInnerAngle
= flValue
;
225 Source
->NeedsUpdate
= AL_TRUE
;
228 alSetError(pContext
, AL_INVALID_VALUE
);
231 case AL_CONE_OUTER_ANGLE
:
232 if(flValue
>= 0.0f
&& flValue
<= 360.0f
)
234 Source
->flOuterAngle
= flValue
;
235 Source
->NeedsUpdate
= AL_TRUE
;
238 alSetError(pContext
, AL_INVALID_VALUE
);
244 Source
->flGain
= flValue
;
245 Source
->NeedsUpdate
= AL_TRUE
;
248 alSetError(pContext
, AL_INVALID_VALUE
);
251 case AL_MAX_DISTANCE
:
254 Source
->flMaxDistance
= flValue
;
255 Source
->NeedsUpdate
= AL_TRUE
;
258 alSetError(pContext
, AL_INVALID_VALUE
);
261 case AL_ROLLOFF_FACTOR
:
264 Source
->flRollOffFactor
= flValue
;
265 Source
->NeedsUpdate
= AL_TRUE
;
268 alSetError(pContext
, AL_INVALID_VALUE
);
271 case AL_REFERENCE_DISTANCE
:
274 Source
->flRefDistance
= flValue
;
275 Source
->NeedsUpdate
= AL_TRUE
;
278 alSetError(pContext
, AL_INVALID_VALUE
);
282 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
284 Source
->flMinGain
= flValue
;
285 Source
->NeedsUpdate
= AL_TRUE
;
288 alSetError(pContext
, AL_INVALID_VALUE
);
292 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
294 Source
->flMaxGain
= flValue
;
295 Source
->NeedsUpdate
= AL_TRUE
;
298 alSetError(pContext
, AL_INVALID_VALUE
);
301 case AL_CONE_OUTER_GAIN
:
302 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
304 Source
->flOuterGain
= flValue
;
305 Source
->NeedsUpdate
= AL_TRUE
;
308 alSetError(pContext
, AL_INVALID_VALUE
);
311 case AL_CONE_OUTER_GAINHF
:
312 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
314 Source
->OuterGainHF
= flValue
;
315 Source
->NeedsUpdate
= AL_TRUE
;
318 alSetError(pContext
, AL_INVALID_VALUE
);
321 case AL_AIR_ABSORPTION_FACTOR
:
322 if(flValue
>= 0.0f
&& flValue
<= 10.0f
)
324 Source
->AirAbsorptionFactor
= flValue
;
325 Source
->NeedsUpdate
= AL_TRUE
;
328 alSetError(pContext
, AL_INVALID_VALUE
);
331 case AL_ROOM_ROLLOFF_FACTOR
:
332 if(flValue
>= 0.0f
&& flValue
<= 10.0f
)
334 Source
->RoomRolloffFactor
= flValue
;
335 Source
->NeedsUpdate
= AL_TRUE
;
338 alSetError(pContext
, AL_INVALID_VALUE
);
341 case AL_DOPPLER_FACTOR
:
342 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
344 Source
->DopplerFactor
= flValue
;
345 Source
->NeedsUpdate
= AL_TRUE
;
348 alSetError(pContext
, AL_INVALID_VALUE
);
352 case AL_SAMPLE_OFFSET
:
356 LockContext(pContext
);
357 Source
->lOffsetType
= eParam
;
359 // Store Offset (convert Seconds into Milliseconds)
360 if(eParam
== AL_SEC_OFFSET
)
361 Source
->lOffset
= (ALint
)(flValue
* 1000.0f
);
363 Source
->lOffset
= (ALint
)flValue
;
365 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
366 !pContext
->DeferUpdates
)
368 if(ApplyOffset(Source
) == AL_FALSE
)
369 alSetError(pContext
, AL_INVALID_VALUE
);
371 UnlockContext(pContext
);
374 alSetError(pContext
, AL_INVALID_VALUE
);
378 alSetError(pContext
, AL_INVALID_ENUM
);
384 // Invalid Source Name
385 alSetError(pContext
, AL_INVALID_NAME
);
388 ALCcontext_DecRef(pContext
);
392 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
394 ALCcontext
*pContext
;
397 pContext
= GetContextRef();
398 if(!pContext
) return;
400 if((Source
=LookupSource(pContext
, source
)) != NULL
)
405 if(isfinite(flValue1
) && isfinite(flValue2
) && isfinite(flValue3
))
407 LockContext(pContext
);
408 Source
->vPosition
[0] = flValue1
;
409 Source
->vPosition
[1] = flValue2
;
410 Source
->vPosition
[2] = flValue3
;
411 UnlockContext(pContext
);
412 Source
->NeedsUpdate
= AL_TRUE
;
415 alSetError(pContext
, AL_INVALID_VALUE
);
419 if(isfinite(flValue1
) && isfinite(flValue2
) && isfinite(flValue3
))
421 LockContext(pContext
);
422 Source
->vVelocity
[0] = flValue1
;
423 Source
->vVelocity
[1] = flValue2
;
424 Source
->vVelocity
[2] = flValue3
;
425 UnlockContext(pContext
);
426 Source
->NeedsUpdate
= AL_TRUE
;
429 alSetError(pContext
, AL_INVALID_VALUE
);
433 if(isfinite(flValue1
) && isfinite(flValue2
) && isfinite(flValue3
))
435 LockContext(pContext
);
436 Source
->vOrientation
[0] = flValue1
;
437 Source
->vOrientation
[1] = flValue2
;
438 Source
->vOrientation
[2] = flValue3
;
439 UnlockContext(pContext
);
440 Source
->NeedsUpdate
= AL_TRUE
;
443 alSetError(pContext
, AL_INVALID_VALUE
);
447 alSetError(pContext
, AL_INVALID_ENUM
);
452 alSetError(pContext
, AL_INVALID_NAME
);
454 ALCcontext_DecRef(pContext
);
458 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
460 ALCcontext
*pContext
;
467 case AL_CONE_INNER_ANGLE
:
468 case AL_CONE_OUTER_ANGLE
:
470 case AL_MAX_DISTANCE
:
471 case AL_ROLLOFF_FACTOR
:
472 case AL_REFERENCE_DISTANCE
:
475 case AL_CONE_OUTER_GAIN
:
476 case AL_CONE_OUTER_GAINHF
:
478 case AL_SAMPLE_OFFSET
:
480 case AL_AIR_ABSORPTION_FACTOR
:
481 case AL_ROOM_ROLLOFF_FACTOR
:
482 alSourcef(source
, eParam
, pflValues
[0]);
488 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
493 pContext
= GetContextRef();
494 if(!pContext
) return;
498 if(LookupSource(pContext
, source
) != NULL
)
503 alSetError(pContext
, AL_INVALID_ENUM
);
508 alSetError(pContext
, AL_INVALID_NAME
);
511 alSetError(pContext
, AL_INVALID_VALUE
);
513 ALCcontext_DecRef(pContext
);
517 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
519 ALCcontext
*pContext
;
521 ALbufferlistitem
*BufferListItem
;
525 case AL_MAX_DISTANCE
:
526 case AL_ROLLOFF_FACTOR
:
527 case AL_CONE_INNER_ANGLE
:
528 case AL_CONE_OUTER_ANGLE
:
529 case AL_REFERENCE_DISTANCE
:
530 alSourcef(source
, eParam
, (ALfloat
)lValue
);
534 pContext
= GetContextRef();
535 if(!pContext
) return;
537 if((Source
=LookupSource(pContext
, source
)) != NULL
)
539 ALCdevice
*device
= pContext
->Device
;
543 case AL_SOURCE_RELATIVE
:
544 if(lValue
== AL_FALSE
|| lValue
== AL_TRUE
)
546 Source
->bHeadRelative
= (ALboolean
)lValue
;
547 Source
->NeedsUpdate
= AL_TRUE
;
550 alSetError(pContext
, AL_INVALID_VALUE
);
554 if(lValue
== AL_FALSE
|| lValue
== AL_TRUE
)
555 Source
->bLooping
= (ALboolean
)lValue
;
557 alSetError(pContext
, AL_INVALID_VALUE
);
561 LockContext(pContext
);
562 if(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
)
564 ALbufferlistitem
*oldlist
;
565 ALbuffer
*buffer
= NULL
;
567 if(lValue
== 0 || (buffer
=LookupBuffer(device
, lValue
)) != NULL
)
569 Source
->BuffersInQueue
= 0;
570 Source
->BuffersPlayed
= 0;
572 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
575 // Source is now in STATIC mode
576 Source
->lSourceType
= AL_STATIC
;
578 // Add the selected buffer to the queue
579 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
580 BufferListItem
->buffer
= buffer
;
581 BufferListItem
->next
= NULL
;
582 BufferListItem
->prev
= NULL
;
583 // Increment reference counter for buffer
584 IncrementRef(&buffer
->ref
);
586 oldlist
= ExchangePtr((void**)&Source
->queue
, BufferListItem
);
587 Source
->BuffersInQueue
= 1;
589 ReadLock(&buffer
->lock
);
590 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
591 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
592 ReadUnlock(&buffer
->lock
);
593 if(buffer
->FmtChannels
== FmtMono
)
594 Source
->Update
= CalcSourceParams
;
596 Source
->Update
= CalcNonAttnSourceParams
;
597 Source
->NeedsUpdate
= AL_TRUE
;
601 // Source is now in UNDETERMINED mode
602 Source
->lSourceType
= AL_UNDETERMINED
;
603 oldlist
= ExchangePtr((void**)&Source
->queue
, NULL
);
606 // Delete all previous elements in the queue
607 while(oldlist
!= NULL
)
609 BufferListItem
= oldlist
;
610 oldlist
= BufferListItem
->next
;
612 if(BufferListItem
->buffer
)
613 DecrementRef(&BufferListItem
->buffer
->ref
);
614 free(BufferListItem
);
618 alSetError(pContext
, AL_INVALID_VALUE
);
621 alSetError(pContext
, AL_INVALID_OPERATION
);
622 UnlockContext(pContext
);
625 case AL_SOURCE_STATE
:
627 alSetError(pContext
, AL_INVALID_OPERATION
);
631 case AL_SAMPLE_OFFSET
:
635 LockContext(pContext
);
636 Source
->lOffsetType
= eParam
;
638 // Store Offset (convert Seconds into Milliseconds)
639 if(eParam
== AL_SEC_OFFSET
)
640 Source
->lOffset
= lValue
* 1000;
642 Source
->lOffset
= lValue
;
644 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
645 !pContext
->DeferUpdates
)
647 if(ApplyOffset(Source
) == AL_FALSE
)
648 alSetError(pContext
, AL_INVALID_VALUE
);
650 UnlockContext(pContext
);
653 alSetError(pContext
, AL_INVALID_VALUE
);
656 case AL_DIRECT_FILTER
: {
657 ALfilter
*filter
= NULL
;
659 if(lValue
== 0 || (filter
=LookupFilter(pContext
->Device
, lValue
)) != NULL
)
661 LockContext(pContext
);
664 Source
->DirectGain
= 1.0f
;
665 Source
->DirectGainHF
= 1.0f
;
669 Source
->DirectGain
= filter
->Gain
;
670 Source
->DirectGainHF
= filter
->GainHF
;
672 UnlockContext(pContext
);
673 Source
->NeedsUpdate
= AL_TRUE
;
676 alSetError(pContext
, AL_INVALID_VALUE
);
679 case AL_DIRECT_FILTER_GAINHF_AUTO
:
680 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
682 Source
->DryGainHFAuto
= lValue
;
683 Source
->NeedsUpdate
= AL_TRUE
;
686 alSetError(pContext
, AL_INVALID_VALUE
);
689 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
690 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
692 Source
->WetGainAuto
= lValue
;
693 Source
->NeedsUpdate
= AL_TRUE
;
696 alSetError(pContext
, AL_INVALID_VALUE
);
699 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
700 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
702 Source
->WetGainHFAuto
= lValue
;
703 Source
->NeedsUpdate
= AL_TRUE
;
706 alSetError(pContext
, AL_INVALID_VALUE
);
709 case AL_VIRTUAL_CHANNELS_SOFT
:
710 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
712 Source
->VirtualChannels
= lValue
;
713 Source
->NeedsUpdate
= AL_TRUE
;
716 alSetError(pContext
, AL_INVALID_VALUE
);
719 case AL_DISTANCE_MODEL
:
720 if(lValue
== AL_NONE
||
721 lValue
== AL_INVERSE_DISTANCE
||
722 lValue
== AL_INVERSE_DISTANCE_CLAMPED
||
723 lValue
== AL_LINEAR_DISTANCE
||
724 lValue
== AL_LINEAR_DISTANCE_CLAMPED
||
725 lValue
== AL_EXPONENT_DISTANCE
||
726 lValue
== AL_EXPONENT_DISTANCE_CLAMPED
)
728 Source
->DistanceModel
= lValue
;
729 if(pContext
->SourceDistanceModel
)
730 Source
->NeedsUpdate
= AL_TRUE
;
733 alSetError(pContext
, AL_INVALID_VALUE
);
737 alSetError(pContext
, AL_INVALID_ENUM
);
742 alSetError(pContext
, AL_INVALID_NAME
);
744 ALCcontext_DecRef(pContext
);
748 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
750 ALCcontext
*pContext
;
758 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
762 pContext
= GetContextRef();
763 if(!pContext
) return;
765 if((Source
=LookupSource(pContext
, source
)) != NULL
)
767 ALCdevice
*device
= pContext
->Device
;
771 case AL_AUXILIARY_SEND_FILTER
: {
772 ALeffectslot
*ALEffectSlot
= NULL
;
773 ALfilter
*ALFilter
= NULL
;
775 LockContext(pContext
);
776 if((ALuint
)lValue2
< device
->NumAuxSends
&&
777 (lValue1
== 0 || (ALEffectSlot
=LookupEffectSlot(pContext
, lValue1
)) != NULL
) &&
778 (lValue3
== 0 || (ALFilter
=LookupFilter(device
, lValue3
)) != NULL
))
780 /* Release refcount on the previous slot, and add one for
782 if(ALEffectSlot
) IncrementRef(&ALEffectSlot
->ref
);
783 ALEffectSlot
= ExchangePtr((void**)&Source
->Send
[lValue2
].Slot
, ALEffectSlot
);
784 if(ALEffectSlot
) DecrementRef(&ALEffectSlot
->ref
);
789 Source
->Send
[lValue2
].WetGain
= 1.0f
;
790 Source
->Send
[lValue2
].WetGainHF
= 1.0f
;
794 Source
->Send
[lValue2
].WetGain
= ALFilter
->Gain
;
795 Source
->Send
[lValue2
].WetGainHF
= ALFilter
->GainHF
;
797 Source
->NeedsUpdate
= AL_TRUE
;
800 alSetError(pContext
, AL_INVALID_VALUE
);
801 UnlockContext(pContext
);
805 alSetError(pContext
, AL_INVALID_ENUM
);
810 alSetError(pContext
, AL_INVALID_NAME
);
812 ALCcontext_DecRef(pContext
);
816 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
818 ALCcontext
*pContext
;
824 case AL_SOURCE_RELATIVE
:
825 case AL_CONE_INNER_ANGLE
:
826 case AL_CONE_OUTER_ANGLE
:
829 case AL_SOURCE_STATE
:
831 case AL_SAMPLE_OFFSET
:
833 case AL_MAX_DISTANCE
:
834 case AL_ROLLOFF_FACTOR
:
835 case AL_REFERENCE_DISTANCE
:
836 case AL_DIRECT_FILTER
:
837 case AL_DIRECT_FILTER_GAINHF_AUTO
:
838 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
839 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
840 case AL_DISTANCE_MODEL
:
841 case AL_VIRTUAL_CHANNELS_SOFT
:
842 alSourcei(source
, eParam
, plValues
[0]);
848 case AL_AUXILIARY_SEND_FILTER
:
849 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
854 pContext
= GetContextRef();
855 if(!pContext
) return;
859 if(LookupSource(pContext
, source
) != NULL
)
864 alSetError(pContext
, AL_INVALID_ENUM
);
869 alSetError(pContext
, AL_INVALID_NAME
);
872 alSetError(pContext
, AL_INVALID_VALUE
);
874 ALCcontext_DecRef(pContext
);
878 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
880 ALCcontext
*pContext
;
885 pContext
= GetContextRef();
886 if(!pContext
) return;
890 if((Source
=LookupSource(pContext
, source
)) != NULL
)
895 *pflValue
= Source
->flPitch
;
899 *pflValue
= Source
->flGain
;
903 *pflValue
= Source
->flMinGain
;
907 *pflValue
= Source
->flMaxGain
;
910 case AL_MAX_DISTANCE
:
911 *pflValue
= Source
->flMaxDistance
;
914 case AL_ROLLOFF_FACTOR
:
915 *pflValue
= Source
->flRollOffFactor
;
918 case AL_CONE_OUTER_GAIN
:
919 *pflValue
= Source
->flOuterGain
;
922 case AL_CONE_OUTER_GAINHF
:
923 *pflValue
= Source
->OuterGainHF
;
927 case AL_SAMPLE_OFFSET
:
929 LockContext(pContext
);
930 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
931 pContext
->Device
->Frequency
;
932 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
933 UnlockContext(pContext
);
934 *pflValue
= (ALfloat
)Offsets
[0];
937 case AL_CONE_INNER_ANGLE
:
938 *pflValue
= Source
->flInnerAngle
;
941 case AL_CONE_OUTER_ANGLE
:
942 *pflValue
= Source
->flOuterAngle
;
945 case AL_REFERENCE_DISTANCE
:
946 *pflValue
= Source
->flRefDistance
;
949 case AL_AIR_ABSORPTION_FACTOR
:
950 *pflValue
= Source
->AirAbsorptionFactor
;
953 case AL_ROOM_ROLLOFF_FACTOR
:
954 *pflValue
= Source
->RoomRolloffFactor
;
957 case AL_DOPPLER_FACTOR
:
958 *pflValue
= Source
->DopplerFactor
;
962 alSetError(pContext
, AL_INVALID_ENUM
);
967 alSetError(pContext
, AL_INVALID_NAME
);
970 alSetError(pContext
, AL_INVALID_VALUE
);
972 ALCcontext_DecRef(pContext
);
976 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
978 ALCcontext
*pContext
;
981 pContext
= GetContextRef();
982 if(!pContext
) return;
984 if(pflValue1
&& pflValue2
&& pflValue3
)
986 if((Source
=LookupSource(pContext
, source
)) != NULL
)
991 LockContext(pContext
);
992 *pflValue1
= Source
->vPosition
[0];
993 *pflValue2
= Source
->vPosition
[1];
994 *pflValue3
= Source
->vPosition
[2];
995 UnlockContext(pContext
);
999 LockContext(pContext
);
1000 *pflValue1
= Source
->vVelocity
[0];
1001 *pflValue2
= Source
->vVelocity
[1];
1002 *pflValue3
= Source
->vVelocity
[2];
1003 UnlockContext(pContext
);
1007 LockContext(pContext
);
1008 *pflValue1
= Source
->vOrientation
[0];
1009 *pflValue2
= Source
->vOrientation
[1];
1010 *pflValue3
= Source
->vOrientation
[2];
1011 UnlockContext(pContext
);
1015 alSetError(pContext
, AL_INVALID_ENUM
);
1020 alSetError(pContext
, AL_INVALID_NAME
);
1023 alSetError(pContext
, AL_INVALID_VALUE
);
1025 ALCcontext_DecRef(pContext
);
1029 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1031 ALCcontext
*pContext
;
1033 ALdouble Offsets
[2];
1042 case AL_MAX_DISTANCE
:
1043 case AL_ROLLOFF_FACTOR
:
1044 case AL_DOPPLER_FACTOR
:
1045 case AL_CONE_OUTER_GAIN
:
1047 case AL_SAMPLE_OFFSET
:
1048 case AL_BYTE_OFFSET
:
1049 case AL_CONE_INNER_ANGLE
:
1050 case AL_CONE_OUTER_ANGLE
:
1051 case AL_REFERENCE_DISTANCE
:
1052 case AL_CONE_OUTER_GAINHF
:
1053 case AL_AIR_ABSORPTION_FACTOR
:
1054 case AL_ROOM_ROLLOFF_FACTOR
:
1055 alGetSourcef(source
, eParam
, pflValues
);
1061 alGetSource3f(source
, eParam
, pflValues
+0, pflValues
+1, pflValues
+2);
1065 pContext
= GetContextRef();
1066 if(!pContext
) return;
1070 if((Source
=LookupSource(pContext
, source
)) != NULL
)
1074 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1075 case AL_BYTE_RW_OFFSETS_SOFT
:
1076 LockContext(pContext
);
1077 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
1078 pContext
->Device
->Frequency
;
1079 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
1080 UnlockContext(pContext
);
1081 pflValues
[0] = (ALfloat
)Offsets
[0];
1082 pflValues
[1] = (ALfloat
)Offsets
[1];
1086 alSetError(pContext
, AL_INVALID_ENUM
);
1091 alSetError(pContext
, AL_INVALID_NAME
);
1094 alSetError(pContext
, AL_INVALID_VALUE
);
1096 ALCcontext_DecRef(pContext
);
1100 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1102 ALbufferlistitem
*BufferList
;
1103 ALCcontext
*pContext
;
1105 ALdouble Offsets
[2];
1108 pContext
= GetContextRef();
1109 if(!pContext
) return;
1113 if((Source
=LookupSource(pContext
, source
)) != NULL
)
1117 case AL_MAX_DISTANCE
:
1118 *plValue
= (ALint
)Source
->flMaxDistance
;
1121 case AL_ROLLOFF_FACTOR
:
1122 *plValue
= (ALint
)Source
->flRollOffFactor
;
1125 case AL_REFERENCE_DISTANCE
:
1126 *plValue
= (ALint
)Source
->flRefDistance
;
1129 case AL_SOURCE_RELATIVE
:
1130 *plValue
= Source
->bHeadRelative
;
1133 case AL_CONE_INNER_ANGLE
:
1134 *plValue
= (ALint
)Source
->flInnerAngle
;
1137 case AL_CONE_OUTER_ANGLE
:
1138 *plValue
= (ALint
)Source
->flOuterAngle
;
1142 *plValue
= Source
->bLooping
;
1146 LockContext(pContext
);
1147 BufferList
= Source
->queue
;
1148 if(Source
->lSourceType
!= AL_STATIC
)
1150 ALuint i
= Source
->BuffersPlayed
;
1153 BufferList
= BufferList
->next
;
1157 *plValue
= ((BufferList
&& BufferList
->buffer
) ?
1158 BufferList
->buffer
->buffer
: 0);
1159 UnlockContext(pContext
);
1162 case AL_SOURCE_STATE
:
1163 *plValue
= Source
->state
;
1166 case AL_BUFFERS_QUEUED
:
1167 *plValue
= Source
->BuffersInQueue
;
1170 case AL_BUFFERS_PROCESSED
:
1171 LockContext(pContext
);
1172 if(Source
->bLooping
|| Source
->lSourceType
!= AL_STREAMING
)
1174 /* Buffers on a looping source are in a perpetual state
1175 * of PENDING, so don't report any as PROCESSED */
1179 *plValue
= Source
->BuffersPlayed
;
1180 UnlockContext(pContext
);
1183 case AL_SOURCE_TYPE
:
1184 *plValue
= Source
->lSourceType
;
1188 case AL_SAMPLE_OFFSET
:
1189 case AL_BYTE_OFFSET
:
1190 LockContext(pContext
);
1191 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
1192 pContext
->Device
->Frequency
;
1193 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
1194 UnlockContext(pContext
);
1195 *plValue
= (ALint
)Offsets
[0];
1198 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1199 *plValue
= Source
->DryGainHFAuto
;
1202 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1203 *plValue
= Source
->WetGainAuto
;
1206 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1207 *plValue
= Source
->WetGainHFAuto
;
1210 case AL_DOPPLER_FACTOR
:
1211 *plValue
= (ALint
)Source
->DopplerFactor
;
1214 case AL_VIRTUAL_CHANNELS_SOFT
:
1215 *plValue
= Source
->VirtualChannels
;
1218 case AL_DISTANCE_MODEL
:
1219 *plValue
= Source
->DistanceModel
;
1223 alSetError(pContext
, AL_INVALID_ENUM
);
1228 alSetError(pContext
, AL_INVALID_NAME
);
1231 alSetError(pContext
, AL_INVALID_VALUE
);
1233 ALCcontext_DecRef(pContext
);
1237 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1239 ALCcontext
*pContext
;
1242 pContext
= GetContextRef();
1243 if(!pContext
) return;
1245 if(plValue1
&& plValue2
&& plValue3
)
1247 if((Source
=LookupSource(pContext
, source
)) != NULL
)
1252 LockContext(pContext
);
1253 *plValue1
= (ALint
)Source
->vPosition
[0];
1254 *plValue2
= (ALint
)Source
->vPosition
[1];
1255 *plValue3
= (ALint
)Source
->vPosition
[2];
1256 UnlockContext(pContext
);
1260 LockContext(pContext
);
1261 *plValue1
= (ALint
)Source
->vVelocity
[0];
1262 *plValue2
= (ALint
)Source
->vVelocity
[1];
1263 *plValue3
= (ALint
)Source
->vVelocity
[2];
1264 UnlockContext(pContext
);
1268 LockContext(pContext
);
1269 *plValue1
= (ALint
)Source
->vOrientation
[0];
1270 *plValue2
= (ALint
)Source
->vOrientation
[1];
1271 *plValue3
= (ALint
)Source
->vOrientation
[2];
1272 UnlockContext(pContext
);
1276 alSetError(pContext
, AL_INVALID_ENUM
);
1281 alSetError(pContext
, AL_INVALID_NAME
);
1284 alSetError(pContext
, AL_INVALID_VALUE
);
1286 ALCcontext_DecRef(pContext
);
1290 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1292 ALCcontext
*pContext
;
1294 ALdouble Offsets
[2];
1299 case AL_SOURCE_RELATIVE
:
1300 case AL_CONE_INNER_ANGLE
:
1301 case AL_CONE_OUTER_ANGLE
:
1304 case AL_SOURCE_STATE
:
1305 case AL_BUFFERS_QUEUED
:
1306 case AL_BUFFERS_PROCESSED
:
1308 case AL_SAMPLE_OFFSET
:
1309 case AL_BYTE_OFFSET
:
1310 case AL_MAX_DISTANCE
:
1311 case AL_ROLLOFF_FACTOR
:
1312 case AL_DOPPLER_FACTOR
:
1313 case AL_REFERENCE_DISTANCE
:
1314 case AL_SOURCE_TYPE
:
1315 case AL_DIRECT_FILTER
:
1316 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1317 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1318 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1319 case AL_DISTANCE_MODEL
:
1320 case AL_VIRTUAL_CHANNELS_SOFT
:
1321 alGetSourcei(source
, eParam
, plValues
);
1327 alGetSource3i(source
, eParam
, plValues
+0, plValues
+1, plValues
+2);
1331 pContext
= GetContextRef();
1332 if(!pContext
) return;
1336 if((Source
=LookupSource(pContext
, source
)) != NULL
)
1340 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1341 case AL_BYTE_RW_OFFSETS_SOFT
:
1342 LockContext(pContext
);
1343 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
1344 pContext
->Device
->Frequency
;
1345 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
1346 UnlockContext(pContext
);
1347 plValues
[0] = (ALint
)Offsets
[0];
1348 plValues
[1] = (ALint
)Offsets
[1];
1352 alSetError(pContext
, AL_INVALID_ENUM
);
1357 alSetError(pContext
, AL_INVALID_NAME
);
1360 alSetError(pContext
, AL_INVALID_VALUE
);
1362 ALCcontext_DecRef(pContext
);
1366 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
1368 alSourcePlayv(1, &source
);
1371 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
1373 ALCcontext
*Context
;
1377 Context
= GetContextRef();
1378 if(!Context
) return;
1382 alSetError(Context
, AL_INVALID_VALUE
);
1385 if(n
> 0 && !sources
)
1387 alSetError(Context
, AL_INVALID_VALUE
);
1391 // Check that all the Sources are valid
1392 for(i
= 0;i
< n
;i
++)
1394 if(!LookupSource(Context
, sources
[i
]))
1396 alSetError(Context
, AL_INVALID_NAME
);
1401 LockContext(Context
);
1402 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
1407 newcount
= Context
->MaxActiveSources
<< 1;
1409 temp
= realloc(Context
->ActiveSources
,
1410 sizeof(*Context
->ActiveSources
) * newcount
);
1413 UnlockContext(Context
);
1414 alSetError(Context
, AL_OUT_OF_MEMORY
);
1418 Context
->ActiveSources
= temp
;
1419 Context
->MaxActiveSources
= newcount
;
1422 for(i
= 0;i
< n
;i
++)
1424 Source
= LookupSource(Context
, sources
[i
]);
1425 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
1426 else SetSourceState(Source
, Context
, AL_PLAYING
);
1428 UnlockContext(Context
);
1431 ALCcontext_DecRef(Context
);
1434 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
1436 alSourcePausev(1, &source
);
1439 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1441 ALCcontext
*Context
;
1445 Context
= GetContextRef();
1446 if(!Context
) return;
1450 alSetError(Context
, AL_INVALID_VALUE
);
1453 if(n
> 0 && !sources
)
1455 alSetError(Context
, AL_INVALID_VALUE
);
1459 // Check all the Sources are valid
1460 for(i
= 0;i
< n
;i
++)
1462 if(!LookupSource(Context
, sources
[i
]))
1464 alSetError(Context
, AL_INVALID_NAME
);
1469 LockContext(Context
);
1470 for(i
= 0;i
< n
;i
++)
1472 Source
= LookupSource(Context
, sources
[i
]);
1473 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
1474 else SetSourceState(Source
, Context
, AL_PAUSED
);
1476 UnlockContext(Context
);
1479 ALCcontext_DecRef(Context
);
1482 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
1484 alSourceStopv(1, &source
);
1487 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1489 ALCcontext
*Context
;
1493 Context
= GetContextRef();
1494 if(!Context
) return;
1498 alSetError(Context
, AL_INVALID_VALUE
);
1501 if(n
> 0 && !sources
)
1503 alSetError(Context
, AL_INVALID_VALUE
);
1507 // Check all the Sources are valid
1508 for(i
= 0;i
< n
;i
++)
1510 if(!LookupSource(Context
, sources
[i
]))
1512 alSetError(Context
, AL_INVALID_NAME
);
1517 LockContext(Context
);
1518 for(i
= 0;i
< n
;i
++)
1520 Source
= LookupSource(Context
, sources
[i
]);
1521 Source
->new_state
= AL_NONE
;
1522 SetSourceState(Source
, Context
, AL_STOPPED
);
1524 UnlockContext(Context
);
1527 ALCcontext_DecRef(Context
);
1530 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
1532 alSourceRewindv(1, &source
);
1535 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1537 ALCcontext
*Context
;
1541 Context
= GetContextRef();
1542 if(!Context
) return;
1546 alSetError(Context
, AL_INVALID_VALUE
);
1549 if(n
> 0 && !sources
)
1551 alSetError(Context
, AL_INVALID_VALUE
);
1555 // Check all the Sources are valid
1556 for(i
= 0;i
< n
;i
++)
1558 if(!LookupSource(Context
, sources
[i
]))
1560 alSetError(Context
, AL_INVALID_NAME
);
1565 LockContext(Context
);
1566 for(i
= 0;i
< n
;i
++)
1568 Source
= LookupSource(Context
, sources
[i
]);
1569 Source
->new_state
= AL_NONE
;
1570 SetSourceState(Source
, Context
, AL_INITIAL
);
1572 UnlockContext(Context
);
1575 ALCcontext_DecRef(Context
);
1579 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei n
, const ALuint
*buffers
)
1581 ALCcontext
*Context
;
1585 ALbufferlistitem
*BufferListStart
= NULL
;
1586 ALbufferlistitem
*BufferList
;
1587 ALbuffer
*BufferFmt
;
1592 Context
= GetContextRef();
1593 if(!Context
) return;
1597 alSetError(Context
, AL_INVALID_VALUE
);
1601 // Check that all buffers are valid or zero and that the source is valid
1603 // Check that this is a valid source
1604 if((Source
=LookupSource(Context
, source
)) == NULL
)
1606 alSetError(Context
, AL_INVALID_NAME
);
1610 LockContext(Context
);
1611 // Check that this is not a STATIC Source
1612 if(Source
->lSourceType
== AL_STATIC
)
1614 UnlockContext(Context
);
1615 // Invalid Source Type (can't queue on a Static Source)
1616 alSetError(Context
, AL_INVALID_OPERATION
);
1620 device
= Context
->Device
;
1624 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1625 BufferList
= Source
->queue
;
1628 if(BufferList
->buffer
)
1630 BufferFmt
= BufferList
->buffer
;
1633 BufferList
= BufferList
->next
;
1636 for(i
= 0;i
< n
;i
++)
1638 ALbuffer
*buffer
= NULL
;
1639 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
1641 UnlockContext(Context
);
1642 alSetError(Context
, AL_INVALID_NAME
);
1646 if(!BufferListStart
)
1648 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
1649 BufferListStart
->buffer
= buffer
;
1650 BufferListStart
->next
= NULL
;
1651 BufferListStart
->prev
= NULL
;
1652 BufferList
= BufferListStart
;
1656 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1657 BufferList
->next
->buffer
= buffer
;
1658 BufferList
->next
->next
= NULL
;
1659 BufferList
->next
->prev
= BufferList
;
1660 BufferList
= BufferList
->next
;
1662 if(!buffer
) continue;
1664 // Increment reference counter for buffer
1665 IncrementRef(&buffer
->ref
);
1666 ReadLock(&buffer
->lock
);
1667 if(BufferFmt
== NULL
)
1671 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
1672 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
1673 if(buffer
->FmtChannels
== FmtMono
)
1674 Source
->Update
= CalcSourceParams
;
1676 Source
->Update
= CalcNonAttnSourceParams
;
1678 Source
->NeedsUpdate
= AL_TRUE
;
1680 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
1681 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
1682 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
1684 ReadUnlock(&buffer
->lock
);
1685 UnlockContext(Context
);
1686 alSetError(Context
, AL_INVALID_OPERATION
);
1689 ReadUnlock(&buffer
->lock
);
1692 // Change Source Type
1693 Source
->lSourceType
= AL_STREAMING
;
1695 if(Source
->queue
== NULL
)
1696 Source
->queue
= BufferListStart
;
1699 // Find end of queue
1700 BufferList
= Source
->queue
;
1701 while(BufferList
->next
!= NULL
)
1702 BufferList
= BufferList
->next
;
1704 BufferListStart
->prev
= BufferList
;
1705 BufferList
->next
= BufferListStart
;
1708 // Update number of buffers in queue
1709 Source
->BuffersInQueue
+= n
;
1711 UnlockContext(Context
);
1712 ALCcontext_DecRef(Context
);
1716 while(BufferListStart
)
1718 BufferList
= BufferListStart
;
1719 BufferListStart
= BufferList
->next
;
1721 if(BufferList
->buffer
)
1722 DecrementRef(&BufferList
->buffer
->ref
);
1725 ALCcontext_DecRef(Context
);
1729 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1730 // an array of buffer IDs that are to be filled with the names of the buffers removed
1731 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1733 ALCcontext
*Context
;
1736 ALbufferlistitem
*BufferList
;
1741 Context
= GetContextRef();
1742 if(!Context
) return;
1746 alSetError(Context
, AL_INVALID_VALUE
);
1750 if((Source
=LookupSource(Context
, source
)) == NULL
)
1752 alSetError(Context
, AL_INVALID_NAME
);
1756 LockContext(Context
);
1757 if(Source
->bLooping
|| Source
->lSourceType
!= AL_STREAMING
||
1758 (ALuint
)n
> Source
->BuffersPlayed
)
1760 UnlockContext(Context
);
1761 // Some buffers can't be unqueue because they have not been processed
1762 alSetError(Context
, AL_INVALID_VALUE
);
1766 for(i
= 0;i
< n
;i
++)
1768 BufferList
= Source
->queue
;
1769 Source
->queue
= BufferList
->next
;
1770 Source
->BuffersInQueue
--;
1771 Source
->BuffersPlayed
--;
1773 if(BufferList
->buffer
)
1775 // Record name of buffer
1776 buffers
[i
] = BufferList
->buffer
->buffer
;
1777 // Decrement buffer reference counter
1778 DecrementRef(&BufferList
->buffer
->ref
);
1783 // Release memory for buffer list item
1787 Source
->queue
->prev
= NULL
;
1788 UnlockContext(Context
);
1791 ALCcontext_DecRef(Context
);
1795 static ALvoid
InitSourceParams(ALsource
*Source
)
1799 Source
->flInnerAngle
= 360.0f
;
1800 Source
->flOuterAngle
= 360.0f
;
1801 Source
->flPitch
= 1.0f
;
1802 Source
->vPosition
[0] = 0.0f
;
1803 Source
->vPosition
[1] = 0.0f
;
1804 Source
->vPosition
[2] = 0.0f
;
1805 Source
->vOrientation
[0] = 0.0f
;
1806 Source
->vOrientation
[1] = 0.0f
;
1807 Source
->vOrientation
[2] = 0.0f
;
1808 Source
->vVelocity
[0] = 0.0f
;
1809 Source
->vVelocity
[1] = 0.0f
;
1810 Source
->vVelocity
[2] = 0.0f
;
1811 Source
->flRefDistance
= 1.0f
;
1812 Source
->flMaxDistance
= FLT_MAX
;
1813 Source
->flRollOffFactor
= 1.0f
;
1814 Source
->bLooping
= AL_FALSE
;
1815 Source
->flGain
= 1.0f
;
1816 Source
->flMinGain
= 0.0f
;
1817 Source
->flMaxGain
= 1.0f
;
1818 Source
->flOuterGain
= 0.0f
;
1819 Source
->OuterGainHF
= 1.0f
;
1821 Source
->DryGainHFAuto
= AL_TRUE
;
1822 Source
->WetGainAuto
= AL_TRUE
;
1823 Source
->WetGainHFAuto
= AL_TRUE
;
1824 Source
->AirAbsorptionFactor
= 0.0f
;
1825 Source
->RoomRolloffFactor
= 0.0f
;
1826 Source
->DopplerFactor
= 1.0f
;
1827 Source
->VirtualChannels
= AL_TRUE
;
1829 Source
->DistanceModel
= AL_INVERSE_DISTANCE_CLAMPED
;
1831 Source
->Resampler
= DefaultResampler
;
1833 Source
->state
= AL_INITIAL
;
1834 Source
->new_state
= AL_NONE
;
1835 Source
->lSourceType
= AL_UNDETERMINED
;
1836 Source
->lOffset
= -1;
1838 Source
->DirectGain
= 1.0f
;
1839 Source
->DirectGainHF
= 1.0f
;
1840 for(i
= 0;i
< MAX_SENDS
;i
++)
1842 Source
->Send
[i
].WetGain
= 1.0f
;
1843 Source
->Send
[i
].WetGainHF
= 1.0f
;
1846 Source
->NeedsUpdate
= AL_TRUE
;
1848 Source
->HrtfMoving
= AL_FALSE
;
1849 Source
->HrtfCounter
= 0;
1856 * Sets the source's new play state given its current state
1858 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
1860 if(state
== AL_PLAYING
)
1862 ALbufferlistitem
*BufferList
;
1865 /* Check that there is a queue containing at least one non-null, non zero length AL Buffer */
1866 BufferList
= Source
->queue
;
1869 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
1871 BufferList
= BufferList
->next
;
1874 if(Source
->state
!= AL_PLAYING
)
1876 for(j
= 0;j
< MAXCHANNELS
;j
++)
1878 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
1879 Source
->HrtfHistory
[j
][k
] = 0.0f
;
1880 for(k
= 0;k
< HRIR_LENGTH
;k
++)
1882 Source
->HrtfValues
[j
][k
][0] = 0.0f
;
1883 Source
->HrtfValues
[j
][k
][1] = 0.0f
;
1888 if(Source
->state
!= AL_PAUSED
)
1890 Source
->state
= AL_PLAYING
;
1891 Source
->position
= 0;
1892 Source
->position_fraction
= 0;
1893 Source
->BuffersPlayed
= 0;
1896 Source
->state
= AL_PLAYING
;
1898 // Check if an Offset has been set
1899 if(Source
->lOffset
!= -1)
1900 ApplyOffset(Source
);
1902 /* If there's nothing to play, or device is disconnected, go right to
1904 if(!BufferList
|| !Context
->Device
->Connected
)
1906 SetSourceState(Source
, Context
, AL_STOPPED
);
1910 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
1912 if(Context
->ActiveSources
[j
] == Source
)
1915 if(j
== Context
->ActiveSourceCount
)
1916 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
1918 else if(state
== AL_PAUSED
)
1920 if(Source
->state
== AL_PLAYING
)
1922 Source
->state
= AL_PAUSED
;
1923 Source
->HrtfMoving
= AL_FALSE
;
1924 Source
->HrtfCounter
= 0;
1927 else if(state
== AL_STOPPED
)
1929 if(Source
->state
!= AL_INITIAL
)
1931 Source
->state
= AL_STOPPED
;
1932 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1933 Source
->HrtfMoving
= AL_FALSE
;
1934 Source
->HrtfCounter
= 0;
1936 Source
->lOffset
= -1;
1938 else if(state
== AL_INITIAL
)
1940 if(Source
->state
!= AL_INITIAL
)
1942 Source
->state
= AL_INITIAL
;
1943 Source
->position
= 0;
1944 Source
->position_fraction
= 0;
1945 Source
->BuffersPlayed
= 0;
1946 Source
->HrtfMoving
= AL_FALSE
;
1947 Source
->HrtfCounter
= 0;
1949 Source
->lOffset
= -1;
1956 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1957 The offset is relative to the start of the queue (not the start of the current buffer)
1959 static ALvoid
GetSourceOffset(ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
1961 const ALbufferlistitem
*BufferList
;
1962 const ALbuffer
*Buffer
= NULL
;
1963 ALuint BufferFreq
= 0;
1964 ALuint readPos
, writePos
;
1965 ALuint totalBufferLen
;
1968 // Find the first non-NULL Buffer in the Queue
1969 BufferList
= Source
->queue
;
1972 if(BufferList
->buffer
)
1974 Buffer
= BufferList
->buffer
;
1975 BufferFreq
= Buffer
->Frequency
;
1978 BufferList
= BufferList
->next
;
1981 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
1988 // Get Current SamplesPlayed (NOTE : This is the offset into the *current* buffer)
1989 readPos
= Source
->position
;
1990 // Add length of any processed buffers in the queue
1992 BufferList
= Source
->queue
;
1993 for(i
= 0;BufferList
;i
++)
1995 if(BufferList
->buffer
)
1997 if(i
< Source
->BuffersPlayed
)
1998 readPos
+= BufferList
->buffer
->SampleLen
;
1999 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
2001 BufferList
= BufferList
->next
;
2003 if(Source
->state
== AL_PLAYING
)
2004 writePos
= readPos
+ (ALuint
)(updateLen
*BufferFreq
);
2008 if(Source
->bLooping
)
2010 readPos
%= totalBufferLen
;
2011 writePos
%= totalBufferLen
;
2015 // Wrap positions back to 0
2016 if(readPos
>= totalBufferLen
)
2018 if(writePos
>= totalBufferLen
)
2025 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2026 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2028 case AL_SAMPLE_OFFSET
:
2029 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2030 offset
[0] = (ALdouble
)readPos
;
2031 offset
[1] = (ALdouble
)writePos
;
2033 case AL_BYTE_OFFSET
:
2034 case AL_BYTE_RW_OFFSETS_SOFT
:
2035 // Take into account the original format of the Buffer
2036 if(Buffer
->OriginalType
== UserFmtIMA4
)
2038 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
2039 ALuint FrameBlockSize
= 65;
2041 // Round down to nearest ADPCM block
2042 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2043 if(Source
->state
!= AL_PLAYING
)
2044 offset
[1] = offset
[0];
2047 // Round up to nearest ADPCM block
2048 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2049 FrameBlockSize
* BlockSize
);
2054 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2055 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2056 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2066 Apply a playback offset to the Source. This function will update the queue (to correctly
2067 mark buffers as 'pending' or 'processed' depending upon the new offset.
2069 ALboolean
ApplyOffset(ALsource
*Source
)
2071 const ALbufferlistitem
*BufferList
;
2072 const ALbuffer
*Buffer
;
2073 ALint bufferLen
, totalBufferLen
;
2074 ALint buffersPlayed
;
2077 // Get true byte offset
2078 offset
= GetSampleOffset(Source
);
2080 // If the offset is invalid, don't apply it
2084 // Sort out the queue (pending and processed states)
2085 BufferList
= Source
->queue
;
2091 Buffer
= BufferList
->buffer
;
2092 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2094 if(bufferLen
<= offset
-totalBufferLen
)
2096 // Offset is past this buffer so increment BuffersPlayed
2099 else if(totalBufferLen
<= offset
)
2101 // Offset is within this buffer
2102 Source
->BuffersPlayed
= buffersPlayed
;
2104 // SW Mixer Positions are in Samples
2105 Source
->position
= offset
- totalBufferLen
;
2109 // Increment the TotalBufferSize
2110 totalBufferLen
+= bufferLen
;
2112 // Move on to next buffer in the Queue
2113 BufferList
= BufferList
->next
;
2115 // Offset is out of range of the buffer queue
2123 Returns the sample offset into the Source's queue (from the Sample, Byte or Millisecond offset
2124 supplied by the application). This takes into account the fact that the buffer format may have
2127 static ALint
GetSampleOffset(ALsource
*Source
)
2129 const ALbuffer
*Buffer
= NULL
;
2130 const ALbufferlistitem
*BufferList
;
2133 // Find the first non-NULL Buffer in the Queue
2134 BufferList
= Source
->queue
;
2137 if(BufferList
->buffer
)
2139 Buffer
= BufferList
->buffer
;
2142 BufferList
= BufferList
->next
;
2147 Source
->lOffset
= -1;
2151 // Determine the ByteOffset (and ensure it is block aligned)
2152 switch(Source
->lOffsetType
)
2154 case AL_BYTE_OFFSET
:
2155 // Take into consideration the original format
2156 Offset
= Source
->lOffset
;
2157 if(Buffer
->OriginalType
== UserFmtIMA4
)
2159 // Round down to nearest ADPCM block
2160 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2161 // Multiply by compression rate (65 sample frames per block)
2165 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2168 case AL_SAMPLE_OFFSET
:
2169 Offset
= Source
->lOffset
;
2173 // Note - lOffset is internally stored as Milliseconds
2174 Offset
= (ALint
)(Source
->lOffset
/ 1000.0 * Buffer
->Frequency
);
2178 Source
->lOffset
= -1;
2184 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2188 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2190 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2191 Context
->SourceMap
.array
[pos
].value
= NULL
;
2193 // For each buffer in the source's queue, decrement its reference counter and remove it
2194 while(temp
->queue
!= NULL
)
2196 ALbufferlistitem
*BufferList
= temp
->queue
;
2197 temp
->queue
= BufferList
->next
;
2199 if(BufferList
->buffer
!= NULL
)
2200 DecrementRef(&BufferList
->buffer
->ref
);
2204 for(j
= 0;j
< MAX_SENDS
;++j
)
2206 if(temp
->Send
[j
].Slot
)
2207 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2208 temp
->Send
[j
].Slot
= NULL
;
2211 // Release source structure
2212 FreeThunkEntry(temp
->source
);
2213 memset(temp
, 0, sizeof(ALsource
));