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 // 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
;
937 case AL_DOPPLER_FACTOR
:
938 *pflValue
= pSource
->DopplerFactor
;
942 alSetError(AL_INVALID_ENUM
);
947 alSetError(AL_INVALID_NAME
);
950 alSetError(AL_INVALID_VALUE
);
952 ProcessContext(pContext
);
955 alSetError(AL_INVALID_OPERATION
);
961 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
963 ALCcontext
*pContext
;
966 pContext
= alcGetCurrentContext();
969 SuspendContext(pContext
);
971 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
973 if (alIsSource(source
))
975 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
980 *pflValue1
= pSource
->vPosition
[0];
981 *pflValue2
= pSource
->vPosition
[1];
982 *pflValue3
= pSource
->vPosition
[2];
986 *pflValue1
= pSource
->vVelocity
[0];
987 *pflValue2
= pSource
->vVelocity
[1];
988 *pflValue3
= pSource
->vVelocity
[2];
992 *pflValue1
= pSource
->vOrientation
[0];
993 *pflValue2
= pSource
->vOrientation
[1];
994 *pflValue3
= pSource
->vOrientation
[2];
998 alSetError(AL_INVALID_ENUM
);
1003 alSetError(AL_INVALID_NAME
);
1006 alSetError(AL_INVALID_VALUE
);
1008 ProcessContext(pContext
);
1011 alSetError(AL_INVALID_OPERATION
);
1017 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1019 ALCcontext
*pContext
;
1022 pContext
= alcGetCurrentContext();
1025 SuspendContext(pContext
);
1029 if (alIsSource(source
))
1031 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1039 case AL_MAX_DISTANCE
:
1040 case AL_ROLLOFF_FACTOR
:
1041 case AL_DOPPLER_FACTOR
:
1042 case AL_CONE_OUTER_GAIN
:
1044 case AL_SAMPLE_OFFSET
:
1045 case AL_BYTE_OFFSET
:
1046 case AL_CONE_INNER_ANGLE
:
1047 case AL_CONE_OUTER_ANGLE
:
1048 case AL_REFERENCE_DISTANCE
:
1049 case AL_CONE_OUTER_GAINHF
:
1050 case AL_AIR_ABSORPTION_FACTOR
:
1051 case AL_ROOM_ROLLOFF_FACTOR
:
1052 alGetSourcef(source
, eParam
, pflValues
);
1056 pflValues
[0] = pSource
->vPosition
[0];
1057 pflValues
[1] = pSource
->vPosition
[1];
1058 pflValues
[2] = pSource
->vPosition
[2];
1062 pflValues
[0] = pSource
->vVelocity
[0];
1063 pflValues
[1] = pSource
->vVelocity
[1];
1064 pflValues
[2] = pSource
->vVelocity
[2];
1068 pflValues
[0] = pSource
->vOrientation
[0];
1069 pflValues
[1] = pSource
->vOrientation
[1];
1070 pflValues
[2] = pSource
->vOrientation
[2];
1074 alSetError(AL_INVALID_ENUM
);
1079 alSetError(AL_INVALID_NAME
);
1082 alSetError(AL_INVALID_VALUE
);
1084 ProcessContext(pContext
);
1087 alSetError(AL_INVALID_OPERATION
);
1093 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1095 ALCcontext
*pContext
;
1099 pContext
= alcGetCurrentContext();
1102 SuspendContext(pContext
);
1106 if (alIsSource(source
))
1108 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1112 case AL_MAX_DISTANCE
:
1113 *plValue
= (ALint
)pSource
->flMaxDistance
;
1116 case AL_ROLLOFF_FACTOR
:
1117 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1120 case AL_REFERENCE_DISTANCE
:
1121 *plValue
= (ALint
)pSource
->flRefDistance
;
1124 case AL_SOURCE_RELATIVE
:
1125 *plValue
= pSource
->bHeadRelative
;
1128 case AL_CONE_INNER_ANGLE
:
1129 *plValue
= (ALint
)pSource
->flInnerAngle
;
1132 case AL_CONE_OUTER_ANGLE
:
1133 *plValue
= (ALint
)pSource
->flOuterAngle
;
1137 *plValue
= pSource
->bLooping
;
1141 *plValue
= pSource
->ulBufferID
;
1144 case AL_SOURCE_STATE
:
1145 *plValue
= pSource
->state
;
1148 case AL_BUFFERS_QUEUED
:
1149 *plValue
= pSource
->BuffersInQueue
;
1152 case AL_BUFFERS_PROCESSED
:
1153 if(pSource
->bLooping
)
1155 /* Buffers on a looping source are in a perpetual state
1156 * of PENDING, so don't report any as PROCESSED */
1160 *plValue
= pSource
->BuffersProcessed
;
1163 case AL_SOURCE_TYPE
:
1164 *plValue
= pSource
->lSourceType
;
1168 case AL_SAMPLE_OFFSET
:
1169 case AL_BYTE_OFFSET
:
1170 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
1171 *plValue
= (ALint
)flOffset
;
1173 alSetError(AL_INVALID_OPERATION
);
1176 case AL_DIRECT_FILTER
:
1177 *plValue
= pSource
->DirectFilter
.filter
;
1180 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1181 *plValue
= pSource
->DryGainHFAuto
;
1184 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1185 *plValue
= pSource
->WetGainAuto
;
1188 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1189 *plValue
= pSource
->WetGainHFAuto
;
1192 case AL_DOPPLER_FACTOR
:
1193 *plValue
= (ALint
)pSource
->DopplerFactor
;
1197 alSetError(AL_INVALID_ENUM
);
1202 alSetError(AL_INVALID_NAME
);
1205 alSetError(AL_INVALID_VALUE
);
1207 ProcessContext(pContext
);
1210 alSetError(AL_INVALID_OPERATION
);
1216 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1218 ALCcontext
*pContext
;
1221 pContext
= alcGetCurrentContext();
1224 SuspendContext(pContext
);
1226 if ((plValue1
) && (plValue2
) && (plValue3
))
1228 if (alIsSource(source
))
1230 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1235 *plValue1
= (ALint
)pSource
->vPosition
[0];
1236 *plValue2
= (ALint
)pSource
->vPosition
[1];
1237 *plValue3
= (ALint
)pSource
->vPosition
[2];
1241 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1242 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1243 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1247 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1248 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1249 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1253 alSetError(AL_INVALID_ENUM
);
1258 alSetError(AL_INVALID_NAME
);
1261 alSetError(AL_INVALID_VALUE
);
1263 ProcessContext(pContext
);
1266 alSetError(AL_INVALID_OPERATION
);
1272 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1274 ALCcontext
*pContext
;
1277 pContext
= alcGetCurrentContext();
1280 SuspendContext(pContext
);
1284 if (alIsSource(source
))
1286 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1290 case AL_SOURCE_RELATIVE
:
1291 case AL_CONE_INNER_ANGLE
:
1292 case AL_CONE_OUTER_ANGLE
:
1295 case AL_SOURCE_STATE
:
1296 case AL_BUFFERS_QUEUED
:
1297 case AL_BUFFERS_PROCESSED
:
1299 case AL_SAMPLE_OFFSET
:
1300 case AL_BYTE_OFFSET
:
1301 case AL_MAX_DISTANCE
:
1302 case AL_ROLLOFF_FACTOR
:
1303 case AL_DOPPLER_FACTOR
:
1304 case AL_REFERENCE_DISTANCE
:
1305 case AL_SOURCE_TYPE
:
1306 case AL_DIRECT_FILTER
:
1307 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1308 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1309 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1310 alGetSourcei(source
, eParam
, plValues
);
1314 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1315 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1316 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1320 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1321 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1322 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1326 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1327 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1328 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1332 alSetError(AL_INVALID_ENUM
);
1337 alSetError(AL_INVALID_NAME
);
1340 alSetError(AL_INVALID_VALUE
);
1342 ProcessContext(pContext
);
1345 alSetError(AL_INVALID_OPERATION
);
1351 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1353 alSourcePlayv(1, &source
);
1357 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1359 ALCcontext
*pContext
;
1361 ALbufferlistitem
*ALBufferList
;
1362 ALboolean bSourcesValid
= AL_TRUE
;
1366 pContext
= alcGetCurrentContext();
1369 SuspendContext(pContext
);
1373 // Check that all the Sources are valid
1374 for (i
= 0; i
< n
; i
++)
1376 if (!alIsSource(pSourceList
[i
]))
1378 alSetError(AL_INVALID_NAME
);
1379 bSourcesValid
= AL_FALSE
;
1386 for (i
= 0; i
< n
; i
++)
1388 // Assume Source won't need to play
1391 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1393 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1394 ALBufferList
= pSource
->queue
;
1395 while (ALBufferList
)
1397 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1402 ALBufferList
= ALBufferList
->next
;
1407 if (pSource
->state
!= AL_PAUSED
)
1409 pSource
->state
= AL_PLAYING
;
1410 pSource
->inuse
= AL_TRUE
;
1411 pSource
->play
= AL_TRUE
;
1412 pSource
->position
= 0;
1413 pSource
->position_fraction
= 0;
1414 pSource
->BuffersProcessed
= 0;
1415 pSource
->BuffersPlayed
= 0;
1416 pSource
->BufferPosition
= 0;
1417 pSource
->lBytesPlayed
= 0;
1419 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1421 // Make sure all the Buffers in the queue are marked as PENDING
1422 ALBufferList
= pSource
->queue
;
1423 while (ALBufferList
)
1425 ALBufferList
->bufferstate
= PENDING
;
1426 ALBufferList
= ALBufferList
->next
;
1431 pSource
->state
= AL_PLAYING
;
1432 pSource
->inuse
= AL_TRUE
;
1433 pSource
->play
= AL_TRUE
;
1436 // Check if an Offset has been set
1437 if (pSource
->lOffset
)
1438 ApplyOffset(pSource
, AL_FALSE
);
1442 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1443 ALBufferList
= pSource
->queue
;
1444 while (ALBufferList
)
1446 ALBufferList
->bufferstate
= PROCESSED
;
1447 ALBufferList
= ALBufferList
->next
;
1450 pSource
->BuffersPlayed
= pSource
->BuffersProcessed
= pSource
->BuffersInQueue
;
1457 // sources is a NULL pointer
1458 alSetError(AL_INVALID_VALUE
);
1461 ProcessContext(pContext
);
1466 alSetError(AL_INVALID_OPERATION
);
1472 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1474 alSourcePausev(1, &source
);
1478 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1480 ALCcontext
*Context
;
1483 ALboolean bSourcesValid
= AL_TRUE
;
1485 Context
=alcGetCurrentContext();
1488 SuspendContext(Context
);
1492 // Check all the Sources are valid
1495 if (!alIsSource(sources
[i
]))
1497 alSetError(AL_INVALID_NAME
);
1498 bSourcesValid
= AL_FALSE
;
1507 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1508 if (Source
->state
==AL_PLAYING
)
1510 Source
->state
=AL_PAUSED
;
1511 Source
->inuse
=AL_FALSE
;
1518 // sources is a NULL pointer
1519 alSetError(AL_INVALID_VALUE
);
1522 ProcessContext(Context
);
1527 alSetError(AL_INVALID_OPERATION
);
1533 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1535 alSourceStopv(1, &source
);
1539 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1541 ALCcontext
*Context
;
1544 ALbufferlistitem
*ALBufferListItem
;
1545 ALboolean bSourcesValid
= AL_TRUE
;
1547 Context
=alcGetCurrentContext();
1550 SuspendContext(Context
);
1554 // Check all the Sources are valid
1557 if (!alIsSource(sources
[i
]))
1559 alSetError(AL_INVALID_NAME
);
1560 bSourcesValid
= AL_FALSE
;
1569 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1570 if (Source
->state
!=AL_INITIAL
)
1572 Source
->state
=AL_STOPPED
;
1573 Source
->inuse
=AL_FALSE
;
1574 Source
->BuffersPlayed
= Source
->BuffersProcessed
= Source
->BuffersInQueue
;
1575 ALBufferListItem
= Source
->queue
;
1576 while (ALBufferListItem
!= NULL
)
1578 ALBufferListItem
->bufferstate
= PROCESSED
;
1579 ALBufferListItem
= ALBufferListItem
->next
;
1582 Source
->lOffset
= 0;
1588 // sources is a NULL pointer
1589 alSetError(AL_INVALID_VALUE
);
1592 ProcessContext(Context
);
1597 alSetError(AL_INVALID_OPERATION
);
1603 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1605 alSourceRewindv(1, &source
);
1609 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1611 ALCcontext
*Context
;
1614 ALbufferlistitem
*ALBufferListItem
;
1615 ALboolean bSourcesValid
= AL_TRUE
;
1617 Context
=alcGetCurrentContext();
1620 SuspendContext(Context
);
1624 // Check all the Sources are valid
1627 if (!alIsSource(sources
[i
]))
1629 alSetError(AL_INVALID_NAME
);
1630 bSourcesValid
= AL_FALSE
;
1639 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1640 if (Source
->state
!=AL_INITIAL
)
1642 Source
->state
=AL_INITIAL
;
1643 Source
->inuse
=AL_FALSE
;
1645 Source
->position_fraction
=0;
1646 Source
->BuffersProcessed
= 0;
1647 ALBufferListItem
= Source
->queue
;
1648 while (ALBufferListItem
!= NULL
)
1650 ALBufferListItem
->bufferstate
= PENDING
;
1651 ALBufferListItem
= ALBufferListItem
->next
;
1654 Source
->ulBufferID
= Source
->queue
->buffer
;
1656 Source
->lOffset
= 0;
1662 // sources is a NULL pointer
1663 alSetError(AL_INVALID_VALUE
);
1666 ProcessContext(Context
);
1671 alSetError(AL_INVALID_OPERATION
);
1678 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1680 ALCcontext
*Context
;
1683 ALbufferlistitem
*ALBufferList
;
1684 ALbufferlistitem
*ALBufferListStart
;
1689 ALboolean bBuffersValid
= AL_TRUE
;
1694 Context
=alcGetCurrentContext();
1697 SuspendContext(Context
);
1702 // Check that all buffers are valid or zero and that the source is valid
1704 // Check that this is a valid source
1705 if (alIsSource(source
))
1707 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1709 // Check that this is not a STATIC Source
1710 if (ALSource
->lSourceType
!= AL_STATIC
)
1715 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1716 ALBufferList
= ALSource
->queue
;
1717 while (ALBufferList
)
1719 if (ALBufferList
->buffer
)
1721 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1722 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1725 ALBufferList
= ALBufferList
->next
;
1728 for (i
= 0; i
< n
; i
++)
1730 if (alIsBuffer(buffers
[i
]))
1734 if ((iFrequency
== -1) && (iFormat
== -1))
1736 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1737 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1741 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1742 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1744 alSetError(AL_INVALID_OPERATION
);
1745 bBuffersValid
= AL_FALSE
;
1753 alSetError(AL_INVALID_NAME
);
1754 bBuffersValid
= AL_FALSE
;
1761 // Change Source Type
1762 ALSource
->lSourceType
= AL_STREAMING
;
1764 // All buffers are valid - so add them to the list
1765 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1766 ALBufferListStart
->buffer
= buffers
[0];
1767 ALBufferListStart
->bufferstate
= PENDING
;
1768 ALBufferListStart
->flag
= 0;
1769 ALBufferListStart
->next
= NULL
;
1772 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1776 DataSize
+= BufferSize
;
1778 // Increment reference counter for buffer
1780 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1782 ALBufferList
= ALBufferListStart
;
1784 for (i
= 1; i
< n
; i
++)
1786 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1787 ALBufferList
->next
->buffer
= buffers
[i
];
1788 ALBufferList
->next
->bufferstate
= PENDING
;
1789 ALBufferList
->next
->flag
= 0;
1790 ALBufferList
->next
->next
= NULL
;
1793 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1797 DataSize
+= BufferSize
;
1799 // Increment reference counter for buffer
1801 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1803 ALBufferList
= ALBufferList
->next
;
1806 if (ALSource
->queue
== NULL
)
1808 ALSource
->queue
= ALBufferListStart
;
1809 // Update Current Buffer
1810 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1814 // Find end of queue
1815 ALBufferList
= ALSource
->queue
;
1816 while (ALBufferList
->next
!= NULL
)
1818 ALBufferList
= ALBufferList
->next
;
1821 ALBufferList
->next
= ALBufferListStart
;
1824 // Update number of buffers in queue
1825 ALSource
->BuffersInQueue
+= n
;
1830 // Invalid Source Type (can't queue on a Static Source)
1831 alSetError(AL_INVALID_OPERATION
);
1836 // Invalid Source Name
1837 alSetError(AL_INVALID_NAME
);
1840 ProcessContext(Context
);
1845 alSetError(AL_INVALID_OPERATION
);
1852 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1853 // an array of buffer IDs that are to be filled with the names of the buffers removed
1854 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1856 ALCcontext
*Context
;
1859 ALbufferlistitem
*ALBufferList
;
1863 ALboolean bBuffersProcessed
;
1870 bBuffersProcessed
= AL_TRUE
;
1872 Context
=alcGetCurrentContext();
1875 SuspendContext(Context
);
1877 if (alIsSource(source
))
1879 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1881 // Check that all 'n' buffers have been processed
1882 ALBufferList
= ALSource
->queue
;
1883 for (i
= 0; i
< n
; i
++)
1885 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1887 ALBufferList
= ALBufferList
->next
;
1891 bBuffersProcessed
= AL_FALSE
;
1896 // If all 'n' buffers have been processed, remove them from the queue
1897 if (bBuffersProcessed
)
1899 for (i
= 0; i
< n
; i
++)
1901 ALBufferList
= ALSource
->queue
;
1903 ALSource
->queue
= ALBufferList
->next
;
1904 // Record name of buffer
1905 buffers
[i
] = ALBufferList
->buffer
;
1906 // Decrement buffer reference counter
1907 if (ALBufferList
->buffer
)
1908 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1909 // Record size of buffer
1910 if (ALBufferList
->buffer
)
1911 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1915 DataSize
+= BufferSize
;
1916 // Release memory for buffer list item
1918 ALSource
->BuffersInQueue
--;
1919 ALSource
->BuffersProcessed
--;
1922 if (ALSource
->state
!= AL_PLAYING
)
1924 if (ALSource
->queue
)
1925 BufferID
= ALSource
->queue
->buffer
;
1929 ALSource
->ulBufferID
= BufferID
;
1932 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1934 ALSource
->BuffersPlayed
= 0;
1935 ALSource
->BufferPosition
= 0;
1938 ALSource
->BuffersPlayed
-= n
;
1942 // Some buffers can't be unqueue because they have not been processed
1943 alSetError(AL_INVALID_VALUE
);
1948 // Invalid Source Name
1949 alSetError(AL_INVALID_NAME
);
1952 ProcessContext(Context
);
1957 alSetError(AL_INVALID_OPERATION
);
1964 static ALvoid
InitSourceParams(ALsource
*pSource
)
1966 pSource
->flInnerAngle
= 360.0f
;
1967 pSource
->flOuterAngle
= 360.0f
;
1968 pSource
->flPitch
= 1.0f
;
1969 pSource
->vPosition
[0] = 0.0f
;
1970 pSource
->vPosition
[1] = 0.0f
;
1971 pSource
->vPosition
[2] = 0.0f
;
1972 pSource
->vOrientation
[0] = 0.0f
;
1973 pSource
->vOrientation
[1] = 0.0f
;
1974 pSource
->vOrientation
[2] = 0.0f
;
1975 pSource
->vVelocity
[0] = 0.0f
;
1976 pSource
->vVelocity
[1] = 0.0f
;
1977 pSource
->vVelocity
[2] = 0.0f
;
1978 pSource
->flRefDistance
= 1.0f
;
1979 pSource
->flMaxDistance
= FLT_MAX
;
1980 pSource
->flRollOffFactor
= 1.0f
;
1981 pSource
->bLooping
= AL_FALSE
;
1982 pSource
->flGain
= 1.0f
;
1983 pSource
->flMinGain
= 0.0f
;
1984 pSource
->flMaxGain
= 1.0f
;
1985 pSource
->flOuterGain
= 0.0f
;
1986 pSource
->OuterGainHF
= 1.0f
;
1988 pSource
->DryGainHFAuto
= AL_TRUE
;
1989 pSource
->WetGainAuto
= AL_TRUE
;
1990 pSource
->WetGainHFAuto
= AL_TRUE
;
1991 pSource
->AirAbsorptionFactor
= 0.0f
;
1992 pSource
->RoomRolloffFactor
= 0.0f
;
1993 pSource
->DopplerFactor
= 1.0f
;
1995 pSource
->state
= AL_INITIAL
;
1996 pSource
->lSourceType
= AL_UNDETERMINED
;
1998 pSource
->ulBufferID
= 0;
2005 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
2006 The offset is relative to the start of the queue (not the start of the current buffer)
2008 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
2010 ALbufferlistitem
*pBufferList
;
2012 ALfloat flBufferFreq
;
2013 ALint lBytesPlayed
, lChannels
;
2014 ALenum eOriginalFormat
;
2015 ALboolean bReturn
= AL_TRUE
;
2016 ALint lTotalBufferDataSize
;
2018 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
2020 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
2021 // Get Current Buffer Size and frequency (in milliseconds)
2022 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
2023 eOriginalFormat
= pBuffer
->eOriginalFormat
;
2024 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2026 // Get Current BytesPlayed
2027 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2028 // Add byte length of any processed buffers in the queue
2029 pBufferList
= pSource
->queue
;
2030 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2032 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2033 pBufferList
= pBufferList
->next
;
2036 lTotalBufferDataSize
= 0;
2037 pBufferList
= pSource
->queue
;
2040 if (pBufferList
->buffer
)
2041 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2042 pBufferList
= pBufferList
->next
;
2045 if (pSource
->bLooping
)
2047 if (lBytesPlayed
< 0)
2050 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
2054 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2055 if(lBytesPlayed
< 0)
2057 if(lBytesPlayed
> lTotalBufferDataSize
)
2058 lBytesPlayed
= lTotalBufferDataSize
;
2064 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
2066 case AL_SAMPLE_OFFSET
:
2067 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
2069 case AL_BYTE_OFFSET
:
2070 // Take into account the original format of the Buffer
2071 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2072 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2074 // Compression rate of the ADPCM supported is 3.6111 to 1
2075 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
2076 // Round down to nearest ADPCM block
2077 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
2079 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2081 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 2);
2083 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2085 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2087 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2089 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2091 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2093 *pflOffset
= (ALfloat
)(lBytesPlayed
<< 1);
2097 *pflOffset
= (ALfloat
)lBytesPlayed
;
2114 Apply a playback offset to the Source. This function will update the queue (to correctly
2115 mark buffers as 'pending' or 'processed' depending upon the new offset.
2117 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2119 ALbufferlistitem
*pBufferList
;
2121 ALint lBufferSize
, lTotalBufferSize
;
2124 // Get true byte offset
2125 lByteOffset
= GetByteOffset(pSource
);
2127 // If this is a valid offset apply it
2128 if (lByteOffset
!= -1)
2130 // Sort out the queue (pending and processed states)
2131 pBufferList
= pSource
->queue
;
2132 lTotalBufferSize
= 0;
2133 pSource
->BuffersPlayed
= 0;
2134 pSource
->BuffersProcessed
= 0;
2137 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2138 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2140 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2142 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2143 // update the state to PROCESSED
2144 pSource
->BuffersPlayed
++;
2146 if (!pSource
->bLooping
)
2148 pBufferList
->bufferstate
= PROCESSED
;
2149 pSource
->BuffersProcessed
++;
2152 else if (lTotalBufferSize
<= lByteOffset
)
2154 // Offset is within this buffer
2155 pBufferList
->bufferstate
= PENDING
;
2157 // Set Current Buffer ID
2158 pSource
->ulBufferID
= pBufferList
->buffer
;
2160 // Set current position in this buffer
2161 pSource
->BufferPosition
= lByteOffset
- lTotalBufferSize
;
2163 // Set Total Bytes Played to Offset
2164 pSource
->lBytesPlayed
= lByteOffset
;
2166 // SW Mixer Positions are in Samples
2167 pSource
->position
= pSource
->BufferPosition
/
2168 aluBytesFromFormat(pBuffer
->format
) /
2169 aluChannelsFromFormat(pBuffer
->format
);
2173 // Offset is before this buffer, so mark as pending
2174 pBufferList
->bufferstate
= PENDING
;
2177 // Increment the TotalBufferSize
2178 lTotalBufferSize
+= lBufferSize
;
2180 // Move on to next buffer in the Queue
2181 pBufferList
= pBufferList
->next
;
2187 alSetError(AL_INVALID_VALUE
);
2191 pSource
->lOffset
= 0;
2198 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2199 offset supplied by the application). This takes into account the fact that the buffer format
2200 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2202 static ALint
GetByteOffset(ALsource
*pSource
)
2204 ALbuffer
*pBuffer
= NULL
;
2205 ALbufferlistitem
*pBufferList
;
2206 ALfloat flBufferFreq
;
2208 ALint lByteOffset
= -1;
2209 ALint lTotalBufferDataSize
;
2211 // Find the first non-NULL Buffer in the Queue
2212 pBufferList
= pSource
->queue
;
2215 if (pBufferList
->buffer
)
2217 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2220 pBufferList
= pBufferList
->next
;
2225 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2226 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2228 // Determine the ByteOffset (and ensure it is block aligned)
2229 switch (pSource
->lOffsetType
)
2231 case AL_BYTE_OFFSET
:
2232 // Take into consideration the original format
2233 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2234 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2236 // Round down to nearest ADPCM block
2237 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2238 // Multiply by compression rate
2239 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2240 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2242 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2244 lByteOffset
= pSource
->lOffset
* 4;
2245 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2247 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2249 lByteOffset
= pSource
->lOffset
* 2;
2250 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2252 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2254 lByteOffset
= pSource
->lOffset
* 2;
2255 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2257 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2259 lByteOffset
= pSource
->lOffset
/ 2;
2260 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2264 lByteOffset
= pSource
->lOffset
;
2265 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2269 case AL_SAMPLE_OFFSET
:
2270 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2274 // Note - lOffset is internally stored as Milliseconds
2275 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2276 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2280 lTotalBufferDataSize
= 0;
2281 pBufferList
= pSource
->queue
;
2284 if (pBufferList
->buffer
)
2285 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2286 pBufferList
= pBufferList
->next
;
2289 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2290 if (lByteOffset
>= lTotalBufferDataSize
)
2298 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2301 if(Context
->SourceCount
> 0)
2302 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", Context
->SourceCount
);
2305 while(Context
->Source
)
2307 ALsource
*temp
= Context
->Source
;
2308 Context
->Source
= Context
->Source
->next
;
2310 // Release source structure
2311 ALTHUNK_REMOVEENTRY(temp
->source
);
2312 memset(temp
, 0, sizeof(ALsource
));
2315 Context
->SourceCount
= 0;