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 if ((ALuint
)n
<= Context
->SourceCount
)
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
));
205 // Trying to delete more Sources than have been generated
206 alSetError(AL_INVALID_NAME
);
211 // No Device created, or attached to Context
212 alSetError(AL_INVALID_OPERATION
);
216 alSetError(AL_INVALID_VALUE
);
218 ProcessContext(Context
);
223 alSetError(AL_INVALID_OPERATION
);
230 ALAPI ALboolean ALAPIENTRY
alIsSource(ALuint source
)
232 ALboolean result
=AL_FALSE
;
236 Context
=alcGetCurrentContext();
239 SuspendContext(Context
);
241 // To determine if this is a valid Source name, look through the list of generated Sources
242 Source
= Context
->Source
;
245 if (Source
== (ALsource
*)ALTHUNK_LOOKUPENTRY(source
))
251 Source
= Source
->next
;
254 ProcessContext(Context
);
259 alSetError(AL_INVALID_OPERATION
);
266 ALAPI ALvoid ALAPIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
268 ALCcontext
*pContext
;
271 pContext
= alcGetCurrentContext();
274 SuspendContext(pContext
);
276 if (alIsSource(source
))
278 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
285 pSource
->flPitch
= flValue
;
286 if(pSource
->flPitch
< 0.001f
)
287 pSource
->flPitch
= 0.001f
;
290 alSetError(AL_INVALID_VALUE
);
293 case AL_CONE_INNER_ANGLE
:
294 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
295 pSource
->flInnerAngle
= flValue
;
297 alSetError(AL_INVALID_VALUE
);
300 case AL_CONE_OUTER_ANGLE
:
301 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
302 pSource
->flOuterAngle
= flValue
;
304 alSetError(AL_INVALID_VALUE
);
309 pSource
->flGain
= flValue
;
311 alSetError(AL_INVALID_VALUE
);
314 case AL_MAX_DISTANCE
:
316 pSource
->flMaxDistance
= flValue
;
318 alSetError(AL_INVALID_VALUE
);
321 case AL_ROLLOFF_FACTOR
:
323 pSource
->flRollOffFactor
= flValue
;
325 alSetError(AL_INVALID_VALUE
);
328 case AL_REFERENCE_DISTANCE
:
330 pSource
->flRefDistance
= flValue
;
332 alSetError(AL_INVALID_VALUE
);
336 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
337 pSource
->flMinGain
= flValue
;
339 alSetError(AL_INVALID_VALUE
);
343 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
344 pSource
->flMaxGain
= flValue
;
346 alSetError(AL_INVALID_VALUE
);
349 case AL_CONE_OUTER_GAIN
:
350 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
351 pSource
->flOuterGain
= flValue
;
353 alSetError(AL_INVALID_VALUE
);
356 case AL_CONE_OUTER_GAINHF
:
357 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
358 pSource
->OuterGainHF
= flValue
;
360 alSetError(AL_INVALID_VALUE
);
363 case AL_AIR_ABSORPTION_FACTOR
:
364 if (flValue
>= 0.0f
&& flValue
<= 10.0f
)
365 pSource
->AirAbsorptionFactor
= flValue
;
367 alSetError(AL_INVALID_VALUE
);
370 case AL_ROOM_ROLLOFF_FACTOR
:
371 if (flValue
>= 0.0f
&& flValue
<= 1.0f
)
372 pSource
->RoomRolloffFactor
= 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 // Set Buffers Processed
638 pSource
->BuffersProcessed
= 0;
640 // Update AL_BUFFER parameter
641 pSource
->ulBufferID
= lValue
;
644 alSetError(AL_INVALID_VALUE
);
647 alSetError(AL_INVALID_OPERATION
);
650 case AL_SOURCE_STATE
:
652 alSetError(AL_INVALID_OPERATION
);
656 case AL_SAMPLE_OFFSET
:
660 pSource
->lOffsetType
= eParam
;
662 // Store Offset (convert Seconds into Milliseconds)
663 if (eParam
== AL_SEC_OFFSET
)
664 pSource
->lOffset
= lValue
* 1000;
666 pSource
->lOffset
= lValue
;
668 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
669 ApplyOffset(pSource
, AL_TRUE
);
672 alSetError(AL_INVALID_VALUE
);
675 case AL_DIRECT_FILTER
:
676 if(alIsFilter(lValue
))
678 ALfilter
*filter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue
);
681 pSource
->DirectFilter
.type
= AL_FILTER_NULL
;
682 pSource
->DirectFilter
.filter
= 0;
685 memcpy(&pSource
->DirectFilter
, filter
, sizeof(*filter
));
688 alSetError(AL_INVALID_VALUE
);
691 case AL_DIRECT_FILTER_GAINHF_AUTO
:
692 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
693 pSource
->DryGainHFAuto
= lValue
;
695 alSetError(AL_INVALID_VALUE
);
698 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
699 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
700 pSource
->WetGainAuto
= lValue
;
702 alSetError(AL_INVALID_VALUE
);
705 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
706 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
707 pSource
->WetGainHFAuto
= lValue
;
709 alSetError(AL_INVALID_VALUE
);
713 alSetError(AL_INVALID_ENUM
);
718 alSetError(AL_INVALID_NAME
);
720 ProcessContext(pContext
);
723 alSetError(AL_INVALID_OPERATION
);
729 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
731 ALCcontext
*pContext
;
733 pContext
= alcGetCurrentContext();
736 SuspendContext(pContext
);
738 if (alIsSource(source
))
740 ALsource
*pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
747 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
750 case AL_AUXILIARY_SEND_FILTER
:
751 if(lValue2
>= 0 && lValue2
< MAX_SENDS
&&
752 (alIsAuxiliaryEffectSlot(lValue1
) || lValue1
== 0) &&
755 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(lValue1
);
756 ALfilter
*ALFilter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue3
);
758 /* Release refcount on the previous slot, and add one for
760 if(pSource
->Send
[lValue2
].Slot
)
761 pSource
->Send
[lValue2
].Slot
->refcount
--;
762 pSource
->Send
[lValue2
].Slot
= ALEffectSlot
;
763 if(pSource
->Send
[lValue2
].Slot
)
764 pSource
->Send
[lValue2
].Slot
->refcount
++;
769 pSource
->Send
[lValue2
].WetFilter
.type
= 0;
770 pSource
->Send
[lValue2
].WetFilter
.filter
= 0;
773 memcpy(&pSource
->Send
[lValue2
].WetFilter
, ALFilter
, sizeof(*ALFilter
));
776 alSetError(AL_INVALID_VALUE
);
780 alSetError(AL_INVALID_ENUM
);
785 alSetError(AL_INVALID_NAME
);
787 ProcessContext(pContext
);
790 alSetError(AL_INVALID_OPERATION
);
796 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
798 ALCcontext
*pContext
;
800 pContext
= alcGetCurrentContext();
803 SuspendContext(pContext
);
807 if (alIsSource(source
))
811 case AL_SOURCE_RELATIVE
:
812 case AL_CONE_INNER_ANGLE
:
813 case AL_CONE_OUTER_ANGLE
:
816 case AL_SOURCE_STATE
:
818 case AL_SAMPLE_OFFSET
:
820 case AL_MAX_DISTANCE
:
821 case AL_ROLLOFF_FACTOR
:
822 case AL_REFERENCE_DISTANCE
:
823 case AL_DIRECT_FILTER
:
824 case AL_DIRECT_FILTER_GAINHF_AUTO
:
825 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
826 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
827 alSourcei(source
, eParam
, plValues
[0]);
833 case AL_AUXILIARY_SEND_FILTER
:
834 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
838 alSetError(AL_INVALID_ENUM
);
843 alSetError(AL_INVALID_NAME
);
846 alSetError(AL_INVALID_VALUE
);
848 ProcessContext(pContext
);
851 alSetError(AL_INVALID_OPERATION
);
857 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
859 ALCcontext
*pContext
;
863 pContext
= alcGetCurrentContext();
866 SuspendContext(pContext
);
870 if (alIsSource(source
))
872 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
877 *pflValue
= pSource
->flPitch
;
881 *pflValue
= pSource
->flGain
;
885 *pflValue
= pSource
->flMinGain
;
889 *pflValue
= pSource
->flMaxGain
;
892 case AL_MAX_DISTANCE
:
893 *pflValue
= pSource
->flMaxDistance
;
896 case AL_ROLLOFF_FACTOR
:
897 *pflValue
= pSource
->flRollOffFactor
;
900 case AL_CONE_OUTER_GAIN
:
901 *pflValue
= pSource
->flOuterGain
;
904 case AL_CONE_OUTER_GAINHF
:
905 *pflValue
= pSource
->OuterGainHF
;
909 case AL_SAMPLE_OFFSET
:
911 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
912 *pflValue
= flOffset
;
914 alSetError(AL_INVALID_OPERATION
);
917 case AL_CONE_INNER_ANGLE
:
918 *pflValue
= pSource
->flInnerAngle
;
921 case AL_CONE_OUTER_ANGLE
:
922 *pflValue
= pSource
->flOuterAngle
;
925 case AL_REFERENCE_DISTANCE
:
926 *pflValue
= pSource
->flRefDistance
;
929 case AL_AIR_ABSORPTION_FACTOR
:
930 *pflValue
= pSource
->AirAbsorptionFactor
;
933 case AL_ROOM_ROLLOFF_FACTOR
:
934 *pflValue
= pSource
->RoomRolloffFactor
;
938 alSetError(AL_INVALID_ENUM
);
943 alSetError(AL_INVALID_NAME
);
946 alSetError(AL_INVALID_VALUE
);
948 ProcessContext(pContext
);
951 alSetError(AL_INVALID_OPERATION
);
957 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
959 ALCcontext
*pContext
;
962 pContext
= alcGetCurrentContext();
965 SuspendContext(pContext
);
967 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
969 if (alIsSource(source
))
971 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
976 *pflValue1
= pSource
->vPosition
[0];
977 *pflValue2
= pSource
->vPosition
[1];
978 *pflValue3
= pSource
->vPosition
[2];
982 *pflValue1
= pSource
->vVelocity
[0];
983 *pflValue2
= pSource
->vVelocity
[1];
984 *pflValue3
= pSource
->vVelocity
[2];
988 *pflValue1
= pSource
->vOrientation
[0];
989 *pflValue2
= pSource
->vOrientation
[1];
990 *pflValue3
= pSource
->vOrientation
[2];
994 alSetError(AL_INVALID_ENUM
);
999 alSetError(AL_INVALID_NAME
);
1002 alSetError(AL_INVALID_VALUE
);
1004 ProcessContext(pContext
);
1007 alSetError(AL_INVALID_OPERATION
);
1013 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1015 ALCcontext
*pContext
;
1018 pContext
= alcGetCurrentContext();
1021 SuspendContext(pContext
);
1025 if (alIsSource(source
))
1027 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1035 case AL_MAX_DISTANCE
:
1036 case AL_ROLLOFF_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
->BuffersProcessed
;
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
;
1188 alSetError(AL_INVALID_ENUM
);
1193 alSetError(AL_INVALID_NAME
);
1196 alSetError(AL_INVALID_VALUE
);
1198 ProcessContext(pContext
);
1201 alSetError(AL_INVALID_OPERATION
);
1207 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1209 ALCcontext
*pContext
;
1212 pContext
= alcGetCurrentContext();
1215 SuspendContext(pContext
);
1217 if ((plValue1
) && (plValue2
) && (plValue3
))
1219 if (alIsSource(source
))
1221 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1226 *plValue1
= (ALint
)pSource
->vPosition
[0];
1227 *plValue2
= (ALint
)pSource
->vPosition
[1];
1228 *plValue3
= (ALint
)pSource
->vPosition
[2];
1232 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1233 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1234 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1238 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1239 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1240 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1244 alSetError(AL_INVALID_ENUM
);
1249 alSetError(AL_INVALID_NAME
);
1252 alSetError(AL_INVALID_VALUE
);
1254 ProcessContext(pContext
);
1257 alSetError(AL_INVALID_OPERATION
);
1263 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1265 ALCcontext
*pContext
;
1268 pContext
= alcGetCurrentContext();
1271 SuspendContext(pContext
);
1275 if (alIsSource(source
))
1277 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1281 case AL_SOURCE_RELATIVE
:
1282 case AL_CONE_INNER_ANGLE
:
1283 case AL_CONE_OUTER_ANGLE
:
1286 case AL_SOURCE_STATE
:
1287 case AL_BUFFERS_QUEUED
:
1288 case AL_BUFFERS_PROCESSED
:
1290 case AL_SAMPLE_OFFSET
:
1291 case AL_BYTE_OFFSET
:
1292 case AL_MAX_DISTANCE
:
1293 case AL_ROLLOFF_FACTOR
:
1294 case AL_REFERENCE_DISTANCE
:
1295 case AL_SOURCE_TYPE
:
1296 case AL_DIRECT_FILTER
:
1297 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1298 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1299 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1300 alGetSourcei(source
, eParam
, plValues
);
1304 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1305 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1306 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1310 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1311 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1312 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1316 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1317 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1318 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1322 alSetError(AL_INVALID_ENUM
);
1327 alSetError(AL_INVALID_NAME
);
1330 alSetError(AL_INVALID_VALUE
);
1332 ProcessContext(pContext
);
1335 alSetError(AL_INVALID_OPERATION
);
1341 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1343 alSourcePlayv(1, &source
);
1347 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1349 ALCcontext
*pContext
;
1351 ALbufferlistitem
*ALBufferList
;
1352 ALboolean bSourcesValid
= AL_TRUE
;
1356 pContext
= alcGetCurrentContext();
1359 SuspendContext(pContext
);
1363 // Check that all the Sources are valid
1364 for (i
= 0; i
< n
; i
++)
1366 if (!alIsSource(pSourceList
[i
]))
1368 alSetError(AL_INVALID_NAME
);
1369 bSourcesValid
= AL_FALSE
;
1376 for (i
= 0; i
< n
; i
++)
1378 // Assume Source won't need to play
1381 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1383 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1384 ALBufferList
= pSource
->queue
;
1385 while (ALBufferList
)
1387 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1392 ALBufferList
= ALBufferList
->next
;
1397 if (pSource
->state
!= AL_PAUSED
)
1399 pSource
->state
= AL_PLAYING
;
1400 pSource
->inuse
= AL_TRUE
;
1401 pSource
->play
= AL_TRUE
;
1402 pSource
->position
= 0;
1403 pSource
->position_fraction
= 0;
1404 pSource
->BuffersProcessed
= 0;
1405 pSource
->BuffersPlayed
= 0;
1406 pSource
->BufferPosition
= 0;
1407 pSource
->lBytesPlayed
= 0;
1409 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1411 // Make sure all the Buffers in the queue are marked as PENDING
1412 ALBufferList
= pSource
->queue
;
1413 while (ALBufferList
)
1415 ALBufferList
->bufferstate
= PENDING
;
1416 ALBufferList
= ALBufferList
->next
;
1421 pSource
->state
= AL_PLAYING
;
1422 pSource
->inuse
= AL_TRUE
;
1423 pSource
->play
= AL_TRUE
;
1426 // Check if an Offset has been set
1427 if (pSource
->lOffset
)
1428 ApplyOffset(pSource
, AL_FALSE
);
1432 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1433 ALBufferList
= pSource
->queue
;
1434 while (ALBufferList
)
1436 ALBufferList
->bufferstate
= PROCESSED
;
1437 ALBufferList
= ALBufferList
->next
;
1440 pSource
->BuffersPlayed
= pSource
->BuffersProcessed
= pSource
->BuffersInQueue
;
1447 // sources is a NULL pointer
1448 alSetError(AL_INVALID_VALUE
);
1451 ProcessContext(pContext
);
1456 alSetError(AL_INVALID_OPERATION
);
1462 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1464 alSourcePausev(1, &source
);
1468 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1470 ALCcontext
*Context
;
1473 ALboolean bSourcesValid
= AL_TRUE
;
1475 Context
=alcGetCurrentContext();
1478 SuspendContext(Context
);
1482 // Check all the Sources are valid
1485 if (!alIsSource(sources
[i
]))
1487 alSetError(AL_INVALID_NAME
);
1488 bSourcesValid
= AL_FALSE
;
1497 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1498 if (Source
->state
==AL_PLAYING
)
1500 Source
->state
=AL_PAUSED
;
1501 Source
->inuse
=AL_FALSE
;
1508 // sources is a NULL pointer
1509 alSetError(AL_INVALID_VALUE
);
1512 ProcessContext(Context
);
1517 alSetError(AL_INVALID_OPERATION
);
1523 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1525 alSourceStopv(1, &source
);
1529 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1531 ALCcontext
*Context
;
1534 ALbufferlistitem
*ALBufferListItem
;
1535 ALboolean bSourcesValid
= AL_TRUE
;
1537 Context
=alcGetCurrentContext();
1540 SuspendContext(Context
);
1544 // Check all the Sources are valid
1547 if (!alIsSource(sources
[i
]))
1549 alSetError(AL_INVALID_NAME
);
1550 bSourcesValid
= AL_FALSE
;
1559 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1560 if (Source
->state
!=AL_INITIAL
)
1562 Source
->state
=AL_STOPPED
;
1563 Source
->inuse
=AL_FALSE
;
1564 Source
->BuffersPlayed
= Source
->BuffersProcessed
= Source
->BuffersInQueue
;
1565 ALBufferListItem
= Source
->queue
;
1566 while (ALBufferListItem
!= NULL
)
1568 ALBufferListItem
->bufferstate
= PROCESSED
;
1569 ALBufferListItem
= ALBufferListItem
->next
;
1572 Source
->lOffset
= 0;
1578 // sources is a NULL pointer
1579 alSetError(AL_INVALID_VALUE
);
1582 ProcessContext(Context
);
1587 alSetError(AL_INVALID_OPERATION
);
1593 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1595 alSourceRewindv(1, &source
);
1599 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1601 ALCcontext
*Context
;
1604 ALbufferlistitem
*ALBufferListItem
;
1605 ALboolean bSourcesValid
= AL_TRUE
;
1607 Context
=alcGetCurrentContext();
1610 SuspendContext(Context
);
1614 // Check all the Sources are valid
1617 if (!alIsSource(sources
[i
]))
1619 alSetError(AL_INVALID_NAME
);
1620 bSourcesValid
= AL_FALSE
;
1629 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1630 if (Source
->state
!=AL_INITIAL
)
1632 Source
->state
=AL_INITIAL
;
1633 Source
->inuse
=AL_FALSE
;
1635 Source
->position_fraction
=0;
1636 Source
->BuffersProcessed
= 0;
1637 ALBufferListItem
= Source
->queue
;
1638 while (ALBufferListItem
!= NULL
)
1640 ALBufferListItem
->bufferstate
= PENDING
;
1641 ALBufferListItem
= ALBufferListItem
->next
;
1644 Source
->ulBufferID
= Source
->queue
->buffer
;
1646 Source
->lOffset
= 0;
1652 // sources is a NULL pointer
1653 alSetError(AL_INVALID_VALUE
);
1656 ProcessContext(Context
);
1661 alSetError(AL_INVALID_OPERATION
);
1668 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1670 ALCcontext
*Context
;
1673 ALbufferlistitem
*ALBufferList
;
1674 ALbufferlistitem
*ALBufferListStart
;
1679 ALboolean bBuffersValid
= AL_TRUE
;
1684 Context
=alcGetCurrentContext();
1687 SuspendContext(Context
);
1692 // Check that all buffers are valid or zero and that the source is valid
1694 // Check that this is a valid source
1695 if (alIsSource(source
))
1697 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1699 // Check that this is not a STATIC Source
1700 if (ALSource
->lSourceType
!= AL_STATIC
)
1705 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1706 ALBufferList
= ALSource
->queue
;
1707 while (ALBufferList
)
1709 if (ALBufferList
->buffer
)
1711 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1712 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1715 ALBufferList
= ALBufferList
->next
;
1718 for (i
= 0; i
< n
; i
++)
1720 if (alIsBuffer(buffers
[i
]))
1724 if ((iFrequency
== -1) && (iFormat
== -1))
1726 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1727 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1731 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1732 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1734 alSetError(AL_INVALID_OPERATION
);
1735 bBuffersValid
= AL_FALSE
;
1743 alSetError(AL_INVALID_NAME
);
1744 bBuffersValid
= AL_FALSE
;
1751 // Change Source Type
1752 ALSource
->lSourceType
= AL_STREAMING
;
1754 // All buffers are valid - so add them to the list
1755 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1756 ALBufferListStart
->buffer
= buffers
[0];
1757 ALBufferListStart
->bufferstate
= PENDING
;
1758 ALBufferListStart
->flag
= 0;
1759 ALBufferListStart
->next
= NULL
;
1762 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1766 DataSize
+= BufferSize
;
1768 // Increment reference counter for buffer
1770 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1772 ALBufferList
= ALBufferListStart
;
1774 for (i
= 1; i
< n
; i
++)
1776 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1777 ALBufferList
->next
->buffer
= buffers
[i
];
1778 ALBufferList
->next
->bufferstate
= PENDING
;
1779 ALBufferList
->next
->flag
= 0;
1780 ALBufferList
->next
->next
= NULL
;
1783 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1787 DataSize
+= BufferSize
;
1789 // Increment reference counter for buffer
1791 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1793 ALBufferList
= ALBufferList
->next
;
1796 if (ALSource
->queue
== NULL
)
1798 ALSource
->queue
= ALBufferListStart
;
1799 // Update Current Buffer
1800 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1804 // Find end of queue
1805 ALBufferList
= ALSource
->queue
;
1806 while (ALBufferList
->next
!= NULL
)
1808 ALBufferList
= ALBufferList
->next
;
1811 ALBufferList
->next
= ALBufferListStart
;
1814 // Update number of buffers in queue
1815 ALSource
->BuffersInQueue
+= n
;
1820 // Invalid Source Type (can't queue on a Static Source)
1821 alSetError(AL_INVALID_OPERATION
);
1826 // Invalid Source Name
1827 alSetError(AL_INVALID_NAME
);
1830 ProcessContext(Context
);
1835 alSetError(AL_INVALID_OPERATION
);
1842 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1843 // an array of buffer IDs that are to be filled with the names of the buffers removed
1844 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1846 ALCcontext
*Context
;
1849 ALbufferlistitem
*ALBufferList
;
1853 ALboolean bBuffersProcessed
;
1860 bBuffersProcessed
= AL_TRUE
;
1862 Context
=alcGetCurrentContext();
1865 SuspendContext(Context
);
1867 if (alIsSource(source
))
1869 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1871 // Check that all 'n' buffers have been processed
1872 ALBufferList
= ALSource
->queue
;
1873 for (i
= 0; i
< n
; i
++)
1875 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1877 ALBufferList
= ALBufferList
->next
;
1881 bBuffersProcessed
= AL_FALSE
;
1886 // If all 'n' buffers have been processed, remove them from the queue
1887 if (bBuffersProcessed
)
1889 for (i
= 0; i
< n
; i
++)
1891 ALBufferList
= ALSource
->queue
;
1893 ALSource
->queue
= ALBufferList
->next
;
1894 // Record name of buffer
1895 buffers
[i
] = ALBufferList
->buffer
;
1896 // Decrement buffer reference counter
1897 if (ALBufferList
->buffer
)
1898 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1899 // Record size of buffer
1900 if (ALBufferList
->buffer
)
1901 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1905 DataSize
+= BufferSize
;
1906 // Release memory for buffer list item
1908 ALSource
->BuffersInQueue
--;
1909 ALSource
->BuffersProcessed
--;
1912 if (ALSource
->state
!= AL_PLAYING
)
1914 if (ALSource
->queue
)
1915 BufferID
= ALSource
->queue
->buffer
;
1919 ALSource
->ulBufferID
= BufferID
;
1922 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1924 ALSource
->BuffersPlayed
= 0;
1925 ALSource
->BufferPosition
= 0;
1928 ALSource
->BuffersPlayed
-= n
;
1932 // Some buffers can't be unqueue because they have not been processed
1933 alSetError(AL_INVALID_VALUE
);
1938 // Invalid Source Name
1939 alSetError(AL_INVALID_NAME
);
1942 ProcessContext(Context
);
1947 alSetError(AL_INVALID_OPERATION
);
1954 static ALvoid
InitSourceParams(ALsource
*pSource
)
1956 pSource
->flInnerAngle
= 360.0f
;
1957 pSource
->flOuterAngle
= 360.0f
;
1958 pSource
->flPitch
= 1.0f
;
1959 pSource
->vPosition
[0] = 0.0f
;
1960 pSource
->vPosition
[1] = 0.0f
;
1961 pSource
->vPosition
[2] = 0.0f
;
1962 pSource
->vOrientation
[0] = 0.0f
;
1963 pSource
->vOrientation
[1] = 0.0f
;
1964 pSource
->vOrientation
[2] = 0.0f
;
1965 pSource
->vVelocity
[0] = 0.0f
;
1966 pSource
->vVelocity
[1] = 0.0f
;
1967 pSource
->vVelocity
[2] = 0.0f
;
1968 pSource
->flRefDistance
= 1.0f
;
1969 pSource
->flMaxDistance
= FLT_MAX
;
1970 pSource
->flRollOffFactor
= 1.0f
;
1971 pSource
->bLooping
= AL_FALSE
;
1972 pSource
->flGain
= 1.0f
;
1973 pSource
->flMinGain
= 0.0f
;
1974 pSource
->flMaxGain
= 1.0f
;
1975 pSource
->flOuterGain
= 0.0f
;
1976 pSource
->OuterGainHF
= 1.0f
;
1978 pSource
->DryGainHFAuto
= AL_TRUE
;
1979 pSource
->WetGainAuto
= AL_TRUE
;
1980 pSource
->WetGainHFAuto
= AL_TRUE
;
1981 pSource
->AirAbsorptionFactor
= 0.0f
;
1982 pSource
->RoomRolloffFactor
= 0.0f
;
1984 pSource
->state
= AL_INITIAL
;
1985 pSource
->lSourceType
= AL_UNDETERMINED
;
1987 pSource
->ulBufferID
= 0;
1994 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1995 The offset is relative to the start of the queue (not the start of the current buffer)
1997 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
1999 ALbufferlistitem
*pBufferList
;
2001 ALfloat flBufferFreq
;
2002 ALint lBytesPlayed
, lChannels
;
2003 ALenum eOriginalFormat
;
2004 ALboolean bReturn
= AL_TRUE
;
2005 ALint lTotalBufferDataSize
;
2007 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
2009 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
2010 // Get Current Buffer Size and frequency (in milliseconds)
2011 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
2012 eOriginalFormat
= pBuffer
->eOriginalFormat
;
2013 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2015 // Get Current BytesPlayed
2016 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2017 // Add byte length of any processed buffers in the queue
2018 pBufferList
= pSource
->queue
;
2019 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2021 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2022 pBufferList
= pBufferList
->next
;
2025 lTotalBufferDataSize
= 0;
2026 pBufferList
= pSource
->queue
;
2029 if (pBufferList
->buffer
)
2030 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2031 pBufferList
= pBufferList
->next
;
2034 if (pSource
->bLooping
)
2036 if (lBytesPlayed
< 0)
2039 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
2043 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2044 if(lBytesPlayed
< 0)
2046 if(lBytesPlayed
> lTotalBufferDataSize
)
2047 lBytesPlayed
= lTotalBufferDataSize
;
2053 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
2055 case AL_SAMPLE_OFFSET
:
2056 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
2058 case AL_BYTE_OFFSET
:
2059 // Take into account the original format of the Buffer
2060 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2061 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2063 // Compression rate of the ADPCM supported is 3.6111 to 1
2064 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
2065 // Round down to nearest ADPCM block
2066 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
2068 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2070 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 2);
2072 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2074 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2076 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2078 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2080 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2082 *pflOffset
= (ALfloat
)(lBytesPlayed
<< 1);
2086 *pflOffset
= (ALfloat
)lBytesPlayed
;
2103 Apply a playback offset to the Source. This function will update the queue (to correctly
2104 mark buffers as 'pending' or 'processed' depending upon the new offset.
2106 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2108 ALbufferlistitem
*pBufferList
;
2110 ALint lBufferSize
, lTotalBufferSize
;
2113 // Get true byte offset
2114 lByteOffset
= GetByteOffset(pSource
);
2116 // If this is a valid offset apply it
2117 if (lByteOffset
!= -1)
2119 // Sort out the queue (pending and processed states)
2120 pBufferList
= pSource
->queue
;
2121 lTotalBufferSize
= 0;
2122 pSource
->BuffersPlayed
= 0;
2123 pSource
->BuffersProcessed
= 0;
2126 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2127 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2129 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2131 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2132 // update the state to PROCESSED
2133 pSource
->BuffersPlayed
++;
2135 if (!pSource
->bLooping
)
2137 pBufferList
->bufferstate
= PROCESSED
;
2138 pSource
->BuffersProcessed
++;
2141 else if (lTotalBufferSize
<= lByteOffset
)
2143 // Offset is within this buffer
2144 pBufferList
->bufferstate
= PENDING
;
2146 // Set Current Buffer ID
2147 pSource
->ulBufferID
= pBufferList
->buffer
;
2149 // Set current position in this buffer
2150 pSource
->BufferPosition
= lByteOffset
- lTotalBufferSize
;
2152 // Set Total Bytes Played to Offset
2153 pSource
->lBytesPlayed
= lByteOffset
;
2155 // SW Mixer Positions are in Samples
2156 pSource
->position
= pSource
->BufferPosition
/
2157 aluBytesFromFormat(pBuffer
->format
) /
2158 aluChannelsFromFormat(pBuffer
->format
);
2162 // Offset is before this buffer, so mark as pending
2163 pBufferList
->bufferstate
= PENDING
;
2166 // Increment the TotalBufferSize
2167 lTotalBufferSize
+= lBufferSize
;
2169 // Move on to next buffer in the Queue
2170 pBufferList
= pBufferList
->next
;
2176 alSetError(AL_INVALID_VALUE
);
2180 pSource
->lOffset
= 0;
2187 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2188 offset supplied by the application). This takes into account the fact that the buffer format
2189 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2191 static ALint
GetByteOffset(ALsource
*pSource
)
2193 ALbuffer
*pBuffer
= NULL
;
2194 ALbufferlistitem
*pBufferList
;
2195 ALfloat flBufferFreq
;
2197 ALint lByteOffset
= -1;
2198 ALint lTotalBufferDataSize
;
2200 // Find the first non-NULL Buffer in the Queue
2201 pBufferList
= pSource
->queue
;
2204 if (pBufferList
->buffer
)
2206 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2209 pBufferList
= pBufferList
->next
;
2214 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2215 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2217 // Determine the ByteOffset (and ensure it is block aligned)
2218 switch (pSource
->lOffsetType
)
2220 case AL_BYTE_OFFSET
:
2221 // Take into consideration the original format
2222 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2223 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2225 // Round down to nearest ADPCM block
2226 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2227 // Multiply by compression rate
2228 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2229 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2231 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2233 lByteOffset
= pSource
->lOffset
* 4;
2234 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2236 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2238 lByteOffset
= pSource
->lOffset
* 2;
2239 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2241 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2243 lByteOffset
= pSource
->lOffset
* 2;
2244 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2246 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2248 lByteOffset
= pSource
->lOffset
/ 2;
2249 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2253 lByteOffset
= pSource
->lOffset
;
2254 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2258 case AL_SAMPLE_OFFSET
:
2259 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2263 // Note - lOffset is internally stored as Milliseconds
2264 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2265 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2269 lTotalBufferDataSize
= 0;
2270 pBufferList
= pSource
->queue
;
2273 if (pBufferList
->buffer
)
2274 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2275 pBufferList
= pBufferList
->next
;
2278 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2279 if (lByteOffset
>= lTotalBufferDataSize
)
2287 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2290 if(Context
->SourceCount
> 0)
2291 AL_PRINT("alcDestroyContext(): %d Source(s) NOT deleted\n", Context
->SourceCount
);
2294 while(Context
->Source
)
2296 ALsource
*temp
= Context
->Source
;
2297 Context
->Source
= Context
->Source
->next
;
2299 // Release source structure
2300 ALTHUNK_REMOVEENTRY(temp
->source
);
2301 memset(temp
, 0, sizeof(ALsource
));
2304 Context
->SourceCount
= 0;