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 InitLowPassFilter(Context
, &(*list
)->iirFilter
);
80 sources
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
81 (*list
)->source
= sources
[i
];
83 InitSourceParams(*list
);
84 Context
->SourceCount
++;
87 list
= &(*list
)->next
;
92 // Not enough resources to create the Sources
93 alSetError(AL_INVALID_VALUE
);
99 alSetError(AL_INVALID_VALUE
);
104 // No Device created, or attached to Context
105 alSetError(AL_INVALID_OPERATION
);
109 ProcessContext(Context
);
114 alSetError(AL_INVALID_OPERATION
);
121 ALAPI ALvoid ALAPIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
128 ALbufferlistitem
*ALBufferList
;
129 ALboolean bSourcesValid
= AL_TRUE
;
131 Context
= alcGetCurrentContext();
134 SuspendContext(Context
);
138 Device
= alcGetContextsDevice(Context
);
142 // Check that all Sources are valid (and can therefore be deleted)
143 for (i
= 0; i
< n
; i
++)
145 if (!alIsSource(sources
[i
]))
147 alSetError(AL_INVALID_NAME
);
148 bSourcesValid
= AL_FALSE
;
155 // All Sources are valid, and can be deleted
156 for (i
= 0; i
< n
; i
++)
158 // Recheck that the Source is valid, because there could be duplicated Source names
159 if (alIsSource(sources
[i
]))
161 ALSource
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
162 alSourceStop((ALuint
)ALSource
->source
);
164 // For each buffer in the source's queue, decrement its reference counter and remove it
165 while (ALSource
->queue
!= NULL
)
167 ALBufferList
= ALSource
->queue
;
168 // Decrement buffer's reference counter
169 if (ALBufferList
->buffer
!= 0)
170 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
171 // Update queue to point to next element in list
172 ALSource
->queue
= ALBufferList
->next
;
173 // Release memory allocated for buffer list item
177 for(j
= 0;j
< MAX_SENDS
;++j
)
179 if(ALSource
->Send
[j
].Slot
)
180 ALSource
->Send
[j
].Slot
->refcount
--;
181 ALSource
->Send
[j
].Slot
= NULL
;
184 // Decrement Source count
185 Context
->SourceCount
--;
187 // Remove Source from list of Sources
188 list
= &Context
->Source
;
189 while(*list
&& *list
!= ALSource
)
190 list
= &(*list
)->next
;
193 *list
= (*list
)->next
;
194 ALTHUNK_REMOVEENTRY(ALSource
->source
);
196 memset(ALSource
,0,sizeof(ALsource
));
204 // No Device created, or attached to Context
205 alSetError(AL_INVALID_OPERATION
);
209 alSetError(AL_INVALID_VALUE
);
211 ProcessContext(Context
);
216 alSetError(AL_INVALID_OPERATION
);
223 ALAPI ALboolean ALAPIENTRY
alIsSource(ALuint source
)
225 ALboolean result
=AL_FALSE
;
229 Context
=alcGetCurrentContext();
232 SuspendContext(Context
);
234 // To determine if this is a valid Source name, look through the list of generated Sources
235 Source
= Context
->Source
;
238 if (Source
== (ALsource
*)ALTHUNK_LOOKUPENTRY(source
))
244 Source
= Source
->next
;
247 ProcessContext(Context
);
252 alSetError(AL_INVALID_OPERATION
);
259 ALAPI ALvoid ALAPIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
261 ALCcontext
*pContext
;
264 pContext
= alcGetCurrentContext();
267 SuspendContext(pContext
);
269 if (alIsSource(source
))
271 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
278 pSource
->flPitch
= flValue
;
279 if(pSource
->flPitch
< 0.001f
)
280 pSource
->flPitch
= 0.001f
;
283 alSetError(AL_INVALID_VALUE
);
286 case AL_CONE_INNER_ANGLE
:
287 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
288 pSource
->flInnerAngle
= flValue
;
290 alSetError(AL_INVALID_VALUE
);
293 case AL_CONE_OUTER_ANGLE
:
294 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
295 pSource
->flOuterAngle
= flValue
;
297 alSetError(AL_INVALID_VALUE
);
302 pSource
->flGain
= flValue
;
304 alSetError(AL_INVALID_VALUE
);
307 case AL_MAX_DISTANCE
:
309 pSource
->flMaxDistance
= flValue
;
311 alSetError(AL_INVALID_VALUE
);
314 case AL_ROLLOFF_FACTOR
:
316 pSource
->flRollOffFactor
= flValue
;
318 alSetError(AL_INVALID_VALUE
);
321 case AL_REFERENCE_DISTANCE
:
323 pSource
->flRefDistance
= flValue
;
325 alSetError(AL_INVALID_VALUE
);
329 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
330 pSource
->flMinGain
= flValue
;
332 alSetError(AL_INVALID_VALUE
);
336 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
337 pSource
->flMaxGain
= flValue
;
339 alSetError(AL_INVALID_VALUE
);
342 case AL_CONE_OUTER_GAIN
:
343 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
344 pSource
->flOuterGain
= flValue
;
346 alSetError(AL_INVALID_VALUE
);
349 case AL_CONE_OUTER_GAINHF
:
350 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
351 pSource
->OuterGainHF
= flValue
;
353 alSetError(AL_INVALID_VALUE
);
356 case AL_AIR_ABSORPTION_FACTOR
:
357 if (flValue
>= 0.0f
&& flValue
<= 10.0f
)
358 pSource
->AirAbsorptionFactor
= flValue
;
360 alSetError(AL_INVALID_VALUE
);
363 case AL_ROOM_ROLLOFF_FACTOR
:
364 if (flValue
>= 0.0f
&& flValue
<= 1.0f
)
365 pSource
->RoomRolloffFactor
= flValue
;
367 alSetError(AL_INVALID_VALUE
);
370 case AL_DOPPLER_FACTOR
:
371 if (flValue
>= 0.0f
&& flValue
<= 1.0f
)
372 pSource
->DopplerFactor
= flValue
;
374 alSetError(AL_INVALID_VALUE
);
378 case AL_SAMPLE_OFFSET
:
382 pSource
->lOffsetType
= eParam
;
384 // Store Offset (convert Seconds into Milliseconds)
385 if (eParam
== AL_SEC_OFFSET
)
386 pSource
->lOffset
= (ALint
)(flValue
* 1000.0f
);
388 pSource
->lOffset
= (ALint
)flValue
;
390 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
391 ApplyOffset(pSource
, AL_TRUE
);
394 alSetError(AL_INVALID_VALUE
);
398 alSetError(AL_INVALID_ENUM
);
404 // Invalid Source Name
405 alSetError(AL_INVALID_NAME
);
408 ProcessContext(pContext
);
413 alSetError(AL_INVALID_OPERATION
);
420 ALAPI ALvoid ALAPIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
422 ALCcontext
*pContext
;
425 pContext
= alcGetCurrentContext();
428 SuspendContext(pContext
);
430 if (alIsSource(source
))
432 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
436 pSource
->vPosition
[0] = flValue1
;
437 pSource
->vPosition
[1] = flValue2
;
438 pSource
->vPosition
[2] = flValue3
;
442 pSource
->vVelocity
[0] = flValue1
;
443 pSource
->vVelocity
[1] = flValue2
;
444 pSource
->vVelocity
[2] = flValue3
;
448 pSource
->vOrientation
[0] = flValue1
;
449 pSource
->vOrientation
[1] = flValue2
;
450 pSource
->vOrientation
[2] = flValue3
;
454 alSetError(AL_INVALID_ENUM
);
459 alSetError(AL_INVALID_NAME
);
461 ProcessContext(pContext
);
465 alSetError(AL_INVALID_OPERATION
);
472 ALAPI ALvoid ALAPIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
474 ALCcontext
*pContext
;
476 pContext
= alcGetCurrentContext();
479 SuspendContext(pContext
);
483 if (alIsSource(source
))
488 case AL_CONE_INNER_ANGLE
:
489 case AL_CONE_OUTER_ANGLE
:
491 case AL_MAX_DISTANCE
:
492 case AL_ROLLOFF_FACTOR
:
493 case AL_REFERENCE_DISTANCE
:
496 case AL_CONE_OUTER_GAIN
:
497 case AL_CONE_OUTER_GAINHF
:
499 case AL_SAMPLE_OFFSET
:
501 case AL_AIR_ABSORPTION_FACTOR
:
502 case AL_ROOM_ROLLOFF_FACTOR
:
503 alSourcef(source
, eParam
, pflValues
[0]);
509 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
513 alSetError(AL_INVALID_ENUM
);
518 alSetError(AL_INVALID_NAME
);
521 alSetError(AL_INVALID_VALUE
);
523 ProcessContext(pContext
);
526 alSetError(AL_INVALID_OPERATION
);
532 ALAPI ALvoid ALAPIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
534 ALCcontext
*pContext
;
536 ALbufferlistitem
*pALBufferListItem
;
541 pContext
= alcGetCurrentContext();
544 SuspendContext(pContext
);
546 if (alIsSource(source
))
548 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
552 case AL_MAX_DISTANCE
:
553 case AL_ROLLOFF_FACTOR
:
554 case AL_REFERENCE_DISTANCE
:
555 alSourcef(source
, eParam
, (ALfloat
)lValue
);
558 case AL_SOURCE_RELATIVE
:
559 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
560 pSource
->bHeadRelative
= (ALboolean
)lValue
;
562 alSetError(AL_INVALID_VALUE
);
565 case AL_CONE_INNER_ANGLE
:
566 if ((lValue
>= 0) && (lValue
<= 360))
567 pSource
->flInnerAngle
= (float)lValue
;
569 alSetError(AL_INVALID_VALUE
);
572 case AL_CONE_OUTER_ANGLE
:
573 if ((lValue
>= 0) && (lValue
<= 360))
574 pSource
->flOuterAngle
= (float)lValue
;
576 alSetError(AL_INVALID_VALUE
);
580 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
581 pSource
->bLooping
= (ALboolean
)lValue
;
583 alSetError(AL_INVALID_VALUE
);
587 if ((pSource
->state
== AL_STOPPED
) || (pSource
->state
== AL_INITIAL
))
589 if (alIsBuffer(lValue
))
591 // Remove all elements in the queue
592 while (pSource
->queue
!= NULL
)
594 pALBufferListItem
= pSource
->queue
;
595 pSource
->queue
= pALBufferListItem
->next
;
596 // Decrement reference counter for buffer
597 if (pALBufferListItem
->buffer
)
598 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
)))->refcount
--;
599 // Record size of buffer
600 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
))->size
;
601 DataSize
+= BufferSize
;
602 // Increment the number of buffers removed from queue
604 // Release memory for buffer list item
605 free(pALBufferListItem
);
606 // Decrement the number of buffers in the queue
607 pSource
->BuffersInQueue
--;
610 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
613 // Source is now in STATIC mode
614 pSource
->lSourceType
= AL_STATIC
;
616 // Add the selected buffer to the queue
617 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
618 pALBufferListItem
->buffer
= lValue
;
619 pALBufferListItem
->bufferstate
= PENDING
;
620 pALBufferListItem
->flag
= 0;
621 pALBufferListItem
->next
= NULL
;
623 pSource
->queue
= pALBufferListItem
;
624 pSource
->BuffersInQueue
= 1;
626 DataSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(lValue
))->size
;
628 // Increment reference counter for buffer
629 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(lValue
)))->refcount
++;
633 // Source is now in UNDETERMINED mode
634 pSource
->lSourceType
= AL_UNDETERMINED
;
637 // Update AL_BUFFER parameter
638 pSource
->ulBufferID
= lValue
;
641 alSetError(AL_INVALID_VALUE
);
644 alSetError(AL_INVALID_OPERATION
);
647 case AL_SOURCE_STATE
:
649 alSetError(AL_INVALID_OPERATION
);
653 case AL_SAMPLE_OFFSET
:
657 pSource
->lOffsetType
= eParam
;
659 // Store Offset (convert Seconds into Milliseconds)
660 if (eParam
== AL_SEC_OFFSET
)
661 pSource
->lOffset
= lValue
* 1000;
663 pSource
->lOffset
= lValue
;
665 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
666 ApplyOffset(pSource
, AL_TRUE
);
669 alSetError(AL_INVALID_VALUE
);
672 case AL_DIRECT_FILTER
:
673 if(alIsFilter(lValue
))
675 ALfilter
*filter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue
);
678 pSource
->DirectFilter
.type
= AL_FILTER_NULL
;
679 pSource
->DirectFilter
.filter
= 0;
682 memcpy(&pSource
->DirectFilter
, filter
, sizeof(*filter
));
685 alSetError(AL_INVALID_VALUE
);
688 case AL_DIRECT_FILTER_GAINHF_AUTO
:
689 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
690 pSource
->DryGainHFAuto
= lValue
;
692 alSetError(AL_INVALID_VALUE
);
695 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
696 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
697 pSource
->WetGainAuto
= lValue
;
699 alSetError(AL_INVALID_VALUE
);
702 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
703 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
704 pSource
->WetGainHFAuto
= lValue
;
706 alSetError(AL_INVALID_VALUE
);
710 alSetError(AL_INVALID_ENUM
);
715 alSetError(AL_INVALID_NAME
);
717 ProcessContext(pContext
);
720 alSetError(AL_INVALID_OPERATION
);
726 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
728 ALCcontext
*pContext
;
730 pContext
= alcGetCurrentContext();
733 SuspendContext(pContext
);
735 if (alIsSource(source
))
737 ALsource
*pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
744 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
747 case AL_AUXILIARY_SEND_FILTER
:
748 if(lValue2
>= 0 && lValue2
< MAX_SENDS
&&
749 (alIsAuxiliaryEffectSlot(lValue1
) || lValue1
== 0) &&
752 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(lValue1
);
753 ALfilter
*ALFilter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue3
);
755 /* Release refcount on the previous slot, and add one for
757 if(pSource
->Send
[lValue2
].Slot
)
758 pSource
->Send
[lValue2
].Slot
->refcount
--;
759 pSource
->Send
[lValue2
].Slot
= ALEffectSlot
;
760 if(pSource
->Send
[lValue2
].Slot
)
761 pSource
->Send
[lValue2
].Slot
->refcount
++;
766 pSource
->Send
[lValue2
].WetFilter
.type
= 0;
767 pSource
->Send
[lValue2
].WetFilter
.filter
= 0;
770 memcpy(&pSource
->Send
[lValue2
].WetFilter
, ALFilter
, sizeof(*ALFilter
));
773 alSetError(AL_INVALID_VALUE
);
777 alSetError(AL_INVALID_ENUM
);
782 alSetError(AL_INVALID_NAME
);
784 ProcessContext(pContext
);
787 alSetError(AL_INVALID_OPERATION
);
793 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
795 ALCcontext
*pContext
;
797 pContext
= alcGetCurrentContext();
800 SuspendContext(pContext
);
804 if (alIsSource(source
))
808 case AL_SOURCE_RELATIVE
:
809 case AL_CONE_INNER_ANGLE
:
810 case AL_CONE_OUTER_ANGLE
:
813 case AL_SOURCE_STATE
:
815 case AL_SAMPLE_OFFSET
:
817 case AL_MAX_DISTANCE
:
818 case AL_ROLLOFF_FACTOR
:
819 case AL_REFERENCE_DISTANCE
:
820 case AL_DIRECT_FILTER
:
821 case AL_DIRECT_FILTER_GAINHF_AUTO
:
822 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
823 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
824 alSourcei(source
, eParam
, plValues
[0]);
830 case AL_AUXILIARY_SEND_FILTER
:
831 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
835 alSetError(AL_INVALID_ENUM
);
840 alSetError(AL_INVALID_NAME
);
843 alSetError(AL_INVALID_VALUE
);
845 ProcessContext(pContext
);
848 alSetError(AL_INVALID_OPERATION
);
854 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
856 ALCcontext
*pContext
;
860 pContext
= alcGetCurrentContext();
863 SuspendContext(pContext
);
867 if (alIsSource(source
))
869 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
874 *pflValue
= pSource
->flPitch
;
878 *pflValue
= pSource
->flGain
;
882 *pflValue
= pSource
->flMinGain
;
886 *pflValue
= pSource
->flMaxGain
;
889 case AL_MAX_DISTANCE
:
890 *pflValue
= pSource
->flMaxDistance
;
893 case AL_ROLLOFF_FACTOR
:
894 *pflValue
= pSource
->flRollOffFactor
;
897 case AL_CONE_OUTER_GAIN
:
898 *pflValue
= pSource
->flOuterGain
;
901 case AL_CONE_OUTER_GAINHF
:
902 *pflValue
= pSource
->OuterGainHF
;
906 case AL_SAMPLE_OFFSET
:
908 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
909 *pflValue
= flOffset
;
911 alSetError(AL_INVALID_OPERATION
);
914 case AL_CONE_INNER_ANGLE
:
915 *pflValue
= pSource
->flInnerAngle
;
918 case AL_CONE_OUTER_ANGLE
:
919 *pflValue
= pSource
->flOuterAngle
;
922 case AL_REFERENCE_DISTANCE
:
923 *pflValue
= pSource
->flRefDistance
;
926 case AL_AIR_ABSORPTION_FACTOR
:
927 *pflValue
= pSource
->AirAbsorptionFactor
;
930 case AL_ROOM_ROLLOFF_FACTOR
:
931 *pflValue
= pSource
->RoomRolloffFactor
;
934 case AL_DOPPLER_FACTOR
:
935 *pflValue
= pSource
->DopplerFactor
;
939 alSetError(AL_INVALID_ENUM
);
944 alSetError(AL_INVALID_NAME
);
947 alSetError(AL_INVALID_VALUE
);
949 ProcessContext(pContext
);
952 alSetError(AL_INVALID_OPERATION
);
958 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
960 ALCcontext
*pContext
;
963 pContext
= alcGetCurrentContext();
966 SuspendContext(pContext
);
968 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
970 if (alIsSource(source
))
972 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
977 *pflValue1
= pSource
->vPosition
[0];
978 *pflValue2
= pSource
->vPosition
[1];
979 *pflValue3
= pSource
->vPosition
[2];
983 *pflValue1
= pSource
->vVelocity
[0];
984 *pflValue2
= pSource
->vVelocity
[1];
985 *pflValue3
= pSource
->vVelocity
[2];
989 *pflValue1
= pSource
->vOrientation
[0];
990 *pflValue2
= pSource
->vOrientation
[1];
991 *pflValue3
= pSource
->vOrientation
[2];
995 alSetError(AL_INVALID_ENUM
);
1000 alSetError(AL_INVALID_NAME
);
1003 alSetError(AL_INVALID_VALUE
);
1005 ProcessContext(pContext
);
1008 alSetError(AL_INVALID_OPERATION
);
1014 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1016 ALCcontext
*pContext
;
1019 pContext
= alcGetCurrentContext();
1022 SuspendContext(pContext
);
1026 if (alIsSource(source
))
1028 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1036 case AL_MAX_DISTANCE
:
1037 case AL_ROLLOFF_FACTOR
:
1038 case AL_DOPPLER_FACTOR
:
1039 case AL_CONE_OUTER_GAIN
:
1041 case AL_SAMPLE_OFFSET
:
1042 case AL_BYTE_OFFSET
:
1043 case AL_CONE_INNER_ANGLE
:
1044 case AL_CONE_OUTER_ANGLE
:
1045 case AL_REFERENCE_DISTANCE
:
1046 case AL_CONE_OUTER_GAINHF
:
1047 case AL_AIR_ABSORPTION_FACTOR
:
1048 case AL_ROOM_ROLLOFF_FACTOR
:
1049 alGetSourcef(source
, eParam
, pflValues
);
1053 pflValues
[0] = pSource
->vPosition
[0];
1054 pflValues
[1] = pSource
->vPosition
[1];
1055 pflValues
[2] = pSource
->vPosition
[2];
1059 pflValues
[0] = pSource
->vVelocity
[0];
1060 pflValues
[1] = pSource
->vVelocity
[1];
1061 pflValues
[2] = pSource
->vVelocity
[2];
1065 pflValues
[0] = pSource
->vOrientation
[0];
1066 pflValues
[1] = pSource
->vOrientation
[1];
1067 pflValues
[2] = pSource
->vOrientation
[2];
1071 alSetError(AL_INVALID_ENUM
);
1076 alSetError(AL_INVALID_NAME
);
1079 alSetError(AL_INVALID_VALUE
);
1081 ProcessContext(pContext
);
1084 alSetError(AL_INVALID_OPERATION
);
1090 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1092 ALCcontext
*pContext
;
1096 pContext
= alcGetCurrentContext();
1099 SuspendContext(pContext
);
1103 if (alIsSource(source
))
1105 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1109 case AL_MAX_DISTANCE
:
1110 *plValue
= (ALint
)pSource
->flMaxDistance
;
1113 case AL_ROLLOFF_FACTOR
:
1114 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1117 case AL_REFERENCE_DISTANCE
:
1118 *plValue
= (ALint
)pSource
->flRefDistance
;
1121 case AL_SOURCE_RELATIVE
:
1122 *plValue
= pSource
->bHeadRelative
;
1125 case AL_CONE_INNER_ANGLE
:
1126 *plValue
= (ALint
)pSource
->flInnerAngle
;
1129 case AL_CONE_OUTER_ANGLE
:
1130 *plValue
= (ALint
)pSource
->flOuterAngle
;
1134 *plValue
= pSource
->bLooping
;
1138 *plValue
= pSource
->ulBufferID
;
1141 case AL_SOURCE_STATE
:
1142 *plValue
= pSource
->state
;
1145 case AL_BUFFERS_QUEUED
:
1146 *plValue
= pSource
->BuffersInQueue
;
1149 case AL_BUFFERS_PROCESSED
:
1150 if(pSource
->bLooping
)
1152 /* Buffers on a looping source are in a perpetual state
1153 * of PENDING, so don't report any as PROCESSED */
1157 *plValue
= pSource
->BuffersPlayed
;
1160 case AL_SOURCE_TYPE
:
1161 *plValue
= pSource
->lSourceType
;
1165 case AL_SAMPLE_OFFSET
:
1166 case AL_BYTE_OFFSET
:
1167 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
1168 *plValue
= (ALint
)flOffset
;
1170 alSetError(AL_INVALID_OPERATION
);
1173 case AL_DIRECT_FILTER
:
1174 *plValue
= pSource
->DirectFilter
.filter
;
1177 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1178 *plValue
= pSource
->DryGainHFAuto
;
1181 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1182 *plValue
= pSource
->WetGainAuto
;
1185 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1186 *plValue
= pSource
->WetGainHFAuto
;
1189 case AL_DOPPLER_FACTOR
:
1190 *plValue
= (ALint
)pSource
->DopplerFactor
;
1194 alSetError(AL_INVALID_ENUM
);
1199 alSetError(AL_INVALID_NAME
);
1202 alSetError(AL_INVALID_VALUE
);
1204 ProcessContext(pContext
);
1207 alSetError(AL_INVALID_OPERATION
);
1213 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1215 ALCcontext
*pContext
;
1218 pContext
= alcGetCurrentContext();
1221 SuspendContext(pContext
);
1223 if ((plValue1
) && (plValue2
) && (plValue3
))
1225 if (alIsSource(source
))
1227 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1232 *plValue1
= (ALint
)pSource
->vPosition
[0];
1233 *plValue2
= (ALint
)pSource
->vPosition
[1];
1234 *plValue3
= (ALint
)pSource
->vPosition
[2];
1238 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1239 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1240 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1244 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1245 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1246 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1250 alSetError(AL_INVALID_ENUM
);
1255 alSetError(AL_INVALID_NAME
);
1258 alSetError(AL_INVALID_VALUE
);
1260 ProcessContext(pContext
);
1263 alSetError(AL_INVALID_OPERATION
);
1269 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1271 ALCcontext
*pContext
;
1274 pContext
= alcGetCurrentContext();
1277 SuspendContext(pContext
);
1281 if (alIsSource(source
))
1283 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1287 case AL_SOURCE_RELATIVE
:
1288 case AL_CONE_INNER_ANGLE
:
1289 case AL_CONE_OUTER_ANGLE
:
1292 case AL_SOURCE_STATE
:
1293 case AL_BUFFERS_QUEUED
:
1294 case AL_BUFFERS_PROCESSED
:
1296 case AL_SAMPLE_OFFSET
:
1297 case AL_BYTE_OFFSET
:
1298 case AL_MAX_DISTANCE
:
1299 case AL_ROLLOFF_FACTOR
:
1300 case AL_DOPPLER_FACTOR
:
1301 case AL_REFERENCE_DISTANCE
:
1302 case AL_SOURCE_TYPE
:
1303 case AL_DIRECT_FILTER
:
1304 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1305 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1306 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1307 alGetSourcei(source
, eParam
, plValues
);
1311 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1312 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1313 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1317 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1318 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1319 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1323 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1324 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1325 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1329 alSetError(AL_INVALID_ENUM
);
1334 alSetError(AL_INVALID_NAME
);
1337 alSetError(AL_INVALID_VALUE
);
1339 ProcessContext(pContext
);
1342 alSetError(AL_INVALID_OPERATION
);
1348 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1350 alSourcePlayv(1, &source
);
1354 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1356 ALCcontext
*pContext
;
1358 ALbufferlistitem
*ALBufferList
;
1359 ALboolean bSourcesValid
= AL_TRUE
;
1363 pContext
= alcGetCurrentContext();
1366 SuspendContext(pContext
);
1370 // Check that all the Sources are valid
1371 for (i
= 0; i
< n
; i
++)
1373 if (!alIsSource(pSourceList
[i
]))
1375 alSetError(AL_INVALID_NAME
);
1376 bSourcesValid
= AL_FALSE
;
1383 for (i
= 0; i
< n
; i
++)
1385 // Assume Source won't need to play
1388 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1390 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1391 ALBufferList
= pSource
->queue
;
1392 while (ALBufferList
)
1394 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1399 ALBufferList
= ALBufferList
->next
;
1404 for(j
= 0;j
< OUTPUTCHANNELS
;j
++)
1406 pSource
->DryGains
[j
] = 0.0f
;
1407 pSource
->WetGains
[j
] = 0.0f
;
1409 pSource
->DryGainHF
= 0.0f
;
1410 pSource
->WetGainHF
= 0.0f
;
1412 if (pSource
->state
!= AL_PAUSED
)
1414 pSource
->state
= AL_PLAYING
;
1415 pSource
->inuse
= AL_TRUE
;
1416 pSource
->play
= AL_TRUE
;
1417 pSource
->position
= 0;
1418 pSource
->position_fraction
= 0;
1419 pSource
->BuffersPlayed
= 0;
1420 pSource
->BufferPosition
= 0;
1421 pSource
->lBytesPlayed
= 0;
1423 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1425 // Make sure all the Buffers in the queue are marked as PENDING
1426 ALBufferList
= pSource
->queue
;
1427 while (ALBufferList
)
1429 ALBufferList
->bufferstate
= PENDING
;
1430 ALBufferList
= ALBufferList
->next
;
1435 pSource
->state
= AL_PLAYING
;
1436 pSource
->inuse
= AL_TRUE
;
1437 pSource
->play
= AL_TRUE
;
1440 // Check if an Offset has been set
1441 if (pSource
->lOffset
)
1442 ApplyOffset(pSource
, AL_FALSE
);
1446 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1447 ALBufferList
= pSource
->queue
;
1448 while (ALBufferList
)
1450 ALBufferList
->bufferstate
= PROCESSED
;
1451 ALBufferList
= ALBufferList
->next
;
1454 pSource
->BuffersPlayed
= pSource
->BuffersInQueue
;
1461 // sources is a NULL pointer
1462 alSetError(AL_INVALID_VALUE
);
1465 ProcessContext(pContext
);
1470 alSetError(AL_INVALID_OPERATION
);
1476 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1478 alSourcePausev(1, &source
);
1482 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1484 ALCcontext
*Context
;
1487 ALboolean bSourcesValid
= AL_TRUE
;
1489 Context
=alcGetCurrentContext();
1492 SuspendContext(Context
);
1496 // Check all the Sources are valid
1499 if (!alIsSource(sources
[i
]))
1501 alSetError(AL_INVALID_NAME
);
1502 bSourcesValid
= AL_FALSE
;
1511 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1512 if (Source
->state
==AL_PLAYING
)
1514 Source
->state
=AL_PAUSED
;
1515 Source
->inuse
=AL_FALSE
;
1522 // sources is a NULL pointer
1523 alSetError(AL_INVALID_VALUE
);
1526 ProcessContext(Context
);
1531 alSetError(AL_INVALID_OPERATION
);
1537 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1539 alSourceStopv(1, &source
);
1543 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1545 ALCcontext
*Context
;
1548 ALbufferlistitem
*ALBufferListItem
;
1549 ALboolean bSourcesValid
= AL_TRUE
;
1551 Context
=alcGetCurrentContext();
1554 SuspendContext(Context
);
1558 // Check all the Sources are valid
1561 if (!alIsSource(sources
[i
]))
1563 alSetError(AL_INVALID_NAME
);
1564 bSourcesValid
= AL_FALSE
;
1573 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1574 if (Source
->state
!=AL_INITIAL
)
1576 Source
->state
=AL_STOPPED
;
1577 Source
->inuse
=AL_FALSE
;
1578 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1579 ALBufferListItem
= Source
->queue
;
1580 while (ALBufferListItem
!= NULL
)
1582 ALBufferListItem
->bufferstate
= PROCESSED
;
1583 ALBufferListItem
= ALBufferListItem
->next
;
1586 Source
->lOffset
= 0;
1592 // sources is a NULL pointer
1593 alSetError(AL_INVALID_VALUE
);
1596 ProcessContext(Context
);
1601 alSetError(AL_INVALID_OPERATION
);
1607 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1609 alSourceRewindv(1, &source
);
1613 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1615 ALCcontext
*Context
;
1618 ALbufferlistitem
*ALBufferListItem
;
1619 ALboolean bSourcesValid
= AL_TRUE
;
1621 Context
=alcGetCurrentContext();
1624 SuspendContext(Context
);
1628 // Check all the Sources are valid
1631 if (!alIsSource(sources
[i
]))
1633 alSetError(AL_INVALID_NAME
);
1634 bSourcesValid
= AL_FALSE
;
1643 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1644 if (Source
->state
!=AL_INITIAL
)
1646 Source
->state
=AL_INITIAL
;
1647 Source
->inuse
=AL_FALSE
;
1649 Source
->position_fraction
=0;
1650 Source
->BuffersPlayed
= 0;
1651 ALBufferListItem
= Source
->queue
;
1652 while (ALBufferListItem
!= NULL
)
1654 ALBufferListItem
->bufferstate
= PENDING
;
1655 ALBufferListItem
= ALBufferListItem
->next
;
1658 Source
->ulBufferID
= Source
->queue
->buffer
;
1660 Source
->lOffset
= 0;
1666 // sources is a NULL pointer
1667 alSetError(AL_INVALID_VALUE
);
1670 ProcessContext(Context
);
1675 alSetError(AL_INVALID_OPERATION
);
1682 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1684 ALCcontext
*Context
;
1687 ALbufferlistitem
*ALBufferList
;
1688 ALbufferlistitem
*ALBufferListStart
;
1693 ALboolean bBuffersValid
= AL_TRUE
;
1698 Context
=alcGetCurrentContext();
1701 SuspendContext(Context
);
1706 // Check that all buffers are valid or zero and that the source is valid
1708 // Check that this is a valid source
1709 if (alIsSource(source
))
1711 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1713 // Check that this is not a STATIC Source
1714 if (ALSource
->lSourceType
!= AL_STATIC
)
1719 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1720 ALBufferList
= ALSource
->queue
;
1721 while (ALBufferList
)
1723 if (ALBufferList
->buffer
)
1725 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1726 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1729 ALBufferList
= ALBufferList
->next
;
1732 for (i
= 0; i
< n
; i
++)
1734 if (alIsBuffer(buffers
[i
]))
1738 if ((iFrequency
== -1) && (iFormat
== -1))
1740 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1741 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1745 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1746 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1748 alSetError(AL_INVALID_OPERATION
);
1749 bBuffersValid
= AL_FALSE
;
1757 alSetError(AL_INVALID_NAME
);
1758 bBuffersValid
= AL_FALSE
;
1765 // Change Source Type
1766 ALSource
->lSourceType
= AL_STREAMING
;
1768 // All buffers are valid - so add them to the list
1769 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1770 ALBufferListStart
->buffer
= buffers
[0];
1771 ALBufferListStart
->bufferstate
= PENDING
;
1772 ALBufferListStart
->flag
= 0;
1773 ALBufferListStart
->next
= NULL
;
1776 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1780 DataSize
+= BufferSize
;
1782 // Increment reference counter for buffer
1784 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1786 ALBufferList
= ALBufferListStart
;
1788 for (i
= 1; i
< n
; i
++)
1790 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1791 ALBufferList
->next
->buffer
= buffers
[i
];
1792 ALBufferList
->next
->bufferstate
= PENDING
;
1793 ALBufferList
->next
->flag
= 0;
1794 ALBufferList
->next
->next
= NULL
;
1797 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1801 DataSize
+= BufferSize
;
1803 // Increment reference counter for buffer
1805 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1807 ALBufferList
= ALBufferList
->next
;
1810 if (ALSource
->queue
== NULL
)
1812 ALSource
->queue
= ALBufferListStart
;
1813 // Update Current Buffer
1814 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1818 // Find end of queue
1819 ALBufferList
= ALSource
->queue
;
1820 while (ALBufferList
->next
!= NULL
)
1822 ALBufferList
= ALBufferList
->next
;
1825 ALBufferList
->next
= ALBufferListStart
;
1828 // Update number of buffers in queue
1829 ALSource
->BuffersInQueue
+= n
;
1834 // Invalid Source Type (can't queue on a Static Source)
1835 alSetError(AL_INVALID_OPERATION
);
1840 // Invalid Source Name
1841 alSetError(AL_INVALID_NAME
);
1844 ProcessContext(Context
);
1849 alSetError(AL_INVALID_OPERATION
);
1856 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1857 // an array of buffer IDs that are to be filled with the names of the buffers removed
1858 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1860 ALCcontext
*Context
;
1863 ALbufferlistitem
*ALBufferList
;
1867 ALboolean bBuffersProcessed
;
1874 bBuffersProcessed
= AL_TRUE
;
1876 Context
=alcGetCurrentContext();
1879 SuspendContext(Context
);
1881 if (alIsSource(source
))
1883 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1885 // Check that all 'n' buffers have been processed
1886 ALBufferList
= ALSource
->queue
;
1887 for (i
= 0; i
< n
; i
++)
1889 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1891 ALBufferList
= ALBufferList
->next
;
1895 bBuffersProcessed
= AL_FALSE
;
1900 // If all 'n' buffers have been processed, remove them from the queue
1901 if (bBuffersProcessed
)
1903 for (i
= 0; i
< n
; i
++)
1905 ALBufferList
= ALSource
->queue
;
1907 ALSource
->queue
= ALBufferList
->next
;
1908 // Record name of buffer
1909 buffers
[i
] = ALBufferList
->buffer
;
1910 // Decrement buffer reference counter
1911 if (ALBufferList
->buffer
)
1912 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1913 // Record size of buffer
1914 if (ALBufferList
->buffer
)
1915 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1919 DataSize
+= BufferSize
;
1920 // Release memory for buffer list item
1922 ALSource
->BuffersInQueue
--;
1925 if (ALSource
->state
!= AL_PLAYING
)
1927 if (ALSource
->queue
)
1928 BufferID
= ALSource
->queue
->buffer
;
1932 ALSource
->ulBufferID
= BufferID
;
1935 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1937 ALSource
->BuffersPlayed
= 0;
1938 ALSource
->BufferPosition
= 0;
1941 ALSource
->BuffersPlayed
-= n
;
1945 // Some buffers can't be unqueue because they have not been processed
1946 alSetError(AL_INVALID_VALUE
);
1951 // Invalid Source Name
1952 alSetError(AL_INVALID_NAME
);
1955 ProcessContext(Context
);
1960 alSetError(AL_INVALID_OPERATION
);
1967 static ALvoid
InitSourceParams(ALsource
*pSource
)
1969 pSource
->flInnerAngle
= 360.0f
;
1970 pSource
->flOuterAngle
= 360.0f
;
1971 pSource
->flPitch
= 1.0f
;
1972 pSource
->vPosition
[0] = 0.0f
;
1973 pSource
->vPosition
[1] = 0.0f
;
1974 pSource
->vPosition
[2] = 0.0f
;
1975 pSource
->vOrientation
[0] = 0.0f
;
1976 pSource
->vOrientation
[1] = 0.0f
;
1977 pSource
->vOrientation
[2] = 0.0f
;
1978 pSource
->vVelocity
[0] = 0.0f
;
1979 pSource
->vVelocity
[1] = 0.0f
;
1980 pSource
->vVelocity
[2] = 0.0f
;
1981 pSource
->flRefDistance
= 1.0f
;
1982 pSource
->flMaxDistance
= FLT_MAX
;
1983 pSource
->flRollOffFactor
= 1.0f
;
1984 pSource
->bLooping
= AL_FALSE
;
1985 pSource
->flGain
= 1.0f
;
1986 pSource
->flMinGain
= 0.0f
;
1987 pSource
->flMaxGain
= 1.0f
;
1988 pSource
->flOuterGain
= 0.0f
;
1989 pSource
->OuterGainHF
= 1.0f
;
1991 pSource
->DryGainHFAuto
= AL_TRUE
;
1992 pSource
->WetGainAuto
= AL_TRUE
;
1993 pSource
->WetGainHFAuto
= AL_TRUE
;
1994 pSource
->AirAbsorptionFactor
= 0.0f
;
1995 pSource
->RoomRolloffFactor
= 0.0f
;
1996 pSource
->DopplerFactor
= 1.0f
;
1998 pSource
->state
= AL_INITIAL
;
1999 pSource
->lSourceType
= AL_UNDETERMINED
;
2001 pSource
->ulBufferID
= 0;
2008 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
2009 The offset is relative to the start of the queue (not the start of the current buffer)
2011 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
2013 ALbufferlistitem
*pBufferList
;
2015 ALfloat flBufferFreq
;
2016 ALint lBytesPlayed
, lChannels
;
2017 ALenum eOriginalFormat
;
2018 ALboolean bReturn
= AL_TRUE
;
2019 ALint lTotalBufferDataSize
;
2021 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
2023 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
2024 // Get Current Buffer Size and frequency (in milliseconds)
2025 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
2026 eOriginalFormat
= pBuffer
->eOriginalFormat
;
2027 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2029 // Get Current BytesPlayed
2030 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2031 // Add byte length of any processed buffers in the queue
2032 pBufferList
= pSource
->queue
;
2033 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2035 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2036 pBufferList
= pBufferList
->next
;
2039 lTotalBufferDataSize
= 0;
2040 pBufferList
= pSource
->queue
;
2043 if (pBufferList
->buffer
)
2044 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2045 pBufferList
= pBufferList
->next
;
2048 if (pSource
->bLooping
)
2050 if (lBytesPlayed
< 0)
2053 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
2057 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2058 if(lBytesPlayed
< 0)
2060 if(lBytesPlayed
> lTotalBufferDataSize
)
2061 lBytesPlayed
= lTotalBufferDataSize
;
2067 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
2069 case AL_SAMPLE_OFFSET
:
2070 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
2072 case AL_BYTE_OFFSET
:
2073 // Take into account the original format of the Buffer
2074 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2075 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2077 // Compression rate of the ADPCM supported is 3.6111 to 1
2078 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
2079 // Round down to nearest ADPCM block
2080 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
2082 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2084 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 2);
2086 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2088 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2090 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2092 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2094 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2096 *pflOffset
= (ALfloat
)(lBytesPlayed
<< 1);
2100 *pflOffset
= (ALfloat
)lBytesPlayed
;
2117 Apply a playback offset to the Source. This function will update the queue (to correctly
2118 mark buffers as 'pending' or 'processed' depending upon the new offset.
2120 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2122 ALbufferlistitem
*pBufferList
;
2124 ALint lBufferSize
, lTotalBufferSize
;
2127 // Get true byte offset
2128 lByteOffset
= GetByteOffset(pSource
);
2130 // If this is a valid offset apply it
2131 if (lByteOffset
!= -1)
2133 // Sort out the queue (pending and processed states)
2134 pBufferList
= pSource
->queue
;
2135 lTotalBufferSize
= 0;
2136 pSource
->BuffersPlayed
= 0;
2139 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2140 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2142 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2144 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2145 // update the state to PROCESSED
2146 pSource
->BuffersPlayed
++;
2148 if (!pSource
->bLooping
)
2149 pBufferList
->bufferstate
= PROCESSED
;
2151 else if (lTotalBufferSize
<= lByteOffset
)
2153 // Offset is within this buffer
2154 pBufferList
->bufferstate
= PENDING
;
2156 // Set Current Buffer ID
2157 pSource
->ulBufferID
= pBufferList
->buffer
;
2159 // Set current position in this buffer
2160 pSource
->BufferPosition
= lByteOffset
- lTotalBufferSize
;
2162 // Set Total Bytes Played to Offset
2163 pSource
->lBytesPlayed
= lByteOffset
;
2165 // SW Mixer Positions are in Samples
2166 pSource
->position
= pSource
->BufferPosition
/
2167 aluBytesFromFormat(pBuffer
->format
) /
2168 aluChannelsFromFormat(pBuffer
->format
);
2172 // Offset is before this buffer, so mark as pending
2173 pBufferList
->bufferstate
= PENDING
;
2176 // Increment the TotalBufferSize
2177 lTotalBufferSize
+= lBufferSize
;
2179 // Move on to next buffer in the Queue
2180 pBufferList
= pBufferList
->next
;
2186 alSetError(AL_INVALID_VALUE
);
2190 pSource
->lOffset
= 0;
2197 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2198 offset supplied by the application). This takes into account the fact that the buffer format
2199 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2201 static ALint
GetByteOffset(ALsource
*pSource
)
2203 ALbuffer
*pBuffer
= NULL
;
2204 ALbufferlistitem
*pBufferList
;
2205 ALfloat flBufferFreq
;
2207 ALint lByteOffset
= -1;
2208 ALint lTotalBufferDataSize
;
2210 // Find the first non-NULL Buffer in the Queue
2211 pBufferList
= pSource
->queue
;
2214 if (pBufferList
->buffer
)
2216 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2219 pBufferList
= pBufferList
->next
;
2224 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2225 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2227 // Determine the ByteOffset (and ensure it is block aligned)
2228 switch (pSource
->lOffsetType
)
2230 case AL_BYTE_OFFSET
:
2231 // Take into consideration the original format
2232 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2233 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2235 // Round down to nearest ADPCM block
2236 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2237 // Multiply by compression rate
2238 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2239 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2241 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2243 lByteOffset
= pSource
->lOffset
* 4;
2244 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2246 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2248 lByteOffset
= pSource
->lOffset
* 2;
2249 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2251 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2253 lByteOffset
= pSource
->lOffset
* 2;
2254 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2256 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2258 lByteOffset
= pSource
->lOffset
/ 2;
2259 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2263 lByteOffset
= pSource
->lOffset
;
2264 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2268 case AL_SAMPLE_OFFSET
:
2269 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2273 // Note - lOffset is internally stored as Milliseconds
2274 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2275 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2279 lTotalBufferDataSize
= 0;
2280 pBufferList
= pSource
->queue
;
2283 if (pBufferList
->buffer
)
2284 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2285 pBufferList
= pBufferList
->next
;
2288 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2289 if (lByteOffset
>= lTotalBufferDataSize
)
2297 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2300 if(Context
->SourceCount
> 0)
2301 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", Context
->SourceCount
);
2304 while(Context
->Source
)
2306 ALsource
*temp
= Context
->Source
;
2307 Context
->Source
= Context
->Source
->next
;
2309 // Release source structure
2310 ALTHUNK_REMOVEENTRY(temp
->source
);
2311 memset(temp
, 0, sizeof(ALsource
));
2314 Context
->SourceCount
= 0;