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
);
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
))
907 *pflValue
= flOffset
;
909 alSetError(AL_INVALID_OPERATION
);
912 case AL_CONE_INNER_ANGLE
:
913 *pflValue
= pSource
->flInnerAngle
;
916 case AL_CONE_OUTER_ANGLE
:
917 *pflValue
= pSource
->flOuterAngle
;
920 case AL_REFERENCE_DISTANCE
:
921 *pflValue
= pSource
->flRefDistance
;
924 case AL_AIR_ABSORPTION_FACTOR
:
925 *pflValue
= pSource
->AirAbsorptionFactor
;
928 case AL_ROOM_ROLLOFF_FACTOR
:
929 *pflValue
= pSource
->RoomRolloffFactor
;
932 case AL_DOPPLER_FACTOR
:
933 *pflValue
= pSource
->DopplerFactor
;
937 alSetError(AL_INVALID_ENUM
);
942 alSetError(AL_INVALID_NAME
);
945 alSetError(AL_INVALID_VALUE
);
947 ProcessContext(pContext
);
950 alSetError(AL_INVALID_OPERATION
);
956 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
958 ALCcontext
*pContext
;
961 pContext
= alcGetCurrentContext();
964 SuspendContext(pContext
);
966 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
968 if (alIsSource(source
))
970 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
975 *pflValue1
= pSource
->vPosition
[0];
976 *pflValue2
= pSource
->vPosition
[1];
977 *pflValue3
= pSource
->vPosition
[2];
981 *pflValue1
= pSource
->vVelocity
[0];
982 *pflValue2
= pSource
->vVelocity
[1];
983 *pflValue3
= pSource
->vVelocity
[2];
987 *pflValue1
= pSource
->vOrientation
[0];
988 *pflValue2
= pSource
->vOrientation
[1];
989 *pflValue3
= pSource
->vOrientation
[2];
993 alSetError(AL_INVALID_ENUM
);
998 alSetError(AL_INVALID_NAME
);
1001 alSetError(AL_INVALID_VALUE
);
1003 ProcessContext(pContext
);
1006 alSetError(AL_INVALID_OPERATION
);
1012 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1014 ALCcontext
*pContext
;
1017 pContext
= alcGetCurrentContext();
1020 SuspendContext(pContext
);
1024 if (alIsSource(source
))
1026 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1034 case AL_MAX_DISTANCE
:
1035 case AL_ROLLOFF_FACTOR
:
1036 case AL_DOPPLER_FACTOR
:
1037 case AL_CONE_OUTER_GAIN
:
1039 case AL_SAMPLE_OFFSET
:
1040 case AL_BYTE_OFFSET
:
1041 case AL_CONE_INNER_ANGLE
:
1042 case AL_CONE_OUTER_ANGLE
:
1043 case AL_REFERENCE_DISTANCE
:
1044 case AL_CONE_OUTER_GAINHF
:
1045 case AL_AIR_ABSORPTION_FACTOR
:
1046 case AL_ROOM_ROLLOFF_FACTOR
:
1047 alGetSourcef(source
, eParam
, pflValues
);
1051 pflValues
[0] = pSource
->vPosition
[0];
1052 pflValues
[1] = pSource
->vPosition
[1];
1053 pflValues
[2] = pSource
->vPosition
[2];
1057 pflValues
[0] = pSource
->vVelocity
[0];
1058 pflValues
[1] = pSource
->vVelocity
[1];
1059 pflValues
[2] = pSource
->vVelocity
[2];
1063 pflValues
[0] = pSource
->vOrientation
[0];
1064 pflValues
[1] = pSource
->vOrientation
[1];
1065 pflValues
[2] = pSource
->vOrientation
[2];
1069 alSetError(AL_INVALID_ENUM
);
1074 alSetError(AL_INVALID_NAME
);
1077 alSetError(AL_INVALID_VALUE
);
1079 ProcessContext(pContext
);
1082 alSetError(AL_INVALID_OPERATION
);
1088 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1090 ALCcontext
*pContext
;
1094 pContext
= alcGetCurrentContext();
1097 SuspendContext(pContext
);
1101 if (alIsSource(source
))
1103 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1107 case AL_MAX_DISTANCE
:
1108 *plValue
= (ALint
)pSource
->flMaxDistance
;
1111 case AL_ROLLOFF_FACTOR
:
1112 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1115 case AL_REFERENCE_DISTANCE
:
1116 *plValue
= (ALint
)pSource
->flRefDistance
;
1119 case AL_SOURCE_RELATIVE
:
1120 *plValue
= pSource
->bHeadRelative
;
1123 case AL_CONE_INNER_ANGLE
:
1124 *plValue
= (ALint
)pSource
->flInnerAngle
;
1127 case AL_CONE_OUTER_ANGLE
:
1128 *plValue
= (ALint
)pSource
->flOuterAngle
;
1132 *plValue
= pSource
->bLooping
;
1136 *plValue
= pSource
->ulBufferID
;
1139 case AL_SOURCE_STATE
:
1140 *plValue
= pSource
->state
;
1143 case AL_BUFFERS_QUEUED
:
1144 *plValue
= pSource
->BuffersInQueue
;
1147 case AL_BUFFERS_PROCESSED
:
1148 if(pSource
->bLooping
)
1150 /* Buffers on a looping source are in a perpetual state
1151 * of PENDING, so don't report any as PROCESSED */
1155 *plValue
= pSource
->BuffersPlayed
;
1158 case AL_SOURCE_TYPE
:
1159 *plValue
= pSource
->lSourceType
;
1163 case AL_SAMPLE_OFFSET
:
1164 case AL_BYTE_OFFSET
:
1165 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
1166 *plValue
= (ALint
)flOffset
;
1168 alSetError(AL_INVALID_OPERATION
);
1171 case AL_DIRECT_FILTER
:
1172 *plValue
= pSource
->DirectFilter
.filter
;
1175 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1176 *plValue
= pSource
->DryGainHFAuto
;
1179 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1180 *plValue
= pSource
->WetGainAuto
;
1183 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1184 *plValue
= pSource
->WetGainHFAuto
;
1187 case AL_DOPPLER_FACTOR
:
1188 *plValue
= (ALint
)pSource
->DopplerFactor
;
1192 alSetError(AL_INVALID_ENUM
);
1197 alSetError(AL_INVALID_NAME
);
1200 alSetError(AL_INVALID_VALUE
);
1202 ProcessContext(pContext
);
1205 alSetError(AL_INVALID_OPERATION
);
1211 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1213 ALCcontext
*pContext
;
1216 pContext
= alcGetCurrentContext();
1219 SuspendContext(pContext
);
1221 if ((plValue1
) && (plValue2
) && (plValue3
))
1223 if (alIsSource(source
))
1225 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1230 *plValue1
= (ALint
)pSource
->vPosition
[0];
1231 *plValue2
= (ALint
)pSource
->vPosition
[1];
1232 *plValue3
= (ALint
)pSource
->vPosition
[2];
1236 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1237 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1238 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1242 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1243 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1244 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1248 alSetError(AL_INVALID_ENUM
);
1253 alSetError(AL_INVALID_NAME
);
1256 alSetError(AL_INVALID_VALUE
);
1258 ProcessContext(pContext
);
1261 alSetError(AL_INVALID_OPERATION
);
1267 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1269 ALCcontext
*pContext
;
1272 pContext
= alcGetCurrentContext();
1275 SuspendContext(pContext
);
1279 if (alIsSource(source
))
1281 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1285 case AL_SOURCE_RELATIVE
:
1286 case AL_CONE_INNER_ANGLE
:
1287 case AL_CONE_OUTER_ANGLE
:
1290 case AL_SOURCE_STATE
:
1291 case AL_BUFFERS_QUEUED
:
1292 case AL_BUFFERS_PROCESSED
:
1294 case AL_SAMPLE_OFFSET
:
1295 case AL_BYTE_OFFSET
:
1296 case AL_MAX_DISTANCE
:
1297 case AL_ROLLOFF_FACTOR
:
1298 case AL_DOPPLER_FACTOR
:
1299 case AL_REFERENCE_DISTANCE
:
1300 case AL_SOURCE_TYPE
:
1301 case AL_DIRECT_FILTER
:
1302 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1303 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1304 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1305 alGetSourcei(source
, eParam
, plValues
);
1309 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1310 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1311 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1315 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1316 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1317 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1321 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1322 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1323 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1327 alSetError(AL_INVALID_ENUM
);
1332 alSetError(AL_INVALID_NAME
);
1335 alSetError(AL_INVALID_VALUE
);
1337 ProcessContext(pContext
);
1340 alSetError(AL_INVALID_OPERATION
);
1346 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1348 alSourcePlayv(1, &source
);
1352 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1354 ALCcontext
*pContext
;
1356 ALbufferlistitem
*ALBufferList
;
1357 ALboolean bSourcesValid
= AL_TRUE
;
1361 pContext
= alcGetCurrentContext();
1364 SuspendContext(pContext
);
1368 // Check that all the Sources are valid
1369 for (i
= 0; i
< n
; i
++)
1371 if (!alIsSource(pSourceList
[i
]))
1373 alSetError(AL_INVALID_NAME
);
1374 bSourcesValid
= AL_FALSE
;
1381 for (i
= 0; i
< n
; i
++)
1383 // Assume Source won't need to play
1386 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1388 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1389 ALBufferList
= pSource
->queue
;
1390 while (ALBufferList
)
1392 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1397 ALBufferList
= ALBufferList
->next
;
1402 for(j
= 0;j
< OUTPUTCHANNELS
;j
++)
1403 pSource
->DryGains
[j
] = 0.0f
;
1404 pSource
->WetGain
= 0.0f
;
1406 if (pSource
->state
!= AL_PAUSED
)
1408 pSource
->state
= AL_PLAYING
;
1409 pSource
->inuse
= AL_TRUE
;
1410 pSource
->play
= AL_TRUE
;
1411 pSource
->position
= 0;
1412 pSource
->position_fraction
= 0;
1413 pSource
->BuffersPlayed
= 0;
1415 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1417 // Make sure all the Buffers in the queue are marked as PENDING
1418 ALBufferList
= pSource
->queue
;
1419 while (ALBufferList
)
1421 ALBufferList
->bufferstate
= PENDING
;
1422 ALBufferList
= ALBufferList
->next
;
1427 pSource
->state
= AL_PLAYING
;
1428 pSource
->inuse
= AL_TRUE
;
1429 pSource
->play
= AL_TRUE
;
1432 // Check if an Offset has been set
1433 if (pSource
->lOffset
)
1434 ApplyOffset(pSource
, AL_FALSE
);
1438 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1439 ALBufferList
= pSource
->queue
;
1440 while (ALBufferList
)
1442 ALBufferList
->bufferstate
= PROCESSED
;
1443 ALBufferList
= ALBufferList
->next
;
1446 pSource
->BuffersPlayed
= pSource
->BuffersInQueue
;
1453 // sources is a NULL pointer
1454 alSetError(AL_INVALID_VALUE
);
1457 ProcessContext(pContext
);
1462 alSetError(AL_INVALID_OPERATION
);
1468 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1470 alSourcePausev(1, &source
);
1474 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1476 ALCcontext
*Context
;
1479 ALboolean bSourcesValid
= AL_TRUE
;
1481 Context
=alcGetCurrentContext();
1484 SuspendContext(Context
);
1488 // Check all the Sources are valid
1491 if (!alIsSource(sources
[i
]))
1493 alSetError(AL_INVALID_NAME
);
1494 bSourcesValid
= AL_FALSE
;
1503 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1504 if (Source
->state
==AL_PLAYING
)
1506 Source
->state
=AL_PAUSED
;
1507 Source
->inuse
=AL_FALSE
;
1514 // sources is a NULL pointer
1515 alSetError(AL_INVALID_VALUE
);
1518 ProcessContext(Context
);
1523 alSetError(AL_INVALID_OPERATION
);
1529 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1531 alSourceStopv(1, &source
);
1535 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1537 ALCcontext
*Context
;
1540 ALbufferlistitem
*ALBufferListItem
;
1541 ALboolean bSourcesValid
= AL_TRUE
;
1543 Context
=alcGetCurrentContext();
1546 SuspendContext(Context
);
1550 // Check all the Sources are valid
1553 if (!alIsSource(sources
[i
]))
1555 alSetError(AL_INVALID_NAME
);
1556 bSourcesValid
= AL_FALSE
;
1565 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1566 if (Source
->state
!=AL_INITIAL
)
1568 Source
->state
=AL_STOPPED
;
1569 Source
->inuse
=AL_FALSE
;
1570 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1571 ALBufferListItem
= Source
->queue
;
1572 while (ALBufferListItem
!= NULL
)
1574 ALBufferListItem
->bufferstate
= PROCESSED
;
1575 ALBufferListItem
= ALBufferListItem
->next
;
1578 Source
->lOffset
= 0;
1584 // sources is a NULL pointer
1585 alSetError(AL_INVALID_VALUE
);
1588 ProcessContext(Context
);
1593 alSetError(AL_INVALID_OPERATION
);
1599 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1601 alSourceRewindv(1, &source
);
1605 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1607 ALCcontext
*Context
;
1610 ALbufferlistitem
*ALBufferListItem
;
1611 ALboolean bSourcesValid
= AL_TRUE
;
1613 Context
=alcGetCurrentContext();
1616 SuspendContext(Context
);
1620 // Check all the Sources are valid
1623 if (!alIsSource(sources
[i
]))
1625 alSetError(AL_INVALID_NAME
);
1626 bSourcesValid
= AL_FALSE
;
1635 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1636 if (Source
->state
!=AL_INITIAL
)
1638 Source
->state
=AL_INITIAL
;
1639 Source
->inuse
=AL_FALSE
;
1641 Source
->position_fraction
=0;
1642 Source
->BuffersPlayed
= 0;
1643 ALBufferListItem
= Source
->queue
;
1644 while (ALBufferListItem
!= NULL
)
1646 ALBufferListItem
->bufferstate
= PENDING
;
1647 ALBufferListItem
= ALBufferListItem
->next
;
1650 Source
->ulBufferID
= Source
->queue
->buffer
;
1652 Source
->lOffset
= 0;
1658 // sources is a NULL pointer
1659 alSetError(AL_INVALID_VALUE
);
1662 ProcessContext(Context
);
1667 alSetError(AL_INVALID_OPERATION
);
1674 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1676 ALCcontext
*Context
;
1679 ALbufferlistitem
*ALBufferList
;
1680 ALbufferlistitem
*ALBufferListStart
;
1685 ALboolean bBuffersValid
= AL_TRUE
;
1690 Context
=alcGetCurrentContext();
1693 SuspendContext(Context
);
1698 // Check that all buffers are valid or zero and that the source is valid
1700 // Check that this is a valid source
1701 if (alIsSource(source
))
1703 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1705 // Check that this is not a STATIC Source
1706 if (ALSource
->lSourceType
!= AL_STATIC
)
1711 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1712 ALBufferList
= ALSource
->queue
;
1713 while (ALBufferList
)
1715 if (ALBufferList
->buffer
)
1717 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1718 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1721 ALBufferList
= ALBufferList
->next
;
1724 for (i
= 0; i
< n
; i
++)
1726 if (alIsBuffer(buffers
[i
]))
1730 if ((iFrequency
== -1) && (iFormat
== -1))
1732 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1733 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1737 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1738 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1740 alSetError(AL_INVALID_OPERATION
);
1741 bBuffersValid
= AL_FALSE
;
1749 alSetError(AL_INVALID_NAME
);
1750 bBuffersValid
= AL_FALSE
;
1757 // Change Source Type
1758 ALSource
->lSourceType
= AL_STREAMING
;
1760 // All buffers are valid - so add them to the list
1761 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1762 ALBufferListStart
->buffer
= buffers
[0];
1763 ALBufferListStart
->bufferstate
= PENDING
;
1764 ALBufferListStart
->flag
= 0;
1765 ALBufferListStart
->next
= NULL
;
1768 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1772 DataSize
+= BufferSize
;
1774 // Increment reference counter for buffer
1776 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1778 ALBufferList
= ALBufferListStart
;
1780 for (i
= 1; i
< n
; i
++)
1782 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1783 ALBufferList
->next
->buffer
= buffers
[i
];
1784 ALBufferList
->next
->bufferstate
= PENDING
;
1785 ALBufferList
->next
->flag
= 0;
1786 ALBufferList
->next
->next
= NULL
;
1789 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1793 DataSize
+= BufferSize
;
1795 // Increment reference counter for buffer
1797 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1799 ALBufferList
= ALBufferList
->next
;
1802 if (ALSource
->queue
== NULL
)
1804 ALSource
->queue
= ALBufferListStart
;
1805 // Update Current Buffer
1806 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1810 // Find end of queue
1811 ALBufferList
= ALSource
->queue
;
1812 while (ALBufferList
->next
!= NULL
)
1814 ALBufferList
= ALBufferList
->next
;
1817 ALBufferList
->next
= ALBufferListStart
;
1820 // Update number of buffers in queue
1821 ALSource
->BuffersInQueue
+= n
;
1826 // Invalid Source Type (can't queue on a Static Source)
1827 alSetError(AL_INVALID_OPERATION
);
1832 // Invalid Source Name
1833 alSetError(AL_INVALID_NAME
);
1836 ProcessContext(Context
);
1841 alSetError(AL_INVALID_OPERATION
);
1848 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1849 // an array of buffer IDs that are to be filled with the names of the buffers removed
1850 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1852 ALCcontext
*Context
;
1855 ALbufferlistitem
*ALBufferList
;
1859 ALboolean bBuffersProcessed
;
1866 bBuffersProcessed
= AL_TRUE
;
1868 Context
=alcGetCurrentContext();
1871 SuspendContext(Context
);
1873 if (alIsSource(source
))
1875 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1877 // Check that all 'n' buffers have been processed
1878 ALBufferList
= ALSource
->queue
;
1879 for (i
= 0; i
< n
; i
++)
1881 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1883 ALBufferList
= ALBufferList
->next
;
1887 bBuffersProcessed
= AL_FALSE
;
1892 // If all 'n' buffers have been processed, remove them from the queue
1893 if (bBuffersProcessed
)
1895 for (i
= 0; i
< n
; i
++)
1897 ALBufferList
= ALSource
->queue
;
1899 ALSource
->queue
= ALBufferList
->next
;
1900 // Record name of buffer
1901 buffers
[i
] = ALBufferList
->buffer
;
1902 // Decrement buffer reference counter
1903 if (ALBufferList
->buffer
)
1904 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1905 // Record size of buffer
1906 if (ALBufferList
->buffer
)
1907 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1911 DataSize
+= BufferSize
;
1912 // Release memory for buffer list item
1914 ALSource
->BuffersInQueue
--;
1917 if (ALSource
->state
!= AL_PLAYING
)
1919 if (ALSource
->queue
)
1920 BufferID
= ALSource
->queue
->buffer
;
1924 ALSource
->ulBufferID
= BufferID
;
1927 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1928 ALSource
->BuffersPlayed
= 0;
1930 ALSource
->BuffersPlayed
-= n
;
1934 // Some buffers can't be unqueue because they have not been processed
1935 alSetError(AL_INVALID_VALUE
);
1940 // Invalid Source Name
1941 alSetError(AL_INVALID_NAME
);
1944 ProcessContext(Context
);
1949 alSetError(AL_INVALID_OPERATION
);
1956 static ALvoid
InitSourceParams(ALsource
*pSource
)
1958 pSource
->flInnerAngle
= 360.0f
;
1959 pSource
->flOuterAngle
= 360.0f
;
1960 pSource
->flPitch
= 1.0f
;
1961 pSource
->vPosition
[0] = 0.0f
;
1962 pSource
->vPosition
[1] = 0.0f
;
1963 pSource
->vPosition
[2] = 0.0f
;
1964 pSource
->vOrientation
[0] = 0.0f
;
1965 pSource
->vOrientation
[1] = 0.0f
;
1966 pSource
->vOrientation
[2] = 0.0f
;
1967 pSource
->vVelocity
[0] = 0.0f
;
1968 pSource
->vVelocity
[1] = 0.0f
;
1969 pSource
->vVelocity
[2] = 0.0f
;
1970 pSource
->flRefDistance
= 1.0f
;
1971 pSource
->flMaxDistance
= FLT_MAX
;
1972 pSource
->flRollOffFactor
= 1.0f
;
1973 pSource
->bLooping
= AL_FALSE
;
1974 pSource
->flGain
= 1.0f
;
1975 pSource
->flMinGain
= 0.0f
;
1976 pSource
->flMaxGain
= 1.0f
;
1977 pSource
->flOuterGain
= 0.0f
;
1978 pSource
->OuterGainHF
= 1.0f
;
1980 pSource
->DryGainHFAuto
= AL_TRUE
;
1981 pSource
->WetGainAuto
= AL_TRUE
;
1982 pSource
->WetGainHFAuto
= AL_TRUE
;
1983 pSource
->AirAbsorptionFactor
= 0.0f
;
1984 pSource
->RoomRolloffFactor
= 0.0f
;
1985 pSource
->DopplerFactor
= 1.0f
;
1987 pSource
->state
= AL_INITIAL
;
1988 pSource
->lSourceType
= AL_UNDETERMINED
;
1990 pSource
->ulBufferID
= 0;
1997 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1998 The offset is relative to the start of the queue (not the start of the current buffer)
2000 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
2002 ALbufferlistitem
*pBufferList
;
2004 ALfloat flBufferFreq
;
2005 ALint lBytesPlayed
, lChannels
;
2006 ALenum eOriginalFormat
;
2007 ALboolean bReturn
= AL_TRUE
;
2008 ALint lTotalBufferDataSize
;
2010 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
2012 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
2013 // Get Current Buffer Size and frequency (in milliseconds)
2014 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
2015 eOriginalFormat
= pBuffer
->eOriginalFormat
;
2016 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2018 // Get Current BytesPlayed
2019 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2020 // Add byte length of any processed buffers in the queue
2021 pBufferList
= pSource
->queue
;
2022 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2024 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2025 pBufferList
= pBufferList
->next
;
2028 lTotalBufferDataSize
= 0;
2029 pBufferList
= pSource
->queue
;
2032 if (pBufferList
->buffer
)
2033 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2034 pBufferList
= pBufferList
->next
;
2037 if (pSource
->bLooping
)
2039 if (lBytesPlayed
< 0)
2042 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
2046 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2047 if(lBytesPlayed
< 0)
2049 if(lBytesPlayed
> lTotalBufferDataSize
)
2050 lBytesPlayed
= lTotalBufferDataSize
;
2056 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
2058 case AL_SAMPLE_OFFSET
:
2059 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
2061 case AL_BYTE_OFFSET
:
2062 // Take into account the original format of the Buffer
2063 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2064 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2066 // Compression rate of the ADPCM supported is 3.6111 to 1
2067 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
2068 // Round down to nearest ADPCM block
2069 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
2071 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2073 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 2);
2075 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2077 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2079 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2081 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2083 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2085 *pflOffset
= (ALfloat
)(lBytesPlayed
<< 1);
2089 *pflOffset
= (ALfloat
)lBytesPlayed
;
2106 Apply a playback offset to the Source. This function will update the queue (to correctly
2107 mark buffers as 'pending' or 'processed' depending upon the new offset.
2109 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2111 ALbufferlistitem
*pBufferList
;
2113 ALint lBufferSize
, lTotalBufferSize
;
2116 // Get true byte offset
2117 lByteOffset
= GetByteOffset(pSource
);
2119 // If this is a valid offset apply it
2120 if (lByteOffset
!= -1)
2122 // Sort out the queue (pending and processed states)
2123 pBufferList
= pSource
->queue
;
2124 lTotalBufferSize
= 0;
2125 pSource
->BuffersPlayed
= 0;
2128 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2129 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2131 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2133 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2134 // update the state to PROCESSED
2135 pSource
->BuffersPlayed
++;
2137 if (!pSource
->bLooping
)
2138 pBufferList
->bufferstate
= PROCESSED
;
2140 else if (lTotalBufferSize
<= lByteOffset
)
2142 // Offset is within this buffer
2143 pBufferList
->bufferstate
= PENDING
;
2145 // Set Current Buffer ID
2146 pSource
->ulBufferID
= pBufferList
->buffer
;
2148 // SW Mixer Positions are in Samples
2149 pSource
->position
= (lByteOffset
- lTotalBufferSize
) /
2150 aluBytesFromFormat(pBuffer
->format
) /
2151 aluChannelsFromFormat(pBuffer
->format
);
2155 // Offset is before this buffer, so mark as pending
2156 pBufferList
->bufferstate
= PENDING
;
2159 // Increment the TotalBufferSize
2160 lTotalBufferSize
+= lBufferSize
;
2162 // Move on to next buffer in the Queue
2163 pBufferList
= pBufferList
->next
;
2169 alSetError(AL_INVALID_VALUE
);
2173 pSource
->lOffset
= 0;
2180 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2181 offset supplied by the application). This takes into account the fact that the buffer format
2182 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2184 static ALint
GetByteOffset(ALsource
*pSource
)
2186 ALbuffer
*pBuffer
= NULL
;
2187 ALbufferlistitem
*pBufferList
;
2188 ALfloat flBufferFreq
;
2190 ALint lByteOffset
= -1;
2191 ALint lTotalBufferDataSize
;
2193 // Find the first non-NULL Buffer in the Queue
2194 pBufferList
= pSource
->queue
;
2197 if (pBufferList
->buffer
)
2199 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2202 pBufferList
= pBufferList
->next
;
2207 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2208 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2210 // Determine the ByteOffset (and ensure it is block aligned)
2211 switch (pSource
->lOffsetType
)
2213 case AL_BYTE_OFFSET
:
2214 // Take into consideration the original format
2215 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2216 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2218 // Round down to nearest ADPCM block
2219 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2220 // Multiply by compression rate
2221 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2222 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2224 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2226 lByteOffset
= pSource
->lOffset
* 4;
2227 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2229 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2231 lByteOffset
= pSource
->lOffset
* 2;
2232 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2234 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2236 lByteOffset
= pSource
->lOffset
* 2;
2237 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2239 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2241 lByteOffset
= pSource
->lOffset
/ 2;
2242 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2246 lByteOffset
= pSource
->lOffset
;
2247 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2251 case AL_SAMPLE_OFFSET
:
2252 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2256 // Note - lOffset is internally stored as Milliseconds
2257 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2258 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2262 lTotalBufferDataSize
= 0;
2263 pBufferList
= pSource
->queue
;
2266 if (pBufferList
->buffer
)
2267 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2268 pBufferList
= pBufferList
->next
;
2271 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2272 if (lByteOffset
>= lTotalBufferDataSize
)
2280 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2283 if(Context
->SourceCount
> 0)
2284 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", Context
->SourceCount
);
2287 while(Context
->Source
)
2289 ALsource
*temp
= Context
->Source
;
2290 Context
->Source
= Context
->Source
->next
;
2292 // Release source structure
2293 ALTHUNK_REMOVEENTRY(temp
->source
);
2294 memset(temp
, 0, sizeof(ALsource
));
2297 Context
->SourceCount
= 0;