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
);
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
;
930 case AL_DOPPLER_FACTOR
:
931 *pflValue
= pSource
->DopplerFactor
;
935 alSetError(AL_INVALID_ENUM
);
940 alSetError(AL_INVALID_NAME
);
943 alSetError(AL_INVALID_VALUE
);
945 ProcessContext(pContext
);
948 alSetError(AL_INVALID_OPERATION
);
954 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
956 ALCcontext
*pContext
;
959 pContext
= alcGetCurrentContext();
962 SuspendContext(pContext
);
964 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
966 if (alIsSource(source
))
968 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
973 *pflValue1
= pSource
->vPosition
[0];
974 *pflValue2
= pSource
->vPosition
[1];
975 *pflValue3
= pSource
->vPosition
[2];
979 *pflValue1
= pSource
->vVelocity
[0];
980 *pflValue2
= pSource
->vVelocity
[1];
981 *pflValue3
= pSource
->vVelocity
[2];
985 *pflValue1
= pSource
->vOrientation
[0];
986 *pflValue2
= pSource
->vOrientation
[1];
987 *pflValue3
= pSource
->vOrientation
[2];
991 alSetError(AL_INVALID_ENUM
);
996 alSetError(AL_INVALID_NAME
);
999 alSetError(AL_INVALID_VALUE
);
1001 ProcessContext(pContext
);
1004 alSetError(AL_INVALID_OPERATION
);
1010 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1012 ALCcontext
*pContext
;
1015 pContext
= alcGetCurrentContext();
1018 SuspendContext(pContext
);
1022 if (alIsSource(source
))
1024 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1032 case AL_MAX_DISTANCE
:
1033 case AL_ROLLOFF_FACTOR
:
1034 case AL_DOPPLER_FACTOR
:
1035 case AL_CONE_OUTER_GAIN
:
1037 case AL_SAMPLE_OFFSET
:
1038 case AL_BYTE_OFFSET
:
1039 case AL_CONE_INNER_ANGLE
:
1040 case AL_CONE_OUTER_ANGLE
:
1041 case AL_REFERENCE_DISTANCE
:
1042 case AL_CONE_OUTER_GAINHF
:
1043 case AL_AIR_ABSORPTION_FACTOR
:
1044 case AL_ROOM_ROLLOFF_FACTOR
:
1045 alGetSourcef(source
, eParam
, pflValues
);
1049 pflValues
[0] = pSource
->vPosition
[0];
1050 pflValues
[1] = pSource
->vPosition
[1];
1051 pflValues
[2] = pSource
->vPosition
[2];
1055 pflValues
[0] = pSource
->vVelocity
[0];
1056 pflValues
[1] = pSource
->vVelocity
[1];
1057 pflValues
[2] = pSource
->vVelocity
[2];
1061 pflValues
[0] = pSource
->vOrientation
[0];
1062 pflValues
[1] = pSource
->vOrientation
[1];
1063 pflValues
[2] = pSource
->vOrientation
[2];
1067 alSetError(AL_INVALID_ENUM
);
1072 alSetError(AL_INVALID_NAME
);
1075 alSetError(AL_INVALID_VALUE
);
1077 ProcessContext(pContext
);
1080 alSetError(AL_INVALID_OPERATION
);
1086 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1088 ALCcontext
*pContext
;
1092 pContext
= alcGetCurrentContext();
1095 SuspendContext(pContext
);
1099 if (alIsSource(source
))
1101 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1105 case AL_MAX_DISTANCE
:
1106 *plValue
= (ALint
)pSource
->flMaxDistance
;
1109 case AL_ROLLOFF_FACTOR
:
1110 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1113 case AL_REFERENCE_DISTANCE
:
1114 *plValue
= (ALint
)pSource
->flRefDistance
;
1117 case AL_SOURCE_RELATIVE
:
1118 *plValue
= pSource
->bHeadRelative
;
1121 case AL_CONE_INNER_ANGLE
:
1122 *plValue
= (ALint
)pSource
->flInnerAngle
;
1125 case AL_CONE_OUTER_ANGLE
:
1126 *plValue
= (ALint
)pSource
->flOuterAngle
;
1130 *plValue
= pSource
->bLooping
;
1134 *plValue
= pSource
->ulBufferID
;
1137 case AL_SOURCE_STATE
:
1138 *plValue
= pSource
->state
;
1141 case AL_BUFFERS_QUEUED
:
1142 *plValue
= pSource
->BuffersInQueue
;
1145 case AL_BUFFERS_PROCESSED
:
1146 if(pSource
->bLooping
)
1148 /* Buffers on a looping source are in a perpetual state
1149 * of PENDING, so don't report any as PROCESSED */
1153 *plValue
= pSource
->BuffersProcessed
;
1156 case AL_SOURCE_TYPE
:
1157 *plValue
= pSource
->lSourceType
;
1161 case AL_SAMPLE_OFFSET
:
1162 case AL_BYTE_OFFSET
:
1163 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
1164 *plValue
= (ALint
)flOffset
;
1166 alSetError(AL_INVALID_OPERATION
);
1169 case AL_DIRECT_FILTER
:
1170 *plValue
= pSource
->DirectFilter
.filter
;
1173 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1174 *plValue
= pSource
->DryGainHFAuto
;
1177 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1178 *plValue
= pSource
->WetGainAuto
;
1181 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1182 *plValue
= pSource
->WetGainHFAuto
;
1185 case AL_DOPPLER_FACTOR
:
1186 *plValue
= (ALint
)pSource
->DopplerFactor
;
1190 alSetError(AL_INVALID_ENUM
);
1195 alSetError(AL_INVALID_NAME
);
1198 alSetError(AL_INVALID_VALUE
);
1200 ProcessContext(pContext
);
1203 alSetError(AL_INVALID_OPERATION
);
1209 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1211 ALCcontext
*pContext
;
1214 pContext
= alcGetCurrentContext();
1217 SuspendContext(pContext
);
1219 if ((plValue1
) && (plValue2
) && (plValue3
))
1221 if (alIsSource(source
))
1223 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1228 *plValue1
= (ALint
)pSource
->vPosition
[0];
1229 *plValue2
= (ALint
)pSource
->vPosition
[1];
1230 *plValue3
= (ALint
)pSource
->vPosition
[2];
1234 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1235 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1236 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1240 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1241 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1242 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1246 alSetError(AL_INVALID_ENUM
);
1251 alSetError(AL_INVALID_NAME
);
1254 alSetError(AL_INVALID_VALUE
);
1256 ProcessContext(pContext
);
1259 alSetError(AL_INVALID_OPERATION
);
1265 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1267 ALCcontext
*pContext
;
1270 pContext
= alcGetCurrentContext();
1273 SuspendContext(pContext
);
1277 if (alIsSource(source
))
1279 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1283 case AL_SOURCE_RELATIVE
:
1284 case AL_CONE_INNER_ANGLE
:
1285 case AL_CONE_OUTER_ANGLE
:
1288 case AL_SOURCE_STATE
:
1289 case AL_BUFFERS_QUEUED
:
1290 case AL_BUFFERS_PROCESSED
:
1292 case AL_SAMPLE_OFFSET
:
1293 case AL_BYTE_OFFSET
:
1294 case AL_MAX_DISTANCE
:
1295 case AL_ROLLOFF_FACTOR
:
1296 case AL_DOPPLER_FACTOR
:
1297 case AL_REFERENCE_DISTANCE
:
1298 case AL_SOURCE_TYPE
:
1299 case AL_DIRECT_FILTER
:
1300 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1301 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1302 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1303 alGetSourcei(source
, eParam
, plValues
);
1307 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1308 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1309 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1313 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1314 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1315 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1319 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1320 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1321 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1325 alSetError(AL_INVALID_ENUM
);
1330 alSetError(AL_INVALID_NAME
);
1333 alSetError(AL_INVALID_VALUE
);
1335 ProcessContext(pContext
);
1338 alSetError(AL_INVALID_OPERATION
);
1344 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1346 alSourcePlayv(1, &source
);
1350 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1352 ALCcontext
*pContext
;
1354 ALbufferlistitem
*ALBufferList
;
1355 ALboolean bSourcesValid
= AL_TRUE
;
1359 pContext
= alcGetCurrentContext();
1362 SuspendContext(pContext
);
1366 // Check that all the Sources are valid
1367 for (i
= 0; i
< n
; i
++)
1369 if (!alIsSource(pSourceList
[i
]))
1371 alSetError(AL_INVALID_NAME
);
1372 bSourcesValid
= AL_FALSE
;
1379 for (i
= 0; i
< n
; i
++)
1381 // Assume Source won't need to play
1384 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1386 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1387 ALBufferList
= pSource
->queue
;
1388 while (ALBufferList
)
1390 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1395 ALBufferList
= ALBufferList
->next
;
1400 if (pSource
->state
!= AL_PAUSED
)
1402 pSource
->state
= AL_PLAYING
;
1403 pSource
->inuse
= AL_TRUE
;
1404 pSource
->play
= AL_TRUE
;
1405 pSource
->position
= 0;
1406 pSource
->position_fraction
= 0;
1407 pSource
->BuffersProcessed
= 0;
1408 pSource
->BuffersPlayed
= 0;
1409 pSource
->BufferPosition
= 0;
1410 pSource
->lBytesPlayed
= 0;
1412 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1414 // Make sure all the Buffers in the queue are marked as PENDING
1415 ALBufferList
= pSource
->queue
;
1416 while (ALBufferList
)
1418 ALBufferList
->bufferstate
= PENDING
;
1419 ALBufferList
= ALBufferList
->next
;
1424 pSource
->state
= AL_PLAYING
;
1425 pSource
->inuse
= AL_TRUE
;
1426 pSource
->play
= AL_TRUE
;
1429 // Check if an Offset has been set
1430 if (pSource
->lOffset
)
1431 ApplyOffset(pSource
, AL_FALSE
);
1435 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1436 ALBufferList
= pSource
->queue
;
1437 while (ALBufferList
)
1439 ALBufferList
->bufferstate
= PROCESSED
;
1440 ALBufferList
= ALBufferList
->next
;
1443 pSource
->BuffersPlayed
= pSource
->BuffersProcessed
= pSource
->BuffersInQueue
;
1450 // sources is a NULL pointer
1451 alSetError(AL_INVALID_VALUE
);
1454 ProcessContext(pContext
);
1459 alSetError(AL_INVALID_OPERATION
);
1465 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1467 alSourcePausev(1, &source
);
1471 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1473 ALCcontext
*Context
;
1476 ALboolean bSourcesValid
= AL_TRUE
;
1478 Context
=alcGetCurrentContext();
1481 SuspendContext(Context
);
1485 // Check all the Sources are valid
1488 if (!alIsSource(sources
[i
]))
1490 alSetError(AL_INVALID_NAME
);
1491 bSourcesValid
= AL_FALSE
;
1500 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1501 if (Source
->state
==AL_PLAYING
)
1503 Source
->state
=AL_PAUSED
;
1504 Source
->inuse
=AL_FALSE
;
1511 // sources is a NULL pointer
1512 alSetError(AL_INVALID_VALUE
);
1515 ProcessContext(Context
);
1520 alSetError(AL_INVALID_OPERATION
);
1526 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1528 alSourceStopv(1, &source
);
1532 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1534 ALCcontext
*Context
;
1537 ALbufferlistitem
*ALBufferListItem
;
1538 ALboolean bSourcesValid
= AL_TRUE
;
1540 Context
=alcGetCurrentContext();
1543 SuspendContext(Context
);
1547 // Check all the Sources are valid
1550 if (!alIsSource(sources
[i
]))
1552 alSetError(AL_INVALID_NAME
);
1553 bSourcesValid
= AL_FALSE
;
1562 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1563 if (Source
->state
!=AL_INITIAL
)
1565 Source
->state
=AL_STOPPED
;
1566 Source
->inuse
=AL_FALSE
;
1567 Source
->BuffersPlayed
= Source
->BuffersProcessed
= Source
->BuffersInQueue
;
1568 ALBufferListItem
= Source
->queue
;
1569 while (ALBufferListItem
!= NULL
)
1571 ALBufferListItem
->bufferstate
= PROCESSED
;
1572 ALBufferListItem
= ALBufferListItem
->next
;
1575 Source
->lOffset
= 0;
1581 // sources is a NULL pointer
1582 alSetError(AL_INVALID_VALUE
);
1585 ProcessContext(Context
);
1590 alSetError(AL_INVALID_OPERATION
);
1596 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1598 alSourceRewindv(1, &source
);
1602 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1604 ALCcontext
*Context
;
1607 ALbufferlistitem
*ALBufferListItem
;
1608 ALboolean bSourcesValid
= AL_TRUE
;
1610 Context
=alcGetCurrentContext();
1613 SuspendContext(Context
);
1617 // Check all the Sources are valid
1620 if (!alIsSource(sources
[i
]))
1622 alSetError(AL_INVALID_NAME
);
1623 bSourcesValid
= AL_FALSE
;
1632 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1633 if (Source
->state
!=AL_INITIAL
)
1635 Source
->state
=AL_INITIAL
;
1636 Source
->inuse
=AL_FALSE
;
1638 Source
->position_fraction
=0;
1639 Source
->BuffersProcessed
= 0;
1640 ALBufferListItem
= Source
->queue
;
1641 while (ALBufferListItem
!= NULL
)
1643 ALBufferListItem
->bufferstate
= PENDING
;
1644 ALBufferListItem
= ALBufferListItem
->next
;
1647 Source
->ulBufferID
= Source
->queue
->buffer
;
1649 Source
->lOffset
= 0;
1655 // sources is a NULL pointer
1656 alSetError(AL_INVALID_VALUE
);
1659 ProcessContext(Context
);
1664 alSetError(AL_INVALID_OPERATION
);
1671 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1673 ALCcontext
*Context
;
1676 ALbufferlistitem
*ALBufferList
;
1677 ALbufferlistitem
*ALBufferListStart
;
1682 ALboolean bBuffersValid
= AL_TRUE
;
1687 Context
=alcGetCurrentContext();
1690 SuspendContext(Context
);
1695 // Check that all buffers are valid or zero and that the source is valid
1697 // Check that this is a valid source
1698 if (alIsSource(source
))
1700 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1702 // Check that this is not a STATIC Source
1703 if (ALSource
->lSourceType
!= AL_STATIC
)
1708 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1709 ALBufferList
= ALSource
->queue
;
1710 while (ALBufferList
)
1712 if (ALBufferList
->buffer
)
1714 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1715 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1718 ALBufferList
= ALBufferList
->next
;
1721 for (i
= 0; i
< n
; i
++)
1723 if (alIsBuffer(buffers
[i
]))
1727 if ((iFrequency
== -1) && (iFormat
== -1))
1729 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1730 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1734 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1735 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1737 alSetError(AL_INVALID_OPERATION
);
1738 bBuffersValid
= AL_FALSE
;
1746 alSetError(AL_INVALID_NAME
);
1747 bBuffersValid
= AL_FALSE
;
1754 // Change Source Type
1755 ALSource
->lSourceType
= AL_STREAMING
;
1757 // All buffers are valid - so add them to the list
1758 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1759 ALBufferListStart
->buffer
= buffers
[0];
1760 ALBufferListStart
->bufferstate
= PENDING
;
1761 ALBufferListStart
->flag
= 0;
1762 ALBufferListStart
->next
= NULL
;
1765 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1769 DataSize
+= BufferSize
;
1771 // Increment reference counter for buffer
1773 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1775 ALBufferList
= ALBufferListStart
;
1777 for (i
= 1; i
< n
; i
++)
1779 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1780 ALBufferList
->next
->buffer
= buffers
[i
];
1781 ALBufferList
->next
->bufferstate
= PENDING
;
1782 ALBufferList
->next
->flag
= 0;
1783 ALBufferList
->next
->next
= NULL
;
1786 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1790 DataSize
+= BufferSize
;
1792 // Increment reference counter for buffer
1794 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1796 ALBufferList
= ALBufferList
->next
;
1799 if (ALSource
->queue
== NULL
)
1801 ALSource
->queue
= ALBufferListStart
;
1802 // Update Current Buffer
1803 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1807 // Find end of queue
1808 ALBufferList
= ALSource
->queue
;
1809 while (ALBufferList
->next
!= NULL
)
1811 ALBufferList
= ALBufferList
->next
;
1814 ALBufferList
->next
= ALBufferListStart
;
1817 // Update number of buffers in queue
1818 ALSource
->BuffersInQueue
+= n
;
1823 // Invalid Source Type (can't queue on a Static Source)
1824 alSetError(AL_INVALID_OPERATION
);
1829 // Invalid Source Name
1830 alSetError(AL_INVALID_NAME
);
1833 ProcessContext(Context
);
1838 alSetError(AL_INVALID_OPERATION
);
1845 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1846 // an array of buffer IDs that are to be filled with the names of the buffers removed
1847 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1849 ALCcontext
*Context
;
1852 ALbufferlistitem
*ALBufferList
;
1856 ALboolean bBuffersProcessed
;
1863 bBuffersProcessed
= AL_TRUE
;
1865 Context
=alcGetCurrentContext();
1868 SuspendContext(Context
);
1870 if (alIsSource(source
))
1872 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1874 // Check that all 'n' buffers have been processed
1875 ALBufferList
= ALSource
->queue
;
1876 for (i
= 0; i
< n
; i
++)
1878 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1880 ALBufferList
= ALBufferList
->next
;
1884 bBuffersProcessed
= AL_FALSE
;
1889 // If all 'n' buffers have been processed, remove them from the queue
1890 if (bBuffersProcessed
)
1892 for (i
= 0; i
< n
; i
++)
1894 ALBufferList
= ALSource
->queue
;
1896 ALSource
->queue
= ALBufferList
->next
;
1897 // Record name of buffer
1898 buffers
[i
] = ALBufferList
->buffer
;
1899 // Decrement buffer reference counter
1900 if (ALBufferList
->buffer
)
1901 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1902 // Record size of buffer
1903 if (ALBufferList
->buffer
)
1904 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1908 DataSize
+= BufferSize
;
1909 // Release memory for buffer list item
1911 ALSource
->BuffersInQueue
--;
1912 ALSource
->BuffersProcessed
--;
1915 if (ALSource
->state
!= AL_PLAYING
)
1917 if (ALSource
->queue
)
1918 BufferID
= ALSource
->queue
->buffer
;
1922 ALSource
->ulBufferID
= BufferID
;
1925 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1927 ALSource
->BuffersPlayed
= 0;
1928 ALSource
->BufferPosition
= 0;
1931 ALSource
->BuffersPlayed
-= n
;
1935 // Some buffers can't be unqueue because they have not been processed
1936 alSetError(AL_INVALID_VALUE
);
1941 // Invalid Source Name
1942 alSetError(AL_INVALID_NAME
);
1945 ProcessContext(Context
);
1950 alSetError(AL_INVALID_OPERATION
);
1957 static ALvoid
InitSourceParams(ALsource
*pSource
)
1959 pSource
->flInnerAngle
= 360.0f
;
1960 pSource
->flOuterAngle
= 360.0f
;
1961 pSource
->flPitch
= 1.0f
;
1962 pSource
->vPosition
[0] = 0.0f
;
1963 pSource
->vPosition
[1] = 0.0f
;
1964 pSource
->vPosition
[2] = 0.0f
;
1965 pSource
->vOrientation
[0] = 0.0f
;
1966 pSource
->vOrientation
[1] = 0.0f
;
1967 pSource
->vOrientation
[2] = 0.0f
;
1968 pSource
->vVelocity
[0] = 0.0f
;
1969 pSource
->vVelocity
[1] = 0.0f
;
1970 pSource
->vVelocity
[2] = 0.0f
;
1971 pSource
->flRefDistance
= 1.0f
;
1972 pSource
->flMaxDistance
= FLT_MAX
;
1973 pSource
->flRollOffFactor
= 1.0f
;
1974 pSource
->bLooping
= AL_FALSE
;
1975 pSource
->flGain
= 1.0f
;
1976 pSource
->flMinGain
= 0.0f
;
1977 pSource
->flMaxGain
= 1.0f
;
1978 pSource
->flOuterGain
= 0.0f
;
1979 pSource
->OuterGainHF
= 1.0f
;
1981 pSource
->DryGainHFAuto
= AL_TRUE
;
1982 pSource
->WetGainAuto
= AL_TRUE
;
1983 pSource
->WetGainHFAuto
= AL_TRUE
;
1984 pSource
->AirAbsorptionFactor
= 0.0f
;
1985 pSource
->RoomRolloffFactor
= 0.0f
;
1986 pSource
->DopplerFactor
= 1.0f
;
1988 pSource
->state
= AL_INITIAL
;
1989 pSource
->lSourceType
= AL_UNDETERMINED
;
1991 pSource
->ulBufferID
= 0;
1998 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1999 The offset is relative to the start of the queue (not the start of the current buffer)
2001 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
2003 ALbufferlistitem
*pBufferList
;
2005 ALfloat flBufferFreq
;
2006 ALint lBytesPlayed
, lChannels
;
2007 ALenum eOriginalFormat
;
2008 ALboolean bReturn
= AL_TRUE
;
2009 ALint lTotalBufferDataSize
;
2011 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
2013 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
2014 // Get Current Buffer Size and frequency (in milliseconds)
2015 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
2016 eOriginalFormat
= pBuffer
->eOriginalFormat
;
2017 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2019 // Get Current BytesPlayed
2020 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2021 // Add byte length of any processed buffers in the queue
2022 pBufferList
= pSource
->queue
;
2023 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2025 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2026 pBufferList
= pBufferList
->next
;
2029 lTotalBufferDataSize
= 0;
2030 pBufferList
= pSource
->queue
;
2033 if (pBufferList
->buffer
)
2034 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2035 pBufferList
= pBufferList
->next
;
2038 if (pSource
->bLooping
)
2040 if (lBytesPlayed
< 0)
2043 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
2047 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2048 if(lBytesPlayed
< 0)
2050 if(lBytesPlayed
> lTotalBufferDataSize
)
2051 lBytesPlayed
= lTotalBufferDataSize
;
2057 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
2059 case AL_SAMPLE_OFFSET
:
2060 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
2062 case AL_BYTE_OFFSET
:
2063 // Take into account the original format of the Buffer
2064 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2065 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2067 // Compression rate of the ADPCM supported is 3.6111 to 1
2068 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
2069 // Round down to nearest ADPCM block
2070 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
2072 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2074 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 2);
2076 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2078 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2080 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2082 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2084 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2086 *pflOffset
= (ALfloat
)(lBytesPlayed
<< 1);
2090 *pflOffset
= (ALfloat
)lBytesPlayed
;
2107 Apply a playback offset to the Source. This function will update the queue (to correctly
2108 mark buffers as 'pending' or 'processed' depending upon the new offset.
2110 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2112 ALbufferlistitem
*pBufferList
;
2114 ALint lBufferSize
, lTotalBufferSize
;
2117 // Get true byte offset
2118 lByteOffset
= GetByteOffset(pSource
);
2120 // If this is a valid offset apply it
2121 if (lByteOffset
!= -1)
2123 // Sort out the queue (pending and processed states)
2124 pBufferList
= pSource
->queue
;
2125 lTotalBufferSize
= 0;
2126 pSource
->BuffersPlayed
= 0;
2127 pSource
->BuffersProcessed
= 0;
2130 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2131 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2133 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2135 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2136 // update the state to PROCESSED
2137 pSource
->BuffersPlayed
++;
2139 if (!pSource
->bLooping
)
2141 pBufferList
->bufferstate
= PROCESSED
;
2142 pSource
->BuffersProcessed
++;
2145 else if (lTotalBufferSize
<= lByteOffset
)
2147 // Offset is within this buffer
2148 pBufferList
->bufferstate
= PENDING
;
2150 // Set Current Buffer ID
2151 pSource
->ulBufferID
= pBufferList
->buffer
;
2153 // Set current position in this buffer
2154 pSource
->BufferPosition
= lByteOffset
- lTotalBufferSize
;
2156 // Set Total Bytes Played to Offset
2157 pSource
->lBytesPlayed
= lByteOffset
;
2159 // SW Mixer Positions are in Samples
2160 pSource
->position
= pSource
->BufferPosition
/
2161 aluBytesFromFormat(pBuffer
->format
) /
2162 aluChannelsFromFormat(pBuffer
->format
);
2166 // Offset is before this buffer, so mark as pending
2167 pBufferList
->bufferstate
= PENDING
;
2170 // Increment the TotalBufferSize
2171 lTotalBufferSize
+= lBufferSize
;
2173 // Move on to next buffer in the Queue
2174 pBufferList
= pBufferList
->next
;
2180 alSetError(AL_INVALID_VALUE
);
2184 pSource
->lOffset
= 0;
2191 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2192 offset supplied by the application). This takes into account the fact that the buffer format
2193 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2195 static ALint
GetByteOffset(ALsource
*pSource
)
2197 ALbuffer
*pBuffer
= NULL
;
2198 ALbufferlistitem
*pBufferList
;
2199 ALfloat flBufferFreq
;
2201 ALint lByteOffset
= -1;
2202 ALint lTotalBufferDataSize
;
2204 // Find the first non-NULL Buffer in the Queue
2205 pBufferList
= pSource
->queue
;
2208 if (pBufferList
->buffer
)
2210 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2213 pBufferList
= pBufferList
->next
;
2218 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2219 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2221 // Determine the ByteOffset (and ensure it is block aligned)
2222 switch (pSource
->lOffsetType
)
2224 case AL_BYTE_OFFSET
:
2225 // Take into consideration the original format
2226 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2227 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2229 // Round down to nearest ADPCM block
2230 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2231 // Multiply by compression rate
2232 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2233 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2235 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2237 lByteOffset
= pSource
->lOffset
* 4;
2238 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2240 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2242 lByteOffset
= pSource
->lOffset
* 2;
2243 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2245 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2247 lByteOffset
= pSource
->lOffset
* 2;
2248 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2250 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2252 lByteOffset
= pSource
->lOffset
/ 2;
2253 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2257 lByteOffset
= pSource
->lOffset
;
2258 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2262 case AL_SAMPLE_OFFSET
:
2263 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2267 // Note - lOffset is internally stored as Milliseconds
2268 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2269 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2273 lTotalBufferDataSize
= 0;
2274 pBufferList
= pSource
->queue
;
2277 if (pBufferList
->buffer
)
2278 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2279 pBufferList
= pBufferList
->next
;
2282 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2283 if (lByteOffset
>= lTotalBufferDataSize
)
2291 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2294 if(Context
->SourceCount
> 0)
2295 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", Context
->SourceCount
);
2298 while(Context
->Source
)
2300 ALsource
*temp
= Context
->Source
;
2301 Context
->Source
= Context
->Source
->next
;
2303 // Release source structure
2304 ALTHUNK_REMOVEENTRY(temp
->source
);
2305 memset(temp
, 0, sizeof(ALsource
));
2308 Context
->SourceCount
= 0;