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"
35 static ALvoid
InitSourceParams(ALCcontext
*Context
, ALsource
*pSource
);
36 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
, ALuint updateSize
);
37 static ALvoid
ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
);
38 static ALint
GetByteOffset(ALsource
*pSource
);
40 ALAPI ALvoid ALAPIENTRY
alGenSources(ALsizei n
,ALuint
*sources
)
46 Context
= alcGetCurrentContext();
49 SuspendContext(Context
);
53 Device
= alcGetContextsDevice(Context
);
57 // Check that enough memory has been allocted in the 'sources' array for n Sources
58 if (!IsBadWritePtr((void*)sources
, n
* sizeof(ALuint
)))
60 // Check that the requested number of sources can be generated
61 if ((Context
->SourceCount
+ n
) <= Device
->MaxNoOfSources
)
63 ALsource
**list
= &Context
->Source
;
65 list
= &(*list
)->next
;
67 // Add additional sources to the list (Source->next points to the location for the next Source structure)
70 *list
= calloc(1, sizeof(ALsource
));
73 alDeleteSources(i
, sources
);
74 alSetError(AL_OUT_OF_MEMORY
);
78 sources
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
79 (*list
)->source
= sources
[i
];
81 InitSourceParams(Context
, *list
);
82 Context
->SourceCount
++;
85 list
= &(*list
)->next
;
90 // Not enough resources to create the Sources
91 alSetError(AL_INVALID_VALUE
);
97 alSetError(AL_INVALID_VALUE
);
102 // No Device created, or attached to Context
103 alSetError(AL_INVALID_OPERATION
);
107 ProcessContext(Context
);
112 alSetError(AL_INVALID_OPERATION
);
119 ALAPI ALvoid ALAPIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
126 ALbufferlistitem
*ALBufferList
;
127 ALboolean bSourcesValid
= AL_TRUE
;
129 Context
= alcGetCurrentContext();
132 SuspendContext(Context
);
136 Device
= alcGetContextsDevice(Context
);
140 // Check that all Sources are valid (and can therefore be deleted)
141 for (i
= 0; i
< n
; i
++)
143 if (!alIsSource(sources
[i
]))
145 alSetError(AL_INVALID_NAME
);
146 bSourcesValid
= AL_FALSE
;
153 // All Sources are valid, and can be deleted
154 for (i
= 0; i
< n
; i
++)
156 // Recheck that the Source is valid, because there could be duplicated Source names
157 if (alIsSource(sources
[i
]))
159 ALSource
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
160 alSourceStop((ALuint
)ALSource
->source
);
162 // For each buffer in the source's queue, decrement its reference counter and remove it
163 while (ALSource
->queue
!= NULL
)
165 ALBufferList
= ALSource
->queue
;
166 // Decrement buffer's reference counter
167 if (ALBufferList
->buffer
!= 0)
168 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
169 // Update queue to point to next element in list
170 ALSource
->queue
= ALBufferList
->next
;
171 // Release memory allocated for buffer list item
175 for(j
= 0;j
< MAX_SENDS
;++j
)
177 if(ALSource
->Send
[j
].Slot
)
178 ALSource
->Send
[j
].Slot
->refcount
--;
179 ALSource
->Send
[j
].Slot
= NULL
;
182 // Decrement Source count
183 Context
->SourceCount
--;
185 // Remove Source from list of Sources
186 list
= &Context
->Source
;
187 while(*list
&& *list
!= ALSource
)
188 list
= &(*list
)->next
;
191 *list
= (*list
)->next
;
192 ALTHUNK_REMOVEENTRY(ALSource
->source
);
194 memset(ALSource
,0,sizeof(ALsource
));
202 // No Device created, or attached to Context
203 alSetError(AL_INVALID_OPERATION
);
207 alSetError(AL_INVALID_VALUE
);
209 ProcessContext(Context
);
214 alSetError(AL_INVALID_OPERATION
);
221 ALAPI ALboolean ALAPIENTRY
alIsSource(ALuint source
)
223 ALboolean result
=AL_FALSE
;
227 Context
=alcGetCurrentContext();
230 SuspendContext(Context
);
232 // To determine if this is a valid Source name, look through the list of generated Sources
233 Source
= Context
->Source
;
236 if (Source
== (ALsource
*)ALTHUNK_LOOKUPENTRY(source
))
242 Source
= Source
->next
;
245 ProcessContext(Context
);
250 alSetError(AL_INVALID_OPERATION
);
257 ALAPI ALvoid ALAPIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
259 ALCcontext
*pContext
;
262 pContext
= alcGetCurrentContext();
265 SuspendContext(pContext
);
267 if (alIsSource(source
))
269 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
276 pSource
->flPitch
= flValue
;
277 if(pSource
->flPitch
< 0.001f
)
278 pSource
->flPitch
= 0.001f
;
281 alSetError(AL_INVALID_VALUE
);
284 case AL_CONE_INNER_ANGLE
:
285 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
286 pSource
->flInnerAngle
= flValue
;
288 alSetError(AL_INVALID_VALUE
);
291 case AL_CONE_OUTER_ANGLE
:
292 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
293 pSource
->flOuterAngle
= flValue
;
295 alSetError(AL_INVALID_VALUE
);
300 pSource
->flGain
= flValue
;
302 alSetError(AL_INVALID_VALUE
);
305 case AL_MAX_DISTANCE
:
307 pSource
->flMaxDistance
= flValue
;
309 alSetError(AL_INVALID_VALUE
);
312 case AL_ROLLOFF_FACTOR
:
314 pSource
->flRollOffFactor
= flValue
;
316 alSetError(AL_INVALID_VALUE
);
319 case AL_REFERENCE_DISTANCE
:
321 pSource
->flRefDistance
= flValue
;
323 alSetError(AL_INVALID_VALUE
);
327 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
328 pSource
->flMinGain
= flValue
;
330 alSetError(AL_INVALID_VALUE
);
334 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
335 pSource
->flMaxGain
= flValue
;
337 alSetError(AL_INVALID_VALUE
);
340 case AL_CONE_OUTER_GAIN
:
341 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
342 pSource
->flOuterGain
= flValue
;
344 alSetError(AL_INVALID_VALUE
);
347 case AL_CONE_OUTER_GAINHF
:
348 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
349 pSource
->OuterGainHF
= flValue
;
351 alSetError(AL_INVALID_VALUE
);
354 case AL_AIR_ABSORPTION_FACTOR
:
355 if (flValue
>= 0.0f
&& flValue
<= 10.0f
)
356 pSource
->AirAbsorptionFactor
= flValue
;
358 alSetError(AL_INVALID_VALUE
);
361 case AL_ROOM_ROLLOFF_FACTOR
:
362 if (flValue
>= 0.0f
&& flValue
<= 10.0f
)
363 pSource
->RoomRolloffFactor
= flValue
;
365 alSetError(AL_INVALID_VALUE
);
368 case AL_DOPPLER_FACTOR
:
369 if (flValue
>= 0.0f
&& flValue
<= 1.0f
)
370 pSource
->DopplerFactor
= flValue
;
372 alSetError(AL_INVALID_VALUE
);
376 case AL_SAMPLE_OFFSET
:
380 pSource
->lOffsetType
= eParam
;
382 // Store Offset (convert Seconds into Milliseconds)
383 if (eParam
== AL_SEC_OFFSET
)
384 pSource
->lOffset
= (ALint
)(flValue
* 1000.0f
);
386 pSource
->lOffset
= (ALint
)flValue
;
388 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
389 ApplyOffset(pSource
, AL_TRUE
);
392 alSetError(AL_INVALID_VALUE
);
396 alSetError(AL_INVALID_ENUM
);
402 // Invalid Source Name
403 alSetError(AL_INVALID_NAME
);
406 ProcessContext(pContext
);
411 alSetError(AL_INVALID_OPERATION
);
418 ALAPI ALvoid ALAPIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
420 ALCcontext
*pContext
;
423 pContext
= alcGetCurrentContext();
426 SuspendContext(pContext
);
428 if (alIsSource(source
))
430 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
434 pSource
->vPosition
[0] = flValue1
;
435 pSource
->vPosition
[1] = flValue2
;
436 pSource
->vPosition
[2] = flValue3
;
440 pSource
->vVelocity
[0] = flValue1
;
441 pSource
->vVelocity
[1] = flValue2
;
442 pSource
->vVelocity
[2] = flValue3
;
446 pSource
->vOrientation
[0] = flValue1
;
447 pSource
->vOrientation
[1] = flValue2
;
448 pSource
->vOrientation
[2] = flValue3
;
452 alSetError(AL_INVALID_ENUM
);
457 alSetError(AL_INVALID_NAME
);
459 ProcessContext(pContext
);
463 alSetError(AL_INVALID_OPERATION
);
470 ALAPI ALvoid ALAPIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
472 ALCcontext
*pContext
;
474 pContext
= alcGetCurrentContext();
477 SuspendContext(pContext
);
481 if (alIsSource(source
))
486 case AL_CONE_INNER_ANGLE
:
487 case AL_CONE_OUTER_ANGLE
:
489 case AL_MAX_DISTANCE
:
490 case AL_ROLLOFF_FACTOR
:
491 case AL_REFERENCE_DISTANCE
:
494 case AL_CONE_OUTER_GAIN
:
495 case AL_CONE_OUTER_GAINHF
:
497 case AL_SAMPLE_OFFSET
:
499 case AL_AIR_ABSORPTION_FACTOR
:
500 case AL_ROOM_ROLLOFF_FACTOR
:
501 alSourcef(source
, eParam
, pflValues
[0]);
507 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
511 alSetError(AL_INVALID_ENUM
);
516 alSetError(AL_INVALID_NAME
);
519 alSetError(AL_INVALID_VALUE
);
521 ProcessContext(pContext
);
524 alSetError(AL_INVALID_OPERATION
);
530 ALAPI ALvoid ALAPIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
532 ALCcontext
*pContext
;
534 ALbufferlistitem
*pALBufferListItem
;
539 pContext
= alcGetCurrentContext();
542 SuspendContext(pContext
);
544 if (alIsSource(source
))
546 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
550 case AL_MAX_DISTANCE
:
551 case AL_ROLLOFF_FACTOR
:
552 case AL_REFERENCE_DISTANCE
:
553 alSourcef(source
, eParam
, (ALfloat
)lValue
);
556 case AL_SOURCE_RELATIVE
:
557 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
558 pSource
->bHeadRelative
= (ALboolean
)lValue
;
560 alSetError(AL_INVALID_VALUE
);
563 case AL_CONE_INNER_ANGLE
:
564 if ((lValue
>= 0) && (lValue
<= 360))
565 pSource
->flInnerAngle
= (float)lValue
;
567 alSetError(AL_INVALID_VALUE
);
570 case AL_CONE_OUTER_ANGLE
:
571 if ((lValue
>= 0) && (lValue
<= 360))
572 pSource
->flOuterAngle
= (float)lValue
;
574 alSetError(AL_INVALID_VALUE
);
578 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
579 pSource
->bLooping
= (ALboolean
)lValue
;
581 alSetError(AL_INVALID_VALUE
);
585 if ((pSource
->state
== AL_STOPPED
) || (pSource
->state
== AL_INITIAL
))
587 if (alIsBuffer(lValue
))
589 // Remove all elements in the queue
590 while (pSource
->queue
!= NULL
)
592 pALBufferListItem
= pSource
->queue
;
593 pSource
->queue
= pALBufferListItem
->next
;
594 // Decrement reference counter for buffer
595 if (pALBufferListItem
->buffer
)
596 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
)))->refcount
--;
597 // Record size of buffer
598 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
))->size
;
599 DataSize
+= BufferSize
;
600 // Increment the number of buffers removed from queue
602 // Release memory for buffer list item
603 free(pALBufferListItem
);
604 // Decrement the number of buffers in the queue
605 pSource
->BuffersInQueue
--;
608 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
611 // Source is now in STATIC mode
612 pSource
->lSourceType
= AL_STATIC
;
614 // Add the selected buffer to the queue
615 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
616 pALBufferListItem
->buffer
= lValue
;
617 pALBufferListItem
->bufferstate
= PENDING
;
618 pALBufferListItem
->flag
= 0;
619 pALBufferListItem
->next
= NULL
;
621 pSource
->queue
= pALBufferListItem
;
622 pSource
->BuffersInQueue
= 1;
624 DataSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(lValue
))->size
;
626 // Increment reference counter for buffer
627 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(lValue
)))->refcount
++;
631 // Source is now in UNDETERMINED mode
632 pSource
->lSourceType
= AL_UNDETERMINED
;
635 // Update AL_BUFFER parameter
636 pSource
->ulBufferID
= lValue
;
639 alSetError(AL_INVALID_VALUE
);
642 alSetError(AL_INVALID_OPERATION
);
645 case AL_SOURCE_STATE
:
647 alSetError(AL_INVALID_OPERATION
);
651 case AL_SAMPLE_OFFSET
:
655 pSource
->lOffsetType
= eParam
;
657 // Store Offset (convert Seconds into Milliseconds)
658 if (eParam
== AL_SEC_OFFSET
)
659 pSource
->lOffset
= lValue
* 1000;
661 pSource
->lOffset
= lValue
;
663 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
664 ApplyOffset(pSource
, AL_TRUE
);
667 alSetError(AL_INVALID_VALUE
);
670 case AL_DIRECT_FILTER
:
671 if(alIsFilter(lValue
))
673 ALfilter
*filter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue
);
676 pSource
->DirectFilter
.type
= AL_FILTER_NULL
;
677 pSource
->DirectFilter
.filter
= 0;
680 memcpy(&pSource
->DirectFilter
, filter
, sizeof(*filter
));
683 alSetError(AL_INVALID_VALUE
);
686 case AL_DIRECT_FILTER_GAINHF_AUTO
:
687 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
688 pSource
->DryGainHFAuto
= lValue
;
690 alSetError(AL_INVALID_VALUE
);
693 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
694 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
695 pSource
->WetGainAuto
= lValue
;
697 alSetError(AL_INVALID_VALUE
);
700 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
701 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
702 pSource
->WetGainHFAuto
= lValue
;
704 alSetError(AL_INVALID_VALUE
);
707 case AL_DISTANCE_MODEL
:
708 if(lValue
== AL_NONE
||
709 lValue
== AL_INVERSE_DISTANCE
||
710 lValue
== AL_INVERSE_DISTANCE_CLAMPED
||
711 lValue
== AL_LINEAR_DISTANCE
||
712 lValue
== AL_LINEAR_DISTANCE_CLAMPED
||
713 lValue
== AL_EXPONENT_DISTANCE
||
714 lValue
== AL_EXPONENT_DISTANCE_CLAMPED
)
715 pSource
->DistanceModel
= lValue
;
717 alSetError(AL_INVALID_VALUE
);
721 alSetError(AL_INVALID_ENUM
);
726 alSetError(AL_INVALID_NAME
);
728 ProcessContext(pContext
);
731 alSetError(AL_INVALID_OPERATION
);
737 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
739 ALCcontext
*pContext
;
741 pContext
= alcGetCurrentContext();
744 SuspendContext(pContext
);
746 if (alIsSource(source
))
748 ALsource
*pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
755 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
758 case AL_AUXILIARY_SEND_FILTER
:
759 if(lValue2
>= 0 && lValue2
< MAX_SENDS
&&
760 (alIsAuxiliaryEffectSlot(lValue1
) || lValue1
== 0) &&
763 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(lValue1
);
764 ALfilter
*ALFilter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue3
);
766 /* Release refcount on the previous slot, and add one for
768 if(pSource
->Send
[lValue2
].Slot
)
769 pSource
->Send
[lValue2
].Slot
->refcount
--;
770 pSource
->Send
[lValue2
].Slot
= ALEffectSlot
;
771 if(pSource
->Send
[lValue2
].Slot
)
772 pSource
->Send
[lValue2
].Slot
->refcount
++;
777 pSource
->Send
[lValue2
].WetFilter
.type
= 0;
778 pSource
->Send
[lValue2
].WetFilter
.filter
= 0;
781 memcpy(&pSource
->Send
[lValue2
].WetFilter
, ALFilter
, sizeof(*ALFilter
));
784 alSetError(AL_INVALID_VALUE
);
788 alSetError(AL_INVALID_ENUM
);
793 alSetError(AL_INVALID_NAME
);
795 ProcessContext(pContext
);
798 alSetError(AL_INVALID_OPERATION
);
804 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
806 ALCcontext
*pContext
;
808 pContext
= alcGetCurrentContext();
811 SuspendContext(pContext
);
815 if (alIsSource(source
))
819 case AL_SOURCE_RELATIVE
:
820 case AL_CONE_INNER_ANGLE
:
821 case AL_CONE_OUTER_ANGLE
:
824 case AL_SOURCE_STATE
:
826 case AL_SAMPLE_OFFSET
:
828 case AL_MAX_DISTANCE
:
829 case AL_ROLLOFF_FACTOR
:
830 case AL_REFERENCE_DISTANCE
:
831 case AL_DIRECT_FILTER
:
832 case AL_DIRECT_FILTER_GAINHF_AUTO
:
833 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
834 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
835 case AL_DISTANCE_MODEL
:
836 alSourcei(source
, eParam
, plValues
[0]);
842 case AL_AUXILIARY_SEND_FILTER
:
843 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
847 alSetError(AL_INVALID_ENUM
);
852 alSetError(AL_INVALID_NAME
);
855 alSetError(AL_INVALID_VALUE
);
857 ProcessContext(pContext
);
860 alSetError(AL_INVALID_OPERATION
);
866 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
868 ALCcontext
*pContext
;
872 pContext
= alcGetCurrentContext();
875 SuspendContext(pContext
);
879 if (alIsSource(source
))
881 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
886 *pflValue
= pSource
->flPitch
;
890 *pflValue
= pSource
->flGain
;
894 *pflValue
= pSource
->flMinGain
;
898 *pflValue
= pSource
->flMaxGain
;
901 case AL_MAX_DISTANCE
:
902 *pflValue
= pSource
->flMaxDistance
;
905 case AL_ROLLOFF_FACTOR
:
906 *pflValue
= pSource
->flRollOffFactor
;
909 case AL_CONE_OUTER_GAIN
:
910 *pflValue
= pSource
->flOuterGain
;
913 case AL_CONE_OUTER_GAINHF
:
914 *pflValue
= pSource
->OuterGainHF
;
918 case AL_SAMPLE_OFFSET
:
920 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
921 *pflValue
= flOffset
[0];
923 alSetError(AL_INVALID_OPERATION
);
926 case AL_SEC_RW_OFFSETS_EXT
:
927 case AL_SAMPLE_RW_OFFSETS_EXT
:
928 case AL_BYTE_RW_OFFSETS_EXT
:
929 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
931 pflValue
[0] = flOffset
[0];
932 pflValue
[1] = flOffset
[1];
935 alSetError(AL_INVALID_OPERATION
);
938 case AL_CONE_INNER_ANGLE
:
939 *pflValue
= pSource
->flInnerAngle
;
942 case AL_CONE_OUTER_ANGLE
:
943 *pflValue
= pSource
->flOuterAngle
;
946 case AL_REFERENCE_DISTANCE
:
947 *pflValue
= pSource
->flRefDistance
;
950 case AL_AIR_ABSORPTION_FACTOR
:
951 *pflValue
= pSource
->AirAbsorptionFactor
;
954 case AL_ROOM_ROLLOFF_FACTOR
:
955 *pflValue
= pSource
->RoomRolloffFactor
;
958 case AL_DOPPLER_FACTOR
:
959 *pflValue
= pSource
->DopplerFactor
;
963 alSetError(AL_INVALID_ENUM
);
968 alSetError(AL_INVALID_NAME
);
971 alSetError(AL_INVALID_VALUE
);
973 ProcessContext(pContext
);
976 alSetError(AL_INVALID_OPERATION
);
982 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
984 ALCcontext
*pContext
;
987 pContext
= alcGetCurrentContext();
990 SuspendContext(pContext
);
992 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
994 if (alIsSource(source
))
996 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1001 *pflValue1
= pSource
->vPosition
[0];
1002 *pflValue2
= pSource
->vPosition
[1];
1003 *pflValue3
= pSource
->vPosition
[2];
1007 *pflValue1
= pSource
->vVelocity
[0];
1008 *pflValue2
= pSource
->vVelocity
[1];
1009 *pflValue3
= pSource
->vVelocity
[2];
1013 *pflValue1
= pSource
->vOrientation
[0];
1014 *pflValue2
= pSource
->vOrientation
[1];
1015 *pflValue3
= pSource
->vOrientation
[2];
1019 alSetError(AL_INVALID_ENUM
);
1024 alSetError(AL_INVALID_NAME
);
1027 alSetError(AL_INVALID_VALUE
);
1029 ProcessContext(pContext
);
1032 alSetError(AL_INVALID_OPERATION
);
1038 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1040 ALCcontext
*pContext
;
1043 pContext
= alcGetCurrentContext();
1046 SuspendContext(pContext
);
1050 if (alIsSource(source
))
1052 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1060 case AL_MAX_DISTANCE
:
1061 case AL_ROLLOFF_FACTOR
:
1062 case AL_DOPPLER_FACTOR
:
1063 case AL_CONE_OUTER_GAIN
:
1065 case AL_SAMPLE_OFFSET
:
1066 case AL_BYTE_OFFSET
:
1067 case AL_CONE_INNER_ANGLE
:
1068 case AL_CONE_OUTER_ANGLE
:
1069 case AL_REFERENCE_DISTANCE
:
1070 case AL_CONE_OUTER_GAINHF
:
1071 case AL_AIR_ABSORPTION_FACTOR
:
1072 case AL_ROOM_ROLLOFF_FACTOR
:
1073 alGetSourcef(source
, eParam
, pflValues
);
1077 pflValues
[0] = pSource
->vPosition
[0];
1078 pflValues
[1] = pSource
->vPosition
[1];
1079 pflValues
[2] = pSource
->vPosition
[2];
1083 pflValues
[0] = pSource
->vVelocity
[0];
1084 pflValues
[1] = pSource
->vVelocity
[1];
1085 pflValues
[2] = pSource
->vVelocity
[2];
1089 pflValues
[0] = pSource
->vOrientation
[0];
1090 pflValues
[1] = pSource
->vOrientation
[1];
1091 pflValues
[2] = pSource
->vOrientation
[2];
1095 alSetError(AL_INVALID_ENUM
);
1100 alSetError(AL_INVALID_NAME
);
1103 alSetError(AL_INVALID_VALUE
);
1105 ProcessContext(pContext
);
1108 alSetError(AL_INVALID_OPERATION
);
1114 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1116 ALCcontext
*pContext
;
1118 ALfloat flOffset
[2];
1120 pContext
= alcGetCurrentContext();
1123 SuspendContext(pContext
);
1127 if (alIsSource(source
))
1129 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1133 case AL_MAX_DISTANCE
:
1134 *plValue
= (ALint
)pSource
->flMaxDistance
;
1137 case AL_ROLLOFF_FACTOR
:
1138 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1141 case AL_REFERENCE_DISTANCE
:
1142 *plValue
= (ALint
)pSource
->flRefDistance
;
1145 case AL_SOURCE_RELATIVE
:
1146 *plValue
= pSource
->bHeadRelative
;
1149 case AL_CONE_INNER_ANGLE
:
1150 *plValue
= (ALint
)pSource
->flInnerAngle
;
1153 case AL_CONE_OUTER_ANGLE
:
1154 *plValue
= (ALint
)pSource
->flOuterAngle
;
1158 *plValue
= pSource
->bLooping
;
1162 *plValue
= pSource
->ulBufferID
;
1165 case AL_SOURCE_STATE
:
1166 *plValue
= pSource
->state
;
1169 case AL_BUFFERS_QUEUED
:
1170 *plValue
= pSource
->BuffersInQueue
;
1173 case AL_BUFFERS_PROCESSED
:
1174 if(pSource
->bLooping
)
1176 /* Buffers on a looping source are in a perpetual state
1177 * of PENDING, so don't report any as PROCESSED */
1181 *plValue
= pSource
->BuffersPlayed
;
1184 case AL_SOURCE_TYPE
:
1185 *plValue
= pSource
->lSourceType
;
1189 case AL_SAMPLE_OFFSET
:
1190 case AL_BYTE_OFFSET
:
1191 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
1192 *plValue
= (ALint
)flOffset
[0];
1194 alSetError(AL_INVALID_OPERATION
);
1197 case AL_SEC_RW_OFFSETS_EXT
:
1198 case AL_SAMPLE_RW_OFFSETS_EXT
:
1199 case AL_BYTE_RW_OFFSETS_EXT
:
1200 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
1202 plValue
[0] = (ALint
)flOffset
[0];
1203 plValue
[1] = (ALint
)flOffset
[1];
1206 alSetError(AL_INVALID_OPERATION
);
1209 case AL_DIRECT_FILTER
:
1210 *plValue
= pSource
->DirectFilter
.filter
;
1213 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1214 *plValue
= pSource
->DryGainHFAuto
;
1217 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1218 *plValue
= pSource
->WetGainAuto
;
1221 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1222 *plValue
= pSource
->WetGainHFAuto
;
1225 case AL_DOPPLER_FACTOR
:
1226 *plValue
= (ALint
)pSource
->DopplerFactor
;
1229 case AL_DISTANCE_MODEL
:
1230 *plValue
= pSource
->DistanceModel
;
1234 alSetError(AL_INVALID_ENUM
);
1239 alSetError(AL_INVALID_NAME
);
1242 alSetError(AL_INVALID_VALUE
);
1244 ProcessContext(pContext
);
1247 alSetError(AL_INVALID_OPERATION
);
1253 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1255 ALCcontext
*pContext
;
1258 pContext
= alcGetCurrentContext();
1261 SuspendContext(pContext
);
1263 if ((plValue1
) && (plValue2
) && (plValue3
))
1265 if (alIsSource(source
))
1267 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1272 *plValue1
= (ALint
)pSource
->vPosition
[0];
1273 *plValue2
= (ALint
)pSource
->vPosition
[1];
1274 *plValue3
= (ALint
)pSource
->vPosition
[2];
1278 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1279 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1280 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1284 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1285 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1286 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1290 alSetError(AL_INVALID_ENUM
);
1295 alSetError(AL_INVALID_NAME
);
1298 alSetError(AL_INVALID_VALUE
);
1300 ProcessContext(pContext
);
1303 alSetError(AL_INVALID_OPERATION
);
1309 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1311 ALCcontext
*pContext
;
1314 pContext
= alcGetCurrentContext();
1317 SuspendContext(pContext
);
1321 if (alIsSource(source
))
1323 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1327 case AL_SOURCE_RELATIVE
:
1328 case AL_CONE_INNER_ANGLE
:
1329 case AL_CONE_OUTER_ANGLE
:
1332 case AL_SOURCE_STATE
:
1333 case AL_BUFFERS_QUEUED
:
1334 case AL_BUFFERS_PROCESSED
:
1336 case AL_SAMPLE_OFFSET
:
1337 case AL_BYTE_OFFSET
:
1338 case AL_MAX_DISTANCE
:
1339 case AL_ROLLOFF_FACTOR
:
1340 case AL_DOPPLER_FACTOR
:
1341 case AL_REFERENCE_DISTANCE
:
1342 case AL_SOURCE_TYPE
:
1343 case AL_DIRECT_FILTER
:
1344 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1345 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1346 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1347 case AL_DISTANCE_MODEL
:
1348 alGetSourcei(source
, eParam
, plValues
);
1352 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1353 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1354 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1358 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1359 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1360 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1364 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1365 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1366 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1370 alSetError(AL_INVALID_ENUM
);
1375 alSetError(AL_INVALID_NAME
);
1378 alSetError(AL_INVALID_VALUE
);
1380 ProcessContext(pContext
);
1383 alSetError(AL_INVALID_OPERATION
);
1389 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1391 alSourcePlayv(1, &source
);
1395 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1397 ALCcontext
*pContext
;
1399 ALbufferlistitem
*ALBufferList
;
1400 ALboolean bSourcesValid
= AL_TRUE
;
1404 pContext
= alcGetCurrentContext();
1407 SuspendContext(pContext
);
1411 // Check that all the Sources are valid
1412 for (i
= 0; i
< n
; i
++)
1414 if (!alIsSource(pSourceList
[i
]))
1416 alSetError(AL_INVALID_NAME
);
1417 bSourcesValid
= AL_FALSE
;
1424 for (i
= 0; i
< n
; i
++)
1426 // Assume Source won't need to play
1429 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1431 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1432 ALBufferList
= pSource
->queue
;
1433 while (ALBufferList
)
1435 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1440 ALBufferList
= ALBufferList
->next
;
1445 for(j
= 0;j
< OUTPUTCHANNELS
;j
++)
1446 pSource
->DryGains
[j
] = 0.0f
;
1447 for(j
= 0;j
< MAX_SENDS
;j
++)
1448 pSource
->WetGains
[j
] = 0.0f
;
1450 if (pSource
->state
!= AL_PAUSED
)
1452 pSource
->state
= AL_PLAYING
;
1453 pSource
->inuse
= AL_TRUE
;
1454 pSource
->play
= AL_TRUE
;
1455 pSource
->position
= 0;
1456 pSource
->position_fraction
= 0;
1457 pSource
->BuffersPlayed
= 0;
1458 pSource
->FirstStart
= AL_TRUE
;
1460 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1462 // Make sure all the Buffers in the queue are marked as PENDING
1463 ALBufferList
= pSource
->queue
;
1464 while (ALBufferList
)
1466 ALBufferList
->bufferstate
= PENDING
;
1467 ALBufferList
= ALBufferList
->next
;
1472 pSource
->state
= AL_PLAYING
;
1473 pSource
->inuse
= AL_TRUE
;
1474 pSource
->play
= AL_TRUE
;
1475 pSource
->FirstStart
= AL_FALSE
;
1478 // Check if an Offset has been set
1479 if (pSource
->lOffset
)
1480 ApplyOffset(pSource
, AL_FALSE
);
1484 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1485 ALBufferList
= pSource
->queue
;
1486 while (ALBufferList
)
1488 ALBufferList
->bufferstate
= PROCESSED
;
1489 ALBufferList
= ALBufferList
->next
;
1492 pSource
->BuffersPlayed
= pSource
->BuffersInQueue
;
1499 // sources is a NULL pointer
1500 alSetError(AL_INVALID_VALUE
);
1503 ProcessContext(pContext
);
1508 alSetError(AL_INVALID_OPERATION
);
1514 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1516 alSourcePausev(1, &source
);
1520 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1522 ALCcontext
*Context
;
1525 ALboolean bSourcesValid
= AL_TRUE
;
1527 Context
=alcGetCurrentContext();
1530 SuspendContext(Context
);
1534 // Check all the Sources are valid
1537 if (!alIsSource(sources
[i
]))
1539 alSetError(AL_INVALID_NAME
);
1540 bSourcesValid
= AL_FALSE
;
1549 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1550 if (Source
->state
==AL_PLAYING
)
1552 Source
->state
=AL_PAUSED
;
1553 Source
->inuse
=AL_FALSE
;
1560 // sources is a NULL pointer
1561 alSetError(AL_INVALID_VALUE
);
1564 ProcessContext(Context
);
1569 alSetError(AL_INVALID_OPERATION
);
1575 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1577 alSourceStopv(1, &source
);
1581 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1583 ALCcontext
*Context
;
1586 ALbufferlistitem
*ALBufferListItem
;
1587 ALboolean bSourcesValid
= AL_TRUE
;
1589 Context
=alcGetCurrentContext();
1592 SuspendContext(Context
);
1596 // Check all the Sources are valid
1599 if (!alIsSource(sources
[i
]))
1601 alSetError(AL_INVALID_NAME
);
1602 bSourcesValid
= AL_FALSE
;
1611 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1612 if (Source
->state
!=AL_INITIAL
)
1614 Source
->state
=AL_STOPPED
;
1615 Source
->inuse
=AL_FALSE
;
1616 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1617 ALBufferListItem
= Source
->queue
;
1618 while (ALBufferListItem
!= NULL
)
1620 ALBufferListItem
->bufferstate
= PROCESSED
;
1621 ALBufferListItem
= ALBufferListItem
->next
;
1624 Source
->lOffset
= 0;
1630 // sources is a NULL pointer
1631 alSetError(AL_INVALID_VALUE
);
1634 ProcessContext(Context
);
1639 alSetError(AL_INVALID_OPERATION
);
1645 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1647 alSourceRewindv(1, &source
);
1651 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1653 ALCcontext
*Context
;
1656 ALbufferlistitem
*ALBufferListItem
;
1657 ALboolean bSourcesValid
= AL_TRUE
;
1659 Context
=alcGetCurrentContext();
1662 SuspendContext(Context
);
1666 // Check all the Sources are valid
1669 if (!alIsSource(sources
[i
]))
1671 alSetError(AL_INVALID_NAME
);
1672 bSourcesValid
= AL_FALSE
;
1681 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1682 if (Source
->state
!=AL_INITIAL
)
1684 Source
->state
=AL_INITIAL
;
1685 Source
->inuse
=AL_FALSE
;
1687 Source
->position_fraction
=0;
1688 Source
->BuffersPlayed
= 0;
1689 ALBufferListItem
= Source
->queue
;
1690 while (ALBufferListItem
!= NULL
)
1692 ALBufferListItem
->bufferstate
= PENDING
;
1693 ALBufferListItem
= ALBufferListItem
->next
;
1696 Source
->ulBufferID
= Source
->queue
->buffer
;
1698 Source
->lOffset
= 0;
1704 // sources is a NULL pointer
1705 alSetError(AL_INVALID_VALUE
);
1708 ProcessContext(Context
);
1713 alSetError(AL_INVALID_OPERATION
);
1720 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1722 ALCcontext
*Context
;
1725 ALbufferlistitem
*ALBufferList
;
1726 ALbufferlistitem
*ALBufferListStart
;
1731 ALboolean bBuffersValid
= AL_TRUE
;
1736 Context
=alcGetCurrentContext();
1739 SuspendContext(Context
);
1744 // Check that all buffers are valid or zero and that the source is valid
1746 // Check that this is a valid source
1747 if (alIsSource(source
))
1749 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1751 // Check that this is not a STATIC Source
1752 if (ALSource
->lSourceType
!= AL_STATIC
)
1757 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1758 ALBufferList
= ALSource
->queue
;
1759 while (ALBufferList
)
1761 if (ALBufferList
->buffer
)
1763 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1764 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1767 ALBufferList
= ALBufferList
->next
;
1770 for (i
= 0; i
< n
; i
++)
1772 if (alIsBuffer(buffers
[i
]))
1776 if ((iFrequency
== -1) && (iFormat
== -1))
1778 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1779 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1783 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1784 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1786 alSetError(AL_INVALID_OPERATION
);
1787 bBuffersValid
= AL_FALSE
;
1795 alSetError(AL_INVALID_NAME
);
1796 bBuffersValid
= AL_FALSE
;
1803 // Change Source Type
1804 ALSource
->lSourceType
= AL_STREAMING
;
1806 // All buffers are valid - so add them to the list
1807 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1808 ALBufferListStart
->buffer
= buffers
[0];
1809 ALBufferListStart
->bufferstate
= PENDING
;
1810 ALBufferListStart
->flag
= 0;
1811 ALBufferListStart
->next
= NULL
;
1814 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1818 DataSize
+= BufferSize
;
1820 // Increment reference counter for buffer
1822 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1824 ALBufferList
= ALBufferListStart
;
1826 for (i
= 1; i
< n
; i
++)
1828 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1829 ALBufferList
->next
->buffer
= buffers
[i
];
1830 ALBufferList
->next
->bufferstate
= PENDING
;
1831 ALBufferList
->next
->flag
= 0;
1832 ALBufferList
->next
->next
= NULL
;
1835 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1839 DataSize
+= BufferSize
;
1841 // Increment reference counter for buffer
1843 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1845 ALBufferList
= ALBufferList
->next
;
1848 if (ALSource
->queue
== NULL
)
1850 ALSource
->queue
= ALBufferListStart
;
1851 // Update Current Buffer
1852 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1856 // Find end of queue
1857 ALBufferList
= ALSource
->queue
;
1858 while (ALBufferList
->next
!= NULL
)
1860 ALBufferList
= ALBufferList
->next
;
1863 ALBufferList
->next
= ALBufferListStart
;
1866 // Update number of buffers in queue
1867 ALSource
->BuffersInQueue
+= n
;
1872 // Invalid Source Type (can't queue on a Static Source)
1873 alSetError(AL_INVALID_OPERATION
);
1878 // Invalid Source Name
1879 alSetError(AL_INVALID_NAME
);
1882 ProcessContext(Context
);
1887 alSetError(AL_INVALID_OPERATION
);
1894 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1895 // an array of buffer IDs that are to be filled with the names of the buffers removed
1896 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1898 ALCcontext
*Context
;
1901 ALbufferlistitem
*ALBufferList
;
1905 ALboolean bBuffersProcessed
;
1912 bBuffersProcessed
= AL_TRUE
;
1914 Context
=alcGetCurrentContext();
1917 SuspendContext(Context
);
1919 if (alIsSource(source
))
1921 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1923 // Check that all 'n' buffers have been processed
1924 ALBufferList
= ALSource
->queue
;
1925 for (i
= 0; i
< n
; i
++)
1927 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1929 ALBufferList
= ALBufferList
->next
;
1933 bBuffersProcessed
= AL_FALSE
;
1938 // If all 'n' buffers have been processed, remove them from the queue
1939 if (bBuffersProcessed
)
1941 for (i
= 0; i
< n
; i
++)
1943 ALBufferList
= ALSource
->queue
;
1945 ALSource
->queue
= ALBufferList
->next
;
1946 // Record name of buffer
1947 buffers
[i
] = ALBufferList
->buffer
;
1948 // Decrement buffer reference counter
1949 if (ALBufferList
->buffer
)
1950 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1951 // Record size of buffer
1952 if (ALBufferList
->buffer
)
1953 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1957 DataSize
+= BufferSize
;
1958 // Release memory for buffer list item
1960 ALSource
->BuffersInQueue
--;
1963 if (ALSource
->state
!= AL_PLAYING
)
1965 if (ALSource
->queue
)
1966 BufferID
= ALSource
->queue
->buffer
;
1970 ALSource
->ulBufferID
= BufferID
;
1973 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1974 ALSource
->BuffersPlayed
= 0;
1976 ALSource
->BuffersPlayed
-= n
;
1980 // Some buffers can't be unqueue because they have not been processed
1981 alSetError(AL_INVALID_VALUE
);
1986 // Invalid Source Name
1987 alSetError(AL_INVALID_NAME
);
1990 ProcessContext(Context
);
1995 alSetError(AL_INVALID_OPERATION
);
2002 static ALvoid
InitSourceParams(ALCcontext
*Context
, ALsource
*pSource
)
2004 pSource
->flInnerAngle
= 360.0f
;
2005 pSource
->flOuterAngle
= 360.0f
;
2006 pSource
->flPitch
= 1.0f
;
2007 pSource
->vPosition
[0] = 0.0f
;
2008 pSource
->vPosition
[1] = 0.0f
;
2009 pSource
->vPosition
[2] = 0.0f
;
2010 pSource
->vOrientation
[0] = 0.0f
;
2011 pSource
->vOrientation
[1] = 0.0f
;
2012 pSource
->vOrientation
[2] = 0.0f
;
2013 pSource
->vVelocity
[0] = 0.0f
;
2014 pSource
->vVelocity
[1] = 0.0f
;
2015 pSource
->vVelocity
[2] = 0.0f
;
2016 pSource
->flRefDistance
= 1.0f
;
2017 pSource
->flMaxDistance
= FLT_MAX
;
2018 pSource
->flRollOffFactor
= 1.0f
;
2019 pSource
->bLooping
= AL_FALSE
;
2020 pSource
->flGain
= 1.0f
;
2021 pSource
->flMinGain
= 0.0f
;
2022 pSource
->flMaxGain
= 1.0f
;
2023 pSource
->flOuterGain
= 0.0f
;
2024 pSource
->OuterGainHF
= 1.0f
;
2026 pSource
->DryGainHFAuto
= AL_TRUE
;
2027 pSource
->WetGainAuto
= AL_TRUE
;
2028 pSource
->WetGainHFAuto
= AL_TRUE
;
2029 pSource
->AirAbsorptionFactor
= 0.0f
;
2030 pSource
->RoomRolloffFactor
= 0.0f
;
2031 pSource
->DopplerFactor
= 1.0f
;
2033 pSource
->DistanceModel
= Context
->DistanceModel
;
2035 pSource
->state
= AL_INITIAL
;
2036 pSource
->lSourceType
= AL_UNDETERMINED
;
2038 pSource
->ulBufferID
= 0;
2045 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
2046 The offset is relative to the start of the queue (not the start of the current buffer)
2048 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
, ALuint updateSize
)
2050 ALbufferlistitem
*pBufferList
;
2052 ALfloat flBufferFreq
;
2054 ALint readPos
, writePos
;
2055 ALenum eOriginalFormat
;
2056 ALboolean bReturn
= AL_TRUE
;
2057 ALint lTotalBufferDataSize
;
2059 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
2061 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
2062 // Get Current Buffer Size and frequency (in milliseconds)
2063 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
2064 eOriginalFormat
= pBuffer
->eOriginalFormat
;
2065 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2067 // Get Current BytesPlayed
2068 readPos
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2069 // Add byte length of any processed buffers in the queue
2070 pBufferList
= pSource
->queue
;
2071 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2073 readPos
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2074 pBufferList
= pBufferList
->next
;
2077 if(pSource
->state
== AL_PLAYING
)
2078 writePos
= readPos
+ (updateSize
* lChannels
* 2);
2082 lTotalBufferDataSize
= 0;
2083 pBufferList
= pSource
->queue
;
2086 if (pBufferList
->buffer
)
2087 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2088 pBufferList
= pBufferList
->next
;
2091 if (pSource
->bLooping
)
2096 readPos
%= lTotalBufferDataSize
;
2100 writePos
%= lTotalBufferDataSize
;
2104 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2107 else if(readPos
> lTotalBufferDataSize
)
2108 readPos
= lTotalBufferDataSize
;
2111 else if(writePos
> lTotalBufferDataSize
)
2112 writePos
= lTotalBufferDataSize
;
2118 case AL_SEC_RW_OFFSETS_EXT
:
2119 pflOffset
[0] = (ALfloat
)readPos
/ (lChannels
* 2.0f
* flBufferFreq
);
2120 pflOffset
[1] = (ALfloat
)writePos
/ (lChannels
* 2.0f
* flBufferFreq
);
2122 case AL_SAMPLE_OFFSET
:
2123 case AL_SAMPLE_RW_OFFSETS_EXT
:
2124 pflOffset
[0] = (ALfloat
)(readPos
/ (lChannels
* 2));
2125 pflOffset
[1] = (ALfloat
)(writePos
/ (lChannels
* 2));
2127 case AL_BYTE_OFFSET
:
2128 case AL_BYTE_RW_OFFSETS_EXT
:
2129 // Take into account the original format of the Buffer
2130 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2131 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2133 // Round down to nearest ADPCM block
2134 pflOffset
[0] = (ALfloat
)((readPos
/ (65 * 2 * lChannels
)) * 36 * lChannels
);
2135 if(pSource
->state
== AL_PLAYING
)
2137 // Round up to nearest ADPCM block
2138 pflOffset
[1] = (ALfloat
)(((writePos
+ (65 * 2 * lChannels
) - 1) / (65 * 2 * lChannels
)) * 36 * lChannels
);
2141 pflOffset
[1] = pflOffset
[0];
2143 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2145 pflOffset
[0] = (ALfloat
)(readPos
>> 2);
2146 pflOffset
[1] = (ALfloat
)(writePos
>> 2);
2148 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2150 pflOffset
[0] = (ALfloat
)(readPos
>> 1);
2151 pflOffset
[1] = (ALfloat
)(writePos
>> 1);
2153 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2155 pflOffset
[0] = (ALfloat
)(readPos
>> 1);
2156 pflOffset
[1] = (ALfloat
)(writePos
>> 1);
2158 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2160 pflOffset
[0] = (ALfloat
)(readPos
<< 1);
2161 pflOffset
[1] = (ALfloat
)(writePos
<< 1);
2165 pflOffset
[0] = (ALfloat
)readPos
;
2166 pflOffset
[1] = (ALfloat
)writePos
;
2173 pflOffset
[0] = 0.0f
;
2174 pflOffset
[1] = 0.0f
;
2184 Apply a playback offset to the Source. This function will update the queue (to correctly
2185 mark buffers as 'pending' or 'processed' depending upon the new offset.
2187 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2189 ALbufferlistitem
*pBufferList
;
2191 ALint lBufferSize
, lTotalBufferSize
;
2194 // Get true byte offset
2195 lByteOffset
= GetByteOffset(pSource
);
2197 // If this is a valid offset apply it
2198 if (lByteOffset
!= -1)
2200 // Sort out the queue (pending and processed states)
2201 pBufferList
= pSource
->queue
;
2202 lTotalBufferSize
= 0;
2203 pSource
->BuffersPlayed
= 0;
2206 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2207 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2209 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2211 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2212 // update the state to PROCESSED
2213 pSource
->BuffersPlayed
++;
2215 if (!pSource
->bLooping
)
2216 pBufferList
->bufferstate
= PROCESSED
;
2218 else if (lTotalBufferSize
<= lByteOffset
)
2220 // Offset is within this buffer
2221 pBufferList
->bufferstate
= PENDING
;
2223 // Set Current Buffer ID
2224 pSource
->ulBufferID
= pBufferList
->buffer
;
2226 // SW Mixer Positions are in Samples
2227 pSource
->position
= (lByteOffset
- lTotalBufferSize
) /
2228 aluBytesFromFormat(pBuffer
->format
) /
2229 aluChannelsFromFormat(pBuffer
->format
);
2233 // Offset is before this buffer, so mark as pending
2234 pBufferList
->bufferstate
= PENDING
;
2237 // Increment the TotalBufferSize
2238 lTotalBufferSize
+= lBufferSize
;
2240 // Move on to next buffer in the Queue
2241 pBufferList
= pBufferList
->next
;
2247 alSetError(AL_INVALID_VALUE
);
2251 pSource
->lOffset
= 0;
2258 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2259 offset supplied by the application). This takes into account the fact that the buffer format
2260 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2262 static ALint
GetByteOffset(ALsource
*pSource
)
2264 ALbuffer
*pBuffer
= NULL
;
2265 ALbufferlistitem
*pBufferList
;
2266 ALfloat flBufferFreq
;
2268 ALint lByteOffset
= -1;
2269 ALint lTotalBufferDataSize
;
2271 // Find the first non-NULL Buffer in the Queue
2272 pBufferList
= pSource
->queue
;
2275 if (pBufferList
->buffer
)
2277 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2280 pBufferList
= pBufferList
->next
;
2285 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2286 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2288 // Determine the ByteOffset (and ensure it is block aligned)
2289 switch (pSource
->lOffsetType
)
2291 case AL_BYTE_OFFSET
:
2292 // Take into consideration the original format
2293 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2294 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2296 // Round down to nearest ADPCM block
2297 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2298 // Multiply by compression rate
2299 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2300 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2302 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2304 lByteOffset
= pSource
->lOffset
* 4;
2305 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2307 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2309 lByteOffset
= pSource
->lOffset
* 2;
2310 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2312 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2314 lByteOffset
= pSource
->lOffset
* 2;
2315 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2317 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2319 lByteOffset
= pSource
->lOffset
/ 2;
2320 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2324 lByteOffset
= pSource
->lOffset
;
2325 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2329 case AL_SAMPLE_OFFSET
:
2330 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2334 // Note - lOffset is internally stored as Milliseconds
2335 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2336 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2340 lTotalBufferDataSize
= 0;
2341 pBufferList
= pSource
->queue
;
2344 if (pBufferList
->buffer
)
2345 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2346 pBufferList
= pBufferList
->next
;
2349 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2350 if (lByteOffset
>= lTotalBufferDataSize
)
2358 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2361 if(Context
->SourceCount
> 0)
2362 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", Context
->SourceCount
);
2365 while(Context
->Source
)
2367 ALsource
*temp
= Context
->Source
;
2368 Context
->Source
= Context
->Source
->next
;
2370 // Release source structure
2371 ALTHUNK_REMOVEENTRY(temp
->source
);
2372 memset(temp
, 0, sizeof(ALsource
));
2375 Context
->SourceCount
= 0;