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(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(*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
);
708 alSetError(AL_INVALID_ENUM
);
713 alSetError(AL_INVALID_NAME
);
715 ProcessContext(pContext
);
718 alSetError(AL_INVALID_OPERATION
);
724 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
726 ALCcontext
*pContext
;
728 pContext
= alcGetCurrentContext();
731 SuspendContext(pContext
);
733 if (alIsSource(source
))
735 ALsource
*pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
742 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
745 case AL_AUXILIARY_SEND_FILTER
:
746 if(lValue2
>= 0 && lValue2
< MAX_SENDS
&&
747 (alIsAuxiliaryEffectSlot(lValue1
) || lValue1
== 0) &&
750 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(lValue1
);
751 ALfilter
*ALFilter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue3
);
753 /* Release refcount on the previous slot, and add one for
755 if(pSource
->Send
[lValue2
].Slot
)
756 pSource
->Send
[lValue2
].Slot
->refcount
--;
757 pSource
->Send
[lValue2
].Slot
= ALEffectSlot
;
758 if(pSource
->Send
[lValue2
].Slot
)
759 pSource
->Send
[lValue2
].Slot
->refcount
++;
764 pSource
->Send
[lValue2
].WetFilter
.type
= 0;
765 pSource
->Send
[lValue2
].WetFilter
.filter
= 0;
768 memcpy(&pSource
->Send
[lValue2
].WetFilter
, ALFilter
, sizeof(*ALFilter
));
771 alSetError(AL_INVALID_VALUE
);
775 alSetError(AL_INVALID_ENUM
);
780 alSetError(AL_INVALID_NAME
);
782 ProcessContext(pContext
);
785 alSetError(AL_INVALID_OPERATION
);
791 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
793 ALCcontext
*pContext
;
795 pContext
= alcGetCurrentContext();
798 SuspendContext(pContext
);
802 if (alIsSource(source
))
806 case AL_SOURCE_RELATIVE
:
807 case AL_CONE_INNER_ANGLE
:
808 case AL_CONE_OUTER_ANGLE
:
811 case AL_SOURCE_STATE
:
813 case AL_SAMPLE_OFFSET
:
815 case AL_MAX_DISTANCE
:
816 case AL_ROLLOFF_FACTOR
:
817 case AL_REFERENCE_DISTANCE
:
818 case AL_DIRECT_FILTER
:
819 case AL_DIRECT_FILTER_GAINHF_AUTO
:
820 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
821 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
822 alSourcei(source
, eParam
, plValues
[0]);
828 case AL_AUXILIARY_SEND_FILTER
:
829 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
833 alSetError(AL_INVALID_ENUM
);
838 alSetError(AL_INVALID_NAME
);
841 alSetError(AL_INVALID_VALUE
);
843 ProcessContext(pContext
);
846 alSetError(AL_INVALID_OPERATION
);
852 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
854 ALCcontext
*pContext
;
858 pContext
= alcGetCurrentContext();
861 SuspendContext(pContext
);
865 if (alIsSource(source
))
867 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
872 *pflValue
= pSource
->flPitch
;
876 *pflValue
= pSource
->flGain
;
880 *pflValue
= pSource
->flMinGain
;
884 *pflValue
= pSource
->flMaxGain
;
887 case AL_MAX_DISTANCE
:
888 *pflValue
= pSource
->flMaxDistance
;
891 case AL_ROLLOFF_FACTOR
:
892 *pflValue
= pSource
->flRollOffFactor
;
895 case AL_CONE_OUTER_GAIN
:
896 *pflValue
= pSource
->flOuterGain
;
899 case AL_CONE_OUTER_GAINHF
:
900 *pflValue
= pSource
->OuterGainHF
;
904 case AL_SAMPLE_OFFSET
:
906 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
907 *pflValue
= flOffset
[0];
909 alSetError(AL_INVALID_OPERATION
);
912 case AL_SEC_RW_OFFSETS_EXT
:
913 case AL_SAMPLE_RW_OFFSETS_EXT
:
914 case AL_BYTE_RW_OFFSETS_EXT
:
915 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
917 pflValue
[0] = flOffset
[0];
918 pflValue
[1] = flOffset
[1];
921 alSetError(AL_INVALID_OPERATION
);
924 case AL_CONE_INNER_ANGLE
:
925 *pflValue
= pSource
->flInnerAngle
;
928 case AL_CONE_OUTER_ANGLE
:
929 *pflValue
= pSource
->flOuterAngle
;
932 case AL_REFERENCE_DISTANCE
:
933 *pflValue
= pSource
->flRefDistance
;
936 case AL_AIR_ABSORPTION_FACTOR
:
937 *pflValue
= pSource
->AirAbsorptionFactor
;
940 case AL_ROOM_ROLLOFF_FACTOR
:
941 *pflValue
= pSource
->RoomRolloffFactor
;
944 case AL_DOPPLER_FACTOR
:
945 *pflValue
= pSource
->DopplerFactor
;
949 alSetError(AL_INVALID_ENUM
);
954 alSetError(AL_INVALID_NAME
);
957 alSetError(AL_INVALID_VALUE
);
959 ProcessContext(pContext
);
962 alSetError(AL_INVALID_OPERATION
);
968 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
970 ALCcontext
*pContext
;
973 pContext
= alcGetCurrentContext();
976 SuspendContext(pContext
);
978 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
980 if (alIsSource(source
))
982 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
987 *pflValue1
= pSource
->vPosition
[0];
988 *pflValue2
= pSource
->vPosition
[1];
989 *pflValue3
= pSource
->vPosition
[2];
993 *pflValue1
= pSource
->vVelocity
[0];
994 *pflValue2
= pSource
->vVelocity
[1];
995 *pflValue3
= pSource
->vVelocity
[2];
999 *pflValue1
= pSource
->vOrientation
[0];
1000 *pflValue2
= pSource
->vOrientation
[1];
1001 *pflValue3
= pSource
->vOrientation
[2];
1005 alSetError(AL_INVALID_ENUM
);
1010 alSetError(AL_INVALID_NAME
);
1013 alSetError(AL_INVALID_VALUE
);
1015 ProcessContext(pContext
);
1018 alSetError(AL_INVALID_OPERATION
);
1024 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1026 ALCcontext
*pContext
;
1029 pContext
= alcGetCurrentContext();
1032 SuspendContext(pContext
);
1036 if (alIsSource(source
))
1038 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1046 case AL_MAX_DISTANCE
:
1047 case AL_ROLLOFF_FACTOR
:
1048 case AL_DOPPLER_FACTOR
:
1049 case AL_CONE_OUTER_GAIN
:
1051 case AL_SAMPLE_OFFSET
:
1052 case AL_BYTE_OFFSET
:
1053 case AL_CONE_INNER_ANGLE
:
1054 case AL_CONE_OUTER_ANGLE
:
1055 case AL_REFERENCE_DISTANCE
:
1056 case AL_CONE_OUTER_GAINHF
:
1057 case AL_AIR_ABSORPTION_FACTOR
:
1058 case AL_ROOM_ROLLOFF_FACTOR
:
1059 alGetSourcef(source
, eParam
, pflValues
);
1063 pflValues
[0] = pSource
->vPosition
[0];
1064 pflValues
[1] = pSource
->vPosition
[1];
1065 pflValues
[2] = pSource
->vPosition
[2];
1069 pflValues
[0] = pSource
->vVelocity
[0];
1070 pflValues
[1] = pSource
->vVelocity
[1];
1071 pflValues
[2] = pSource
->vVelocity
[2];
1075 pflValues
[0] = pSource
->vOrientation
[0];
1076 pflValues
[1] = pSource
->vOrientation
[1];
1077 pflValues
[2] = pSource
->vOrientation
[2];
1081 alSetError(AL_INVALID_ENUM
);
1086 alSetError(AL_INVALID_NAME
);
1089 alSetError(AL_INVALID_VALUE
);
1091 ProcessContext(pContext
);
1094 alSetError(AL_INVALID_OPERATION
);
1100 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1102 ALCcontext
*pContext
;
1104 ALfloat flOffset
[2];
1106 pContext
= alcGetCurrentContext();
1109 SuspendContext(pContext
);
1113 if (alIsSource(source
))
1115 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1119 case AL_MAX_DISTANCE
:
1120 *plValue
= (ALint
)pSource
->flMaxDistance
;
1123 case AL_ROLLOFF_FACTOR
:
1124 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1127 case AL_REFERENCE_DISTANCE
:
1128 *plValue
= (ALint
)pSource
->flRefDistance
;
1131 case AL_SOURCE_RELATIVE
:
1132 *plValue
= pSource
->bHeadRelative
;
1135 case AL_CONE_INNER_ANGLE
:
1136 *plValue
= (ALint
)pSource
->flInnerAngle
;
1139 case AL_CONE_OUTER_ANGLE
:
1140 *plValue
= (ALint
)pSource
->flOuterAngle
;
1144 *plValue
= pSource
->bLooping
;
1148 *plValue
= pSource
->ulBufferID
;
1151 case AL_SOURCE_STATE
:
1152 *plValue
= pSource
->state
;
1155 case AL_BUFFERS_QUEUED
:
1156 *plValue
= pSource
->BuffersInQueue
;
1159 case AL_BUFFERS_PROCESSED
:
1160 if(pSource
->bLooping
)
1162 /* Buffers on a looping source are in a perpetual state
1163 * of PENDING, so don't report any as PROCESSED */
1167 *plValue
= pSource
->BuffersPlayed
;
1170 case AL_SOURCE_TYPE
:
1171 *plValue
= pSource
->lSourceType
;
1175 case AL_SAMPLE_OFFSET
:
1176 case AL_BYTE_OFFSET
:
1177 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
1178 *plValue
= (ALint
)flOffset
[0];
1180 alSetError(AL_INVALID_OPERATION
);
1183 case AL_SEC_RW_OFFSETS_EXT
:
1184 case AL_SAMPLE_RW_OFFSETS_EXT
:
1185 case AL_BYTE_RW_OFFSETS_EXT
:
1186 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
1188 plValue
[0] = (ALint
)flOffset
[0];
1189 plValue
[1] = (ALint
)flOffset
[1];
1192 alSetError(AL_INVALID_OPERATION
);
1195 case AL_DIRECT_FILTER
:
1196 *plValue
= pSource
->DirectFilter
.filter
;
1199 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1200 *plValue
= pSource
->DryGainHFAuto
;
1203 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1204 *plValue
= pSource
->WetGainAuto
;
1207 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1208 *plValue
= pSource
->WetGainHFAuto
;
1211 case AL_DOPPLER_FACTOR
:
1212 *plValue
= (ALint
)pSource
->DopplerFactor
;
1216 alSetError(AL_INVALID_ENUM
);
1221 alSetError(AL_INVALID_NAME
);
1224 alSetError(AL_INVALID_VALUE
);
1226 ProcessContext(pContext
);
1229 alSetError(AL_INVALID_OPERATION
);
1235 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1237 ALCcontext
*pContext
;
1240 pContext
= alcGetCurrentContext();
1243 SuspendContext(pContext
);
1245 if ((plValue1
) && (plValue2
) && (plValue3
))
1247 if (alIsSource(source
))
1249 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1254 *plValue1
= (ALint
)pSource
->vPosition
[0];
1255 *plValue2
= (ALint
)pSource
->vPosition
[1];
1256 *plValue3
= (ALint
)pSource
->vPosition
[2];
1260 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1261 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1262 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1266 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1267 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1268 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1272 alSetError(AL_INVALID_ENUM
);
1277 alSetError(AL_INVALID_NAME
);
1280 alSetError(AL_INVALID_VALUE
);
1282 ProcessContext(pContext
);
1285 alSetError(AL_INVALID_OPERATION
);
1291 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1293 ALCcontext
*pContext
;
1296 pContext
= alcGetCurrentContext();
1299 SuspendContext(pContext
);
1303 if (alIsSource(source
))
1305 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1309 case AL_SOURCE_RELATIVE
:
1310 case AL_CONE_INNER_ANGLE
:
1311 case AL_CONE_OUTER_ANGLE
:
1314 case AL_SOURCE_STATE
:
1315 case AL_BUFFERS_QUEUED
:
1316 case AL_BUFFERS_PROCESSED
:
1318 case AL_SAMPLE_OFFSET
:
1319 case AL_BYTE_OFFSET
:
1320 case AL_MAX_DISTANCE
:
1321 case AL_ROLLOFF_FACTOR
:
1322 case AL_DOPPLER_FACTOR
:
1323 case AL_REFERENCE_DISTANCE
:
1324 case AL_SOURCE_TYPE
:
1325 case AL_DIRECT_FILTER
:
1326 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1327 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1328 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1329 alGetSourcei(source
, eParam
, plValues
);
1333 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1334 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1335 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1339 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1340 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1341 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1345 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1346 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1347 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1351 alSetError(AL_INVALID_ENUM
);
1356 alSetError(AL_INVALID_NAME
);
1359 alSetError(AL_INVALID_VALUE
);
1361 ProcessContext(pContext
);
1364 alSetError(AL_INVALID_OPERATION
);
1370 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1372 alSourcePlayv(1, &source
);
1376 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1378 ALCcontext
*pContext
;
1380 ALbufferlistitem
*ALBufferList
;
1381 ALboolean bSourcesValid
= AL_TRUE
;
1385 pContext
= alcGetCurrentContext();
1388 SuspendContext(pContext
);
1392 // Check that all the Sources are valid
1393 for (i
= 0; i
< n
; i
++)
1395 if (!alIsSource(pSourceList
[i
]))
1397 alSetError(AL_INVALID_NAME
);
1398 bSourcesValid
= AL_FALSE
;
1405 for (i
= 0; i
< n
; i
++)
1407 // Assume Source won't need to play
1410 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1412 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1413 ALBufferList
= pSource
->queue
;
1414 while (ALBufferList
)
1416 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1421 ALBufferList
= ALBufferList
->next
;
1426 for(j
= 0;j
< OUTPUTCHANNELS
;j
++)
1427 pSource
->DryGains
[j
] = 0.0f
;
1428 pSource
->WetGain
= 0.0f
;
1430 if (pSource
->state
!= AL_PAUSED
)
1432 pSource
->state
= AL_PLAYING
;
1433 pSource
->inuse
= AL_TRUE
;
1434 pSource
->play
= AL_TRUE
;
1435 pSource
->position
= 0;
1436 pSource
->position_fraction
= 0;
1437 pSource
->BuffersPlayed
= 0;
1438 pSource
->FirstStart
= AL_TRUE
;
1440 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1442 // Make sure all the Buffers in the queue are marked as PENDING
1443 ALBufferList
= pSource
->queue
;
1444 while (ALBufferList
)
1446 ALBufferList
->bufferstate
= PENDING
;
1447 ALBufferList
= ALBufferList
->next
;
1452 pSource
->state
= AL_PLAYING
;
1453 pSource
->inuse
= AL_TRUE
;
1454 pSource
->play
= AL_TRUE
;
1455 pSource
->FirstStart
= AL_FALSE
;
1458 // Check if an Offset has been set
1459 if (pSource
->lOffset
)
1460 ApplyOffset(pSource
, AL_FALSE
);
1464 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1465 ALBufferList
= pSource
->queue
;
1466 while (ALBufferList
)
1468 ALBufferList
->bufferstate
= PROCESSED
;
1469 ALBufferList
= ALBufferList
->next
;
1472 pSource
->BuffersPlayed
= pSource
->BuffersInQueue
;
1479 // sources is a NULL pointer
1480 alSetError(AL_INVALID_VALUE
);
1483 ProcessContext(pContext
);
1488 alSetError(AL_INVALID_OPERATION
);
1494 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1496 alSourcePausev(1, &source
);
1500 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1502 ALCcontext
*Context
;
1505 ALboolean bSourcesValid
= AL_TRUE
;
1507 Context
=alcGetCurrentContext();
1510 SuspendContext(Context
);
1514 // Check all the Sources are valid
1517 if (!alIsSource(sources
[i
]))
1519 alSetError(AL_INVALID_NAME
);
1520 bSourcesValid
= AL_FALSE
;
1529 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1530 if (Source
->state
==AL_PLAYING
)
1532 Source
->state
=AL_PAUSED
;
1533 Source
->inuse
=AL_FALSE
;
1540 // sources is a NULL pointer
1541 alSetError(AL_INVALID_VALUE
);
1544 ProcessContext(Context
);
1549 alSetError(AL_INVALID_OPERATION
);
1555 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1557 alSourceStopv(1, &source
);
1561 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1563 ALCcontext
*Context
;
1566 ALbufferlistitem
*ALBufferListItem
;
1567 ALboolean bSourcesValid
= AL_TRUE
;
1569 Context
=alcGetCurrentContext();
1572 SuspendContext(Context
);
1576 // Check all the Sources are valid
1579 if (!alIsSource(sources
[i
]))
1581 alSetError(AL_INVALID_NAME
);
1582 bSourcesValid
= AL_FALSE
;
1591 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1592 if (Source
->state
!=AL_INITIAL
)
1594 Source
->state
=AL_STOPPED
;
1595 Source
->inuse
=AL_FALSE
;
1596 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1597 ALBufferListItem
= Source
->queue
;
1598 while (ALBufferListItem
!= NULL
)
1600 ALBufferListItem
->bufferstate
= PROCESSED
;
1601 ALBufferListItem
= ALBufferListItem
->next
;
1604 Source
->lOffset
= 0;
1610 // sources is a NULL pointer
1611 alSetError(AL_INVALID_VALUE
);
1614 ProcessContext(Context
);
1619 alSetError(AL_INVALID_OPERATION
);
1625 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1627 alSourceRewindv(1, &source
);
1631 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1633 ALCcontext
*Context
;
1636 ALbufferlistitem
*ALBufferListItem
;
1637 ALboolean bSourcesValid
= AL_TRUE
;
1639 Context
=alcGetCurrentContext();
1642 SuspendContext(Context
);
1646 // Check all the Sources are valid
1649 if (!alIsSource(sources
[i
]))
1651 alSetError(AL_INVALID_NAME
);
1652 bSourcesValid
= AL_FALSE
;
1661 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1662 if (Source
->state
!=AL_INITIAL
)
1664 Source
->state
=AL_INITIAL
;
1665 Source
->inuse
=AL_FALSE
;
1667 Source
->position_fraction
=0;
1668 Source
->BuffersPlayed
= 0;
1669 ALBufferListItem
= Source
->queue
;
1670 while (ALBufferListItem
!= NULL
)
1672 ALBufferListItem
->bufferstate
= PENDING
;
1673 ALBufferListItem
= ALBufferListItem
->next
;
1676 Source
->ulBufferID
= Source
->queue
->buffer
;
1678 Source
->lOffset
= 0;
1684 // sources is a NULL pointer
1685 alSetError(AL_INVALID_VALUE
);
1688 ProcessContext(Context
);
1693 alSetError(AL_INVALID_OPERATION
);
1700 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1702 ALCcontext
*Context
;
1705 ALbufferlistitem
*ALBufferList
;
1706 ALbufferlistitem
*ALBufferListStart
;
1711 ALboolean bBuffersValid
= AL_TRUE
;
1716 Context
=alcGetCurrentContext();
1719 SuspendContext(Context
);
1724 // Check that all buffers are valid or zero and that the source is valid
1726 // Check that this is a valid source
1727 if (alIsSource(source
))
1729 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1731 // Check that this is not a STATIC Source
1732 if (ALSource
->lSourceType
!= AL_STATIC
)
1737 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1738 ALBufferList
= ALSource
->queue
;
1739 while (ALBufferList
)
1741 if (ALBufferList
->buffer
)
1743 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1744 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1747 ALBufferList
= ALBufferList
->next
;
1750 for (i
= 0; i
< n
; i
++)
1752 if (alIsBuffer(buffers
[i
]))
1756 if ((iFrequency
== -1) && (iFormat
== -1))
1758 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1759 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1763 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1764 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1766 alSetError(AL_INVALID_OPERATION
);
1767 bBuffersValid
= AL_FALSE
;
1775 alSetError(AL_INVALID_NAME
);
1776 bBuffersValid
= AL_FALSE
;
1783 // Change Source Type
1784 ALSource
->lSourceType
= AL_STREAMING
;
1786 // All buffers are valid - so add them to the list
1787 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1788 ALBufferListStart
->buffer
= buffers
[0];
1789 ALBufferListStart
->bufferstate
= PENDING
;
1790 ALBufferListStart
->flag
= 0;
1791 ALBufferListStart
->next
= NULL
;
1794 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1798 DataSize
+= BufferSize
;
1800 // Increment reference counter for buffer
1802 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1804 ALBufferList
= ALBufferListStart
;
1806 for (i
= 1; i
< n
; i
++)
1808 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1809 ALBufferList
->next
->buffer
= buffers
[i
];
1810 ALBufferList
->next
->bufferstate
= PENDING
;
1811 ALBufferList
->next
->flag
= 0;
1812 ALBufferList
->next
->next
= NULL
;
1815 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1819 DataSize
+= BufferSize
;
1821 // Increment reference counter for buffer
1823 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1825 ALBufferList
= ALBufferList
->next
;
1828 if (ALSource
->queue
== NULL
)
1830 ALSource
->queue
= ALBufferListStart
;
1831 // Update Current Buffer
1832 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1836 // Find end of queue
1837 ALBufferList
= ALSource
->queue
;
1838 while (ALBufferList
->next
!= NULL
)
1840 ALBufferList
= ALBufferList
->next
;
1843 ALBufferList
->next
= ALBufferListStart
;
1846 // Update number of buffers in queue
1847 ALSource
->BuffersInQueue
+= n
;
1852 // Invalid Source Type (can't queue on a Static Source)
1853 alSetError(AL_INVALID_OPERATION
);
1858 // Invalid Source Name
1859 alSetError(AL_INVALID_NAME
);
1862 ProcessContext(Context
);
1867 alSetError(AL_INVALID_OPERATION
);
1874 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1875 // an array of buffer IDs that are to be filled with the names of the buffers removed
1876 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1878 ALCcontext
*Context
;
1881 ALbufferlistitem
*ALBufferList
;
1885 ALboolean bBuffersProcessed
;
1892 bBuffersProcessed
= AL_TRUE
;
1894 Context
=alcGetCurrentContext();
1897 SuspendContext(Context
);
1899 if (alIsSource(source
))
1901 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1903 // Check that all 'n' buffers have been processed
1904 ALBufferList
= ALSource
->queue
;
1905 for (i
= 0; i
< n
; i
++)
1907 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1909 ALBufferList
= ALBufferList
->next
;
1913 bBuffersProcessed
= AL_FALSE
;
1918 // If all 'n' buffers have been processed, remove them from the queue
1919 if (bBuffersProcessed
)
1921 for (i
= 0; i
< n
; i
++)
1923 ALBufferList
= ALSource
->queue
;
1925 ALSource
->queue
= ALBufferList
->next
;
1926 // Record name of buffer
1927 buffers
[i
] = ALBufferList
->buffer
;
1928 // Decrement buffer reference counter
1929 if (ALBufferList
->buffer
)
1930 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1931 // Record size of buffer
1932 if (ALBufferList
->buffer
)
1933 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1937 DataSize
+= BufferSize
;
1938 // Release memory for buffer list item
1940 ALSource
->BuffersInQueue
--;
1943 if (ALSource
->state
!= AL_PLAYING
)
1945 if (ALSource
->queue
)
1946 BufferID
= ALSource
->queue
->buffer
;
1950 ALSource
->ulBufferID
= BufferID
;
1953 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1954 ALSource
->BuffersPlayed
= 0;
1956 ALSource
->BuffersPlayed
-= n
;
1960 // Some buffers can't be unqueue because they have not been processed
1961 alSetError(AL_INVALID_VALUE
);
1966 // Invalid Source Name
1967 alSetError(AL_INVALID_NAME
);
1970 ProcessContext(Context
);
1975 alSetError(AL_INVALID_OPERATION
);
1982 static ALvoid
InitSourceParams(ALsource
*pSource
)
1984 pSource
->flInnerAngle
= 360.0f
;
1985 pSource
->flOuterAngle
= 360.0f
;
1986 pSource
->flPitch
= 1.0f
;
1987 pSource
->vPosition
[0] = 0.0f
;
1988 pSource
->vPosition
[1] = 0.0f
;
1989 pSource
->vPosition
[2] = 0.0f
;
1990 pSource
->vOrientation
[0] = 0.0f
;
1991 pSource
->vOrientation
[1] = 0.0f
;
1992 pSource
->vOrientation
[2] = 0.0f
;
1993 pSource
->vVelocity
[0] = 0.0f
;
1994 pSource
->vVelocity
[1] = 0.0f
;
1995 pSource
->vVelocity
[2] = 0.0f
;
1996 pSource
->flRefDistance
= 1.0f
;
1997 pSource
->flMaxDistance
= FLT_MAX
;
1998 pSource
->flRollOffFactor
= 1.0f
;
1999 pSource
->bLooping
= AL_FALSE
;
2000 pSource
->flGain
= 1.0f
;
2001 pSource
->flMinGain
= 0.0f
;
2002 pSource
->flMaxGain
= 1.0f
;
2003 pSource
->flOuterGain
= 0.0f
;
2004 pSource
->OuterGainHF
= 1.0f
;
2006 pSource
->DryGainHFAuto
= AL_TRUE
;
2007 pSource
->WetGainAuto
= AL_TRUE
;
2008 pSource
->WetGainHFAuto
= AL_TRUE
;
2009 pSource
->AirAbsorptionFactor
= 0.0f
;
2010 pSource
->RoomRolloffFactor
= 0.0f
;
2011 pSource
->DopplerFactor
= 1.0f
;
2013 pSource
->state
= AL_INITIAL
;
2014 pSource
->lSourceType
= AL_UNDETERMINED
;
2016 pSource
->ulBufferID
= 0;
2023 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
2024 The offset is relative to the start of the queue (not the start of the current buffer)
2026 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
, ALuint updateSize
)
2028 ALbufferlistitem
*pBufferList
;
2030 ALfloat flBufferFreq
;
2032 ALint readPos
, writePos
;
2033 ALenum eOriginalFormat
;
2034 ALboolean bReturn
= AL_TRUE
;
2035 ALint lTotalBufferDataSize
;
2037 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
2039 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
2040 // Get Current Buffer Size and frequency (in milliseconds)
2041 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
2042 eOriginalFormat
= pBuffer
->eOriginalFormat
;
2043 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2045 // Get Current BytesPlayed
2046 readPos
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2047 // Add byte length of any processed buffers in the queue
2048 pBufferList
= pSource
->queue
;
2049 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2051 readPos
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2052 pBufferList
= pBufferList
->next
;
2055 if(pSource
->state
== AL_PLAYING
)
2056 writePos
= readPos
+ (updateSize
* lChannels
* 2);
2060 lTotalBufferDataSize
= 0;
2061 pBufferList
= pSource
->queue
;
2064 if (pBufferList
->buffer
)
2065 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2066 pBufferList
= pBufferList
->next
;
2069 if (pSource
->bLooping
)
2074 readPos
%= lTotalBufferDataSize
;
2078 writePos
%= lTotalBufferDataSize
;
2082 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2085 else if(readPos
> lTotalBufferDataSize
)
2086 readPos
= lTotalBufferDataSize
;
2089 else if(writePos
> lTotalBufferDataSize
)
2090 writePos
= lTotalBufferDataSize
;
2096 case AL_SEC_RW_OFFSETS_EXT
:
2097 pflOffset
[0] = (ALfloat
)readPos
/ (lChannels
* 2.0f
* flBufferFreq
);
2098 pflOffset
[1] = (ALfloat
)writePos
/ (lChannels
* 2.0f
* flBufferFreq
);
2100 case AL_SAMPLE_OFFSET
:
2101 case AL_SAMPLE_RW_OFFSETS_EXT
:
2102 pflOffset
[0] = (ALfloat
)(readPos
/ (lChannels
* 2));
2103 pflOffset
[1] = (ALfloat
)(writePos
/ (lChannels
* 2));
2105 case AL_BYTE_OFFSET
:
2106 case AL_BYTE_RW_OFFSETS_EXT
:
2107 // Take into account the original format of the Buffer
2108 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2109 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2111 // Round down to nearest ADPCM block
2112 pflOffset
[0] = (ALfloat
)((readPos
/ (65 * 2 * lChannels
)) * 36 * lChannels
);
2113 if(pSource
->state
== AL_PLAYING
)
2115 // Round up to nearest ADPCM block
2116 pflOffset
[1] = (ALfloat
)(((writePos
+ (65 * 2 * lChannels
) - 1) / (65 * 2 * lChannels
)) * 36 * lChannels
);
2119 pflOffset
[1] = pflOffset
[0];
2121 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2123 pflOffset
[0] = (ALfloat
)(readPos
>> 2);
2124 pflOffset
[1] = (ALfloat
)(writePos
>> 2);
2126 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2128 pflOffset
[0] = (ALfloat
)(readPos
>> 1);
2129 pflOffset
[1] = (ALfloat
)(writePos
>> 1);
2131 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2133 pflOffset
[0] = (ALfloat
)(readPos
>> 1);
2134 pflOffset
[1] = (ALfloat
)(writePos
>> 1);
2136 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2138 pflOffset
[0] = (ALfloat
)(readPos
<< 1);
2139 pflOffset
[1] = (ALfloat
)(writePos
<< 1);
2143 pflOffset
[0] = (ALfloat
)readPos
;
2144 pflOffset
[1] = (ALfloat
)writePos
;
2151 pflOffset
[0] = 0.0f
;
2152 pflOffset
[1] = 0.0f
;
2162 Apply a playback offset to the Source. This function will update the queue (to correctly
2163 mark buffers as 'pending' or 'processed' depending upon the new offset.
2165 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2167 ALbufferlistitem
*pBufferList
;
2169 ALint lBufferSize
, lTotalBufferSize
;
2172 // Get true byte offset
2173 lByteOffset
= GetByteOffset(pSource
);
2175 // If this is a valid offset apply it
2176 if (lByteOffset
!= -1)
2178 // Sort out the queue (pending and processed states)
2179 pBufferList
= pSource
->queue
;
2180 lTotalBufferSize
= 0;
2181 pSource
->BuffersPlayed
= 0;
2184 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2185 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2187 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2189 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2190 // update the state to PROCESSED
2191 pSource
->BuffersPlayed
++;
2193 if (!pSource
->bLooping
)
2194 pBufferList
->bufferstate
= PROCESSED
;
2196 else if (lTotalBufferSize
<= lByteOffset
)
2198 // Offset is within this buffer
2199 pBufferList
->bufferstate
= PENDING
;
2201 // Set Current Buffer ID
2202 pSource
->ulBufferID
= pBufferList
->buffer
;
2204 // SW Mixer Positions are in Samples
2205 pSource
->position
= (lByteOffset
- lTotalBufferSize
) /
2206 aluBytesFromFormat(pBuffer
->format
) /
2207 aluChannelsFromFormat(pBuffer
->format
);
2211 // Offset is before this buffer, so mark as pending
2212 pBufferList
->bufferstate
= PENDING
;
2215 // Increment the TotalBufferSize
2216 lTotalBufferSize
+= lBufferSize
;
2218 // Move on to next buffer in the Queue
2219 pBufferList
= pBufferList
->next
;
2225 alSetError(AL_INVALID_VALUE
);
2229 pSource
->lOffset
= 0;
2236 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2237 offset supplied by the application). This takes into account the fact that the buffer format
2238 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2240 static ALint
GetByteOffset(ALsource
*pSource
)
2242 ALbuffer
*pBuffer
= NULL
;
2243 ALbufferlistitem
*pBufferList
;
2244 ALfloat flBufferFreq
;
2246 ALint lByteOffset
= -1;
2247 ALint lTotalBufferDataSize
;
2249 // Find the first non-NULL Buffer in the Queue
2250 pBufferList
= pSource
->queue
;
2253 if (pBufferList
->buffer
)
2255 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2258 pBufferList
= pBufferList
->next
;
2263 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2264 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2266 // Determine the ByteOffset (and ensure it is block aligned)
2267 switch (pSource
->lOffsetType
)
2269 case AL_BYTE_OFFSET
:
2270 // Take into consideration the original format
2271 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2272 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2274 // Round down to nearest ADPCM block
2275 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2276 // Multiply by compression rate
2277 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2278 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2280 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2282 lByteOffset
= pSource
->lOffset
* 4;
2283 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2285 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2287 lByteOffset
= pSource
->lOffset
* 2;
2288 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2290 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2292 lByteOffset
= pSource
->lOffset
* 2;
2293 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2295 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2297 lByteOffset
= pSource
->lOffset
/ 2;
2298 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2302 lByteOffset
= pSource
->lOffset
;
2303 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2307 case AL_SAMPLE_OFFSET
:
2308 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2312 // Note - lOffset is internally stored as Milliseconds
2313 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2314 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2318 lTotalBufferDataSize
= 0;
2319 pBufferList
= pSource
->queue
;
2322 if (pBufferList
->buffer
)
2323 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2324 pBufferList
= pBufferList
->next
;
2327 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2328 if (lByteOffset
>= lTotalBufferDataSize
)
2336 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2339 if(Context
->SourceCount
> 0)
2340 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", Context
->SourceCount
);
2343 while(Context
->Source
)
2345 ALsource
*temp
= Context
->Source
;
2346 Context
->Source
= Context
->Source
->next
;
2348 // Release source structure
2349 ALTHUNK_REMOVEENTRY(temp
->source
);
2350 memset(temp
, 0, sizeof(ALsource
));
2353 Context
->SourceCount
= 0;