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;
1439 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1441 // Make sure all the Buffers in the queue are marked as PENDING
1442 ALBufferList
= pSource
->queue
;
1443 while (ALBufferList
)
1445 ALBufferList
->bufferstate
= PENDING
;
1446 ALBufferList
= ALBufferList
->next
;
1451 pSource
->state
= AL_PLAYING
;
1452 pSource
->inuse
= AL_TRUE
;
1453 pSource
->play
= AL_TRUE
;
1456 // Check if an Offset has been set
1457 if (pSource
->lOffset
)
1458 ApplyOffset(pSource
, AL_FALSE
);
1462 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1463 ALBufferList
= pSource
->queue
;
1464 while (ALBufferList
)
1466 ALBufferList
->bufferstate
= PROCESSED
;
1467 ALBufferList
= ALBufferList
->next
;
1470 pSource
->BuffersPlayed
= pSource
->BuffersInQueue
;
1477 // sources is a NULL pointer
1478 alSetError(AL_INVALID_VALUE
);
1481 ProcessContext(pContext
);
1486 alSetError(AL_INVALID_OPERATION
);
1492 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1494 alSourcePausev(1, &source
);
1498 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1500 ALCcontext
*Context
;
1503 ALboolean bSourcesValid
= AL_TRUE
;
1505 Context
=alcGetCurrentContext();
1508 SuspendContext(Context
);
1512 // Check all the Sources are valid
1515 if (!alIsSource(sources
[i
]))
1517 alSetError(AL_INVALID_NAME
);
1518 bSourcesValid
= AL_FALSE
;
1527 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1528 if (Source
->state
==AL_PLAYING
)
1530 Source
->state
=AL_PAUSED
;
1531 Source
->inuse
=AL_FALSE
;
1538 // sources is a NULL pointer
1539 alSetError(AL_INVALID_VALUE
);
1542 ProcessContext(Context
);
1547 alSetError(AL_INVALID_OPERATION
);
1553 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1555 alSourceStopv(1, &source
);
1559 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1561 ALCcontext
*Context
;
1564 ALbufferlistitem
*ALBufferListItem
;
1565 ALboolean bSourcesValid
= AL_TRUE
;
1567 Context
=alcGetCurrentContext();
1570 SuspendContext(Context
);
1574 // Check all the Sources are valid
1577 if (!alIsSource(sources
[i
]))
1579 alSetError(AL_INVALID_NAME
);
1580 bSourcesValid
= AL_FALSE
;
1589 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1590 if (Source
->state
!=AL_INITIAL
)
1592 Source
->state
=AL_STOPPED
;
1593 Source
->inuse
=AL_FALSE
;
1594 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1595 ALBufferListItem
= Source
->queue
;
1596 while (ALBufferListItem
!= NULL
)
1598 ALBufferListItem
->bufferstate
= PROCESSED
;
1599 ALBufferListItem
= ALBufferListItem
->next
;
1602 Source
->lOffset
= 0;
1608 // sources is a NULL pointer
1609 alSetError(AL_INVALID_VALUE
);
1612 ProcessContext(Context
);
1617 alSetError(AL_INVALID_OPERATION
);
1623 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1625 alSourceRewindv(1, &source
);
1629 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1631 ALCcontext
*Context
;
1634 ALbufferlistitem
*ALBufferListItem
;
1635 ALboolean bSourcesValid
= AL_TRUE
;
1637 Context
=alcGetCurrentContext();
1640 SuspendContext(Context
);
1644 // Check all the Sources are valid
1647 if (!alIsSource(sources
[i
]))
1649 alSetError(AL_INVALID_NAME
);
1650 bSourcesValid
= AL_FALSE
;
1659 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1660 if (Source
->state
!=AL_INITIAL
)
1662 Source
->state
=AL_INITIAL
;
1663 Source
->inuse
=AL_FALSE
;
1665 Source
->position_fraction
=0;
1666 Source
->BuffersPlayed
= 0;
1667 ALBufferListItem
= Source
->queue
;
1668 while (ALBufferListItem
!= NULL
)
1670 ALBufferListItem
->bufferstate
= PENDING
;
1671 ALBufferListItem
= ALBufferListItem
->next
;
1674 Source
->ulBufferID
= Source
->queue
->buffer
;
1676 Source
->lOffset
= 0;
1682 // sources is a NULL pointer
1683 alSetError(AL_INVALID_VALUE
);
1686 ProcessContext(Context
);
1691 alSetError(AL_INVALID_OPERATION
);
1698 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1700 ALCcontext
*Context
;
1703 ALbufferlistitem
*ALBufferList
;
1704 ALbufferlistitem
*ALBufferListStart
;
1709 ALboolean bBuffersValid
= AL_TRUE
;
1714 Context
=alcGetCurrentContext();
1717 SuspendContext(Context
);
1722 // Check that all buffers are valid or zero and that the source is valid
1724 // Check that this is a valid source
1725 if (alIsSource(source
))
1727 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1729 // Check that this is not a STATIC Source
1730 if (ALSource
->lSourceType
!= AL_STATIC
)
1735 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1736 ALBufferList
= ALSource
->queue
;
1737 while (ALBufferList
)
1739 if (ALBufferList
->buffer
)
1741 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1742 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1745 ALBufferList
= ALBufferList
->next
;
1748 for (i
= 0; i
< n
; i
++)
1750 if (alIsBuffer(buffers
[i
]))
1754 if ((iFrequency
== -1) && (iFormat
== -1))
1756 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1757 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1761 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1762 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1764 alSetError(AL_INVALID_OPERATION
);
1765 bBuffersValid
= AL_FALSE
;
1773 alSetError(AL_INVALID_NAME
);
1774 bBuffersValid
= AL_FALSE
;
1781 // Change Source Type
1782 ALSource
->lSourceType
= AL_STREAMING
;
1784 // All buffers are valid - so add them to the list
1785 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1786 ALBufferListStart
->buffer
= buffers
[0];
1787 ALBufferListStart
->bufferstate
= PENDING
;
1788 ALBufferListStart
->flag
= 0;
1789 ALBufferListStart
->next
= NULL
;
1792 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1796 DataSize
+= BufferSize
;
1798 // Increment reference counter for buffer
1800 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1802 ALBufferList
= ALBufferListStart
;
1804 for (i
= 1; i
< n
; i
++)
1806 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1807 ALBufferList
->next
->buffer
= buffers
[i
];
1808 ALBufferList
->next
->bufferstate
= PENDING
;
1809 ALBufferList
->next
->flag
= 0;
1810 ALBufferList
->next
->next
= NULL
;
1813 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1817 DataSize
+= BufferSize
;
1819 // Increment reference counter for buffer
1821 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1823 ALBufferList
= ALBufferList
->next
;
1826 if (ALSource
->queue
== NULL
)
1828 ALSource
->queue
= ALBufferListStart
;
1829 // Update Current Buffer
1830 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1834 // Find end of queue
1835 ALBufferList
= ALSource
->queue
;
1836 while (ALBufferList
->next
!= NULL
)
1838 ALBufferList
= ALBufferList
->next
;
1841 ALBufferList
->next
= ALBufferListStart
;
1844 // Update number of buffers in queue
1845 ALSource
->BuffersInQueue
+= n
;
1850 // Invalid Source Type (can't queue on a Static Source)
1851 alSetError(AL_INVALID_OPERATION
);
1856 // Invalid Source Name
1857 alSetError(AL_INVALID_NAME
);
1860 ProcessContext(Context
);
1865 alSetError(AL_INVALID_OPERATION
);
1872 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1873 // an array of buffer IDs that are to be filled with the names of the buffers removed
1874 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1876 ALCcontext
*Context
;
1879 ALbufferlistitem
*ALBufferList
;
1883 ALboolean bBuffersProcessed
;
1890 bBuffersProcessed
= AL_TRUE
;
1892 Context
=alcGetCurrentContext();
1895 SuspendContext(Context
);
1897 if (alIsSource(source
))
1899 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1901 // Check that all 'n' buffers have been processed
1902 ALBufferList
= ALSource
->queue
;
1903 for (i
= 0; i
< n
; i
++)
1905 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1907 ALBufferList
= ALBufferList
->next
;
1911 bBuffersProcessed
= AL_FALSE
;
1916 // If all 'n' buffers have been processed, remove them from the queue
1917 if (bBuffersProcessed
)
1919 for (i
= 0; i
< n
; i
++)
1921 ALBufferList
= ALSource
->queue
;
1923 ALSource
->queue
= ALBufferList
->next
;
1924 // Record name of buffer
1925 buffers
[i
] = ALBufferList
->buffer
;
1926 // Decrement buffer reference counter
1927 if (ALBufferList
->buffer
)
1928 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1929 // Record size of buffer
1930 if (ALBufferList
->buffer
)
1931 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1935 DataSize
+= BufferSize
;
1936 // Release memory for buffer list item
1938 ALSource
->BuffersInQueue
--;
1941 if (ALSource
->state
!= AL_PLAYING
)
1943 if (ALSource
->queue
)
1944 BufferID
= ALSource
->queue
->buffer
;
1948 ALSource
->ulBufferID
= BufferID
;
1951 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1952 ALSource
->BuffersPlayed
= 0;
1954 ALSource
->BuffersPlayed
-= n
;
1958 // Some buffers can't be unqueue because they have not been processed
1959 alSetError(AL_INVALID_VALUE
);
1964 // Invalid Source Name
1965 alSetError(AL_INVALID_NAME
);
1968 ProcessContext(Context
);
1973 alSetError(AL_INVALID_OPERATION
);
1980 static ALvoid
InitSourceParams(ALsource
*pSource
)
1982 pSource
->flInnerAngle
= 360.0f
;
1983 pSource
->flOuterAngle
= 360.0f
;
1984 pSource
->flPitch
= 1.0f
;
1985 pSource
->vPosition
[0] = 0.0f
;
1986 pSource
->vPosition
[1] = 0.0f
;
1987 pSource
->vPosition
[2] = 0.0f
;
1988 pSource
->vOrientation
[0] = 0.0f
;
1989 pSource
->vOrientation
[1] = 0.0f
;
1990 pSource
->vOrientation
[2] = 0.0f
;
1991 pSource
->vVelocity
[0] = 0.0f
;
1992 pSource
->vVelocity
[1] = 0.0f
;
1993 pSource
->vVelocity
[2] = 0.0f
;
1994 pSource
->flRefDistance
= 1.0f
;
1995 pSource
->flMaxDistance
= FLT_MAX
;
1996 pSource
->flRollOffFactor
= 1.0f
;
1997 pSource
->bLooping
= AL_FALSE
;
1998 pSource
->flGain
= 1.0f
;
1999 pSource
->flMinGain
= 0.0f
;
2000 pSource
->flMaxGain
= 1.0f
;
2001 pSource
->flOuterGain
= 0.0f
;
2002 pSource
->OuterGainHF
= 1.0f
;
2004 pSource
->DryGainHFAuto
= AL_TRUE
;
2005 pSource
->WetGainAuto
= AL_TRUE
;
2006 pSource
->WetGainHFAuto
= AL_TRUE
;
2007 pSource
->AirAbsorptionFactor
= 0.0f
;
2008 pSource
->RoomRolloffFactor
= 0.0f
;
2009 pSource
->DopplerFactor
= 1.0f
;
2011 pSource
->state
= AL_INITIAL
;
2012 pSource
->lSourceType
= AL_UNDETERMINED
;
2014 pSource
->ulBufferID
= 0;
2021 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
2022 The offset is relative to the start of the queue (not the start of the current buffer)
2024 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
, ALuint updateSize
)
2026 ALbufferlistitem
*pBufferList
;
2028 ALfloat flBufferFreq
;
2030 ALint readPos
, writePos
;
2031 ALenum eOriginalFormat
;
2032 ALboolean bReturn
= AL_TRUE
;
2033 ALint lTotalBufferDataSize
;
2035 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
2037 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
2038 // Get Current Buffer Size and frequency (in milliseconds)
2039 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
2040 eOriginalFormat
= pBuffer
->eOriginalFormat
;
2041 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2043 // Get Current BytesPlayed
2044 readPos
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2045 // Add byte length of any processed buffers in the queue
2046 pBufferList
= pSource
->queue
;
2047 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2049 readPos
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2050 pBufferList
= pBufferList
->next
;
2053 if(pSource
->state
== AL_PLAYING
)
2054 writePos
= readPos
+ (updateSize
* lChannels
* 2);
2058 lTotalBufferDataSize
= 0;
2059 pBufferList
= pSource
->queue
;
2062 if (pBufferList
->buffer
)
2063 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2064 pBufferList
= pBufferList
->next
;
2067 if (pSource
->bLooping
)
2072 readPos
%= lTotalBufferDataSize
;
2076 writePos
%= lTotalBufferDataSize
;
2080 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2083 else if(readPos
> lTotalBufferDataSize
)
2084 readPos
= lTotalBufferDataSize
;
2087 else if(writePos
> lTotalBufferDataSize
)
2088 writePos
= lTotalBufferDataSize
;
2094 case AL_SEC_RW_OFFSETS_EXT
:
2095 pflOffset
[0] = (ALfloat
)readPos
/ (lChannels
* 2.0f
* flBufferFreq
);
2096 pflOffset
[1] = (ALfloat
)writePos
/ (lChannels
* 2.0f
* flBufferFreq
);
2098 case AL_SAMPLE_OFFSET
:
2099 case AL_SAMPLE_RW_OFFSETS_EXT
:
2100 pflOffset
[0] = (ALfloat
)(readPos
/ (lChannels
* 2));
2101 pflOffset
[1] = (ALfloat
)(writePos
/ (lChannels
* 2));
2103 case AL_BYTE_OFFSET
:
2104 case AL_BYTE_RW_OFFSETS_EXT
:
2105 // Take into account the original format of the Buffer
2106 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2107 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2109 // Compression rate of the ADPCM supported is 3.6111 to 1
2110 readPos
= (ALint
)((ALfloat
)readPos
/ 3.6111f
);
2111 writePos
= (ALint
)((ALfloat
)writePos
/ 3.6111f
);
2112 // Round down to nearest ADPCM block
2113 pflOffset
[0] = (ALfloat
)((readPos
/ (36 * lChannels
)) * 36 * lChannels
);
2114 if(pSource
->state
== AL_PLAYING
)
2116 // Round up to nearest ADPCM block
2117 pflOffset
[1] = (ALfloat
)(((writePos
+ (36 * lChannels
) - 1) / (36 * lChannels
)) * 36 * lChannels
);
2120 pflOffset
[1] = pflOffset
[0];
2122 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2124 pflOffset
[0] = (ALfloat
)(readPos
>> 2);
2125 pflOffset
[1] = (ALfloat
)(writePos
>> 2);
2127 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2129 pflOffset
[0] = (ALfloat
)(readPos
>> 1);
2130 pflOffset
[1] = (ALfloat
)(writePos
>> 1);
2132 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2134 pflOffset
[0] = (ALfloat
)(readPos
>> 1);
2135 pflOffset
[1] = (ALfloat
)(writePos
>> 1);
2137 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2139 pflOffset
[0] = (ALfloat
)(readPos
<< 1);
2140 pflOffset
[1] = (ALfloat
)(writePos
<< 1);
2144 pflOffset
[0] = (ALfloat
)readPos
;
2145 pflOffset
[1] = (ALfloat
)writePos
;
2152 pflOffset
[0] = 0.0f
;
2153 pflOffset
[1] = 0.0f
;
2163 Apply a playback offset to the Source. This function will update the queue (to correctly
2164 mark buffers as 'pending' or 'processed' depending upon the new offset.
2166 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2168 ALbufferlistitem
*pBufferList
;
2170 ALint lBufferSize
, lTotalBufferSize
;
2173 // Get true byte offset
2174 lByteOffset
= GetByteOffset(pSource
);
2176 // If this is a valid offset apply it
2177 if (lByteOffset
!= -1)
2179 // Sort out the queue (pending and processed states)
2180 pBufferList
= pSource
->queue
;
2181 lTotalBufferSize
= 0;
2182 pSource
->BuffersPlayed
= 0;
2185 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2186 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2188 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2190 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2191 // update the state to PROCESSED
2192 pSource
->BuffersPlayed
++;
2194 if (!pSource
->bLooping
)
2195 pBufferList
->bufferstate
= PROCESSED
;
2197 else if (lTotalBufferSize
<= lByteOffset
)
2199 // Offset is within this buffer
2200 pBufferList
->bufferstate
= PENDING
;
2202 // Set Current Buffer ID
2203 pSource
->ulBufferID
= pBufferList
->buffer
;
2205 // SW Mixer Positions are in Samples
2206 pSource
->position
= (lByteOffset
- lTotalBufferSize
) /
2207 aluBytesFromFormat(pBuffer
->format
) /
2208 aluChannelsFromFormat(pBuffer
->format
);
2212 // Offset is before this buffer, so mark as pending
2213 pBufferList
->bufferstate
= PENDING
;
2216 // Increment the TotalBufferSize
2217 lTotalBufferSize
+= lBufferSize
;
2219 // Move on to next buffer in the Queue
2220 pBufferList
= pBufferList
->next
;
2226 alSetError(AL_INVALID_VALUE
);
2230 pSource
->lOffset
= 0;
2237 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2238 offset supplied by the application). This takes into account the fact that the buffer format
2239 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2241 static ALint
GetByteOffset(ALsource
*pSource
)
2243 ALbuffer
*pBuffer
= NULL
;
2244 ALbufferlistitem
*pBufferList
;
2245 ALfloat flBufferFreq
;
2247 ALint lByteOffset
= -1;
2248 ALint lTotalBufferDataSize
;
2250 // Find the first non-NULL Buffer in the Queue
2251 pBufferList
= pSource
->queue
;
2254 if (pBufferList
->buffer
)
2256 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2259 pBufferList
= pBufferList
->next
;
2264 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2265 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2267 // Determine the ByteOffset (and ensure it is block aligned)
2268 switch (pSource
->lOffsetType
)
2270 case AL_BYTE_OFFSET
:
2271 // Take into consideration the original format
2272 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2273 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2275 // Round down to nearest ADPCM block
2276 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2277 // Multiply by compression rate
2278 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2279 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2281 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2283 lByteOffset
= pSource
->lOffset
* 4;
2284 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2286 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2288 lByteOffset
= pSource
->lOffset
* 2;
2289 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2291 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2293 lByteOffset
= pSource
->lOffset
* 2;
2294 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2296 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2298 lByteOffset
= pSource
->lOffset
/ 2;
2299 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2303 lByteOffset
= pSource
->lOffset
;
2304 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2308 case AL_SAMPLE_OFFSET
:
2309 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2313 // Note - lOffset is internally stored as Milliseconds
2314 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2315 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2319 lTotalBufferDataSize
= 0;
2320 pBufferList
= pSource
->queue
;
2323 if (pBufferList
->buffer
)
2324 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2325 pBufferList
= pBufferList
->next
;
2328 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2329 if (lByteOffset
>= lTotalBufferDataSize
)
2337 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2340 if(Context
->SourceCount
> 0)
2341 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", Context
->SourceCount
);
2344 while(Context
->Source
)
2346 ALsource
*temp
= Context
->Source
;
2347 Context
->Source
= Context
->Source
->next
;
2349 // Release source structure
2350 ALTHUNK_REMOVEENTRY(temp
->source
);
2351 memset(temp
, 0, sizeof(ALsource
));
2354 Context
->SourceCount
= 0;