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 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
)
58 Context
= GetContextRef();
61 if(n
< 0 || IsBadWritePtr((void*)sources
, n
* sizeof(ALuint
)))
62 alSetError(Context
, AL_INVALID_VALUE
);
68 // Add additional sources to the list
72 ALsource
*source
= calloc(1, sizeof(ALsource
));
75 alSetError(Context
, AL_OUT_OF_MEMORY
);
76 alDeleteSources(i
, sources
);
79 InitSourceParams(source
);
81 err
= NewThunkEntry(&source
->source
);
82 if(err
== AL_NO_ERROR
)
83 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->source
, source
);
84 if(err
!= AL_NO_ERROR
)
86 FreeThunkEntry(source
->source
);
87 memset(source
, 0, sizeof(ALsource
));
90 alSetError(Context
, err
);
91 alDeleteSources(i
, sources
);
95 sources
[i
++] = source
->source
;
99 ALCcontext_DecRef(Context
);
103 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
108 ALbufferlistitem
*BufferList
;
110 Context
= GetContextRef();
114 alSetError(Context
, AL_INVALID_VALUE
);
117 // Check that all Sources are valid (and can therefore be deleted)
120 if(LookupSource(Context
, sources
[i
]) == NULL
)
122 alSetError(Context
, AL_INVALID_NAME
);
128 // All Sources are valid, and can be deleted
131 ALsource
**srclist
, **srclistend
;
133 // Remove Source from list of Sources
134 if((Source
=RemoveSource(Context
, sources
[i
])) == NULL
)
137 FreeThunkEntry(Source
->source
);
139 LockContext(Context
);
140 srclist
= Context
->ActiveSources
;
141 srclistend
= srclist
+ Context
->ActiveSourceCount
;
142 while(srclist
!= srclistend
)
144 if(*srclist
== Source
)
146 Context
->ActiveSourceCount
--;
147 *srclist
= *(--srclistend
);
152 UnlockContext(Context
);
154 // For each buffer in the source's queue...
155 while(Source
->queue
!= NULL
)
157 BufferList
= Source
->queue
;
158 Source
->queue
= BufferList
->next
;
160 if(BufferList
->buffer
!= NULL
)
161 DecrementRef(&BufferList
->buffer
->ref
);
165 for(j
= 0;j
< MAX_SENDS
;++j
)
167 if(Source
->Send
[j
].Slot
)
168 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
169 Source
->Send
[j
].Slot
= NULL
;
172 memset(Source
,0,sizeof(ALsource
));
177 ALCcontext_DecRef(Context
);
181 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
186 Context
= GetContextRef();
187 if(!Context
) return AL_FALSE
;
189 result
= (LookupSource(Context
, source
) ? AL_TRUE
: AL_FALSE
);
191 ALCcontext_DecRef(Context
);
197 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
199 ALCcontext
*pContext
;
202 pContext
= GetContextRef();
203 if(!pContext
) return;
205 if((Source
=LookupSource(pContext
, source
)) != NULL
)
212 Source
->flPitch
= flValue
;
213 Source
->NeedsUpdate
= AL_TRUE
;
216 alSetError(pContext
, AL_INVALID_VALUE
);
219 case AL_CONE_INNER_ANGLE
:
220 if(flValue
>= 0.0f
&& flValue
<= 360.0f
)
222 Source
->flInnerAngle
= flValue
;
223 Source
->NeedsUpdate
= AL_TRUE
;
226 alSetError(pContext
, AL_INVALID_VALUE
);
229 case AL_CONE_OUTER_ANGLE
:
230 if(flValue
>= 0.0f
&& flValue
<= 360.0f
)
232 Source
->flOuterAngle
= flValue
;
233 Source
->NeedsUpdate
= AL_TRUE
;
236 alSetError(pContext
, AL_INVALID_VALUE
);
242 Source
->flGain
= flValue
;
243 Source
->NeedsUpdate
= AL_TRUE
;
246 alSetError(pContext
, AL_INVALID_VALUE
);
249 case AL_MAX_DISTANCE
:
252 Source
->flMaxDistance
= flValue
;
253 Source
->NeedsUpdate
= AL_TRUE
;
256 alSetError(pContext
, AL_INVALID_VALUE
);
259 case AL_ROLLOFF_FACTOR
:
262 Source
->flRollOffFactor
= flValue
;
263 Source
->NeedsUpdate
= AL_TRUE
;
266 alSetError(pContext
, AL_INVALID_VALUE
);
269 case AL_REFERENCE_DISTANCE
:
272 Source
->flRefDistance
= flValue
;
273 Source
->NeedsUpdate
= AL_TRUE
;
276 alSetError(pContext
, AL_INVALID_VALUE
);
280 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
282 Source
->flMinGain
= flValue
;
283 Source
->NeedsUpdate
= AL_TRUE
;
286 alSetError(pContext
, AL_INVALID_VALUE
);
290 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
292 Source
->flMaxGain
= flValue
;
293 Source
->NeedsUpdate
= AL_TRUE
;
296 alSetError(pContext
, AL_INVALID_VALUE
);
299 case AL_CONE_OUTER_GAIN
:
300 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
302 Source
->flOuterGain
= flValue
;
303 Source
->NeedsUpdate
= AL_TRUE
;
306 alSetError(pContext
, AL_INVALID_VALUE
);
309 case AL_CONE_OUTER_GAINHF
:
310 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
312 Source
->OuterGainHF
= flValue
;
313 Source
->NeedsUpdate
= AL_TRUE
;
316 alSetError(pContext
, AL_INVALID_VALUE
);
319 case AL_AIR_ABSORPTION_FACTOR
:
320 if(flValue
>= 0.0f
&& flValue
<= 10.0f
)
322 Source
->AirAbsorptionFactor
= flValue
;
323 Source
->NeedsUpdate
= AL_TRUE
;
326 alSetError(pContext
, AL_INVALID_VALUE
);
329 case AL_ROOM_ROLLOFF_FACTOR
:
330 if(flValue
>= 0.0f
&& flValue
<= 10.0f
)
332 Source
->RoomRolloffFactor
= flValue
;
333 Source
->NeedsUpdate
= AL_TRUE
;
336 alSetError(pContext
, AL_INVALID_VALUE
);
339 case AL_DOPPLER_FACTOR
:
340 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
342 Source
->DopplerFactor
= flValue
;
343 Source
->NeedsUpdate
= AL_TRUE
;
346 alSetError(pContext
, AL_INVALID_VALUE
);
350 case AL_SAMPLE_OFFSET
:
354 LockContext(pContext
);
355 Source
->lOffsetType
= eParam
;
357 // Store Offset (convert Seconds into Milliseconds)
358 if(eParam
== AL_SEC_OFFSET
)
359 Source
->lOffset
= (ALint
)(flValue
* 1000.0f
);
361 Source
->lOffset
= (ALint
)flValue
;
363 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
364 !pContext
->DeferUpdates
)
366 if(ApplyOffset(Source
) == AL_FALSE
)
367 alSetError(pContext
, AL_INVALID_VALUE
);
369 UnlockContext(pContext
);
372 alSetError(pContext
, AL_INVALID_VALUE
);
376 alSetError(pContext
, AL_INVALID_ENUM
);
382 // Invalid Source Name
383 alSetError(pContext
, AL_INVALID_NAME
);
386 ALCcontext_DecRef(pContext
);
390 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
392 ALCcontext
*pContext
;
395 pContext
= GetContextRef();
396 if(!pContext
) return;
398 if((Source
=LookupSource(pContext
, source
)) != NULL
)
403 if(isfinite(flValue1
) && isfinite(flValue2
) && isfinite(flValue3
))
405 LockContext(pContext
);
406 Source
->vPosition
[0] = flValue1
;
407 Source
->vPosition
[1] = flValue2
;
408 Source
->vPosition
[2] = flValue3
;
409 UnlockContext(pContext
);
410 Source
->NeedsUpdate
= AL_TRUE
;
413 alSetError(pContext
, AL_INVALID_VALUE
);
417 if(isfinite(flValue1
) && isfinite(flValue2
) && isfinite(flValue3
))
419 LockContext(pContext
);
420 Source
->vVelocity
[0] = flValue1
;
421 Source
->vVelocity
[1] = flValue2
;
422 Source
->vVelocity
[2] = flValue3
;
423 UnlockContext(pContext
);
424 Source
->NeedsUpdate
= AL_TRUE
;
427 alSetError(pContext
, AL_INVALID_VALUE
);
431 if(isfinite(flValue1
) && isfinite(flValue2
) && isfinite(flValue3
))
433 LockContext(pContext
);
434 Source
->vOrientation
[0] = flValue1
;
435 Source
->vOrientation
[1] = flValue2
;
436 Source
->vOrientation
[2] = flValue3
;
437 UnlockContext(pContext
);
438 Source
->NeedsUpdate
= AL_TRUE
;
441 alSetError(pContext
, AL_INVALID_VALUE
);
445 alSetError(pContext
, AL_INVALID_ENUM
);
450 alSetError(pContext
, AL_INVALID_NAME
);
452 ALCcontext_DecRef(pContext
);
456 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
458 ALCcontext
*pContext
;
465 case AL_CONE_INNER_ANGLE
:
466 case AL_CONE_OUTER_ANGLE
:
468 case AL_MAX_DISTANCE
:
469 case AL_ROLLOFF_FACTOR
:
470 case AL_REFERENCE_DISTANCE
:
473 case AL_CONE_OUTER_GAIN
:
474 case AL_CONE_OUTER_GAINHF
:
476 case AL_SAMPLE_OFFSET
:
478 case AL_AIR_ABSORPTION_FACTOR
:
479 case AL_ROOM_ROLLOFF_FACTOR
:
480 alSourcef(source
, eParam
, pflValues
[0]);
486 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
491 pContext
= GetContextRef();
492 if(!pContext
) return;
496 if(LookupSource(pContext
, source
) != NULL
)
501 alSetError(pContext
, AL_INVALID_ENUM
);
506 alSetError(pContext
, AL_INVALID_NAME
);
509 alSetError(pContext
, AL_INVALID_VALUE
);
511 ALCcontext_DecRef(pContext
);
515 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
517 ALCcontext
*pContext
;
519 ALbufferlistitem
*BufferListItem
;
523 case AL_MAX_DISTANCE
:
524 case AL_ROLLOFF_FACTOR
:
525 case AL_CONE_INNER_ANGLE
:
526 case AL_CONE_OUTER_ANGLE
:
527 case AL_REFERENCE_DISTANCE
:
528 alSourcef(source
, eParam
, (ALfloat
)lValue
);
532 pContext
= GetContextRef();
533 if(!pContext
) return;
535 if((Source
=LookupSource(pContext
, source
)) != NULL
)
537 ALCdevice
*device
= pContext
->Device
;
541 case AL_SOURCE_RELATIVE
:
542 if(lValue
== AL_FALSE
|| lValue
== AL_TRUE
)
544 Source
->bHeadRelative
= (ALboolean
)lValue
;
545 Source
->NeedsUpdate
= AL_TRUE
;
548 alSetError(pContext
, AL_INVALID_VALUE
);
552 if(lValue
== AL_FALSE
|| lValue
== AL_TRUE
)
553 Source
->bLooping
= (ALboolean
)lValue
;
555 alSetError(pContext
, AL_INVALID_VALUE
);
559 LockContext(pContext
);
560 if(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
)
562 ALbufferlistitem
*oldlist
;
563 ALbuffer
*buffer
= NULL
;
565 if(lValue
== 0 || (buffer
=LookupBuffer(device
, lValue
)) != NULL
)
567 Source
->BuffersInQueue
= 0;
568 Source
->BuffersPlayed
= 0;
570 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
573 // Source is now in STATIC mode
574 Source
->lSourceType
= AL_STATIC
;
576 // Add the selected buffer to the queue
577 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
578 BufferListItem
->buffer
= buffer
;
579 BufferListItem
->next
= NULL
;
580 BufferListItem
->prev
= NULL
;
581 // Increment reference counter for buffer
582 IncrementRef(&buffer
->ref
);
584 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, BufferListItem
);
585 Source
->BuffersInQueue
= 1;
587 ReadLock(&buffer
->lock
);
588 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
589 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
590 ReadUnlock(&buffer
->lock
);
591 if(buffer
->FmtChannels
== FmtMono
)
592 Source
->Update
= CalcSourceParams
;
594 Source
->Update
= CalcNonAttnSourceParams
;
595 Source
->NeedsUpdate
= AL_TRUE
;
599 // Source is now in UNDETERMINED mode
600 Source
->lSourceType
= AL_UNDETERMINED
;
601 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, NULL
);
604 // Delete all previous elements in the queue
605 while(oldlist
!= NULL
)
607 BufferListItem
= oldlist
;
608 oldlist
= BufferListItem
->next
;
610 if(BufferListItem
->buffer
)
611 DecrementRef(&BufferListItem
->buffer
->ref
);
612 free(BufferListItem
);
616 alSetError(pContext
, AL_INVALID_VALUE
);
619 alSetError(pContext
, AL_INVALID_OPERATION
);
620 UnlockContext(pContext
);
623 case AL_SOURCE_STATE
:
625 alSetError(pContext
, AL_INVALID_OPERATION
);
629 case AL_SAMPLE_OFFSET
:
633 LockContext(pContext
);
634 Source
->lOffsetType
= eParam
;
636 // Store Offset (convert Seconds into Milliseconds)
637 if(eParam
== AL_SEC_OFFSET
)
638 Source
->lOffset
= lValue
* 1000;
640 Source
->lOffset
= lValue
;
642 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
643 !pContext
->DeferUpdates
)
645 if(ApplyOffset(Source
) == AL_FALSE
)
646 alSetError(pContext
, AL_INVALID_VALUE
);
648 UnlockContext(pContext
);
651 alSetError(pContext
, AL_INVALID_VALUE
);
654 case AL_DIRECT_FILTER
: {
655 ALfilter
*filter
= NULL
;
657 if(lValue
== 0 || (filter
=LookupFilter(pContext
->Device
, lValue
)) != NULL
)
659 LockContext(pContext
);
662 Source
->DirectGain
= 1.0f
;
663 Source
->DirectGainHF
= 1.0f
;
667 Source
->DirectGain
= filter
->Gain
;
668 Source
->DirectGainHF
= filter
->GainHF
;
670 UnlockContext(pContext
);
671 Source
->NeedsUpdate
= AL_TRUE
;
674 alSetError(pContext
, AL_INVALID_VALUE
);
677 case AL_DIRECT_FILTER_GAINHF_AUTO
:
678 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
680 Source
->DryGainHFAuto
= lValue
;
681 Source
->NeedsUpdate
= AL_TRUE
;
684 alSetError(pContext
, AL_INVALID_VALUE
);
687 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
688 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
690 Source
->WetGainAuto
= lValue
;
691 Source
->NeedsUpdate
= AL_TRUE
;
694 alSetError(pContext
, AL_INVALID_VALUE
);
697 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
698 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
700 Source
->WetGainHFAuto
= lValue
;
701 Source
->NeedsUpdate
= AL_TRUE
;
704 alSetError(pContext
, AL_INVALID_VALUE
);
707 case AL_DIRECT_CHANNELS_SOFT
:
708 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
710 Source
->DirectChannels
= lValue
;
711 Source
->NeedsUpdate
= AL_TRUE
;
714 alSetError(pContext
, AL_INVALID_VALUE
);
717 case AL_DISTANCE_MODEL
:
718 if(lValue
== AL_NONE
||
719 lValue
== AL_INVERSE_DISTANCE
||
720 lValue
== AL_INVERSE_DISTANCE_CLAMPED
||
721 lValue
== AL_LINEAR_DISTANCE
||
722 lValue
== AL_LINEAR_DISTANCE_CLAMPED
||
723 lValue
== AL_EXPONENT_DISTANCE
||
724 lValue
== AL_EXPONENT_DISTANCE_CLAMPED
)
726 Source
->DistanceModel
= lValue
;
727 if(pContext
->SourceDistanceModel
)
728 Source
->NeedsUpdate
= AL_TRUE
;
731 alSetError(pContext
, AL_INVALID_VALUE
);
735 alSetError(pContext
, AL_INVALID_ENUM
);
740 alSetError(pContext
, AL_INVALID_NAME
);
742 ALCcontext_DecRef(pContext
);
746 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
748 ALCcontext
*pContext
;
756 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
760 pContext
= GetContextRef();
761 if(!pContext
) return;
763 if((Source
=LookupSource(pContext
, source
)) != NULL
)
765 ALCdevice
*device
= pContext
->Device
;
769 case AL_AUXILIARY_SEND_FILTER
: {
770 ALeffectslot
*ALEffectSlot
= NULL
;
771 ALfilter
*ALFilter
= NULL
;
773 LockContext(pContext
);
774 if((ALuint
)lValue2
< device
->NumAuxSends
&&
775 (lValue1
== 0 || (ALEffectSlot
=LookupEffectSlot(pContext
, lValue1
)) != NULL
) &&
776 (lValue3
== 0 || (ALFilter
=LookupFilter(device
, lValue3
)) != NULL
))
778 /* Release refcount on the previous slot, and add one for
780 if(ALEffectSlot
) IncrementRef(&ALEffectSlot
->ref
);
781 ALEffectSlot
= ExchangePtr((XchgPtr
*)&Source
->Send
[lValue2
].Slot
, ALEffectSlot
);
782 if(ALEffectSlot
) DecrementRef(&ALEffectSlot
->ref
);
787 Source
->Send
[lValue2
].WetGain
= 1.0f
;
788 Source
->Send
[lValue2
].WetGainHF
= 1.0f
;
792 Source
->Send
[lValue2
].WetGain
= ALFilter
->Gain
;
793 Source
->Send
[lValue2
].WetGainHF
= ALFilter
->GainHF
;
795 Source
->NeedsUpdate
= AL_TRUE
;
798 alSetError(pContext
, AL_INVALID_VALUE
);
799 UnlockContext(pContext
);
803 alSetError(pContext
, AL_INVALID_ENUM
);
808 alSetError(pContext
, AL_INVALID_NAME
);
810 ALCcontext_DecRef(pContext
);
814 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
816 ALCcontext
*pContext
;
822 case AL_SOURCE_RELATIVE
:
823 case AL_CONE_INNER_ANGLE
:
824 case AL_CONE_OUTER_ANGLE
:
827 case AL_SOURCE_STATE
:
829 case AL_SAMPLE_OFFSET
:
831 case AL_MAX_DISTANCE
:
832 case AL_ROLLOFF_FACTOR
:
833 case AL_REFERENCE_DISTANCE
:
834 case AL_DIRECT_FILTER
:
835 case AL_DIRECT_FILTER_GAINHF_AUTO
:
836 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
837 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
838 case AL_DISTANCE_MODEL
:
839 case AL_DIRECT_CHANNELS_SOFT
:
840 alSourcei(source
, eParam
, plValues
[0]);
846 case AL_AUXILIARY_SEND_FILTER
:
847 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
852 pContext
= GetContextRef();
853 if(!pContext
) return;
857 if(LookupSource(pContext
, source
) != NULL
)
862 alSetError(pContext
, AL_INVALID_ENUM
);
867 alSetError(pContext
, AL_INVALID_NAME
);
870 alSetError(pContext
, AL_INVALID_VALUE
);
872 ALCcontext_DecRef(pContext
);
876 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
878 ALCcontext
*pContext
;
883 pContext
= GetContextRef();
884 if(!pContext
) return;
888 if((Source
=LookupSource(pContext
, source
)) != NULL
)
893 *pflValue
= Source
->flPitch
;
897 *pflValue
= Source
->flGain
;
901 *pflValue
= Source
->flMinGain
;
905 *pflValue
= Source
->flMaxGain
;
908 case AL_MAX_DISTANCE
:
909 *pflValue
= Source
->flMaxDistance
;
912 case AL_ROLLOFF_FACTOR
:
913 *pflValue
= Source
->flRollOffFactor
;
916 case AL_CONE_OUTER_GAIN
:
917 *pflValue
= Source
->flOuterGain
;
920 case AL_CONE_OUTER_GAINHF
:
921 *pflValue
= Source
->OuterGainHF
;
925 case AL_SAMPLE_OFFSET
:
927 LockContext(pContext
);
928 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
929 pContext
->Device
->Frequency
;
930 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
931 UnlockContext(pContext
);
932 *pflValue
= (ALfloat
)Offsets
[0];
935 case AL_CONE_INNER_ANGLE
:
936 *pflValue
= Source
->flInnerAngle
;
939 case AL_CONE_OUTER_ANGLE
:
940 *pflValue
= Source
->flOuterAngle
;
943 case AL_REFERENCE_DISTANCE
:
944 *pflValue
= Source
->flRefDistance
;
947 case AL_AIR_ABSORPTION_FACTOR
:
948 *pflValue
= Source
->AirAbsorptionFactor
;
951 case AL_ROOM_ROLLOFF_FACTOR
:
952 *pflValue
= Source
->RoomRolloffFactor
;
955 case AL_DOPPLER_FACTOR
:
956 *pflValue
= Source
->DopplerFactor
;
960 alSetError(pContext
, AL_INVALID_ENUM
);
965 alSetError(pContext
, AL_INVALID_NAME
);
968 alSetError(pContext
, AL_INVALID_VALUE
);
970 ALCcontext_DecRef(pContext
);
974 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
976 ALCcontext
*pContext
;
979 pContext
= GetContextRef();
980 if(!pContext
) return;
982 if(pflValue1
&& pflValue2
&& pflValue3
)
984 if((Source
=LookupSource(pContext
, source
)) != NULL
)
989 LockContext(pContext
);
990 *pflValue1
= Source
->vPosition
[0];
991 *pflValue2
= Source
->vPosition
[1];
992 *pflValue3
= Source
->vPosition
[2];
993 UnlockContext(pContext
);
997 LockContext(pContext
);
998 *pflValue1
= Source
->vVelocity
[0];
999 *pflValue2
= Source
->vVelocity
[1];
1000 *pflValue3
= Source
->vVelocity
[2];
1001 UnlockContext(pContext
);
1005 LockContext(pContext
);
1006 *pflValue1
= Source
->vOrientation
[0];
1007 *pflValue2
= Source
->vOrientation
[1];
1008 *pflValue3
= Source
->vOrientation
[2];
1009 UnlockContext(pContext
);
1013 alSetError(pContext
, AL_INVALID_ENUM
);
1018 alSetError(pContext
, AL_INVALID_NAME
);
1021 alSetError(pContext
, AL_INVALID_VALUE
);
1023 ALCcontext_DecRef(pContext
);
1027 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1029 ALCcontext
*pContext
;
1031 ALdouble Offsets
[2];
1040 case AL_MAX_DISTANCE
:
1041 case AL_ROLLOFF_FACTOR
:
1042 case AL_DOPPLER_FACTOR
:
1043 case AL_CONE_OUTER_GAIN
:
1045 case AL_SAMPLE_OFFSET
:
1046 case AL_BYTE_OFFSET
:
1047 case AL_CONE_INNER_ANGLE
:
1048 case AL_CONE_OUTER_ANGLE
:
1049 case AL_REFERENCE_DISTANCE
:
1050 case AL_CONE_OUTER_GAINHF
:
1051 case AL_AIR_ABSORPTION_FACTOR
:
1052 case AL_ROOM_ROLLOFF_FACTOR
:
1053 alGetSourcef(source
, eParam
, pflValues
);
1059 alGetSource3f(source
, eParam
, pflValues
+0, pflValues
+1, pflValues
+2);
1063 pContext
= GetContextRef();
1064 if(!pContext
) return;
1068 if((Source
=LookupSource(pContext
, source
)) != NULL
)
1072 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1073 case AL_BYTE_RW_OFFSETS_SOFT
:
1074 LockContext(pContext
);
1075 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
1076 pContext
->Device
->Frequency
;
1077 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
1078 UnlockContext(pContext
);
1079 pflValues
[0] = (ALfloat
)Offsets
[0];
1080 pflValues
[1] = (ALfloat
)Offsets
[1];
1084 alSetError(pContext
, AL_INVALID_ENUM
);
1089 alSetError(pContext
, AL_INVALID_NAME
);
1092 alSetError(pContext
, AL_INVALID_VALUE
);
1094 ALCcontext_DecRef(pContext
);
1098 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1100 ALbufferlistitem
*BufferList
;
1101 ALCcontext
*pContext
;
1103 ALdouble Offsets
[2];
1106 pContext
= GetContextRef();
1107 if(!pContext
) return;
1111 if((Source
=LookupSource(pContext
, source
)) != NULL
)
1115 case AL_MAX_DISTANCE
:
1116 *plValue
= (ALint
)Source
->flMaxDistance
;
1119 case AL_ROLLOFF_FACTOR
:
1120 *plValue
= (ALint
)Source
->flRollOffFactor
;
1123 case AL_REFERENCE_DISTANCE
:
1124 *plValue
= (ALint
)Source
->flRefDistance
;
1127 case AL_SOURCE_RELATIVE
:
1128 *plValue
= Source
->bHeadRelative
;
1131 case AL_CONE_INNER_ANGLE
:
1132 *plValue
= (ALint
)Source
->flInnerAngle
;
1135 case AL_CONE_OUTER_ANGLE
:
1136 *plValue
= (ALint
)Source
->flOuterAngle
;
1140 *plValue
= Source
->bLooping
;
1144 LockContext(pContext
);
1145 BufferList
= Source
->queue
;
1146 if(Source
->lSourceType
!= AL_STATIC
)
1148 ALuint i
= Source
->BuffersPlayed
;
1151 BufferList
= BufferList
->next
;
1155 *plValue
= ((BufferList
&& BufferList
->buffer
) ?
1156 BufferList
->buffer
->buffer
: 0);
1157 UnlockContext(pContext
);
1160 case AL_SOURCE_STATE
:
1161 *plValue
= Source
->state
;
1164 case AL_BUFFERS_QUEUED
:
1165 *plValue
= Source
->BuffersInQueue
;
1168 case AL_BUFFERS_PROCESSED
:
1169 LockContext(pContext
);
1170 if(Source
->bLooping
|| Source
->lSourceType
!= AL_STREAMING
)
1172 /* Buffers on a looping source are in a perpetual state
1173 * of PENDING, so don't report any as PROCESSED */
1177 *plValue
= Source
->BuffersPlayed
;
1178 UnlockContext(pContext
);
1181 case AL_SOURCE_TYPE
:
1182 *plValue
= Source
->lSourceType
;
1186 case AL_SAMPLE_OFFSET
:
1187 case AL_BYTE_OFFSET
:
1188 LockContext(pContext
);
1189 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
1190 pContext
->Device
->Frequency
;
1191 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
1192 UnlockContext(pContext
);
1193 *plValue
= (ALint
)Offsets
[0];
1196 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1197 *plValue
= Source
->DryGainHFAuto
;
1200 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1201 *plValue
= Source
->WetGainAuto
;
1204 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1205 *plValue
= Source
->WetGainHFAuto
;
1208 case AL_DOPPLER_FACTOR
:
1209 *plValue
= (ALint
)Source
->DopplerFactor
;
1212 case AL_DIRECT_CHANNELS_SOFT
:
1213 *plValue
= Source
->DirectChannels
;
1216 case AL_DISTANCE_MODEL
:
1217 *plValue
= Source
->DistanceModel
;
1221 alSetError(pContext
, AL_INVALID_ENUM
);
1226 alSetError(pContext
, AL_INVALID_NAME
);
1229 alSetError(pContext
, AL_INVALID_VALUE
);
1231 ALCcontext_DecRef(pContext
);
1235 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1237 ALCcontext
*pContext
;
1240 pContext
= GetContextRef();
1241 if(!pContext
) return;
1243 if(plValue1
&& plValue2
&& plValue3
)
1245 if((Source
=LookupSource(pContext
, source
)) != NULL
)
1250 LockContext(pContext
);
1251 *plValue1
= (ALint
)Source
->vPosition
[0];
1252 *plValue2
= (ALint
)Source
->vPosition
[1];
1253 *plValue3
= (ALint
)Source
->vPosition
[2];
1254 UnlockContext(pContext
);
1258 LockContext(pContext
);
1259 *plValue1
= (ALint
)Source
->vVelocity
[0];
1260 *plValue2
= (ALint
)Source
->vVelocity
[1];
1261 *plValue3
= (ALint
)Source
->vVelocity
[2];
1262 UnlockContext(pContext
);
1266 LockContext(pContext
);
1267 *plValue1
= (ALint
)Source
->vOrientation
[0];
1268 *plValue2
= (ALint
)Source
->vOrientation
[1];
1269 *plValue3
= (ALint
)Source
->vOrientation
[2];
1270 UnlockContext(pContext
);
1274 alSetError(pContext
, AL_INVALID_ENUM
);
1279 alSetError(pContext
, AL_INVALID_NAME
);
1282 alSetError(pContext
, AL_INVALID_VALUE
);
1284 ALCcontext_DecRef(pContext
);
1288 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1290 ALCcontext
*pContext
;
1292 ALdouble Offsets
[2];
1297 case AL_SOURCE_RELATIVE
:
1298 case AL_CONE_INNER_ANGLE
:
1299 case AL_CONE_OUTER_ANGLE
:
1302 case AL_SOURCE_STATE
:
1303 case AL_BUFFERS_QUEUED
:
1304 case AL_BUFFERS_PROCESSED
:
1306 case AL_SAMPLE_OFFSET
:
1307 case AL_BYTE_OFFSET
:
1308 case AL_MAX_DISTANCE
:
1309 case AL_ROLLOFF_FACTOR
:
1310 case AL_DOPPLER_FACTOR
:
1311 case AL_REFERENCE_DISTANCE
:
1312 case AL_SOURCE_TYPE
:
1313 case AL_DIRECT_FILTER
:
1314 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1315 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1316 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1317 case AL_DISTANCE_MODEL
:
1318 case AL_DIRECT_CHANNELS_SOFT
:
1319 alGetSourcei(source
, eParam
, plValues
);
1325 alGetSource3i(source
, eParam
, plValues
+0, plValues
+1, plValues
+2);
1329 pContext
= GetContextRef();
1330 if(!pContext
) return;
1334 if((Source
=LookupSource(pContext
, source
)) != NULL
)
1338 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1339 case AL_BYTE_RW_OFFSETS_SOFT
:
1340 LockContext(pContext
);
1341 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
1342 pContext
->Device
->Frequency
;
1343 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
1344 UnlockContext(pContext
);
1345 plValues
[0] = (ALint
)Offsets
[0];
1346 plValues
[1] = (ALint
)Offsets
[1];
1350 alSetError(pContext
, AL_INVALID_ENUM
);
1355 alSetError(pContext
, AL_INVALID_NAME
);
1358 alSetError(pContext
, AL_INVALID_VALUE
);
1360 ALCcontext_DecRef(pContext
);
1364 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
1366 alSourcePlayv(1, &source
);
1369 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
1371 ALCcontext
*Context
;
1375 Context
= GetContextRef();
1376 if(!Context
) return;
1380 alSetError(Context
, AL_INVALID_VALUE
);
1383 if(n
> 0 && !sources
)
1385 alSetError(Context
, AL_INVALID_VALUE
);
1389 // Check that all the Sources are valid
1390 for(i
= 0;i
< n
;i
++)
1392 if(!LookupSource(Context
, sources
[i
]))
1394 alSetError(Context
, AL_INVALID_NAME
);
1399 LockContext(Context
);
1400 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
1405 newcount
= Context
->MaxActiveSources
<< 1;
1407 temp
= realloc(Context
->ActiveSources
,
1408 sizeof(*Context
->ActiveSources
) * newcount
);
1411 UnlockContext(Context
);
1412 alSetError(Context
, AL_OUT_OF_MEMORY
);
1416 Context
->ActiveSources
= temp
;
1417 Context
->MaxActiveSources
= newcount
;
1420 for(i
= 0;i
< n
;i
++)
1422 Source
= LookupSource(Context
, sources
[i
]);
1423 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
1424 else SetSourceState(Source
, Context
, AL_PLAYING
);
1426 UnlockContext(Context
);
1429 ALCcontext_DecRef(Context
);
1432 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
1434 alSourcePausev(1, &source
);
1437 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1439 ALCcontext
*Context
;
1443 Context
= GetContextRef();
1444 if(!Context
) return;
1448 alSetError(Context
, AL_INVALID_VALUE
);
1451 if(n
> 0 && !sources
)
1453 alSetError(Context
, AL_INVALID_VALUE
);
1457 // Check all the Sources are valid
1458 for(i
= 0;i
< n
;i
++)
1460 if(!LookupSource(Context
, sources
[i
]))
1462 alSetError(Context
, AL_INVALID_NAME
);
1467 LockContext(Context
);
1468 for(i
= 0;i
< n
;i
++)
1470 Source
= LookupSource(Context
, sources
[i
]);
1471 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
1472 else SetSourceState(Source
, Context
, AL_PAUSED
);
1474 UnlockContext(Context
);
1477 ALCcontext_DecRef(Context
);
1480 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
1482 alSourceStopv(1, &source
);
1485 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1487 ALCcontext
*Context
;
1491 Context
= GetContextRef();
1492 if(!Context
) return;
1496 alSetError(Context
, AL_INVALID_VALUE
);
1499 if(n
> 0 && !sources
)
1501 alSetError(Context
, AL_INVALID_VALUE
);
1505 // Check all the Sources are valid
1506 for(i
= 0;i
< n
;i
++)
1508 if(!LookupSource(Context
, sources
[i
]))
1510 alSetError(Context
, AL_INVALID_NAME
);
1515 LockContext(Context
);
1516 for(i
= 0;i
< n
;i
++)
1518 Source
= LookupSource(Context
, sources
[i
]);
1519 Source
->new_state
= AL_NONE
;
1520 SetSourceState(Source
, Context
, AL_STOPPED
);
1522 UnlockContext(Context
);
1525 ALCcontext_DecRef(Context
);
1528 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
1530 alSourceRewindv(1, &source
);
1533 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1535 ALCcontext
*Context
;
1539 Context
= GetContextRef();
1540 if(!Context
) return;
1544 alSetError(Context
, AL_INVALID_VALUE
);
1547 if(n
> 0 && !sources
)
1549 alSetError(Context
, AL_INVALID_VALUE
);
1553 // Check all the Sources are valid
1554 for(i
= 0;i
< n
;i
++)
1556 if(!LookupSource(Context
, sources
[i
]))
1558 alSetError(Context
, AL_INVALID_NAME
);
1563 LockContext(Context
);
1564 for(i
= 0;i
< n
;i
++)
1566 Source
= LookupSource(Context
, sources
[i
]);
1567 Source
->new_state
= AL_NONE
;
1568 SetSourceState(Source
, Context
, AL_INITIAL
);
1570 UnlockContext(Context
);
1573 ALCcontext_DecRef(Context
);
1577 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei n
, const ALuint
*buffers
)
1579 ALCcontext
*Context
;
1583 ALbufferlistitem
*BufferListStart
= NULL
;
1584 ALbufferlistitem
*BufferList
;
1585 ALbuffer
*BufferFmt
;
1590 Context
= GetContextRef();
1591 if(!Context
) return;
1595 alSetError(Context
, AL_INVALID_VALUE
);
1599 // Check that all buffers are valid or zero and that the source is valid
1601 // Check that this is a valid source
1602 if((Source
=LookupSource(Context
, source
)) == NULL
)
1604 alSetError(Context
, AL_INVALID_NAME
);
1608 LockContext(Context
);
1609 // Check that this is not a STATIC Source
1610 if(Source
->lSourceType
== AL_STATIC
)
1612 UnlockContext(Context
);
1613 // Invalid Source Type (can't queue on a Static Source)
1614 alSetError(Context
, AL_INVALID_OPERATION
);
1618 device
= Context
->Device
;
1622 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1623 BufferList
= Source
->queue
;
1626 if(BufferList
->buffer
)
1628 BufferFmt
= BufferList
->buffer
;
1631 BufferList
= BufferList
->next
;
1634 for(i
= 0;i
< n
;i
++)
1636 ALbuffer
*buffer
= NULL
;
1637 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
1639 UnlockContext(Context
);
1640 alSetError(Context
, AL_INVALID_NAME
);
1644 if(!BufferListStart
)
1646 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
1647 BufferListStart
->buffer
= buffer
;
1648 BufferListStart
->next
= NULL
;
1649 BufferListStart
->prev
= NULL
;
1650 BufferList
= BufferListStart
;
1654 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1655 BufferList
->next
->buffer
= buffer
;
1656 BufferList
->next
->next
= NULL
;
1657 BufferList
->next
->prev
= BufferList
;
1658 BufferList
= BufferList
->next
;
1660 if(!buffer
) continue;
1662 // Increment reference counter for buffer
1663 IncrementRef(&buffer
->ref
);
1664 ReadLock(&buffer
->lock
);
1665 if(BufferFmt
== NULL
)
1669 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
1670 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
1671 if(buffer
->FmtChannels
== FmtMono
)
1672 Source
->Update
= CalcSourceParams
;
1674 Source
->Update
= CalcNonAttnSourceParams
;
1676 Source
->NeedsUpdate
= AL_TRUE
;
1678 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
1679 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
1680 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
1682 ReadUnlock(&buffer
->lock
);
1683 UnlockContext(Context
);
1684 alSetError(Context
, AL_INVALID_OPERATION
);
1687 ReadUnlock(&buffer
->lock
);
1690 // Change Source Type
1691 Source
->lSourceType
= AL_STREAMING
;
1693 if(Source
->queue
== NULL
)
1694 Source
->queue
= BufferListStart
;
1697 // Find end of queue
1698 BufferList
= Source
->queue
;
1699 while(BufferList
->next
!= NULL
)
1700 BufferList
= BufferList
->next
;
1702 BufferListStart
->prev
= BufferList
;
1703 BufferList
->next
= BufferListStart
;
1706 // Update number of buffers in queue
1707 Source
->BuffersInQueue
+= n
;
1709 UnlockContext(Context
);
1710 ALCcontext_DecRef(Context
);
1714 while(BufferListStart
)
1716 BufferList
= BufferListStart
;
1717 BufferListStart
= BufferList
->next
;
1719 if(BufferList
->buffer
)
1720 DecrementRef(&BufferList
->buffer
->ref
);
1723 ALCcontext_DecRef(Context
);
1727 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1728 // an array of buffer IDs that are to be filled with the names of the buffers removed
1729 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1731 ALCcontext
*Context
;
1734 ALbufferlistitem
*BufferList
;
1739 Context
= GetContextRef();
1740 if(!Context
) return;
1744 alSetError(Context
, AL_INVALID_VALUE
);
1748 if((Source
=LookupSource(Context
, source
)) == NULL
)
1750 alSetError(Context
, AL_INVALID_NAME
);
1754 LockContext(Context
);
1755 if(Source
->bLooping
|| Source
->lSourceType
!= AL_STREAMING
||
1756 (ALuint
)n
> Source
->BuffersPlayed
)
1758 UnlockContext(Context
);
1759 // Some buffers can't be unqueue because they have not been processed
1760 alSetError(Context
, AL_INVALID_VALUE
);
1764 for(i
= 0;i
< n
;i
++)
1766 BufferList
= Source
->queue
;
1767 Source
->queue
= BufferList
->next
;
1768 Source
->BuffersInQueue
--;
1769 Source
->BuffersPlayed
--;
1771 if(BufferList
->buffer
)
1773 // Record name of buffer
1774 buffers
[i
] = BufferList
->buffer
->buffer
;
1775 // Decrement buffer reference counter
1776 DecrementRef(&BufferList
->buffer
->ref
);
1781 // Release memory for buffer list item
1785 Source
->queue
->prev
= NULL
;
1786 UnlockContext(Context
);
1789 ALCcontext_DecRef(Context
);
1793 static ALvoid
InitSourceParams(ALsource
*Source
)
1797 Source
->flInnerAngle
= 360.0f
;
1798 Source
->flOuterAngle
= 360.0f
;
1799 Source
->flPitch
= 1.0f
;
1800 Source
->vPosition
[0] = 0.0f
;
1801 Source
->vPosition
[1] = 0.0f
;
1802 Source
->vPosition
[2] = 0.0f
;
1803 Source
->vOrientation
[0] = 0.0f
;
1804 Source
->vOrientation
[1] = 0.0f
;
1805 Source
->vOrientation
[2] = 0.0f
;
1806 Source
->vVelocity
[0] = 0.0f
;
1807 Source
->vVelocity
[1] = 0.0f
;
1808 Source
->vVelocity
[2] = 0.0f
;
1809 Source
->flRefDistance
= 1.0f
;
1810 Source
->flMaxDistance
= FLT_MAX
;
1811 Source
->flRollOffFactor
= 1.0f
;
1812 Source
->bLooping
= AL_FALSE
;
1813 Source
->flGain
= 1.0f
;
1814 Source
->flMinGain
= 0.0f
;
1815 Source
->flMaxGain
= 1.0f
;
1816 Source
->flOuterGain
= 0.0f
;
1817 Source
->OuterGainHF
= 1.0f
;
1819 Source
->DryGainHFAuto
= AL_TRUE
;
1820 Source
->WetGainAuto
= AL_TRUE
;
1821 Source
->WetGainHFAuto
= AL_TRUE
;
1822 Source
->AirAbsorptionFactor
= 0.0f
;
1823 Source
->RoomRolloffFactor
= 0.0f
;
1824 Source
->DopplerFactor
= 1.0f
;
1825 Source
->DirectChannels
= AL_FALSE
;
1827 Source
->DistanceModel
= DefaultDistanceModel
;
1829 Source
->Resampler
= DefaultResampler
;
1831 Source
->state
= AL_INITIAL
;
1832 Source
->new_state
= AL_NONE
;
1833 Source
->lSourceType
= AL_UNDETERMINED
;
1834 Source
->lOffset
= -1;
1836 Source
->DirectGain
= 1.0f
;
1837 Source
->DirectGainHF
= 1.0f
;
1838 for(i
= 0;i
< MAX_SENDS
;i
++)
1840 Source
->Send
[i
].WetGain
= 1.0f
;
1841 Source
->Send
[i
].WetGainHF
= 1.0f
;
1844 Source
->NeedsUpdate
= AL_TRUE
;
1846 Source
->HrtfMoving
= AL_FALSE
;
1847 Source
->HrtfCounter
= 0;
1854 * Sets the source's new play state given its current state
1856 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
1858 if(state
== AL_PLAYING
)
1860 ALbufferlistitem
*BufferList
;
1863 /* Check that there is a queue containing at least one non-null, non zero length AL Buffer */
1864 BufferList
= Source
->queue
;
1867 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
1869 BufferList
= BufferList
->next
;
1872 if(Source
->state
!= AL_PLAYING
)
1874 for(j
= 0;j
< MAXCHANNELS
;j
++)
1876 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
1877 Source
->HrtfHistory
[j
][k
] = 0.0f
;
1878 for(k
= 0;k
< HRIR_LENGTH
;k
++)
1880 Source
->HrtfValues
[j
][k
][0] = 0.0f
;
1881 Source
->HrtfValues
[j
][k
][1] = 0.0f
;
1886 if(Source
->state
!= AL_PAUSED
)
1888 Source
->state
= AL_PLAYING
;
1889 Source
->position
= 0;
1890 Source
->position_fraction
= 0;
1891 Source
->BuffersPlayed
= 0;
1894 Source
->state
= AL_PLAYING
;
1896 // Check if an Offset has been set
1897 if(Source
->lOffset
!= -1)
1898 ApplyOffset(Source
);
1900 /* If there's nothing to play, or device is disconnected, go right to
1902 if(!BufferList
|| !Context
->Device
->Connected
)
1904 SetSourceState(Source
, Context
, AL_STOPPED
);
1908 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
1910 if(Context
->ActiveSources
[j
] == Source
)
1913 if(j
== Context
->ActiveSourceCount
)
1914 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
1916 else if(state
== AL_PAUSED
)
1918 if(Source
->state
== AL_PLAYING
)
1920 Source
->state
= AL_PAUSED
;
1921 Source
->HrtfMoving
= AL_FALSE
;
1922 Source
->HrtfCounter
= 0;
1925 else if(state
== AL_STOPPED
)
1927 if(Source
->state
!= AL_INITIAL
)
1929 Source
->state
= AL_STOPPED
;
1930 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1931 Source
->HrtfMoving
= AL_FALSE
;
1932 Source
->HrtfCounter
= 0;
1934 Source
->lOffset
= -1;
1936 else if(state
== AL_INITIAL
)
1938 if(Source
->state
!= AL_INITIAL
)
1940 Source
->state
= AL_INITIAL
;
1941 Source
->position
= 0;
1942 Source
->position_fraction
= 0;
1943 Source
->BuffersPlayed
= 0;
1944 Source
->HrtfMoving
= AL_FALSE
;
1945 Source
->HrtfCounter
= 0;
1947 Source
->lOffset
= -1;
1954 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1955 The offset is relative to the start of the queue (not the start of the current buffer)
1957 static ALvoid
GetSourceOffset(ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
1959 const ALbufferlistitem
*BufferList
;
1960 const ALbuffer
*Buffer
= NULL
;
1961 ALuint BufferFreq
= 0;
1962 ALuint readPos
, writePos
;
1963 ALuint totalBufferLen
;
1966 // Find the first non-NULL Buffer in the Queue
1967 BufferList
= Source
->queue
;
1970 if(BufferList
->buffer
)
1972 Buffer
= BufferList
->buffer
;
1973 BufferFreq
= Buffer
->Frequency
;
1976 BufferList
= BufferList
->next
;
1979 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
1986 if(updateLen
> 0.0 && updateLen
< 0.015)
1989 // Get Current SamplesPlayed (NOTE : This is the offset into the *current* buffer)
1990 readPos
= Source
->position
;
1991 // Add length of any processed buffers in the queue
1993 BufferList
= Source
->queue
;
1994 for(i
= 0;BufferList
;i
++)
1996 if(BufferList
->buffer
)
1998 if(i
< Source
->BuffersPlayed
)
1999 readPos
+= BufferList
->buffer
->SampleLen
;
2000 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
2002 BufferList
= BufferList
->next
;
2004 if(Source
->state
== AL_PLAYING
)
2005 writePos
= readPos
+ (ALuint
)(updateLen
*BufferFreq
);
2009 if(Source
->bLooping
)
2011 readPos
%= totalBufferLen
;
2012 writePos
%= totalBufferLen
;
2016 // Wrap positions back to 0
2017 if(readPos
>= totalBufferLen
)
2019 if(writePos
>= totalBufferLen
)
2026 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2027 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2029 case AL_SAMPLE_OFFSET
:
2030 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2031 offset
[0] = (ALdouble
)readPos
;
2032 offset
[1] = (ALdouble
)writePos
;
2034 case AL_BYTE_OFFSET
:
2035 case AL_BYTE_RW_OFFSETS_SOFT
:
2036 // Take into account the original format of the Buffer
2037 if(Buffer
->OriginalType
== UserFmtIMA4
)
2039 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
2040 ALuint FrameBlockSize
= 65;
2042 // Round down to nearest ADPCM block
2043 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2044 if(Source
->state
!= AL_PLAYING
)
2045 offset
[1] = offset
[0];
2048 // Round up to nearest ADPCM block
2049 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2050 FrameBlockSize
* BlockSize
);
2055 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2056 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2057 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2067 Apply a playback offset to the Source. This function will update the queue (to correctly
2068 mark buffers as 'pending' or 'processed' depending upon the new offset.
2070 ALboolean
ApplyOffset(ALsource
*Source
)
2072 const ALbufferlistitem
*BufferList
;
2073 const ALbuffer
*Buffer
;
2074 ALint bufferLen
, totalBufferLen
;
2075 ALint buffersPlayed
;
2078 // Get true byte offset
2079 offset
= GetSampleOffset(Source
);
2081 // If the offset is invalid, don't apply it
2085 // Sort out the queue (pending and processed states)
2086 BufferList
= Source
->queue
;
2092 Buffer
= BufferList
->buffer
;
2093 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2095 if(bufferLen
<= offset
-totalBufferLen
)
2097 // Offset is past this buffer so increment BuffersPlayed
2100 else if(totalBufferLen
<= offset
)
2102 // Offset is within this buffer
2103 Source
->BuffersPlayed
= buffersPlayed
;
2105 // SW Mixer Positions are in Samples
2106 Source
->position
= offset
- totalBufferLen
;
2110 // Increment the TotalBufferSize
2111 totalBufferLen
+= bufferLen
;
2113 // Move on to next buffer in the Queue
2114 BufferList
= BufferList
->next
;
2116 // Offset is out of range of the buffer queue
2124 Returns the sample offset into the Source's queue (from the Sample, Byte or Millisecond offset
2125 supplied by the application). This takes into account the fact that the buffer format may have
2128 static ALint
GetSampleOffset(ALsource
*Source
)
2130 const ALbuffer
*Buffer
= NULL
;
2131 const ALbufferlistitem
*BufferList
;
2134 // Find the first non-NULL Buffer in the Queue
2135 BufferList
= Source
->queue
;
2138 if(BufferList
->buffer
)
2140 Buffer
= BufferList
->buffer
;
2143 BufferList
= BufferList
->next
;
2148 Source
->lOffset
= -1;
2152 // Determine the ByteOffset (and ensure it is block aligned)
2153 switch(Source
->lOffsetType
)
2155 case AL_BYTE_OFFSET
:
2156 // Take into consideration the original format
2157 Offset
= Source
->lOffset
;
2158 if(Buffer
->OriginalType
== UserFmtIMA4
)
2160 // Round down to nearest ADPCM block
2161 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2162 // Multiply by compression rate (65 sample frames per block)
2166 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2169 case AL_SAMPLE_OFFSET
:
2170 Offset
= Source
->lOffset
;
2174 // Note - lOffset is internally stored as Milliseconds
2175 Offset
= (ALint
)(Source
->lOffset
/ 1000.0 * Buffer
->Frequency
);
2179 Source
->lOffset
= -1;
2185 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2189 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2191 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2192 Context
->SourceMap
.array
[pos
].value
= NULL
;
2194 // For each buffer in the source's queue, decrement its reference counter and remove it
2195 while(temp
->queue
!= NULL
)
2197 ALbufferlistitem
*BufferList
= temp
->queue
;
2198 temp
->queue
= BufferList
->next
;
2200 if(BufferList
->buffer
!= NULL
)
2201 DecrementRef(&BufferList
->buffer
->ref
);
2205 for(j
= 0;j
< MAX_SENDS
;++j
)
2207 if(temp
->Send
[j
].Slot
)
2208 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2209 temp
->Send
[j
].Slot
= NULL
;
2212 // Release source structure
2213 FreeThunkEntry(temp
->source
);
2214 memset(temp
, 0, sizeof(ALsource
));