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
<= 1.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 pSource
->WetGain
= 0.0f
;
1449 if (pSource
->state
!= AL_PAUSED
)
1451 pSource
->state
= AL_PLAYING
;
1452 pSource
->inuse
= AL_TRUE
;
1453 pSource
->play
= AL_TRUE
;
1454 pSource
->position
= 0;
1455 pSource
->position_fraction
= 0;
1456 pSource
->BuffersPlayed
= 0;
1457 pSource
->FirstStart
= AL_TRUE
;
1459 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1461 // Make sure all the Buffers in the queue are marked as PENDING
1462 ALBufferList
= pSource
->queue
;
1463 while (ALBufferList
)
1465 ALBufferList
->bufferstate
= PENDING
;
1466 ALBufferList
= ALBufferList
->next
;
1471 pSource
->state
= AL_PLAYING
;
1472 pSource
->inuse
= AL_TRUE
;
1473 pSource
->play
= AL_TRUE
;
1474 pSource
->FirstStart
= AL_FALSE
;
1477 // Check if an Offset has been set
1478 if (pSource
->lOffset
)
1479 ApplyOffset(pSource
, AL_FALSE
);
1483 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1484 ALBufferList
= pSource
->queue
;
1485 while (ALBufferList
)
1487 ALBufferList
->bufferstate
= PROCESSED
;
1488 ALBufferList
= ALBufferList
->next
;
1491 pSource
->BuffersPlayed
= pSource
->BuffersInQueue
;
1498 // sources is a NULL pointer
1499 alSetError(AL_INVALID_VALUE
);
1502 ProcessContext(pContext
);
1507 alSetError(AL_INVALID_OPERATION
);
1513 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1515 alSourcePausev(1, &source
);
1519 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1521 ALCcontext
*Context
;
1524 ALboolean bSourcesValid
= AL_TRUE
;
1526 Context
=alcGetCurrentContext();
1529 SuspendContext(Context
);
1533 // Check all the Sources are valid
1536 if (!alIsSource(sources
[i
]))
1538 alSetError(AL_INVALID_NAME
);
1539 bSourcesValid
= AL_FALSE
;
1548 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1549 if (Source
->state
==AL_PLAYING
)
1551 Source
->state
=AL_PAUSED
;
1552 Source
->inuse
=AL_FALSE
;
1559 // sources is a NULL pointer
1560 alSetError(AL_INVALID_VALUE
);
1563 ProcessContext(Context
);
1568 alSetError(AL_INVALID_OPERATION
);
1574 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1576 alSourceStopv(1, &source
);
1580 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1582 ALCcontext
*Context
;
1585 ALbufferlistitem
*ALBufferListItem
;
1586 ALboolean bSourcesValid
= AL_TRUE
;
1588 Context
=alcGetCurrentContext();
1591 SuspendContext(Context
);
1595 // Check all the Sources are valid
1598 if (!alIsSource(sources
[i
]))
1600 alSetError(AL_INVALID_NAME
);
1601 bSourcesValid
= AL_FALSE
;
1610 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1611 if (Source
->state
!=AL_INITIAL
)
1613 Source
->state
=AL_STOPPED
;
1614 Source
->inuse
=AL_FALSE
;
1615 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1616 ALBufferListItem
= Source
->queue
;
1617 while (ALBufferListItem
!= NULL
)
1619 ALBufferListItem
->bufferstate
= PROCESSED
;
1620 ALBufferListItem
= ALBufferListItem
->next
;
1623 Source
->lOffset
= 0;
1629 // sources is a NULL pointer
1630 alSetError(AL_INVALID_VALUE
);
1633 ProcessContext(Context
);
1638 alSetError(AL_INVALID_OPERATION
);
1644 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1646 alSourceRewindv(1, &source
);
1650 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1652 ALCcontext
*Context
;
1655 ALbufferlistitem
*ALBufferListItem
;
1656 ALboolean bSourcesValid
= AL_TRUE
;
1658 Context
=alcGetCurrentContext();
1661 SuspendContext(Context
);
1665 // Check all the Sources are valid
1668 if (!alIsSource(sources
[i
]))
1670 alSetError(AL_INVALID_NAME
);
1671 bSourcesValid
= AL_FALSE
;
1680 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1681 if (Source
->state
!=AL_INITIAL
)
1683 Source
->state
=AL_INITIAL
;
1684 Source
->inuse
=AL_FALSE
;
1686 Source
->position_fraction
=0;
1687 Source
->BuffersPlayed
= 0;
1688 ALBufferListItem
= Source
->queue
;
1689 while (ALBufferListItem
!= NULL
)
1691 ALBufferListItem
->bufferstate
= PENDING
;
1692 ALBufferListItem
= ALBufferListItem
->next
;
1695 Source
->ulBufferID
= Source
->queue
->buffer
;
1697 Source
->lOffset
= 0;
1703 // sources is a NULL pointer
1704 alSetError(AL_INVALID_VALUE
);
1707 ProcessContext(Context
);
1712 alSetError(AL_INVALID_OPERATION
);
1719 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1721 ALCcontext
*Context
;
1724 ALbufferlistitem
*ALBufferList
;
1725 ALbufferlistitem
*ALBufferListStart
;
1730 ALboolean bBuffersValid
= AL_TRUE
;
1735 Context
=alcGetCurrentContext();
1738 SuspendContext(Context
);
1743 // Check that all buffers are valid or zero and that the source is valid
1745 // Check that this is a valid source
1746 if (alIsSource(source
))
1748 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1750 // Check that this is not a STATIC Source
1751 if (ALSource
->lSourceType
!= AL_STATIC
)
1756 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1757 ALBufferList
= ALSource
->queue
;
1758 while (ALBufferList
)
1760 if (ALBufferList
->buffer
)
1762 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1763 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1766 ALBufferList
= ALBufferList
->next
;
1769 for (i
= 0; i
< n
; i
++)
1771 if (alIsBuffer(buffers
[i
]))
1775 if ((iFrequency
== -1) && (iFormat
== -1))
1777 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1778 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1782 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1783 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1785 alSetError(AL_INVALID_OPERATION
);
1786 bBuffersValid
= AL_FALSE
;
1794 alSetError(AL_INVALID_NAME
);
1795 bBuffersValid
= AL_FALSE
;
1802 // Change Source Type
1803 ALSource
->lSourceType
= AL_STREAMING
;
1805 // All buffers are valid - so add them to the list
1806 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1807 ALBufferListStart
->buffer
= buffers
[0];
1808 ALBufferListStart
->bufferstate
= PENDING
;
1809 ALBufferListStart
->flag
= 0;
1810 ALBufferListStart
->next
= NULL
;
1813 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1817 DataSize
+= BufferSize
;
1819 // Increment reference counter for buffer
1821 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1823 ALBufferList
= ALBufferListStart
;
1825 for (i
= 1; i
< n
; i
++)
1827 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1828 ALBufferList
->next
->buffer
= buffers
[i
];
1829 ALBufferList
->next
->bufferstate
= PENDING
;
1830 ALBufferList
->next
->flag
= 0;
1831 ALBufferList
->next
->next
= NULL
;
1834 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1838 DataSize
+= BufferSize
;
1840 // Increment reference counter for buffer
1842 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1844 ALBufferList
= ALBufferList
->next
;
1847 if (ALSource
->queue
== NULL
)
1849 ALSource
->queue
= ALBufferListStart
;
1850 // Update Current Buffer
1851 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1855 // Find end of queue
1856 ALBufferList
= ALSource
->queue
;
1857 while (ALBufferList
->next
!= NULL
)
1859 ALBufferList
= ALBufferList
->next
;
1862 ALBufferList
->next
= ALBufferListStart
;
1865 // Update number of buffers in queue
1866 ALSource
->BuffersInQueue
+= n
;
1871 // Invalid Source Type (can't queue on a Static Source)
1872 alSetError(AL_INVALID_OPERATION
);
1877 // Invalid Source Name
1878 alSetError(AL_INVALID_NAME
);
1881 ProcessContext(Context
);
1886 alSetError(AL_INVALID_OPERATION
);
1893 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1894 // an array of buffer IDs that are to be filled with the names of the buffers removed
1895 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1897 ALCcontext
*Context
;
1900 ALbufferlistitem
*ALBufferList
;
1904 ALboolean bBuffersProcessed
;
1911 bBuffersProcessed
= AL_TRUE
;
1913 Context
=alcGetCurrentContext();
1916 SuspendContext(Context
);
1918 if (alIsSource(source
))
1920 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1922 // Check that all 'n' buffers have been processed
1923 ALBufferList
= ALSource
->queue
;
1924 for (i
= 0; i
< n
; i
++)
1926 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1928 ALBufferList
= ALBufferList
->next
;
1932 bBuffersProcessed
= AL_FALSE
;
1937 // If all 'n' buffers have been processed, remove them from the queue
1938 if (bBuffersProcessed
)
1940 for (i
= 0; i
< n
; i
++)
1942 ALBufferList
= ALSource
->queue
;
1944 ALSource
->queue
= ALBufferList
->next
;
1945 // Record name of buffer
1946 buffers
[i
] = ALBufferList
->buffer
;
1947 // Decrement buffer reference counter
1948 if (ALBufferList
->buffer
)
1949 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1950 // Record size of buffer
1951 if (ALBufferList
->buffer
)
1952 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1956 DataSize
+= BufferSize
;
1957 // Release memory for buffer list item
1959 ALSource
->BuffersInQueue
--;
1962 if (ALSource
->state
!= AL_PLAYING
)
1964 if (ALSource
->queue
)
1965 BufferID
= ALSource
->queue
->buffer
;
1969 ALSource
->ulBufferID
= BufferID
;
1972 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1973 ALSource
->BuffersPlayed
= 0;
1975 ALSource
->BuffersPlayed
-= n
;
1979 // Some buffers can't be unqueue because they have not been processed
1980 alSetError(AL_INVALID_VALUE
);
1985 // Invalid Source Name
1986 alSetError(AL_INVALID_NAME
);
1989 ProcessContext(Context
);
1994 alSetError(AL_INVALID_OPERATION
);
2001 static ALvoid
InitSourceParams(ALCcontext
*Context
, ALsource
*pSource
)
2003 pSource
->flInnerAngle
= 360.0f
;
2004 pSource
->flOuterAngle
= 360.0f
;
2005 pSource
->flPitch
= 1.0f
;
2006 pSource
->vPosition
[0] = 0.0f
;
2007 pSource
->vPosition
[1] = 0.0f
;
2008 pSource
->vPosition
[2] = 0.0f
;
2009 pSource
->vOrientation
[0] = 0.0f
;
2010 pSource
->vOrientation
[1] = 0.0f
;
2011 pSource
->vOrientation
[2] = 0.0f
;
2012 pSource
->vVelocity
[0] = 0.0f
;
2013 pSource
->vVelocity
[1] = 0.0f
;
2014 pSource
->vVelocity
[2] = 0.0f
;
2015 pSource
->flRefDistance
= 1.0f
;
2016 pSource
->flMaxDistance
= FLT_MAX
;
2017 pSource
->flRollOffFactor
= 1.0f
;
2018 pSource
->bLooping
= AL_FALSE
;
2019 pSource
->flGain
= 1.0f
;
2020 pSource
->flMinGain
= 0.0f
;
2021 pSource
->flMaxGain
= 1.0f
;
2022 pSource
->flOuterGain
= 0.0f
;
2023 pSource
->OuterGainHF
= 1.0f
;
2025 pSource
->DryGainHFAuto
= AL_TRUE
;
2026 pSource
->WetGainAuto
= AL_TRUE
;
2027 pSource
->WetGainHFAuto
= AL_TRUE
;
2028 pSource
->AirAbsorptionFactor
= 0.0f
;
2029 pSource
->RoomRolloffFactor
= 0.0f
;
2030 pSource
->DopplerFactor
= 1.0f
;
2032 pSource
->DistanceModel
= Context
->DistanceModel
;
2034 pSource
->state
= AL_INITIAL
;
2035 pSource
->lSourceType
= AL_UNDETERMINED
;
2037 pSource
->ulBufferID
= 0;
2044 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
2045 The offset is relative to the start of the queue (not the start of the current buffer)
2047 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
, ALuint updateSize
)
2049 ALbufferlistitem
*pBufferList
;
2051 ALfloat flBufferFreq
;
2053 ALint readPos
, writePos
;
2054 ALenum eOriginalFormat
;
2055 ALboolean bReturn
= AL_TRUE
;
2056 ALint lTotalBufferDataSize
;
2058 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
2060 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
2061 // Get Current Buffer Size and frequency (in milliseconds)
2062 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
2063 eOriginalFormat
= pBuffer
->eOriginalFormat
;
2064 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2066 // Get Current BytesPlayed
2067 readPos
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2068 // Add byte length of any processed buffers in the queue
2069 pBufferList
= pSource
->queue
;
2070 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2072 readPos
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2073 pBufferList
= pBufferList
->next
;
2076 if(pSource
->state
== AL_PLAYING
)
2077 writePos
= readPos
+ (updateSize
* lChannels
* 2);
2081 lTotalBufferDataSize
= 0;
2082 pBufferList
= pSource
->queue
;
2085 if (pBufferList
->buffer
)
2086 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2087 pBufferList
= pBufferList
->next
;
2090 if (pSource
->bLooping
)
2095 readPos
%= lTotalBufferDataSize
;
2099 writePos
%= lTotalBufferDataSize
;
2103 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2106 else if(readPos
> lTotalBufferDataSize
)
2107 readPos
= lTotalBufferDataSize
;
2110 else if(writePos
> lTotalBufferDataSize
)
2111 writePos
= lTotalBufferDataSize
;
2117 case AL_SEC_RW_OFFSETS_EXT
:
2118 pflOffset
[0] = (ALfloat
)readPos
/ (lChannels
* 2.0f
* flBufferFreq
);
2119 pflOffset
[1] = (ALfloat
)writePos
/ (lChannels
* 2.0f
* flBufferFreq
);
2121 case AL_SAMPLE_OFFSET
:
2122 case AL_SAMPLE_RW_OFFSETS_EXT
:
2123 pflOffset
[0] = (ALfloat
)(readPos
/ (lChannels
* 2));
2124 pflOffset
[1] = (ALfloat
)(writePos
/ (lChannels
* 2));
2126 case AL_BYTE_OFFSET
:
2127 case AL_BYTE_RW_OFFSETS_EXT
:
2128 // Take into account the original format of the Buffer
2129 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2130 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2132 // Round down to nearest ADPCM block
2133 pflOffset
[0] = (ALfloat
)((readPos
/ (65 * 2 * lChannels
)) * 36 * lChannels
);
2134 if(pSource
->state
== AL_PLAYING
)
2136 // Round up to nearest ADPCM block
2137 pflOffset
[1] = (ALfloat
)(((writePos
+ (65 * 2 * lChannels
) - 1) / (65 * 2 * lChannels
)) * 36 * lChannels
);
2140 pflOffset
[1] = pflOffset
[0];
2142 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2144 pflOffset
[0] = (ALfloat
)(readPos
>> 2);
2145 pflOffset
[1] = (ALfloat
)(writePos
>> 2);
2147 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2149 pflOffset
[0] = (ALfloat
)(readPos
>> 1);
2150 pflOffset
[1] = (ALfloat
)(writePos
>> 1);
2152 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2154 pflOffset
[0] = (ALfloat
)(readPos
>> 1);
2155 pflOffset
[1] = (ALfloat
)(writePos
>> 1);
2157 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2159 pflOffset
[0] = (ALfloat
)(readPos
<< 1);
2160 pflOffset
[1] = (ALfloat
)(writePos
<< 1);
2164 pflOffset
[0] = (ALfloat
)readPos
;
2165 pflOffset
[1] = (ALfloat
)writePos
;
2172 pflOffset
[0] = 0.0f
;
2173 pflOffset
[1] = 0.0f
;
2183 Apply a playback offset to the Source. This function will update the queue (to correctly
2184 mark buffers as 'pending' or 'processed' depending upon the new offset.
2186 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2188 ALbufferlistitem
*pBufferList
;
2190 ALint lBufferSize
, lTotalBufferSize
;
2193 // Get true byte offset
2194 lByteOffset
= GetByteOffset(pSource
);
2196 // If this is a valid offset apply it
2197 if (lByteOffset
!= -1)
2199 // Sort out the queue (pending and processed states)
2200 pBufferList
= pSource
->queue
;
2201 lTotalBufferSize
= 0;
2202 pSource
->BuffersPlayed
= 0;
2205 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2206 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2208 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2210 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2211 // update the state to PROCESSED
2212 pSource
->BuffersPlayed
++;
2214 if (!pSource
->bLooping
)
2215 pBufferList
->bufferstate
= PROCESSED
;
2217 else if (lTotalBufferSize
<= lByteOffset
)
2219 // Offset is within this buffer
2220 pBufferList
->bufferstate
= PENDING
;
2222 // Set Current Buffer ID
2223 pSource
->ulBufferID
= pBufferList
->buffer
;
2225 // SW Mixer Positions are in Samples
2226 pSource
->position
= (lByteOffset
- lTotalBufferSize
) /
2227 aluBytesFromFormat(pBuffer
->format
) /
2228 aluChannelsFromFormat(pBuffer
->format
);
2232 // Offset is before this buffer, so mark as pending
2233 pBufferList
->bufferstate
= PENDING
;
2236 // Increment the TotalBufferSize
2237 lTotalBufferSize
+= lBufferSize
;
2239 // Move on to next buffer in the Queue
2240 pBufferList
= pBufferList
->next
;
2246 alSetError(AL_INVALID_VALUE
);
2250 pSource
->lOffset
= 0;
2257 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2258 offset supplied by the application). This takes into account the fact that the buffer format
2259 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2261 static ALint
GetByteOffset(ALsource
*pSource
)
2263 ALbuffer
*pBuffer
= NULL
;
2264 ALbufferlistitem
*pBufferList
;
2265 ALfloat flBufferFreq
;
2267 ALint lByteOffset
= -1;
2268 ALint lTotalBufferDataSize
;
2270 // Find the first non-NULL Buffer in the Queue
2271 pBufferList
= pSource
->queue
;
2274 if (pBufferList
->buffer
)
2276 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2279 pBufferList
= pBufferList
->next
;
2284 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2285 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2287 // Determine the ByteOffset (and ensure it is block aligned)
2288 switch (pSource
->lOffsetType
)
2290 case AL_BYTE_OFFSET
:
2291 // Take into consideration the original format
2292 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2293 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2295 // Round down to nearest ADPCM block
2296 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2297 // Multiply by compression rate
2298 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2299 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2301 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2303 lByteOffset
= pSource
->lOffset
* 4;
2304 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2306 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2308 lByteOffset
= pSource
->lOffset
* 2;
2309 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2311 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2313 lByteOffset
= pSource
->lOffset
* 2;
2314 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2316 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2318 lByteOffset
= pSource
->lOffset
/ 2;
2319 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2323 lByteOffset
= pSource
->lOffset
;
2324 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2328 case AL_SAMPLE_OFFSET
:
2329 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2333 // Note - lOffset is internally stored as Milliseconds
2334 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2335 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2339 lTotalBufferDataSize
= 0;
2340 pBufferList
= pSource
->queue
;
2343 if (pBufferList
->buffer
)
2344 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2345 pBufferList
= pBufferList
->next
;
2348 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2349 if (lByteOffset
>= lTotalBufferDataSize
)
2357 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2360 if(Context
->SourceCount
> 0)
2361 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", Context
->SourceCount
);
2364 while(Context
->Source
)
2366 ALsource
*temp
= Context
->Source
;
2367 Context
->Source
= Context
->Source
->next
;
2369 // Release source structure
2370 ALTHUNK_REMOVEENTRY(temp
->source
);
2371 memset(temp
, 0, sizeof(ALsource
));
2374 Context
->SourceCount
= 0;