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
);
356 Source
->OffsetType
= eParam
;
357 Source
->Offset
= flValue
;
359 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
360 !pContext
->DeferUpdates
)
362 if(ApplyOffset(Source
) == AL_FALSE
)
363 alSetError(pContext
, AL_INVALID_VALUE
);
365 UnlockContext(pContext
);
368 alSetError(pContext
, AL_INVALID_VALUE
);
372 alSetError(pContext
, AL_INVALID_ENUM
);
378 // Invalid Source Name
379 alSetError(pContext
, AL_INVALID_NAME
);
382 ALCcontext_DecRef(pContext
);
386 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
388 ALCcontext
*pContext
;
391 pContext
= GetContextRef();
392 if(!pContext
) return;
394 if((Source
=LookupSource(pContext
, source
)) != NULL
)
399 if(isfinite(flValue1
) && isfinite(flValue2
) && isfinite(flValue3
))
401 LockContext(pContext
);
402 Source
->vPosition
[0] = flValue1
;
403 Source
->vPosition
[1] = flValue2
;
404 Source
->vPosition
[2] = flValue3
;
405 UnlockContext(pContext
);
406 Source
->NeedsUpdate
= AL_TRUE
;
409 alSetError(pContext
, AL_INVALID_VALUE
);
413 if(isfinite(flValue1
) && isfinite(flValue2
) && isfinite(flValue3
))
415 LockContext(pContext
);
416 Source
->vVelocity
[0] = flValue1
;
417 Source
->vVelocity
[1] = flValue2
;
418 Source
->vVelocity
[2] = flValue3
;
419 UnlockContext(pContext
);
420 Source
->NeedsUpdate
= AL_TRUE
;
423 alSetError(pContext
, AL_INVALID_VALUE
);
427 if(isfinite(flValue1
) && isfinite(flValue2
) && isfinite(flValue3
))
429 LockContext(pContext
);
430 Source
->vOrientation
[0] = flValue1
;
431 Source
->vOrientation
[1] = flValue2
;
432 Source
->vOrientation
[2] = flValue3
;
433 UnlockContext(pContext
);
434 Source
->NeedsUpdate
= AL_TRUE
;
437 alSetError(pContext
, AL_INVALID_VALUE
);
441 alSetError(pContext
, AL_INVALID_ENUM
);
446 alSetError(pContext
, AL_INVALID_NAME
);
448 ALCcontext_DecRef(pContext
);
452 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
454 ALCcontext
*pContext
;
461 case AL_CONE_INNER_ANGLE
:
462 case AL_CONE_OUTER_ANGLE
:
464 case AL_MAX_DISTANCE
:
465 case AL_ROLLOFF_FACTOR
:
466 case AL_REFERENCE_DISTANCE
:
469 case AL_CONE_OUTER_GAIN
:
470 case AL_CONE_OUTER_GAINHF
:
472 case AL_SAMPLE_OFFSET
:
474 case AL_AIR_ABSORPTION_FACTOR
:
475 case AL_ROOM_ROLLOFF_FACTOR
:
476 alSourcef(source
, eParam
, pflValues
[0]);
482 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
487 pContext
= GetContextRef();
488 if(!pContext
) return;
492 if(LookupSource(pContext
, source
) != NULL
)
497 alSetError(pContext
, AL_INVALID_ENUM
);
502 alSetError(pContext
, AL_INVALID_NAME
);
505 alSetError(pContext
, AL_INVALID_VALUE
);
507 ALCcontext_DecRef(pContext
);
511 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
513 ALCcontext
*pContext
;
515 ALbufferlistitem
*BufferListItem
;
519 case AL_MAX_DISTANCE
:
520 case AL_ROLLOFF_FACTOR
:
521 case AL_CONE_INNER_ANGLE
:
522 case AL_CONE_OUTER_ANGLE
:
523 case AL_REFERENCE_DISTANCE
:
524 alSourcef(source
, eParam
, (ALfloat
)lValue
);
528 pContext
= GetContextRef();
529 if(!pContext
) return;
531 if((Source
=LookupSource(pContext
, source
)) != NULL
)
533 ALCdevice
*device
= pContext
->Device
;
537 case AL_SOURCE_RELATIVE
:
538 if(lValue
== AL_FALSE
|| lValue
== AL_TRUE
)
540 Source
->bHeadRelative
= (ALboolean
)lValue
;
541 Source
->NeedsUpdate
= AL_TRUE
;
544 alSetError(pContext
, AL_INVALID_VALUE
);
548 if(lValue
== AL_FALSE
|| lValue
== AL_TRUE
)
549 Source
->bLooping
= (ALboolean
)lValue
;
551 alSetError(pContext
, AL_INVALID_VALUE
);
555 LockContext(pContext
);
556 if(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
)
558 ALbufferlistitem
*oldlist
;
559 ALbuffer
*buffer
= NULL
;
561 if(lValue
== 0 || (buffer
=LookupBuffer(device
, lValue
)) != NULL
)
563 Source
->BuffersInQueue
= 0;
564 Source
->BuffersPlayed
= 0;
566 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
569 // Source is now in STATIC mode
570 Source
->lSourceType
= AL_STATIC
;
572 // Add the selected buffer to the queue
573 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
574 BufferListItem
->buffer
= buffer
;
575 BufferListItem
->next
= NULL
;
576 BufferListItem
->prev
= NULL
;
577 // Increment reference counter for buffer
578 IncrementRef(&buffer
->ref
);
580 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, BufferListItem
);
581 Source
->BuffersInQueue
= 1;
583 ReadLock(&buffer
->lock
);
584 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
585 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
586 ReadUnlock(&buffer
->lock
);
587 if(buffer
->FmtChannels
== FmtMono
)
588 Source
->Update
= CalcSourceParams
;
590 Source
->Update
= CalcNonAttnSourceParams
;
591 Source
->NeedsUpdate
= AL_TRUE
;
595 // Source is now in UNDETERMINED mode
596 Source
->lSourceType
= AL_UNDETERMINED
;
597 oldlist
= ExchangePtr((XchgPtr
*)&Source
->queue
, NULL
);
600 // Delete all previous elements in the queue
601 while(oldlist
!= NULL
)
603 BufferListItem
= oldlist
;
604 oldlist
= BufferListItem
->next
;
606 if(BufferListItem
->buffer
)
607 DecrementRef(&BufferListItem
->buffer
->ref
);
608 free(BufferListItem
);
612 alSetError(pContext
, AL_INVALID_VALUE
);
615 alSetError(pContext
, AL_INVALID_OPERATION
);
616 UnlockContext(pContext
);
619 case AL_SOURCE_STATE
:
621 alSetError(pContext
, AL_INVALID_OPERATION
);
625 case AL_SAMPLE_OFFSET
:
629 LockContext(pContext
);
631 Source
->OffsetType
= eParam
;
632 Source
->Offset
= lValue
;
634 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
635 !pContext
->DeferUpdates
)
637 if(ApplyOffset(Source
) == AL_FALSE
)
638 alSetError(pContext
, AL_INVALID_VALUE
);
640 UnlockContext(pContext
);
643 alSetError(pContext
, AL_INVALID_VALUE
);
646 case AL_DIRECT_FILTER
: {
647 ALfilter
*filter
= NULL
;
649 if(lValue
== 0 || (filter
=LookupFilter(pContext
->Device
, lValue
)) != NULL
)
651 LockContext(pContext
);
654 Source
->DirectGain
= 1.0f
;
655 Source
->DirectGainHF
= 1.0f
;
659 Source
->DirectGain
= filter
->Gain
;
660 Source
->DirectGainHF
= filter
->GainHF
;
662 UnlockContext(pContext
);
663 Source
->NeedsUpdate
= AL_TRUE
;
666 alSetError(pContext
, AL_INVALID_VALUE
);
669 case AL_DIRECT_FILTER_GAINHF_AUTO
:
670 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
672 Source
->DryGainHFAuto
= lValue
;
673 Source
->NeedsUpdate
= AL_TRUE
;
676 alSetError(pContext
, AL_INVALID_VALUE
);
679 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
680 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
682 Source
->WetGainAuto
= lValue
;
683 Source
->NeedsUpdate
= AL_TRUE
;
686 alSetError(pContext
, AL_INVALID_VALUE
);
689 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
690 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
692 Source
->WetGainHFAuto
= lValue
;
693 Source
->NeedsUpdate
= AL_TRUE
;
696 alSetError(pContext
, AL_INVALID_VALUE
);
699 case AL_DIRECT_CHANNELS_SOFT
:
700 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
702 Source
->DirectChannels
= lValue
;
703 Source
->NeedsUpdate
= AL_TRUE
;
706 alSetError(pContext
, AL_INVALID_VALUE
);
709 case AL_DISTANCE_MODEL
:
710 if(lValue
== AL_NONE
||
711 lValue
== AL_INVERSE_DISTANCE
||
712 lValue
== AL_INVERSE_DISTANCE_CLAMPED
||
713 lValue
== AL_LINEAR_DISTANCE
||
714 lValue
== AL_LINEAR_DISTANCE_CLAMPED
||
715 lValue
== AL_EXPONENT_DISTANCE
||
716 lValue
== AL_EXPONENT_DISTANCE_CLAMPED
)
718 Source
->DistanceModel
= lValue
;
719 if(pContext
->SourceDistanceModel
)
720 Source
->NeedsUpdate
= AL_TRUE
;
723 alSetError(pContext
, AL_INVALID_VALUE
);
727 alSetError(pContext
, AL_INVALID_ENUM
);
732 alSetError(pContext
, AL_INVALID_NAME
);
734 ALCcontext_DecRef(pContext
);
738 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
740 ALCcontext
*pContext
;
748 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
752 pContext
= GetContextRef();
753 if(!pContext
) return;
755 if((Source
=LookupSource(pContext
, source
)) != NULL
)
757 ALCdevice
*device
= pContext
->Device
;
761 case AL_AUXILIARY_SEND_FILTER
: {
762 ALeffectslot
*ALEffectSlot
= NULL
;
763 ALfilter
*ALFilter
= NULL
;
765 LockContext(pContext
);
766 if((ALuint
)lValue2
< device
->NumAuxSends
&&
767 (lValue1
== 0 || (ALEffectSlot
=LookupEffectSlot(pContext
, lValue1
)) != NULL
) &&
768 (lValue3
== 0 || (ALFilter
=LookupFilter(device
, lValue3
)) != NULL
))
770 /* Release refcount on the previous slot, and add one for
772 if(ALEffectSlot
) IncrementRef(&ALEffectSlot
->ref
);
773 ALEffectSlot
= ExchangePtr((XchgPtr
*)&Source
->Send
[lValue2
].Slot
, ALEffectSlot
);
774 if(ALEffectSlot
) DecrementRef(&ALEffectSlot
->ref
);
779 Source
->Send
[lValue2
].WetGain
= 1.0f
;
780 Source
->Send
[lValue2
].WetGainHF
= 1.0f
;
784 Source
->Send
[lValue2
].WetGain
= ALFilter
->Gain
;
785 Source
->Send
[lValue2
].WetGainHF
= ALFilter
->GainHF
;
787 Source
->NeedsUpdate
= AL_TRUE
;
790 alSetError(pContext
, AL_INVALID_VALUE
);
791 UnlockContext(pContext
);
795 alSetError(pContext
, AL_INVALID_ENUM
);
800 alSetError(pContext
, AL_INVALID_NAME
);
802 ALCcontext_DecRef(pContext
);
806 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
808 ALCcontext
*pContext
;
814 case AL_SOURCE_RELATIVE
:
815 case AL_CONE_INNER_ANGLE
:
816 case AL_CONE_OUTER_ANGLE
:
819 case AL_SOURCE_STATE
:
821 case AL_SAMPLE_OFFSET
:
823 case AL_MAX_DISTANCE
:
824 case AL_ROLLOFF_FACTOR
:
825 case AL_REFERENCE_DISTANCE
:
826 case AL_DIRECT_FILTER
:
827 case AL_DIRECT_FILTER_GAINHF_AUTO
:
828 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
829 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
830 case AL_DISTANCE_MODEL
:
831 case AL_DIRECT_CHANNELS_SOFT
:
832 alSourcei(source
, eParam
, plValues
[0]);
838 case AL_AUXILIARY_SEND_FILTER
:
839 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
844 pContext
= GetContextRef();
845 if(!pContext
) return;
849 if(LookupSource(pContext
, source
) != NULL
)
854 alSetError(pContext
, AL_INVALID_ENUM
);
859 alSetError(pContext
, AL_INVALID_NAME
);
862 alSetError(pContext
, AL_INVALID_VALUE
);
864 ALCcontext_DecRef(pContext
);
868 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
870 ALCcontext
*pContext
;
875 pContext
= GetContextRef();
876 if(!pContext
) return;
880 if((Source
=LookupSource(pContext
, source
)) != NULL
)
885 *pflValue
= Source
->flPitch
;
889 *pflValue
= Source
->flGain
;
893 *pflValue
= Source
->flMinGain
;
897 *pflValue
= Source
->flMaxGain
;
900 case AL_MAX_DISTANCE
:
901 *pflValue
= Source
->flMaxDistance
;
904 case AL_ROLLOFF_FACTOR
:
905 *pflValue
= Source
->flRollOffFactor
;
908 case AL_CONE_OUTER_GAIN
:
909 *pflValue
= Source
->flOuterGain
;
912 case AL_CONE_OUTER_GAINHF
:
913 *pflValue
= Source
->OuterGainHF
;
917 case AL_SAMPLE_OFFSET
:
919 LockContext(pContext
);
920 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
921 pContext
->Device
->Frequency
;
922 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
923 UnlockContext(pContext
);
924 *pflValue
= (ALfloat
)Offsets
[0];
927 case AL_CONE_INNER_ANGLE
:
928 *pflValue
= Source
->flInnerAngle
;
931 case AL_CONE_OUTER_ANGLE
:
932 *pflValue
= Source
->flOuterAngle
;
935 case AL_REFERENCE_DISTANCE
:
936 *pflValue
= Source
->flRefDistance
;
939 case AL_AIR_ABSORPTION_FACTOR
:
940 *pflValue
= Source
->AirAbsorptionFactor
;
943 case AL_ROOM_ROLLOFF_FACTOR
:
944 *pflValue
= Source
->RoomRolloffFactor
;
947 case AL_DOPPLER_FACTOR
:
948 *pflValue
= Source
->DopplerFactor
;
952 alSetError(pContext
, AL_INVALID_ENUM
);
957 alSetError(pContext
, AL_INVALID_NAME
);
960 alSetError(pContext
, AL_INVALID_VALUE
);
962 ALCcontext_DecRef(pContext
);
966 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
968 ALCcontext
*pContext
;
971 pContext
= GetContextRef();
972 if(!pContext
) return;
974 if(pflValue1
&& pflValue2
&& pflValue3
)
976 if((Source
=LookupSource(pContext
, source
)) != NULL
)
981 LockContext(pContext
);
982 *pflValue1
= Source
->vPosition
[0];
983 *pflValue2
= Source
->vPosition
[1];
984 *pflValue3
= Source
->vPosition
[2];
985 UnlockContext(pContext
);
989 LockContext(pContext
);
990 *pflValue1
= Source
->vVelocity
[0];
991 *pflValue2
= Source
->vVelocity
[1];
992 *pflValue3
= Source
->vVelocity
[2];
993 UnlockContext(pContext
);
997 LockContext(pContext
);
998 *pflValue1
= Source
->vOrientation
[0];
999 *pflValue2
= Source
->vOrientation
[1];
1000 *pflValue3
= Source
->vOrientation
[2];
1001 UnlockContext(pContext
);
1005 alSetError(pContext
, AL_INVALID_ENUM
);
1010 alSetError(pContext
, AL_INVALID_NAME
);
1013 alSetError(pContext
, AL_INVALID_VALUE
);
1015 ALCcontext_DecRef(pContext
);
1019 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1021 ALCcontext
*pContext
;
1023 ALdouble Offsets
[2];
1032 case AL_MAX_DISTANCE
:
1033 case AL_ROLLOFF_FACTOR
:
1034 case AL_DOPPLER_FACTOR
:
1035 case AL_CONE_OUTER_GAIN
:
1037 case AL_SAMPLE_OFFSET
:
1038 case AL_BYTE_OFFSET
:
1039 case AL_CONE_INNER_ANGLE
:
1040 case AL_CONE_OUTER_ANGLE
:
1041 case AL_REFERENCE_DISTANCE
:
1042 case AL_CONE_OUTER_GAINHF
:
1043 case AL_AIR_ABSORPTION_FACTOR
:
1044 case AL_ROOM_ROLLOFF_FACTOR
:
1045 alGetSourcef(source
, eParam
, pflValues
);
1051 alGetSource3f(source
, eParam
, pflValues
+0, pflValues
+1, pflValues
+2);
1055 pContext
= GetContextRef();
1056 if(!pContext
) return;
1060 if((Source
=LookupSource(pContext
, source
)) != NULL
)
1064 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1065 case AL_BYTE_RW_OFFSETS_SOFT
:
1066 LockContext(pContext
);
1067 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
1068 pContext
->Device
->Frequency
;
1069 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
1070 UnlockContext(pContext
);
1071 pflValues
[0] = (ALfloat
)Offsets
[0];
1072 pflValues
[1] = (ALfloat
)Offsets
[1];
1076 alSetError(pContext
, AL_INVALID_ENUM
);
1081 alSetError(pContext
, AL_INVALID_NAME
);
1084 alSetError(pContext
, AL_INVALID_VALUE
);
1086 ALCcontext_DecRef(pContext
);
1090 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1092 ALbufferlistitem
*BufferList
;
1093 ALCcontext
*pContext
;
1095 ALdouble Offsets
[2];
1098 pContext
= GetContextRef();
1099 if(!pContext
) return;
1103 if((Source
=LookupSource(pContext
, source
)) != NULL
)
1107 case AL_MAX_DISTANCE
:
1108 *plValue
= (ALint
)Source
->flMaxDistance
;
1111 case AL_ROLLOFF_FACTOR
:
1112 *plValue
= (ALint
)Source
->flRollOffFactor
;
1115 case AL_REFERENCE_DISTANCE
:
1116 *plValue
= (ALint
)Source
->flRefDistance
;
1119 case AL_SOURCE_RELATIVE
:
1120 *plValue
= Source
->bHeadRelative
;
1123 case AL_CONE_INNER_ANGLE
:
1124 *plValue
= (ALint
)Source
->flInnerAngle
;
1127 case AL_CONE_OUTER_ANGLE
:
1128 *plValue
= (ALint
)Source
->flOuterAngle
;
1132 *plValue
= Source
->bLooping
;
1136 LockContext(pContext
);
1137 BufferList
= Source
->queue
;
1138 if(Source
->lSourceType
!= AL_STATIC
)
1140 ALuint i
= Source
->BuffersPlayed
;
1143 BufferList
= BufferList
->next
;
1147 *plValue
= ((BufferList
&& BufferList
->buffer
) ?
1148 BufferList
->buffer
->buffer
: 0);
1149 UnlockContext(pContext
);
1152 case AL_SOURCE_STATE
:
1153 *plValue
= Source
->state
;
1156 case AL_BUFFERS_QUEUED
:
1157 *plValue
= Source
->BuffersInQueue
;
1160 case AL_BUFFERS_PROCESSED
:
1161 LockContext(pContext
);
1162 if(Source
->bLooping
|| Source
->lSourceType
!= AL_STREAMING
)
1164 /* Buffers on a looping source are in a perpetual state
1165 * of PENDING, so don't report any as PROCESSED */
1169 *plValue
= Source
->BuffersPlayed
;
1170 UnlockContext(pContext
);
1173 case AL_SOURCE_TYPE
:
1174 *plValue
= Source
->lSourceType
;
1178 case AL_SAMPLE_OFFSET
:
1179 case AL_BYTE_OFFSET
:
1180 LockContext(pContext
);
1181 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
1182 pContext
->Device
->Frequency
;
1183 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
1184 UnlockContext(pContext
);
1185 *plValue
= (ALint
)Offsets
[0];
1188 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1189 *plValue
= Source
->DryGainHFAuto
;
1192 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1193 *plValue
= Source
->WetGainAuto
;
1196 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1197 *plValue
= Source
->WetGainHFAuto
;
1200 case AL_DOPPLER_FACTOR
:
1201 *plValue
= (ALint
)Source
->DopplerFactor
;
1204 case AL_DIRECT_CHANNELS_SOFT
:
1205 *plValue
= Source
->DirectChannels
;
1208 case AL_DISTANCE_MODEL
:
1209 *plValue
= Source
->DistanceModel
;
1213 alSetError(pContext
, AL_INVALID_ENUM
);
1218 alSetError(pContext
, AL_INVALID_NAME
);
1221 alSetError(pContext
, AL_INVALID_VALUE
);
1223 ALCcontext_DecRef(pContext
);
1227 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1229 ALCcontext
*pContext
;
1232 pContext
= GetContextRef();
1233 if(!pContext
) return;
1235 if(plValue1
&& plValue2
&& plValue3
)
1237 if((Source
=LookupSource(pContext
, source
)) != NULL
)
1242 LockContext(pContext
);
1243 *plValue1
= (ALint
)Source
->vPosition
[0];
1244 *plValue2
= (ALint
)Source
->vPosition
[1];
1245 *plValue3
= (ALint
)Source
->vPosition
[2];
1246 UnlockContext(pContext
);
1250 LockContext(pContext
);
1251 *plValue1
= (ALint
)Source
->vVelocity
[0];
1252 *plValue2
= (ALint
)Source
->vVelocity
[1];
1253 *plValue3
= (ALint
)Source
->vVelocity
[2];
1254 UnlockContext(pContext
);
1258 LockContext(pContext
);
1259 *plValue1
= (ALint
)Source
->vOrientation
[0];
1260 *plValue2
= (ALint
)Source
->vOrientation
[1];
1261 *plValue3
= (ALint
)Source
->vOrientation
[2];
1262 UnlockContext(pContext
);
1266 alSetError(pContext
, AL_INVALID_ENUM
);
1271 alSetError(pContext
, AL_INVALID_NAME
);
1274 alSetError(pContext
, AL_INVALID_VALUE
);
1276 ALCcontext_DecRef(pContext
);
1280 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1282 ALCcontext
*pContext
;
1284 ALdouble Offsets
[2];
1289 case AL_SOURCE_RELATIVE
:
1290 case AL_CONE_INNER_ANGLE
:
1291 case AL_CONE_OUTER_ANGLE
:
1294 case AL_SOURCE_STATE
:
1295 case AL_BUFFERS_QUEUED
:
1296 case AL_BUFFERS_PROCESSED
:
1298 case AL_SAMPLE_OFFSET
:
1299 case AL_BYTE_OFFSET
:
1300 case AL_MAX_DISTANCE
:
1301 case AL_ROLLOFF_FACTOR
:
1302 case AL_DOPPLER_FACTOR
:
1303 case AL_REFERENCE_DISTANCE
:
1304 case AL_SOURCE_TYPE
:
1305 case AL_DIRECT_FILTER
:
1306 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1307 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1308 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1309 case AL_DISTANCE_MODEL
:
1310 case AL_DIRECT_CHANNELS_SOFT
:
1311 alGetSourcei(source
, eParam
, plValues
);
1317 alGetSource3i(source
, eParam
, plValues
+0, plValues
+1, plValues
+2);
1321 pContext
= GetContextRef();
1322 if(!pContext
) return;
1326 if((Source
=LookupSource(pContext
, source
)) != NULL
)
1330 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1331 case AL_BYTE_RW_OFFSETS_SOFT
:
1332 LockContext(pContext
);
1333 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
1334 pContext
->Device
->Frequency
;
1335 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
1336 UnlockContext(pContext
);
1337 plValues
[0] = (ALint
)Offsets
[0];
1338 plValues
[1] = (ALint
)Offsets
[1];
1342 alSetError(pContext
, AL_INVALID_ENUM
);
1347 alSetError(pContext
, AL_INVALID_NAME
);
1350 alSetError(pContext
, AL_INVALID_VALUE
);
1352 ALCcontext_DecRef(pContext
);
1356 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
1358 alSourcePlayv(1, &source
);
1361 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
1363 ALCcontext
*Context
;
1367 Context
= GetContextRef();
1368 if(!Context
) return;
1372 alSetError(Context
, AL_INVALID_VALUE
);
1375 if(n
> 0 && !sources
)
1377 alSetError(Context
, AL_INVALID_VALUE
);
1381 // Check that all the Sources are valid
1382 for(i
= 0;i
< n
;i
++)
1384 if(!LookupSource(Context
, sources
[i
]))
1386 alSetError(Context
, AL_INVALID_NAME
);
1391 LockContext(Context
);
1392 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
1397 newcount
= Context
->MaxActiveSources
<< 1;
1399 temp
= realloc(Context
->ActiveSources
,
1400 sizeof(*Context
->ActiveSources
) * newcount
);
1403 UnlockContext(Context
);
1404 alSetError(Context
, AL_OUT_OF_MEMORY
);
1408 Context
->ActiveSources
= temp
;
1409 Context
->MaxActiveSources
= newcount
;
1412 for(i
= 0;i
< n
;i
++)
1414 Source
= LookupSource(Context
, sources
[i
]);
1415 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
1416 else SetSourceState(Source
, Context
, AL_PLAYING
);
1418 UnlockContext(Context
);
1421 ALCcontext_DecRef(Context
);
1424 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
1426 alSourcePausev(1, &source
);
1429 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1431 ALCcontext
*Context
;
1435 Context
= GetContextRef();
1436 if(!Context
) return;
1440 alSetError(Context
, AL_INVALID_VALUE
);
1443 if(n
> 0 && !sources
)
1445 alSetError(Context
, AL_INVALID_VALUE
);
1449 // Check all the Sources are valid
1450 for(i
= 0;i
< n
;i
++)
1452 if(!LookupSource(Context
, sources
[i
]))
1454 alSetError(Context
, AL_INVALID_NAME
);
1459 LockContext(Context
);
1460 for(i
= 0;i
< n
;i
++)
1462 Source
= LookupSource(Context
, sources
[i
]);
1463 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
1464 else SetSourceState(Source
, Context
, AL_PAUSED
);
1466 UnlockContext(Context
);
1469 ALCcontext_DecRef(Context
);
1472 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
1474 alSourceStopv(1, &source
);
1477 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1479 ALCcontext
*Context
;
1483 Context
= GetContextRef();
1484 if(!Context
) return;
1488 alSetError(Context
, AL_INVALID_VALUE
);
1491 if(n
> 0 && !sources
)
1493 alSetError(Context
, AL_INVALID_VALUE
);
1497 // Check all the Sources are valid
1498 for(i
= 0;i
< n
;i
++)
1500 if(!LookupSource(Context
, sources
[i
]))
1502 alSetError(Context
, AL_INVALID_NAME
);
1507 LockContext(Context
);
1508 for(i
= 0;i
< n
;i
++)
1510 Source
= LookupSource(Context
, sources
[i
]);
1511 Source
->new_state
= AL_NONE
;
1512 SetSourceState(Source
, Context
, AL_STOPPED
);
1514 UnlockContext(Context
);
1517 ALCcontext_DecRef(Context
);
1520 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
1522 alSourceRewindv(1, &source
);
1525 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1527 ALCcontext
*Context
;
1531 Context
= GetContextRef();
1532 if(!Context
) return;
1536 alSetError(Context
, AL_INVALID_VALUE
);
1539 if(n
> 0 && !sources
)
1541 alSetError(Context
, AL_INVALID_VALUE
);
1545 // Check all the Sources are valid
1546 for(i
= 0;i
< n
;i
++)
1548 if(!LookupSource(Context
, sources
[i
]))
1550 alSetError(Context
, AL_INVALID_NAME
);
1555 LockContext(Context
);
1556 for(i
= 0;i
< n
;i
++)
1558 Source
= LookupSource(Context
, sources
[i
]);
1559 Source
->new_state
= AL_NONE
;
1560 SetSourceState(Source
, Context
, AL_INITIAL
);
1562 UnlockContext(Context
);
1565 ALCcontext_DecRef(Context
);
1569 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei n
, const ALuint
*buffers
)
1571 ALCcontext
*Context
;
1575 ALbufferlistitem
*BufferListStart
= NULL
;
1576 ALbufferlistitem
*BufferList
;
1577 ALbuffer
*BufferFmt
;
1582 Context
= GetContextRef();
1583 if(!Context
) return;
1587 alSetError(Context
, AL_INVALID_VALUE
);
1591 // Check that all buffers are valid or zero and that the source is valid
1593 // Check that this is a valid source
1594 if((Source
=LookupSource(Context
, source
)) == NULL
)
1596 alSetError(Context
, AL_INVALID_NAME
);
1600 LockContext(Context
);
1601 // Check that this is not a STATIC Source
1602 if(Source
->lSourceType
== AL_STATIC
)
1604 UnlockContext(Context
);
1605 // Invalid Source Type (can't queue on a Static Source)
1606 alSetError(Context
, AL_INVALID_OPERATION
);
1610 device
= Context
->Device
;
1614 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1615 BufferList
= Source
->queue
;
1618 if(BufferList
->buffer
)
1620 BufferFmt
= BufferList
->buffer
;
1623 BufferList
= BufferList
->next
;
1626 for(i
= 0;i
< n
;i
++)
1628 ALbuffer
*buffer
= NULL
;
1629 if(buffers
[i
] && (buffer
=LookupBuffer(device
, buffers
[i
])) == NULL
)
1631 UnlockContext(Context
);
1632 alSetError(Context
, AL_INVALID_NAME
);
1636 if(!BufferListStart
)
1638 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
1639 BufferListStart
->buffer
= buffer
;
1640 BufferListStart
->next
= NULL
;
1641 BufferListStart
->prev
= NULL
;
1642 BufferList
= BufferListStart
;
1646 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1647 BufferList
->next
->buffer
= buffer
;
1648 BufferList
->next
->next
= NULL
;
1649 BufferList
->next
->prev
= BufferList
;
1650 BufferList
= BufferList
->next
;
1652 if(!buffer
) continue;
1654 // Increment reference counter for buffer
1655 IncrementRef(&buffer
->ref
);
1656 ReadLock(&buffer
->lock
);
1657 if(BufferFmt
== NULL
)
1661 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
1662 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
1663 if(buffer
->FmtChannels
== FmtMono
)
1664 Source
->Update
= CalcSourceParams
;
1666 Source
->Update
= CalcNonAttnSourceParams
;
1668 Source
->NeedsUpdate
= AL_TRUE
;
1670 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
1671 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
1672 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
1674 ReadUnlock(&buffer
->lock
);
1675 UnlockContext(Context
);
1676 alSetError(Context
, AL_INVALID_OPERATION
);
1679 ReadUnlock(&buffer
->lock
);
1682 // Change Source Type
1683 Source
->lSourceType
= AL_STREAMING
;
1685 if(Source
->queue
== NULL
)
1686 Source
->queue
= BufferListStart
;
1689 // Find end of queue
1690 BufferList
= Source
->queue
;
1691 while(BufferList
->next
!= NULL
)
1692 BufferList
= BufferList
->next
;
1694 BufferListStart
->prev
= BufferList
;
1695 BufferList
->next
= BufferListStart
;
1698 // Update number of buffers in queue
1699 Source
->BuffersInQueue
+= n
;
1701 UnlockContext(Context
);
1702 ALCcontext_DecRef(Context
);
1706 while(BufferListStart
)
1708 BufferList
= BufferListStart
;
1709 BufferListStart
= BufferList
->next
;
1711 if(BufferList
->buffer
)
1712 DecrementRef(&BufferList
->buffer
->ref
);
1715 ALCcontext_DecRef(Context
);
1719 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1720 // an array of buffer IDs that are to be filled with the names of the buffers removed
1721 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1723 ALCcontext
*Context
;
1726 ALbufferlistitem
*BufferList
;
1731 Context
= GetContextRef();
1732 if(!Context
) return;
1736 alSetError(Context
, AL_INVALID_VALUE
);
1740 if((Source
=LookupSource(Context
, source
)) == NULL
)
1742 alSetError(Context
, AL_INVALID_NAME
);
1746 LockContext(Context
);
1747 if(Source
->bLooping
|| Source
->lSourceType
!= AL_STREAMING
||
1748 (ALuint
)n
> Source
->BuffersPlayed
)
1750 UnlockContext(Context
);
1751 // Some buffers can't be unqueue because they have not been processed
1752 alSetError(Context
, AL_INVALID_VALUE
);
1756 for(i
= 0;i
< n
;i
++)
1758 BufferList
= Source
->queue
;
1759 Source
->queue
= BufferList
->next
;
1760 Source
->BuffersInQueue
--;
1761 Source
->BuffersPlayed
--;
1763 if(BufferList
->buffer
)
1765 // Record name of buffer
1766 buffers
[i
] = BufferList
->buffer
->buffer
;
1767 // Decrement buffer reference counter
1768 DecrementRef(&BufferList
->buffer
->ref
);
1773 // Release memory for buffer list item
1777 Source
->queue
->prev
= NULL
;
1778 UnlockContext(Context
);
1781 ALCcontext_DecRef(Context
);
1785 static ALvoid
InitSourceParams(ALsource
*Source
)
1789 Source
->flInnerAngle
= 360.0f
;
1790 Source
->flOuterAngle
= 360.0f
;
1791 Source
->flPitch
= 1.0f
;
1792 Source
->vPosition
[0] = 0.0f
;
1793 Source
->vPosition
[1] = 0.0f
;
1794 Source
->vPosition
[2] = 0.0f
;
1795 Source
->vOrientation
[0] = 0.0f
;
1796 Source
->vOrientation
[1] = 0.0f
;
1797 Source
->vOrientation
[2] = 0.0f
;
1798 Source
->vVelocity
[0] = 0.0f
;
1799 Source
->vVelocity
[1] = 0.0f
;
1800 Source
->vVelocity
[2] = 0.0f
;
1801 Source
->flRefDistance
= 1.0f
;
1802 Source
->flMaxDistance
= FLT_MAX
;
1803 Source
->flRollOffFactor
= 1.0f
;
1804 Source
->bLooping
= AL_FALSE
;
1805 Source
->flGain
= 1.0f
;
1806 Source
->flMinGain
= 0.0f
;
1807 Source
->flMaxGain
= 1.0f
;
1808 Source
->flOuterGain
= 0.0f
;
1809 Source
->OuterGainHF
= 1.0f
;
1811 Source
->DryGainHFAuto
= AL_TRUE
;
1812 Source
->WetGainAuto
= AL_TRUE
;
1813 Source
->WetGainHFAuto
= AL_TRUE
;
1814 Source
->AirAbsorptionFactor
= 0.0f
;
1815 Source
->RoomRolloffFactor
= 0.0f
;
1816 Source
->DopplerFactor
= 1.0f
;
1817 Source
->DirectChannels
= AL_FALSE
;
1819 Source
->DistanceModel
= DefaultDistanceModel
;
1821 Source
->Resampler
= DefaultResampler
;
1823 Source
->state
= AL_INITIAL
;
1824 Source
->new_state
= AL_NONE
;
1825 Source
->lSourceType
= AL_UNDETERMINED
;
1826 Source
->Offset
= -1.0;
1828 Source
->DirectGain
= 1.0f
;
1829 Source
->DirectGainHF
= 1.0f
;
1830 for(i
= 0;i
< MAX_SENDS
;i
++)
1832 Source
->Send
[i
].WetGain
= 1.0f
;
1833 Source
->Send
[i
].WetGainHF
= 1.0f
;
1836 Source
->NeedsUpdate
= AL_TRUE
;
1838 Source
->HrtfMoving
= AL_FALSE
;
1839 Source
->HrtfCounter
= 0;
1846 * Sets the source's new play state given its current state
1848 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
1850 if(state
== AL_PLAYING
)
1852 ALbufferlistitem
*BufferList
;
1855 /* Check that there is a queue containing at least one non-null, non zero length AL Buffer */
1856 BufferList
= Source
->queue
;
1859 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->SampleLen
)
1861 BufferList
= BufferList
->next
;
1864 if(Source
->state
!= AL_PLAYING
)
1866 for(j
= 0;j
< MAXCHANNELS
;j
++)
1868 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
1869 Source
->HrtfHistory
[j
][k
] = 0.0f
;
1870 for(k
= 0;k
< HRIR_LENGTH
;k
++)
1872 Source
->HrtfValues
[j
][k
][0] = 0.0f
;
1873 Source
->HrtfValues
[j
][k
][1] = 0.0f
;
1878 if(Source
->state
!= AL_PAUSED
)
1880 Source
->state
= AL_PLAYING
;
1881 Source
->position
= 0;
1882 Source
->position_fraction
= 0;
1883 Source
->BuffersPlayed
= 0;
1886 Source
->state
= AL_PLAYING
;
1888 // Check if an Offset has been set
1889 if(Source
->Offset
>= 0.0)
1890 ApplyOffset(Source
);
1892 /* If there's nothing to play, or device is disconnected, go right to
1894 if(!BufferList
|| !Context
->Device
->Connected
)
1896 SetSourceState(Source
, Context
, AL_STOPPED
);
1900 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
1902 if(Context
->ActiveSources
[j
] == Source
)
1905 if(j
== Context
->ActiveSourceCount
)
1906 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
1908 else if(state
== AL_PAUSED
)
1910 if(Source
->state
== AL_PLAYING
)
1912 Source
->state
= AL_PAUSED
;
1913 Source
->HrtfMoving
= AL_FALSE
;
1914 Source
->HrtfCounter
= 0;
1917 else if(state
== AL_STOPPED
)
1919 if(Source
->state
!= AL_INITIAL
)
1921 Source
->state
= AL_STOPPED
;
1922 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1923 Source
->HrtfMoving
= AL_FALSE
;
1924 Source
->HrtfCounter
= 0;
1926 Source
->Offset
= -1.0;
1928 else if(state
== AL_INITIAL
)
1930 if(Source
->state
!= AL_INITIAL
)
1932 Source
->state
= AL_INITIAL
;
1933 Source
->position
= 0;
1934 Source
->position_fraction
= 0;
1935 Source
->BuffersPlayed
= 0;
1936 Source
->HrtfMoving
= AL_FALSE
;
1937 Source
->HrtfCounter
= 0;
1939 Source
->Offset
= -1.0;
1946 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1947 The offset is relative to the start of the queue (not the start of the current buffer)
1949 static ALvoid
GetSourceOffset(ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
1951 const ALbufferlistitem
*BufferList
;
1952 const ALbuffer
*Buffer
= NULL
;
1953 ALuint BufferFreq
= 0;
1954 ALuint readPos
, writePos
;
1955 ALuint totalBufferLen
;
1958 // Find the first non-NULL Buffer in the Queue
1959 BufferList
= Source
->queue
;
1962 if(BufferList
->buffer
)
1964 Buffer
= BufferList
->buffer
;
1965 BufferFreq
= Buffer
->Frequency
;
1968 BufferList
= BufferList
->next
;
1971 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
1978 if(updateLen
> 0.0 && updateLen
< 0.015)
1981 // Get Current SamplesPlayed (NOTE : This is the offset into the *current* buffer)
1982 readPos
= Source
->position
;
1983 // Add length of any processed buffers in the queue
1985 BufferList
= Source
->queue
;
1986 for(i
= 0;BufferList
;i
++)
1988 if(BufferList
->buffer
)
1990 if(i
< Source
->BuffersPlayed
)
1991 readPos
+= BufferList
->buffer
->SampleLen
;
1992 totalBufferLen
+= BufferList
->buffer
->SampleLen
;
1994 BufferList
= BufferList
->next
;
1996 if(Source
->state
== AL_PLAYING
)
1997 writePos
= readPos
+ (ALuint
)(updateLen
*BufferFreq
);
2001 if(Source
->bLooping
)
2003 readPos
%= totalBufferLen
;
2004 writePos
%= totalBufferLen
;
2008 // Wrap positions back to 0
2009 if(readPos
>= totalBufferLen
)
2011 if(writePos
>= totalBufferLen
)
2018 offset
[0] = (ALdouble
)readPos
/ Buffer
->Frequency
;
2019 offset
[1] = (ALdouble
)writePos
/ Buffer
->Frequency
;
2021 case AL_SAMPLE_OFFSET
:
2022 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2023 offset
[0] = (ALdouble
)readPos
;
2024 offset
[1] = (ALdouble
)writePos
;
2026 case AL_BYTE_OFFSET
:
2027 case AL_BYTE_RW_OFFSETS_SOFT
:
2028 // Take into account the original format of the Buffer
2029 if(Buffer
->OriginalType
== UserFmtIMA4
)
2031 ALuint BlockSize
= 36 * ChannelsFromFmt(Buffer
->FmtChannels
);
2032 ALuint FrameBlockSize
= 65;
2034 // Round down to nearest ADPCM block
2035 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2036 if(Source
->state
!= AL_PLAYING
)
2037 offset
[1] = offset
[0];
2040 // Round up to nearest ADPCM block
2041 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2042 FrameBlockSize
* BlockSize
);
2047 ALuint FrameSize
= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2048 offset
[0] = (ALdouble
)(readPos
* FrameSize
);
2049 offset
[1] = (ALdouble
)(writePos
* FrameSize
);
2059 Apply a playback offset to the Source. This function will update the queue (to correctly
2060 mark buffers as 'pending' or 'processed' depending upon the new offset.
2062 ALboolean
ApplyOffset(ALsource
*Source
)
2064 const ALbufferlistitem
*BufferList
;
2065 const ALbuffer
*Buffer
;
2066 ALint bufferLen
, totalBufferLen
;
2067 ALint buffersPlayed
;
2070 // Get true byte offset
2071 offset
= GetSampleOffset(Source
);
2073 // If the offset is invalid, don't apply it
2077 // Sort out the queue (pending and processed states)
2078 BufferList
= Source
->queue
;
2084 Buffer
= BufferList
->buffer
;
2085 bufferLen
= Buffer
? Buffer
->SampleLen
: 0;
2087 if(bufferLen
<= offset
-totalBufferLen
)
2089 // Offset is past this buffer so increment BuffersPlayed
2092 else if(totalBufferLen
<= offset
)
2094 // Offset is within this buffer
2095 Source
->BuffersPlayed
= buffersPlayed
;
2097 // SW Mixer Positions are in Samples
2098 Source
->position
= offset
- totalBufferLen
;
2102 // Increment the TotalBufferSize
2103 totalBufferLen
+= bufferLen
;
2105 // Move on to next buffer in the Queue
2106 BufferList
= BufferList
->next
;
2108 // Offset is out of range of the buffer queue
2116 Returns the sample offset into the Source's queue (from the Sample, Byte or Millisecond offset
2117 supplied by the application). This takes into account the fact that the buffer format may have
2120 static ALint
GetSampleOffset(ALsource
*Source
)
2122 const ALbuffer
*Buffer
= NULL
;
2123 const ALbufferlistitem
*BufferList
;
2126 // Find the first non-NULL Buffer in the Queue
2127 BufferList
= Source
->queue
;
2130 if(BufferList
->buffer
)
2132 Buffer
= BufferList
->buffer
;
2135 BufferList
= BufferList
->next
;
2140 Source
->Offset
= -1.0;
2144 // Determine the ByteOffset (and ensure it is block aligned)
2145 switch(Source
->OffsetType
)
2147 case AL_BYTE_OFFSET
:
2148 // Take into consideration the original format
2149 Offset
= (ALint
)Source
->Offset
;
2150 if(Buffer
->OriginalType
== UserFmtIMA4
)
2152 // Round down to nearest ADPCM block
2153 Offset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2154 // Multiply by compression rate (65 sample frames per block)
2158 Offset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2161 case AL_SAMPLE_OFFSET
:
2162 Offset
= (ALint
)Source
->Offset
;
2166 Offset
= (ALint
)(Source
->Offset
* Buffer
->Frequency
);
2170 Source
->Offset
= -1.0;
2176 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2180 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2182 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2183 Context
->SourceMap
.array
[pos
].value
= NULL
;
2185 // For each buffer in the source's queue, decrement its reference counter and remove it
2186 while(temp
->queue
!= NULL
)
2188 ALbufferlistitem
*BufferList
= temp
->queue
;
2189 temp
->queue
= BufferList
->next
;
2191 if(BufferList
->buffer
!= NULL
)
2192 DecrementRef(&BufferList
->buffer
->ref
);
2196 for(j
= 0;j
< MAX_SENDS
;++j
)
2198 if(temp
->Send
[j
].Slot
)
2199 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2200 temp
->Send
[j
].Slot
= NULL
;
2203 // Release source structure
2204 FreeThunkEntry(temp
->source
);
2205 memset(temp
, 0, sizeof(ALsource
));