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 // Decrement Source count
178 Context
->SourceCount
--;
180 // Remove Source from list of Sources
181 list
= &Context
->Source
;
182 while(*list
&& *list
!= ALSource
)
183 list
= &(*list
)->next
;
186 *list
= (*list
)->next
;
187 ALTHUNK_REMOVEENTRY(ALSource
->source
);
189 memset(ALSource
,0,sizeof(ALsource
));
198 // Trying to delete more Sources than have been generated
199 alSetError(AL_INVALID_NAME
);
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
);
371 case AL_SAMPLE_OFFSET
:
375 pSource
->lOffsetType
= eParam
;
377 // Store Offset (convert Seconds into Milliseconds)
378 if (eParam
== AL_SEC_OFFSET
)
379 pSource
->lOffset
= (ALint
)(flValue
* 1000.0f
);
381 pSource
->lOffset
= (ALint
)flValue
;
383 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
384 ApplyOffset(pSource
, AL_TRUE
);
387 alSetError(AL_INVALID_VALUE
);
391 alSetError(AL_INVALID_ENUM
);
397 // Invalid Source Name
398 alSetError(AL_INVALID_NAME
);
401 ProcessContext(pContext
);
406 alSetError(AL_INVALID_OPERATION
);
413 ALAPI ALvoid ALAPIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
415 ALCcontext
*pContext
;
418 pContext
= alcGetCurrentContext();
421 SuspendContext(pContext
);
423 if (alIsSource(source
))
425 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
429 pSource
->vPosition
[0] = flValue1
;
430 pSource
->vPosition
[1] = flValue2
;
431 pSource
->vPosition
[2] = flValue3
;
435 pSource
->vVelocity
[0] = flValue1
;
436 pSource
->vVelocity
[1] = flValue2
;
437 pSource
->vVelocity
[2] = flValue3
;
441 pSource
->vOrientation
[0] = flValue1
;
442 pSource
->vOrientation
[1] = flValue2
;
443 pSource
->vOrientation
[2] = flValue3
;
447 alSetError(AL_INVALID_ENUM
);
452 alSetError(AL_INVALID_NAME
);
454 ProcessContext(pContext
);
458 alSetError(AL_INVALID_OPERATION
);
465 ALAPI ALvoid ALAPIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
467 ALCcontext
*pContext
;
469 pContext
= alcGetCurrentContext();
472 SuspendContext(pContext
);
476 if (alIsSource(source
))
481 case AL_CONE_INNER_ANGLE
:
482 case AL_CONE_OUTER_ANGLE
:
484 case AL_MAX_DISTANCE
:
485 case AL_ROLLOFF_FACTOR
:
486 case AL_REFERENCE_DISTANCE
:
489 case AL_CONE_OUTER_GAIN
:
490 case AL_CONE_OUTER_GAINHF
:
492 case AL_SAMPLE_OFFSET
:
494 case AL_AIR_ABSORPTION_FACTOR
:
495 case AL_ROOM_ROLLOFF_FACTOR
:
496 alSourcef(source
, eParam
, pflValues
[0]);
502 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
506 alSetError(AL_INVALID_ENUM
);
511 alSetError(AL_INVALID_NAME
);
514 alSetError(AL_INVALID_VALUE
);
516 ProcessContext(pContext
);
519 alSetError(AL_INVALID_OPERATION
);
525 ALAPI ALvoid ALAPIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
527 ALCcontext
*pContext
;
529 ALbufferlistitem
*pALBufferListItem
;
534 pContext
= alcGetCurrentContext();
537 SuspendContext(pContext
);
539 if (alIsSource(source
))
541 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
545 case AL_MAX_DISTANCE
:
546 case AL_ROLLOFF_FACTOR
:
547 case AL_REFERENCE_DISTANCE
:
548 alSourcef(source
, eParam
, (ALfloat
)lValue
);
551 case AL_SOURCE_RELATIVE
:
552 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
553 pSource
->bHeadRelative
= (ALboolean
)lValue
;
555 alSetError(AL_INVALID_VALUE
);
558 case AL_CONE_INNER_ANGLE
:
559 if ((lValue
>= 0) && (lValue
<= 360))
560 pSource
->flInnerAngle
= (float)lValue
;
562 alSetError(AL_INVALID_VALUE
);
565 case AL_CONE_OUTER_ANGLE
:
566 if ((lValue
>= 0) && (lValue
<= 360))
567 pSource
->flOuterAngle
= (float)lValue
;
569 alSetError(AL_INVALID_VALUE
);
573 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
574 pSource
->bLooping
= (ALboolean
)lValue
;
576 alSetError(AL_INVALID_VALUE
);
580 if ((pSource
->state
== AL_STOPPED
) || (pSource
->state
== AL_INITIAL
))
582 if (alIsBuffer(lValue
))
584 // Remove all elements in the queue
585 while (pSource
->queue
!= NULL
)
587 pALBufferListItem
= pSource
->queue
;
588 pSource
->queue
= pALBufferListItem
->next
;
589 // Decrement reference counter for buffer
590 if (pALBufferListItem
->buffer
)
591 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
)))->refcount
--;
592 // Record size of buffer
593 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
))->size
;
594 DataSize
+= BufferSize
;
595 // Increment the number of buffers removed from queue
597 // Release memory for buffer list item
598 free(pALBufferListItem
);
599 // Decrement the number of buffers in the queue
600 pSource
->BuffersInQueue
--;
603 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
606 // Source is now in STATIC mode
607 pSource
->lSourceType
= AL_STATIC
;
609 // Add the selected buffer to the queue
610 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
611 pALBufferListItem
->buffer
= lValue
;
612 pALBufferListItem
->bufferstate
= PENDING
;
613 pALBufferListItem
->flag
= 0;
614 pALBufferListItem
->next
= NULL
;
616 pSource
->queue
= pALBufferListItem
;
617 pSource
->BuffersInQueue
= 1;
619 DataSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(lValue
))->size
;
621 // Increment reference counter for buffer
622 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(lValue
)))->refcount
++;
626 // Source is now in UNDETERMINED mode
627 pSource
->lSourceType
= AL_UNDETERMINED
;
630 // Set Buffers Processed
631 pSource
->BuffersProcessed
= 0;
633 // Update AL_BUFFER parameter
634 pSource
->ulBufferID
= lValue
;
637 alSetError(AL_INVALID_VALUE
);
640 alSetError(AL_INVALID_OPERATION
);
643 case AL_SOURCE_STATE
:
645 alSetError(AL_INVALID_OPERATION
);
649 case AL_SAMPLE_OFFSET
:
653 pSource
->lOffsetType
= eParam
;
655 // Store Offset (convert Seconds into Milliseconds)
656 if (eParam
== AL_SEC_OFFSET
)
657 pSource
->lOffset
= lValue
* 1000;
659 pSource
->lOffset
= lValue
;
661 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
662 ApplyOffset(pSource
, AL_TRUE
);
665 alSetError(AL_INVALID_VALUE
);
668 case AL_DIRECT_FILTER
:
669 if(alIsFilter(lValue
))
671 ALfilter
*filter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue
);
674 pSource
->DirectFilter
.type
= AL_FILTER_NULL
;
675 pSource
->DirectFilter
.filter
= 0;
678 memcpy(&pSource
->DirectFilter
, filter
, sizeof(*filter
));
681 alSetError(AL_INVALID_VALUE
);
684 case AL_DIRECT_FILTER_GAINHF_AUTO
:
685 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
686 pSource
->DryGainHFAuto
= lValue
;
688 alSetError(AL_INVALID_VALUE
);
691 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
692 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
693 pSource
->WetGainAuto
= lValue
;
695 alSetError(AL_INVALID_VALUE
);
698 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
699 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
700 pSource
->WetGainHFAuto
= lValue
;
702 alSetError(AL_INVALID_VALUE
);
706 alSetError(AL_INVALID_ENUM
);
711 alSetError(AL_INVALID_NAME
);
713 ProcessContext(pContext
);
716 alSetError(AL_INVALID_OPERATION
);
722 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
724 ALCcontext
*pContext
;
726 pContext
= alcGetCurrentContext();
729 SuspendContext(pContext
);
731 if (alIsSource(source
))
733 ALsource
*pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
740 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
743 case AL_AUXILIARY_SEND_FILTER
:
744 if(lValue2
>= 0 && lValue2
< MAX_SENDS
&&
745 (alIsAuxiliaryEffectSlot(lValue1
) || lValue1
== 0) &&
748 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(lValue1
);
749 ALfilter
*ALFilter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue3
);
751 /* Release refcount on the previous slot, and add one for
753 if(pSource
->Send
[lValue2
].Slot
)
754 pSource
->Send
[lValue2
].Slot
->refcount
--;
755 pSource
->Send
[lValue2
].Slot
= ALEffectSlot
;
756 if(pSource
->Send
[lValue2
].Slot
)
757 pSource
->Send
[lValue2
].Slot
->refcount
++;
762 pSource
->Send
[lValue2
].WetFilter
.type
= 0;
763 pSource
->Send
[lValue2
].WetFilter
.filter
= 0;
766 memcpy(&pSource
->Send
[lValue2
].WetFilter
, ALFilter
, sizeof(*ALFilter
));
769 alSetError(AL_INVALID_VALUE
);
773 alSetError(AL_INVALID_ENUM
);
778 alSetError(AL_INVALID_NAME
);
780 ProcessContext(pContext
);
783 alSetError(AL_INVALID_OPERATION
);
789 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
791 ALCcontext
*pContext
;
793 pContext
= alcGetCurrentContext();
796 SuspendContext(pContext
);
800 if (alIsSource(source
))
804 case AL_SOURCE_RELATIVE
:
805 case AL_CONE_INNER_ANGLE
:
806 case AL_CONE_OUTER_ANGLE
:
809 case AL_SOURCE_STATE
:
811 case AL_SAMPLE_OFFSET
:
813 case AL_MAX_DISTANCE
:
814 case AL_ROLLOFF_FACTOR
:
815 case AL_REFERENCE_DISTANCE
:
816 case AL_DIRECT_FILTER
:
817 case AL_DIRECT_FILTER_GAINHF_AUTO
:
818 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
819 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
820 alSourcei(source
, eParam
, plValues
[0]);
826 case AL_AUXILIARY_SEND_FILTER
:
827 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
831 alSetError(AL_INVALID_ENUM
);
836 alSetError(AL_INVALID_NAME
);
839 alSetError(AL_INVALID_VALUE
);
841 ProcessContext(pContext
);
844 alSetError(AL_INVALID_OPERATION
);
850 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
852 ALCcontext
*pContext
;
856 pContext
= alcGetCurrentContext();
859 SuspendContext(pContext
);
863 if (alIsSource(source
))
865 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
870 *pflValue
= pSource
->flPitch
;
874 *pflValue
= pSource
->flGain
;
878 *pflValue
= pSource
->flMinGain
;
882 *pflValue
= pSource
->flMaxGain
;
885 case AL_MAX_DISTANCE
:
886 *pflValue
= pSource
->flMaxDistance
;
889 case AL_ROLLOFF_FACTOR
:
890 *pflValue
= pSource
->flRollOffFactor
;
893 case AL_CONE_OUTER_GAIN
:
894 *pflValue
= pSource
->flOuterGain
;
897 case AL_CONE_OUTER_GAINHF
:
898 *pflValue
= pSource
->OuterGainHF
;
902 case AL_SAMPLE_OFFSET
:
904 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
905 *pflValue
= flOffset
;
907 alSetError(AL_INVALID_OPERATION
);
910 case AL_CONE_INNER_ANGLE
:
911 *pflValue
= pSource
->flInnerAngle
;
914 case AL_CONE_OUTER_ANGLE
:
915 *pflValue
= pSource
->flOuterAngle
;
918 case AL_REFERENCE_DISTANCE
:
919 *pflValue
= pSource
->flRefDistance
;
922 case AL_AIR_ABSORPTION_FACTOR
:
923 *pflValue
= pSource
->AirAbsorptionFactor
;
926 case AL_ROOM_ROLLOFF_FACTOR
:
927 *pflValue
= pSource
->RoomRolloffFactor
;
931 alSetError(AL_INVALID_ENUM
);
936 alSetError(AL_INVALID_NAME
);
939 alSetError(AL_INVALID_VALUE
);
941 ProcessContext(pContext
);
944 alSetError(AL_INVALID_OPERATION
);
950 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
952 ALCcontext
*pContext
;
955 pContext
= alcGetCurrentContext();
958 SuspendContext(pContext
);
960 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
962 if (alIsSource(source
))
964 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
969 *pflValue1
= pSource
->vPosition
[0];
970 *pflValue2
= pSource
->vPosition
[1];
971 *pflValue3
= pSource
->vPosition
[2];
975 *pflValue1
= pSource
->vVelocity
[0];
976 *pflValue2
= pSource
->vVelocity
[1];
977 *pflValue3
= pSource
->vVelocity
[2];
981 *pflValue1
= pSource
->vOrientation
[0];
982 *pflValue2
= pSource
->vOrientation
[1];
983 *pflValue3
= pSource
->vOrientation
[2];
987 alSetError(AL_INVALID_ENUM
);
992 alSetError(AL_INVALID_NAME
);
995 alSetError(AL_INVALID_VALUE
);
997 ProcessContext(pContext
);
1000 alSetError(AL_INVALID_OPERATION
);
1006 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1008 ALCcontext
*pContext
;
1011 pContext
= alcGetCurrentContext();
1014 SuspendContext(pContext
);
1018 if (alIsSource(source
))
1020 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1028 case AL_MAX_DISTANCE
:
1029 case AL_ROLLOFF_FACTOR
:
1030 case AL_CONE_OUTER_GAIN
:
1032 case AL_SAMPLE_OFFSET
:
1033 case AL_BYTE_OFFSET
:
1034 case AL_CONE_INNER_ANGLE
:
1035 case AL_CONE_OUTER_ANGLE
:
1036 case AL_REFERENCE_DISTANCE
:
1037 case AL_CONE_OUTER_GAINHF
:
1038 case AL_AIR_ABSORPTION_FACTOR
:
1039 case AL_ROOM_ROLLOFF_FACTOR
:
1040 alGetSourcef(source
, eParam
, pflValues
);
1044 pflValues
[0] = pSource
->vPosition
[0];
1045 pflValues
[1] = pSource
->vPosition
[1];
1046 pflValues
[2] = pSource
->vPosition
[2];
1050 pflValues
[0] = pSource
->vVelocity
[0];
1051 pflValues
[1] = pSource
->vVelocity
[1];
1052 pflValues
[2] = pSource
->vVelocity
[2];
1056 pflValues
[0] = pSource
->vOrientation
[0];
1057 pflValues
[1] = pSource
->vOrientation
[1];
1058 pflValues
[2] = pSource
->vOrientation
[2];
1062 alSetError(AL_INVALID_ENUM
);
1067 alSetError(AL_INVALID_NAME
);
1070 alSetError(AL_INVALID_VALUE
);
1072 ProcessContext(pContext
);
1075 alSetError(AL_INVALID_OPERATION
);
1081 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1083 ALCcontext
*pContext
;
1087 pContext
= alcGetCurrentContext();
1090 SuspendContext(pContext
);
1094 if (alIsSource(source
))
1096 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1100 case AL_MAX_DISTANCE
:
1101 *plValue
= (ALint
)pSource
->flMaxDistance
;
1104 case AL_ROLLOFF_FACTOR
:
1105 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1108 case AL_REFERENCE_DISTANCE
:
1109 *plValue
= (ALint
)pSource
->flRefDistance
;
1112 case AL_SOURCE_RELATIVE
:
1113 *plValue
= pSource
->bHeadRelative
;
1116 case AL_CONE_INNER_ANGLE
:
1117 *plValue
= (ALint
)pSource
->flInnerAngle
;
1120 case AL_CONE_OUTER_ANGLE
:
1121 *plValue
= (ALint
)pSource
->flOuterAngle
;
1125 *plValue
= pSource
->bLooping
;
1129 *plValue
= pSource
->ulBufferID
;
1132 case AL_SOURCE_STATE
:
1133 *plValue
= pSource
->state
;
1136 case AL_BUFFERS_QUEUED
:
1137 *plValue
= pSource
->BuffersInQueue
;
1140 case AL_BUFFERS_PROCESSED
:
1141 if(pSource
->bLooping
)
1143 /* Buffers on a looping source are in a perpetual state
1144 * of PENDING, so don't report any as PROCESSED */
1148 *plValue
= pSource
->BuffersProcessed
;
1151 case AL_SOURCE_TYPE
:
1152 *plValue
= pSource
->lSourceType
;
1156 case AL_SAMPLE_OFFSET
:
1157 case AL_BYTE_OFFSET
:
1158 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
1159 *plValue
= (ALint
)flOffset
;
1161 alSetError(AL_INVALID_OPERATION
);
1164 case AL_DIRECT_FILTER
:
1165 *plValue
= pSource
->DirectFilter
.filter
;
1168 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1169 *plValue
= pSource
->DryGainHFAuto
;
1172 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1173 *plValue
= pSource
->WetGainAuto
;
1176 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1177 *plValue
= pSource
->WetGainHFAuto
;
1181 alSetError(AL_INVALID_ENUM
);
1186 alSetError(AL_INVALID_NAME
);
1189 alSetError(AL_INVALID_VALUE
);
1191 ProcessContext(pContext
);
1194 alSetError(AL_INVALID_OPERATION
);
1200 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1202 ALCcontext
*pContext
;
1205 pContext
= alcGetCurrentContext();
1208 SuspendContext(pContext
);
1210 if ((plValue1
) && (plValue2
) && (plValue3
))
1212 if (alIsSource(source
))
1214 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1219 *plValue1
= (ALint
)pSource
->vPosition
[0];
1220 *plValue2
= (ALint
)pSource
->vPosition
[1];
1221 *plValue3
= (ALint
)pSource
->vPosition
[2];
1225 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1226 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1227 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1231 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1232 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1233 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1237 alSetError(AL_INVALID_ENUM
);
1242 alSetError(AL_INVALID_NAME
);
1245 alSetError(AL_INVALID_VALUE
);
1247 ProcessContext(pContext
);
1250 alSetError(AL_INVALID_OPERATION
);
1256 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1258 ALCcontext
*pContext
;
1261 pContext
= alcGetCurrentContext();
1264 SuspendContext(pContext
);
1268 if (alIsSource(source
))
1270 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1274 case AL_SOURCE_RELATIVE
:
1275 case AL_CONE_INNER_ANGLE
:
1276 case AL_CONE_OUTER_ANGLE
:
1279 case AL_SOURCE_STATE
:
1280 case AL_BUFFERS_QUEUED
:
1281 case AL_BUFFERS_PROCESSED
:
1283 case AL_SAMPLE_OFFSET
:
1284 case AL_BYTE_OFFSET
:
1285 case AL_MAX_DISTANCE
:
1286 case AL_ROLLOFF_FACTOR
:
1287 case AL_REFERENCE_DISTANCE
:
1288 case AL_SOURCE_TYPE
:
1289 case AL_DIRECT_FILTER
:
1290 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1291 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1292 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1293 alGetSourcei(source
, eParam
, plValues
);
1297 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1298 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1299 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1303 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1304 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1305 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1309 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1310 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1311 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1315 alSetError(AL_INVALID_ENUM
);
1320 alSetError(AL_INVALID_NAME
);
1323 alSetError(AL_INVALID_VALUE
);
1325 ProcessContext(pContext
);
1328 alSetError(AL_INVALID_OPERATION
);
1334 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1336 alSourcePlayv(1, &source
);
1340 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1342 ALCcontext
*pContext
;
1344 ALbufferlistitem
*ALBufferList
;
1345 ALboolean bSourcesValid
= AL_TRUE
;
1349 pContext
= alcGetCurrentContext();
1352 SuspendContext(pContext
);
1356 // Check that all the Sources are valid
1357 for (i
= 0; i
< n
; i
++)
1359 if (!alIsSource(pSourceList
[i
]))
1361 alSetError(AL_INVALID_NAME
);
1362 bSourcesValid
= AL_FALSE
;
1369 for (i
= 0; i
< n
; i
++)
1371 // Assume Source won't need to play
1374 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1376 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1377 ALBufferList
= pSource
->queue
;
1378 while (ALBufferList
)
1380 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1385 ALBufferList
= ALBufferList
->next
;
1390 if (pSource
->state
!= AL_PAUSED
)
1392 pSource
->state
= AL_PLAYING
;
1393 pSource
->inuse
= AL_TRUE
;
1394 pSource
->play
= AL_TRUE
;
1395 pSource
->position
= 0;
1396 pSource
->position_fraction
= 0;
1397 pSource
->BuffersProcessed
= 0;
1398 pSource
->BuffersPlayed
= 0;
1399 pSource
->BufferPosition
= 0;
1400 pSource
->lBytesPlayed
= 0;
1402 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1404 // Make sure all the Buffers in the queue are marked as PENDING
1405 ALBufferList
= pSource
->queue
;
1406 while (ALBufferList
)
1408 ALBufferList
->bufferstate
= PENDING
;
1409 ALBufferList
= ALBufferList
->next
;
1414 pSource
->state
= AL_PLAYING
;
1415 pSource
->inuse
= AL_TRUE
;
1416 pSource
->play
= AL_TRUE
;
1419 // Check if an Offset has been set
1420 if (pSource
->lOffset
)
1421 ApplyOffset(pSource
, AL_FALSE
);
1425 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1426 ALBufferList
= pSource
->queue
;
1427 while (ALBufferList
)
1429 ALBufferList
->bufferstate
= PROCESSED
;
1430 ALBufferList
= ALBufferList
->next
;
1433 pSource
->BuffersPlayed
= pSource
->BuffersProcessed
= pSource
->BuffersInQueue
;
1440 // sources is a NULL pointer
1441 alSetError(AL_INVALID_VALUE
);
1444 ProcessContext(pContext
);
1449 alSetError(AL_INVALID_OPERATION
);
1455 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1457 alSourcePausev(1, &source
);
1461 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1463 ALCcontext
*Context
;
1466 ALboolean bSourcesValid
= AL_TRUE
;
1468 Context
=alcGetCurrentContext();
1471 SuspendContext(Context
);
1475 // Check all the Sources are valid
1478 if (!alIsSource(sources
[i
]))
1480 alSetError(AL_INVALID_NAME
);
1481 bSourcesValid
= AL_FALSE
;
1490 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1491 if (Source
->state
==AL_PLAYING
)
1493 Source
->state
=AL_PAUSED
;
1494 Source
->inuse
=AL_FALSE
;
1501 // sources is a NULL pointer
1502 alSetError(AL_INVALID_VALUE
);
1505 ProcessContext(Context
);
1510 alSetError(AL_INVALID_OPERATION
);
1516 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1518 alSourceStopv(1, &source
);
1522 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1524 ALCcontext
*Context
;
1527 ALbufferlistitem
*ALBufferListItem
;
1528 ALboolean bSourcesValid
= AL_TRUE
;
1530 Context
=alcGetCurrentContext();
1533 SuspendContext(Context
);
1537 // Check all the Sources are valid
1540 if (!alIsSource(sources
[i
]))
1542 alSetError(AL_INVALID_NAME
);
1543 bSourcesValid
= AL_FALSE
;
1552 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1553 if (Source
->state
!=AL_INITIAL
)
1555 Source
->state
=AL_STOPPED
;
1556 Source
->inuse
=AL_FALSE
;
1557 Source
->BuffersPlayed
= Source
->BuffersProcessed
= Source
->BuffersInQueue
;
1558 ALBufferListItem
= Source
->queue
;
1559 while (ALBufferListItem
!= NULL
)
1561 ALBufferListItem
->bufferstate
= PROCESSED
;
1562 ALBufferListItem
= ALBufferListItem
->next
;
1565 Source
->lOffset
= 0;
1571 // sources is a NULL pointer
1572 alSetError(AL_INVALID_VALUE
);
1575 ProcessContext(Context
);
1580 alSetError(AL_INVALID_OPERATION
);
1586 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1588 alSourceRewindv(1, &source
);
1592 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1594 ALCcontext
*Context
;
1597 ALbufferlistitem
*ALBufferListItem
;
1598 ALboolean bSourcesValid
= AL_TRUE
;
1600 Context
=alcGetCurrentContext();
1603 SuspendContext(Context
);
1607 // Check all the Sources are valid
1610 if (!alIsSource(sources
[i
]))
1612 alSetError(AL_INVALID_NAME
);
1613 bSourcesValid
= AL_FALSE
;
1622 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1623 if (Source
->state
!=AL_INITIAL
)
1625 Source
->state
=AL_INITIAL
;
1626 Source
->inuse
=AL_FALSE
;
1628 Source
->position_fraction
=0;
1629 Source
->BuffersProcessed
= 0;
1630 ALBufferListItem
= Source
->queue
;
1631 while (ALBufferListItem
!= NULL
)
1633 ALBufferListItem
->bufferstate
= PENDING
;
1634 ALBufferListItem
= ALBufferListItem
->next
;
1637 Source
->ulBufferID
= Source
->queue
->buffer
;
1639 Source
->lOffset
= 0;
1645 // sources is a NULL pointer
1646 alSetError(AL_INVALID_VALUE
);
1649 ProcessContext(Context
);
1654 alSetError(AL_INVALID_OPERATION
);
1661 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1663 ALCcontext
*Context
;
1666 ALbufferlistitem
*ALBufferList
;
1667 ALbufferlistitem
*ALBufferListStart
;
1672 ALboolean bBuffersValid
= AL_TRUE
;
1677 Context
=alcGetCurrentContext();
1680 SuspendContext(Context
);
1685 // Check that all buffers are valid or zero and that the source is valid
1687 // Check that this is a valid source
1688 if (alIsSource(source
))
1690 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1692 // Check that this is not a STATIC Source
1693 if (ALSource
->lSourceType
!= AL_STATIC
)
1698 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1699 ALBufferList
= ALSource
->queue
;
1700 while (ALBufferList
)
1702 if (ALBufferList
->buffer
)
1704 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1705 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1708 ALBufferList
= ALBufferList
->next
;
1711 for (i
= 0; i
< n
; i
++)
1713 if (alIsBuffer(buffers
[i
]))
1717 if ((iFrequency
== -1) && (iFormat
== -1))
1719 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1720 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1724 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1725 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1727 alSetError(AL_INVALID_OPERATION
);
1728 bBuffersValid
= AL_FALSE
;
1736 alSetError(AL_INVALID_NAME
);
1737 bBuffersValid
= AL_FALSE
;
1744 // Change Source Type
1745 ALSource
->lSourceType
= AL_STREAMING
;
1747 // All buffers are valid - so add them to the list
1748 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1749 ALBufferListStart
->buffer
= buffers
[0];
1750 ALBufferListStart
->bufferstate
= PENDING
;
1751 ALBufferListStart
->flag
= 0;
1752 ALBufferListStart
->next
= NULL
;
1755 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1759 DataSize
+= BufferSize
;
1761 // Increment reference counter for buffer
1763 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1765 ALBufferList
= ALBufferListStart
;
1767 for (i
= 1; i
< n
; i
++)
1769 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1770 ALBufferList
->next
->buffer
= buffers
[i
];
1771 ALBufferList
->next
->bufferstate
= PENDING
;
1772 ALBufferList
->next
->flag
= 0;
1773 ALBufferList
->next
->next
= NULL
;
1776 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1780 DataSize
+= BufferSize
;
1782 // Increment reference counter for buffer
1784 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1786 ALBufferList
= ALBufferList
->next
;
1789 if (ALSource
->queue
== NULL
)
1791 ALSource
->queue
= ALBufferListStart
;
1792 // Update Current Buffer
1793 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1797 // Find end of queue
1798 ALBufferList
= ALSource
->queue
;
1799 while (ALBufferList
->next
!= NULL
)
1801 ALBufferList
= ALBufferList
->next
;
1804 ALBufferList
->next
= ALBufferListStart
;
1807 // Update number of buffers in queue
1808 ALSource
->BuffersInQueue
+= n
;
1813 // Invalid Source Type (can't queue on a Static Source)
1814 alSetError(AL_INVALID_OPERATION
);
1819 // Invalid Source Name
1820 alSetError(AL_INVALID_NAME
);
1823 ProcessContext(Context
);
1828 alSetError(AL_INVALID_OPERATION
);
1835 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1836 // an array of buffer IDs that are to be filled with the names of the buffers removed
1837 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1839 ALCcontext
*Context
;
1842 ALbufferlistitem
*ALBufferList
;
1846 ALboolean bBuffersProcessed
;
1853 bBuffersProcessed
= AL_TRUE
;
1855 Context
=alcGetCurrentContext();
1858 SuspendContext(Context
);
1860 if (alIsSource(source
))
1862 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1864 // Check that all 'n' buffers have been processed
1865 ALBufferList
= ALSource
->queue
;
1866 for (i
= 0; i
< n
; i
++)
1868 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1870 ALBufferList
= ALBufferList
->next
;
1874 bBuffersProcessed
= AL_FALSE
;
1879 // If all 'n' buffers have been processed, remove them from the queue
1880 if (bBuffersProcessed
)
1882 for (i
= 0; i
< n
; i
++)
1884 ALBufferList
= ALSource
->queue
;
1886 ALSource
->queue
= ALBufferList
->next
;
1887 // Record name of buffer
1888 buffers
[i
] = ALBufferList
->buffer
;
1889 // Decrement buffer reference counter
1890 if (ALBufferList
->buffer
)
1891 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1892 // Record size of buffer
1893 if (ALBufferList
->buffer
)
1894 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1898 DataSize
+= BufferSize
;
1899 // Release memory for buffer list item
1901 ALSource
->BuffersInQueue
--;
1902 ALSource
->BuffersProcessed
--;
1905 if (ALSource
->state
!= AL_PLAYING
)
1907 if (ALSource
->queue
)
1908 BufferID
= ALSource
->queue
->buffer
;
1912 ALSource
->ulBufferID
= BufferID
;
1915 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1917 ALSource
->BuffersPlayed
= 0;
1918 ALSource
->BufferPosition
= 0;
1921 ALSource
->BuffersPlayed
-= n
;
1925 // Some buffers can't be unqueue because they have not been processed
1926 alSetError(AL_INVALID_VALUE
);
1931 // Invalid Source Name
1932 alSetError(AL_INVALID_NAME
);
1935 ProcessContext(Context
);
1940 alSetError(AL_INVALID_OPERATION
);
1947 static ALvoid
InitSourceParams(ALsource
*pSource
)
1949 pSource
->flInnerAngle
= 360.0f
;
1950 pSource
->flOuterAngle
= 360.0f
;
1951 pSource
->flPitch
= 1.0f
;
1952 pSource
->vPosition
[0] = 0.0f
;
1953 pSource
->vPosition
[1] = 0.0f
;
1954 pSource
->vPosition
[2] = 0.0f
;
1955 pSource
->vOrientation
[0] = 0.0f
;
1956 pSource
->vOrientation
[1] = 0.0f
;
1957 pSource
->vOrientation
[2] = 0.0f
;
1958 pSource
->vVelocity
[0] = 0.0f
;
1959 pSource
->vVelocity
[1] = 0.0f
;
1960 pSource
->vVelocity
[2] = 0.0f
;
1961 pSource
->flRefDistance
= 1.0f
;
1962 pSource
->flMaxDistance
= FLT_MAX
;
1963 pSource
->flRollOffFactor
= 1.0f
;
1964 pSource
->bLooping
= AL_FALSE
;
1965 pSource
->flGain
= 1.0f
;
1966 pSource
->flMinGain
= 0.0f
;
1967 pSource
->flMaxGain
= 1.0f
;
1968 pSource
->flOuterGain
= 0.0f
;
1969 pSource
->OuterGainHF
= 1.0f
;
1971 pSource
->DryGainHFAuto
= AL_TRUE
;
1972 pSource
->WetGainAuto
= AL_TRUE
;
1973 pSource
->WetGainHFAuto
= AL_TRUE
;
1974 pSource
->AirAbsorptionFactor
= 0.0f
;
1975 pSource
->RoomRolloffFactor
= 0.0f
;
1977 pSource
->state
= AL_INITIAL
;
1978 pSource
->lSourceType
= AL_UNDETERMINED
;
1980 pSource
->ulBufferID
= 0;
1987 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1988 The offset is relative to the start of the queue (not the start of the current buffer)
1990 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
1992 ALbufferlistitem
*pBufferList
;
1994 ALfloat flBufferFreq
;
1995 ALint lBytesPlayed
, lChannels
;
1996 ALenum eOriginalFormat
;
1997 ALboolean bReturn
= AL_TRUE
;
1998 ALint lTotalBufferDataSize
;
2000 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
2002 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
2003 // Get Current Buffer Size and frequency (in milliseconds)
2004 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
2005 eOriginalFormat
= pBuffer
->eOriginalFormat
;
2006 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2008 // Get Current BytesPlayed
2009 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2010 // Add byte length of any processed buffers in the queue
2011 pBufferList
= pSource
->queue
;
2012 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2014 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2015 pBufferList
= pBufferList
->next
;
2018 lTotalBufferDataSize
= 0;
2019 pBufferList
= pSource
->queue
;
2022 if (pBufferList
->buffer
)
2023 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2024 pBufferList
= pBufferList
->next
;
2027 if (pSource
->bLooping
)
2029 if (lBytesPlayed
< 0)
2032 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
2036 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2037 if(lBytesPlayed
< 0)
2039 if(lBytesPlayed
> lTotalBufferDataSize
)
2040 lBytesPlayed
= lTotalBufferDataSize
;
2046 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
2048 case AL_SAMPLE_OFFSET
:
2049 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
2051 case AL_BYTE_OFFSET
:
2052 // Take into account the original format of the Buffer
2053 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2054 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2056 // Compression rate of the ADPCM supported is 3.6111 to 1
2057 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
2058 // Round down to nearest ADPCM block
2059 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
2061 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2063 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 2);
2065 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2067 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2069 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2071 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2073 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2075 *pflOffset
= (ALfloat
)(lBytesPlayed
<< 1);
2079 *pflOffset
= (ALfloat
)lBytesPlayed
;
2096 Apply a playback offset to the Source. This function will update the queue (to correctly
2097 mark buffers as 'pending' or 'processed' depending upon the new offset.
2099 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2101 ALbufferlistitem
*pBufferList
;
2103 ALint lBufferSize
, lTotalBufferSize
;
2106 // Get true byte offset
2107 lByteOffset
= GetByteOffset(pSource
);
2109 // If this is a valid offset apply it
2110 if (lByteOffset
!= -1)
2112 // Sort out the queue (pending and processed states)
2113 pBufferList
= pSource
->queue
;
2114 lTotalBufferSize
= 0;
2115 pSource
->BuffersPlayed
= 0;
2116 pSource
->BuffersProcessed
= 0;
2119 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2120 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2122 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2124 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2125 // update the state to PROCESSED
2126 pSource
->BuffersPlayed
++;
2128 if (!pSource
->bLooping
)
2130 pBufferList
->bufferstate
= PROCESSED
;
2131 pSource
->BuffersProcessed
++;
2134 else if (lTotalBufferSize
<= lByteOffset
)
2136 // Offset is within this buffer
2137 pBufferList
->bufferstate
= PENDING
;
2139 // Set Current Buffer ID
2140 pSource
->ulBufferID
= pBufferList
->buffer
;
2142 // Set current position in this buffer
2143 pSource
->BufferPosition
= lByteOffset
- lTotalBufferSize
;
2145 // Set Total Bytes Played to Offset
2146 pSource
->lBytesPlayed
= lByteOffset
;
2148 // SW Mixer Positions are in Samples
2149 pSource
->position
= pSource
->BufferPosition
/
2150 aluBytesFromFormat(pBuffer
->format
) /
2151 aluChannelsFromFormat(pBuffer
->format
);
2155 // Offset is before this buffer, so mark as pending
2156 pBufferList
->bufferstate
= PENDING
;
2159 // Increment the TotalBufferSize
2160 lTotalBufferSize
+= lBufferSize
;
2162 // Move on to next buffer in the Queue
2163 pBufferList
= pBufferList
->next
;
2169 alSetError(AL_INVALID_VALUE
);
2173 pSource
->lOffset
= 0;
2180 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2181 offset supplied by the application). This takes into account the fact that the buffer format
2182 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2184 static ALint
GetByteOffset(ALsource
*pSource
)
2186 ALbuffer
*pBuffer
= NULL
;
2187 ALbufferlistitem
*pBufferList
;
2188 ALfloat flBufferFreq
;
2190 ALint lByteOffset
= -1;
2191 ALint lTotalBufferDataSize
;
2193 // Find the first non-NULL Buffer in the Queue
2194 pBufferList
= pSource
->queue
;
2197 if (pBufferList
->buffer
)
2199 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2202 pBufferList
= pBufferList
->next
;
2207 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2208 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2210 // Determine the ByteOffset (and ensure it is block aligned)
2211 switch (pSource
->lOffsetType
)
2213 case AL_BYTE_OFFSET
:
2214 // Take into consideration the original format
2215 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2216 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2218 // Round down to nearest ADPCM block
2219 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2220 // Multiply by compression rate
2221 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2222 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2224 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2226 lByteOffset
= pSource
->lOffset
* 4;
2227 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2229 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2231 lByteOffset
= pSource
->lOffset
* 2;
2232 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2234 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2236 lByteOffset
= pSource
->lOffset
* 2;
2237 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2239 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2241 lByteOffset
= pSource
->lOffset
/ 2;
2242 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2246 lByteOffset
= pSource
->lOffset
;
2247 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2251 case AL_SAMPLE_OFFSET
:
2252 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2256 // Note - lOffset is internally stored as Milliseconds
2257 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2258 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2262 lTotalBufferDataSize
= 0;
2263 pBufferList
= pSource
->queue
;
2266 if (pBufferList
->buffer
)
2267 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2268 pBufferList
= pBufferList
->next
;
2271 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2272 if (lByteOffset
>= lTotalBufferDataSize
)
2280 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2283 if(Context
->SourceCount
> 0)
2284 AL_PRINT("destroycontext: %d Source(s) NOT deleted\n", Context
->SourceCount
);
2287 while(Context
->Source
)
2289 ALsource
*temp
= Context
->Source
;
2290 Context
->Source
= Context
->Source
->next
;
2292 // Release source structure
2293 memset(temp
, 0, sizeof(ALsource
));
2296 Context
->SourceCount
= 0;