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
30 static ALvoid
InitSourceParams(ALsource
*pSource
);
31 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
);
32 static ALvoid
ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
);
33 static ALint
GetByteOffset(ALsource
*pSource
);
35 ALAPI ALvoid ALAPIENTRY
alGenSources(ALsizei n
,ALuint
*sources
)
41 Context
= alcGetCurrentContext();
44 SuspendContext(Context
);
48 Device
= alcGetContextsDevice(Context
);
52 // Check that enough memory has been allocted in the 'sources' array for n Sources
53 if (!IsBadWritePtr((void*)sources
, n
* sizeof(ALuint
)))
55 // Check that the requested number of sources can be generated
56 if ((Context
->SourceCount
+ n
) <= Device
->MaxNoOfSources
)
58 ALsource
**list
= &Context
->Source
;
60 list
= &(*list
)->next
;
62 // Add additional sources to the list (Source->next points to the location for the next Source structure)
65 *list
= calloc(1, sizeof(ALsource
));
68 sources
[i
]=(ALuint
)ALTHUNK_ADDENTRY(*list
);
69 (*list
)->source
= sources
[i
];
71 InitSourceParams(*list
);
72 Context
->SourceCount
++;
75 list
= &(*list
)->next
;
79 // If we didn't create all the Sources, we must have run out or memory
81 alSetError(AL_OUT_OF_MEMORY
);
85 // Not enough resources to create the Sources
86 alSetError(AL_INVALID_VALUE
);
92 alSetError(AL_INVALID_VALUE
);
97 // No Device created, or attached to Context
98 alSetError(AL_INVALID_OPERATION
);
102 ProcessContext(Context
);
107 alSetError(AL_INVALID_OPERATION
);
114 ALAPI ALvoid ALAPIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
121 ALbufferlistitem
*ALBufferList
;
122 ALboolean bSourcesValid
= AL_TRUE
;
124 Context
= alcGetCurrentContext();
127 SuspendContext(Context
);
131 Device
= alcGetContextsDevice(Context
);
135 if ((ALuint
)n
<= Context
->SourceCount
)
137 // Check that all Sources are valid (and can therefore be deleted)
138 for (i
= 0; i
< n
; i
++)
140 if (!alIsSource(sources
[i
]))
142 alSetError(AL_INVALID_NAME
);
143 bSourcesValid
= AL_FALSE
;
150 // All Sources are valid, and can be deleted
151 for (i
= 0; i
< n
; i
++)
153 // Recheck that the Source is valid, because there could be duplicated Source names
154 if (alIsSource(sources
[i
]))
156 ALSource
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
157 alSourceStop((ALuint
)ALSource
->source
);
159 // For each buffer in the source's queue, decrement its reference counter and remove it
160 while (ALSource
->queue
!= NULL
)
162 ALBufferList
= ALSource
->queue
;
163 // Decrement buffer's reference counter
164 if (ALBufferList
->buffer
!= 0)
165 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
166 // Update queue to point to next element in list
167 ALSource
->queue
= ALBufferList
->next
;
168 // Release memory allocated for buffer list item
172 // Decrement Source count
173 Context
->SourceCount
--;
175 // Remove Source from list of Sources
176 list
= &Context
->Source
;
177 while(*list
&& *list
!= ALSource
)
178 list
= &(*list
)->next
;
181 *list
= (*list
)->next
;
182 ALTHUNK_REMOVEENTRY(ALSource
->source
);
184 memset(ALSource
,0,sizeof(ALsource
));
193 // Trying to delete more Sources than have been generated
194 alSetError(AL_INVALID_NAME
);
199 // No Device created, or attached to Context
200 alSetError(AL_INVALID_OPERATION
);
204 alSetError(AL_INVALID_VALUE
);
206 ProcessContext(Context
);
211 alSetError(AL_INVALID_OPERATION
);
218 ALAPI ALboolean ALAPIENTRY
alIsSource(ALuint source
)
220 ALboolean result
=AL_FALSE
;
224 Context
=alcGetCurrentContext();
227 SuspendContext(Context
);
229 // To determine if this is a valid Source name, look through the list of generated Sources
230 Source
= Context
->Source
;
233 if (Source
== (ALsource
*)ALTHUNK_LOOKUPENTRY(source
))
239 Source
= Source
->next
;
242 ProcessContext(Context
);
247 alSetError(AL_INVALID_OPERATION
);
254 ALAPI ALvoid ALAPIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
256 ALCcontext
*pContext
;
259 pContext
= alcGetCurrentContext();
262 SuspendContext(pContext
);
264 if (alIsSource(source
))
266 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
273 pSource
->flPitch
= flValue
;
274 if(pSource
->flPitch
< 0.001f
)
275 pSource
->flPitch
= 0.001f
;
278 alSetError(AL_INVALID_VALUE
);
281 case AL_CONE_INNER_ANGLE
:
282 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
283 pSource
->flInnerAngle
= flValue
;
285 alSetError(AL_INVALID_VALUE
);
288 case AL_CONE_OUTER_ANGLE
:
289 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
290 pSource
->flOuterAngle
= flValue
;
292 alSetError(AL_INVALID_VALUE
);
297 pSource
->flGain
= flValue
;
299 alSetError(AL_INVALID_VALUE
);
302 case AL_MAX_DISTANCE
:
304 pSource
->flMaxDistance
= flValue
;
306 alSetError(AL_INVALID_VALUE
);
309 case AL_ROLLOFF_FACTOR
:
311 pSource
->flRollOffFactor
= flValue
;
313 alSetError(AL_INVALID_VALUE
);
316 case AL_REFERENCE_DISTANCE
:
318 pSource
->flRefDistance
= flValue
;
320 alSetError(AL_INVALID_VALUE
);
324 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
325 pSource
->flMinGain
= flValue
;
327 alSetError(AL_INVALID_VALUE
);
331 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
332 pSource
->flMaxGain
= flValue
;
334 alSetError(AL_INVALID_VALUE
);
337 case AL_CONE_OUTER_GAIN
:
338 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
339 pSource
->flOuterGain
= flValue
;
341 alSetError(AL_INVALID_VALUE
);
344 case AL_CONE_OUTER_GAINHF
:
345 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
346 pSource
->OuterGainHF
= flValue
;
348 alSetError(AL_INVALID_VALUE
);
351 case AL_AIR_ABSORPTION_FACTOR
:
352 if (flValue
>= 0.0f
&& flValue
<= 10.0f
)
353 pSource
->AirAbsorptionFactor
= flValue
;
355 alSetError(AL_INVALID_VALUE
);
358 case AL_ROOM_ROLLOFF_FACTOR
:
359 if (flValue
>= 0.0f
&& flValue
<= 1.0f
)
360 pSource
->RoomRolloffFactor
= flValue
;
362 alSetError(AL_INVALID_VALUE
);
366 case AL_SAMPLE_OFFSET
:
370 pSource
->lOffsetType
= eParam
;
372 // Store Offset (convert Seconds into Milliseconds)
373 if (eParam
== AL_SEC_OFFSET
)
374 pSource
->lOffset
= (ALint
)(flValue
* 1000.0f
);
376 pSource
->lOffset
= (ALint
)flValue
;
378 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
379 ApplyOffset(pSource
, AL_TRUE
);
382 alSetError(AL_INVALID_VALUE
);
386 alSetError(AL_INVALID_ENUM
);
392 // Invalid Source Name
393 alSetError(AL_INVALID_NAME
);
396 ProcessContext(pContext
);
401 alSetError(AL_INVALID_OPERATION
);
408 ALAPI ALvoid ALAPIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
410 ALCcontext
*pContext
;
413 pContext
= alcGetCurrentContext();
416 SuspendContext(pContext
);
418 if (alIsSource(source
))
420 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
424 pSource
->vPosition
[0] = flValue1
;
425 pSource
->vPosition
[1] = flValue2
;
426 pSource
->vPosition
[2] = flValue3
;
430 pSource
->vVelocity
[0] = flValue1
;
431 pSource
->vVelocity
[1] = flValue2
;
432 pSource
->vVelocity
[2] = flValue3
;
436 pSource
->vOrientation
[0] = flValue1
;
437 pSource
->vOrientation
[1] = flValue2
;
438 pSource
->vOrientation
[2] = flValue3
;
442 alSetError(AL_INVALID_ENUM
);
447 alSetError(AL_INVALID_NAME
);
449 ProcessContext(pContext
);
453 alSetError(AL_INVALID_OPERATION
);
460 ALAPI ALvoid ALAPIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
462 ALCcontext
*pContext
;
464 pContext
= alcGetCurrentContext();
467 SuspendContext(pContext
);
471 if (alIsSource(source
))
476 case AL_CONE_INNER_ANGLE
:
477 case AL_CONE_OUTER_ANGLE
:
479 case AL_MAX_DISTANCE
:
480 case AL_ROLLOFF_FACTOR
:
481 case AL_REFERENCE_DISTANCE
:
484 case AL_CONE_OUTER_GAIN
:
485 case AL_CONE_OUTER_GAINHF
:
487 case AL_SAMPLE_OFFSET
:
489 case AL_AIR_ABSORPTION_FACTOR
:
490 case AL_ROOM_ROLLOFF_FACTOR
:
491 alSourcef(source
, eParam
, pflValues
[0]);
497 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
501 alSetError(AL_INVALID_ENUM
);
506 alSetError(AL_INVALID_NAME
);
509 alSetError(AL_INVALID_VALUE
);
511 ProcessContext(pContext
);
514 alSetError(AL_INVALID_OPERATION
);
520 ALAPI ALvoid ALAPIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
522 ALCcontext
*pContext
;
524 ALbufferlistitem
*pALBufferListItem
;
529 pContext
= alcGetCurrentContext();
532 SuspendContext(pContext
);
534 if (alIsSource(source
))
536 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
540 case AL_MAX_DISTANCE
:
541 case AL_ROLLOFF_FACTOR
:
542 case AL_REFERENCE_DISTANCE
:
543 alSourcef(source
, eParam
, (ALfloat
)lValue
);
546 case AL_SOURCE_RELATIVE
:
547 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
548 pSource
->bHeadRelative
= (ALboolean
)lValue
;
550 alSetError(AL_INVALID_VALUE
);
553 case AL_CONE_INNER_ANGLE
:
554 if ((lValue
>= 0) && (lValue
<= 360))
555 pSource
->flInnerAngle
= (float)lValue
;
557 alSetError(AL_INVALID_VALUE
);
560 case AL_CONE_OUTER_ANGLE
:
561 if ((lValue
>= 0) && (lValue
<= 360))
562 pSource
->flOuterAngle
= (float)lValue
;
564 alSetError(AL_INVALID_VALUE
);
568 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
569 pSource
->bLooping
= (ALboolean
)lValue
;
571 alSetError(AL_INVALID_VALUE
);
575 if ((pSource
->state
== AL_STOPPED
) || (pSource
->state
== AL_INITIAL
))
577 if (alIsBuffer(lValue
))
579 // Remove all elements in the queue
580 while (pSource
->queue
!= NULL
)
582 pALBufferListItem
= pSource
->queue
;
583 pSource
->queue
= pALBufferListItem
->next
;
584 // Decrement reference counter for buffer
585 if (pALBufferListItem
->buffer
)
586 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
)))->refcount
--;
587 // Record size of buffer
588 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
))->size
;
589 DataSize
+= BufferSize
;
590 // Increment the number of buffers removed from queue
592 // Release memory for buffer list item
593 free(pALBufferListItem
);
594 // Decrement the number of buffers in the queue
595 pSource
->BuffersInQueue
--;
598 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
601 // Source is now in STATIC mode
602 pSource
->lSourceType
= AL_STATIC
;
604 // Add the selected buffer to the queue
605 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
606 pALBufferListItem
->buffer
= lValue
;
607 pALBufferListItem
->bufferstate
= PENDING
;
608 pALBufferListItem
->flag
= 0;
609 pALBufferListItem
->next
= NULL
;
611 pSource
->queue
= pALBufferListItem
;
612 pSource
->BuffersInQueue
= 1;
614 DataSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(lValue
))->size
;
616 // Increment reference counter for buffer
617 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(lValue
)))->refcount
++;
621 // Source is now in UNDETERMINED mode
622 pSource
->lSourceType
= AL_UNDETERMINED
;
625 // Set Buffers Processed
626 pSource
->BuffersProcessed
= 0;
628 // Update AL_BUFFER parameter
629 pSource
->ulBufferID
= lValue
;
632 alSetError(AL_INVALID_VALUE
);
635 alSetError(AL_INVALID_OPERATION
);
638 case AL_SOURCE_STATE
:
640 alSetError(AL_INVALID_OPERATION
);
644 case AL_SAMPLE_OFFSET
:
648 pSource
->lOffsetType
= eParam
;
650 // Store Offset (convert Seconds into Milliseconds)
651 if (eParam
== AL_SEC_OFFSET
)
652 pSource
->lOffset
= lValue
* 1000;
654 pSource
->lOffset
= lValue
;
656 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
657 ApplyOffset(pSource
, AL_TRUE
);
660 alSetError(AL_INVALID_VALUE
);
663 case AL_DIRECT_FILTER
:
664 if(alIsFilter(lValue
))
666 ALfilter
*filter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue
);
669 pSource
->DirectFilter
.type
= AL_FILTER_NULL
;
670 pSource
->DirectFilter
.filter
= 0;
673 memcpy(&pSource
->DirectFilter
, filter
, sizeof(*filter
));
676 alSetError(AL_INVALID_VALUE
);
679 case AL_DIRECT_FILTER_GAINHF_AUTO
:
680 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
681 pSource
->DryGainHFAuto
= lValue
;
683 alSetError(AL_INVALID_VALUE
);
686 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
687 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
688 pSource
->WetGainAuto
= lValue
;
690 alSetError(AL_INVALID_VALUE
);
693 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
694 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
695 pSource
->WetGainHFAuto
= lValue
;
697 alSetError(AL_INVALID_VALUE
);
701 alSetError(AL_INVALID_ENUM
);
706 alSetError(AL_INVALID_NAME
);
708 ProcessContext(pContext
);
711 alSetError(AL_INVALID_OPERATION
);
717 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
719 ALCcontext
*pContext
;
721 pContext
= alcGetCurrentContext();
724 SuspendContext(pContext
);
726 if (alIsSource(source
))
728 ALsource
*pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
735 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
738 case AL_AUXILIARY_SEND_FILTER
:
739 if(lValue2
>= 0 && lValue2
< MAX_SENDS
&&
740 (alIsAuxiliaryEffectSlot(lValue1
) || lValue1
== 0) &&
743 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(lValue1
);
744 ALfilter
*ALFilter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue3
);
749 pSource
->Send
[lValue2
].Slot
.effectslot
= 0;
752 memcpy(&pSource
->Send
[lValue2
].Slot
, ALEffectSlot
, sizeof(*ALEffectSlot
));
757 pSource
->Send
[lValue2
].WetFilter
.type
= 0;
758 pSource
->Send
[lValue2
].WetFilter
.filter
= 0;
761 memcpy(&pSource
->Send
[lValue2
].WetFilter
, ALFilter
, sizeof(*ALFilter
));
764 alSetError(AL_INVALID_VALUE
);
768 alSetError(AL_INVALID_ENUM
);
773 alSetError(AL_INVALID_NAME
);
775 ProcessContext(pContext
);
778 alSetError(AL_INVALID_OPERATION
);
784 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
786 ALCcontext
*pContext
;
788 pContext
= alcGetCurrentContext();
791 SuspendContext(pContext
);
795 if (alIsSource(source
))
799 case AL_SOURCE_RELATIVE
:
800 case AL_CONE_INNER_ANGLE
:
801 case AL_CONE_OUTER_ANGLE
:
804 case AL_SOURCE_STATE
:
806 case AL_SAMPLE_OFFSET
:
808 case AL_MAX_DISTANCE
:
809 case AL_ROLLOFF_FACTOR
:
810 case AL_REFERENCE_DISTANCE
:
811 case AL_DIRECT_FILTER
:
812 case AL_DIRECT_FILTER_GAINHF_AUTO
:
813 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
814 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
815 alSourcei(source
, eParam
, plValues
[0]);
821 case AL_AUXILIARY_SEND_FILTER
:
822 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
826 alSetError(AL_INVALID_ENUM
);
831 alSetError(AL_INVALID_NAME
);
834 alSetError(AL_INVALID_VALUE
);
836 ProcessContext(pContext
);
839 alSetError(AL_INVALID_OPERATION
);
845 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
847 ALCcontext
*pContext
;
851 pContext
= alcGetCurrentContext();
854 SuspendContext(pContext
);
858 if (alIsSource(source
))
860 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
865 *pflValue
= pSource
->flPitch
;
869 *pflValue
= pSource
->flGain
;
873 *pflValue
= pSource
->flMinGain
;
877 *pflValue
= pSource
->flMaxGain
;
880 case AL_MAX_DISTANCE
:
881 *pflValue
= pSource
->flMaxDistance
;
884 case AL_ROLLOFF_FACTOR
:
885 *pflValue
= pSource
->flRollOffFactor
;
888 case AL_CONE_OUTER_GAIN
:
889 *pflValue
= pSource
->flOuterGain
;
892 case AL_CONE_OUTER_GAINHF
:
893 *pflValue
= pSource
->OuterGainHF
;
897 case AL_SAMPLE_OFFSET
:
899 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
900 *pflValue
= flOffset
;
902 alSetError(AL_INVALID_OPERATION
);
905 case AL_CONE_INNER_ANGLE
:
906 *pflValue
= pSource
->flInnerAngle
;
909 case AL_CONE_OUTER_ANGLE
:
910 *pflValue
= pSource
->flOuterAngle
;
913 case AL_REFERENCE_DISTANCE
:
914 *pflValue
= pSource
->flRefDistance
;
917 case AL_AIR_ABSORPTION_FACTOR
:
918 *pflValue
= pSource
->AirAbsorptionFactor
;
921 case AL_ROOM_ROLLOFF_FACTOR
:
922 *pflValue
= pSource
->RoomRolloffFactor
;
926 alSetError(AL_INVALID_ENUM
);
931 alSetError(AL_INVALID_NAME
);
934 alSetError(AL_INVALID_VALUE
);
936 ProcessContext(pContext
);
939 alSetError(AL_INVALID_OPERATION
);
945 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
947 ALCcontext
*pContext
;
950 pContext
= alcGetCurrentContext();
953 SuspendContext(pContext
);
955 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
957 if (alIsSource(source
))
959 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
964 *pflValue1
= pSource
->vPosition
[0];
965 *pflValue2
= pSource
->vPosition
[1];
966 *pflValue3
= pSource
->vPosition
[2];
970 *pflValue1
= pSource
->vVelocity
[0];
971 *pflValue2
= pSource
->vVelocity
[1];
972 *pflValue3
= pSource
->vVelocity
[2];
976 *pflValue1
= pSource
->vOrientation
[0];
977 *pflValue2
= pSource
->vOrientation
[1];
978 *pflValue3
= pSource
->vOrientation
[2];
982 alSetError(AL_INVALID_ENUM
);
987 alSetError(AL_INVALID_NAME
);
990 alSetError(AL_INVALID_VALUE
);
992 ProcessContext(pContext
);
995 alSetError(AL_INVALID_OPERATION
);
1001 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1003 ALCcontext
*pContext
;
1006 pContext
= alcGetCurrentContext();
1009 SuspendContext(pContext
);
1013 if (alIsSource(source
))
1015 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1023 case AL_MAX_DISTANCE
:
1024 case AL_ROLLOFF_FACTOR
:
1025 case AL_CONE_OUTER_GAIN
:
1027 case AL_SAMPLE_OFFSET
:
1028 case AL_BYTE_OFFSET
:
1029 case AL_CONE_INNER_ANGLE
:
1030 case AL_CONE_OUTER_ANGLE
:
1031 case AL_REFERENCE_DISTANCE
:
1032 case AL_CONE_OUTER_GAINHF
:
1033 case AL_AIR_ABSORPTION_FACTOR
:
1034 case AL_ROOM_ROLLOFF_FACTOR
:
1035 alGetSourcef(source
, eParam
, pflValues
);
1039 pflValues
[0] = pSource
->vPosition
[0];
1040 pflValues
[1] = pSource
->vPosition
[1];
1041 pflValues
[2] = pSource
->vPosition
[2];
1045 pflValues
[0] = pSource
->vVelocity
[0];
1046 pflValues
[1] = pSource
->vVelocity
[1];
1047 pflValues
[2] = pSource
->vVelocity
[2];
1051 pflValues
[0] = pSource
->vOrientation
[0];
1052 pflValues
[1] = pSource
->vOrientation
[1];
1053 pflValues
[2] = pSource
->vOrientation
[2];
1057 alSetError(AL_INVALID_ENUM
);
1062 alSetError(AL_INVALID_NAME
);
1065 alSetError(AL_INVALID_VALUE
);
1067 ProcessContext(pContext
);
1070 alSetError(AL_INVALID_OPERATION
);
1076 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1078 ALCcontext
*pContext
;
1082 pContext
= alcGetCurrentContext();
1085 SuspendContext(pContext
);
1089 if (alIsSource(source
))
1091 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1095 case AL_MAX_DISTANCE
:
1096 *plValue
= (ALint
)pSource
->flMaxDistance
;
1099 case AL_ROLLOFF_FACTOR
:
1100 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1103 case AL_REFERENCE_DISTANCE
:
1104 *plValue
= (ALint
)pSource
->flRefDistance
;
1107 case AL_SOURCE_RELATIVE
:
1108 *plValue
= pSource
->bHeadRelative
;
1111 case AL_CONE_INNER_ANGLE
:
1112 *plValue
= (ALint
)pSource
->flInnerAngle
;
1115 case AL_CONE_OUTER_ANGLE
:
1116 *plValue
= (ALint
)pSource
->flOuterAngle
;
1120 *plValue
= pSource
->bLooping
;
1124 *plValue
= pSource
->ulBufferID
;
1127 case AL_SOURCE_STATE
:
1128 *plValue
= pSource
->state
;
1131 case AL_BUFFERS_QUEUED
:
1132 *plValue
= pSource
->BuffersInQueue
;
1135 case AL_BUFFERS_PROCESSED
:
1136 if(pSource
->bLooping
)
1138 /* Buffers on a looping source are in a perpetual state
1139 * of PENDING, so don't report any as PROCESSED */
1143 *plValue
= pSource
->BuffersProcessed
;
1146 case AL_SOURCE_TYPE
:
1147 *plValue
= pSource
->lSourceType
;
1151 case AL_SAMPLE_OFFSET
:
1152 case AL_BYTE_OFFSET
:
1153 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
1154 *plValue
= (ALint
)flOffset
;
1156 alSetError(AL_INVALID_OPERATION
);
1159 case AL_DIRECT_FILTER
:
1160 *plValue
= pSource
->DirectFilter
.filter
;
1163 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1164 *plValue
= pSource
->DryGainHFAuto
;
1167 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1168 *plValue
= pSource
->WetGainAuto
;
1171 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1172 *plValue
= pSource
->WetGainHFAuto
;
1176 alSetError(AL_INVALID_ENUM
);
1181 alSetError(AL_INVALID_NAME
);
1184 alSetError(AL_INVALID_VALUE
);
1186 ProcessContext(pContext
);
1189 alSetError(AL_INVALID_OPERATION
);
1195 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1197 ALCcontext
*pContext
;
1200 pContext
= alcGetCurrentContext();
1203 SuspendContext(pContext
);
1205 if ((plValue1
) && (plValue2
) && (plValue3
))
1207 if (alIsSource(source
))
1209 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1214 *plValue1
= (ALint
)pSource
->vPosition
[0];
1215 *plValue2
= (ALint
)pSource
->vPosition
[1];
1216 *plValue3
= (ALint
)pSource
->vPosition
[2];
1220 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1221 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1222 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1226 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1227 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1228 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1232 alSetError(AL_INVALID_ENUM
);
1237 alSetError(AL_INVALID_NAME
);
1240 alSetError(AL_INVALID_VALUE
);
1242 ProcessContext(pContext
);
1245 alSetError(AL_INVALID_OPERATION
);
1251 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1253 ALCcontext
*pContext
;
1256 pContext
= alcGetCurrentContext();
1259 SuspendContext(pContext
);
1263 if (alIsSource(source
))
1265 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1269 case AL_SOURCE_RELATIVE
:
1270 case AL_CONE_INNER_ANGLE
:
1271 case AL_CONE_OUTER_ANGLE
:
1274 case AL_SOURCE_STATE
:
1275 case AL_BUFFERS_QUEUED
:
1276 case AL_BUFFERS_PROCESSED
:
1278 case AL_SAMPLE_OFFSET
:
1279 case AL_BYTE_OFFSET
:
1280 case AL_MAX_DISTANCE
:
1281 case AL_ROLLOFF_FACTOR
:
1282 case AL_REFERENCE_DISTANCE
:
1283 case AL_SOURCE_TYPE
:
1284 case AL_DIRECT_FILTER
:
1285 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1286 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1287 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1288 alGetSourcei(source
, eParam
, plValues
);
1292 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1293 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1294 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1298 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1299 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1300 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1304 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1305 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1306 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1310 alSetError(AL_INVALID_ENUM
);
1315 alSetError(AL_INVALID_NAME
);
1318 alSetError(AL_INVALID_VALUE
);
1320 ProcessContext(pContext
);
1323 alSetError(AL_INVALID_OPERATION
);
1329 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1331 alSourcePlayv(1, &source
);
1335 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1337 ALCcontext
*pContext
;
1339 ALbufferlistitem
*ALBufferList
;
1340 ALboolean bSourcesValid
= AL_TRUE
;
1344 pContext
= alcGetCurrentContext();
1347 SuspendContext(pContext
);
1351 // Check that all the Sources are valid
1352 for (i
= 0; i
< n
; i
++)
1354 if (!alIsSource(pSourceList
[i
]))
1356 alSetError(AL_INVALID_NAME
);
1357 bSourcesValid
= AL_FALSE
;
1364 for (i
= 0; i
< n
; i
++)
1366 // Assume Source won't need to play
1369 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1371 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1372 ALBufferList
= pSource
->queue
;
1373 while (ALBufferList
)
1375 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1380 ALBufferList
= ALBufferList
->next
;
1385 if (pSource
->state
!= AL_PAUSED
)
1387 pSource
->state
= AL_PLAYING
;
1388 pSource
->inuse
= AL_TRUE
;
1389 pSource
->play
= AL_TRUE
;
1390 pSource
->position
= 0;
1391 pSource
->position_fraction
= 0;
1392 pSource
->BuffersProcessed
= 0;
1393 pSource
->BuffersPlayed
= 0;
1394 pSource
->BufferPosition
= 0;
1395 pSource
->lBytesPlayed
= 0;
1397 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1399 // Make sure all the Buffers in the queue are marked as PENDING
1400 ALBufferList
= pSource
->queue
;
1401 while (ALBufferList
)
1403 ALBufferList
->bufferstate
= PENDING
;
1404 ALBufferList
= ALBufferList
->next
;
1409 pSource
->state
= AL_PLAYING
;
1410 pSource
->inuse
= AL_TRUE
;
1411 pSource
->play
= AL_TRUE
;
1414 // Check if an Offset has been set
1415 if (pSource
->lOffset
)
1416 ApplyOffset(pSource
, AL_FALSE
);
1420 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1421 ALBufferList
= pSource
->queue
;
1422 while (ALBufferList
)
1424 ALBufferList
->bufferstate
= PROCESSED
;
1425 ALBufferList
= ALBufferList
->next
;
1428 pSource
->BuffersPlayed
= pSource
->BuffersProcessed
= pSource
->BuffersInQueue
;
1435 // sources is a NULL pointer
1436 alSetError(AL_INVALID_VALUE
);
1439 ProcessContext(pContext
);
1444 alSetError(AL_INVALID_OPERATION
);
1450 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1452 alSourcePausev(1, &source
);
1456 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1458 ALCcontext
*Context
;
1461 ALboolean bSourcesValid
= AL_TRUE
;
1463 Context
=alcGetCurrentContext();
1466 SuspendContext(Context
);
1470 // Check all the Sources are valid
1473 if (!alIsSource(sources
[i
]))
1475 alSetError(AL_INVALID_NAME
);
1476 bSourcesValid
= AL_FALSE
;
1485 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1486 if (Source
->state
==AL_PLAYING
)
1488 Source
->state
=AL_PAUSED
;
1489 Source
->inuse
=AL_FALSE
;
1496 // sources is a NULL pointer
1497 alSetError(AL_INVALID_VALUE
);
1500 ProcessContext(Context
);
1505 alSetError(AL_INVALID_OPERATION
);
1511 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1513 alSourceStopv(1, &source
);
1517 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1519 ALCcontext
*Context
;
1522 ALbufferlistitem
*ALBufferListItem
;
1523 ALboolean bSourcesValid
= AL_TRUE
;
1525 Context
=alcGetCurrentContext();
1528 SuspendContext(Context
);
1532 // Check all the Sources are valid
1535 if (!alIsSource(sources
[i
]))
1537 alSetError(AL_INVALID_NAME
);
1538 bSourcesValid
= AL_FALSE
;
1547 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1548 if (Source
->state
!=AL_INITIAL
)
1550 Source
->state
=AL_STOPPED
;
1551 Source
->inuse
=AL_FALSE
;
1552 Source
->BuffersPlayed
= Source
->BuffersProcessed
= Source
->BuffersInQueue
;
1553 ALBufferListItem
= Source
->queue
;
1554 while (ALBufferListItem
!= NULL
)
1556 ALBufferListItem
->bufferstate
= PROCESSED
;
1557 ALBufferListItem
= ALBufferListItem
->next
;
1560 Source
->lOffset
= 0;
1566 // sources is a NULL pointer
1567 alSetError(AL_INVALID_VALUE
);
1570 ProcessContext(Context
);
1575 alSetError(AL_INVALID_OPERATION
);
1581 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1583 alSourceRewindv(1, &source
);
1587 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1589 ALCcontext
*Context
;
1592 ALbufferlistitem
*ALBufferListItem
;
1593 ALboolean bSourcesValid
= AL_TRUE
;
1595 Context
=alcGetCurrentContext();
1598 SuspendContext(Context
);
1602 // Check all the Sources are valid
1605 if (!alIsSource(sources
[i
]))
1607 alSetError(AL_INVALID_NAME
);
1608 bSourcesValid
= AL_FALSE
;
1617 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1618 if (Source
->state
!=AL_INITIAL
)
1620 Source
->state
=AL_INITIAL
;
1621 Source
->inuse
=AL_FALSE
;
1623 Source
->position_fraction
=0;
1624 Source
->BuffersProcessed
= 0;
1625 ALBufferListItem
= Source
->queue
;
1626 while (ALBufferListItem
!= NULL
)
1628 ALBufferListItem
->bufferstate
= PENDING
;
1629 ALBufferListItem
= ALBufferListItem
->next
;
1632 Source
->ulBufferID
= Source
->queue
->buffer
;
1634 Source
->lOffset
= 0;
1640 // sources is a NULL pointer
1641 alSetError(AL_INVALID_VALUE
);
1644 ProcessContext(Context
);
1649 alSetError(AL_INVALID_OPERATION
);
1656 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1658 ALCcontext
*Context
;
1661 ALbufferlistitem
*ALBufferList
;
1662 ALbufferlistitem
*ALBufferListStart
;
1667 ALboolean bBuffersValid
= AL_TRUE
;
1672 Context
=alcGetCurrentContext();
1675 SuspendContext(Context
);
1680 // Check that all buffers are valid or zero and that the source is valid
1682 // Check that this is a valid source
1683 if (alIsSource(source
))
1685 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1687 // Check that this is not a STATIC Source
1688 if (ALSource
->lSourceType
!= AL_STATIC
)
1693 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1694 ALBufferList
= ALSource
->queue
;
1695 while (ALBufferList
)
1697 if (ALBufferList
->buffer
)
1699 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1700 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1703 ALBufferList
= ALBufferList
->next
;
1706 for (i
= 0; i
< n
; i
++)
1708 if (alIsBuffer(buffers
[i
]))
1712 if ((iFrequency
== -1) && (iFormat
== -1))
1714 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1715 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1719 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1720 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1722 alSetError(AL_INVALID_OPERATION
);
1723 bBuffersValid
= AL_FALSE
;
1731 alSetError(AL_INVALID_NAME
);
1732 bBuffersValid
= AL_FALSE
;
1739 // Change Source Type
1740 ALSource
->lSourceType
= AL_STREAMING
;
1742 // All buffers are valid - so add them to the list
1743 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1744 ALBufferListStart
->buffer
= buffers
[0];
1745 ALBufferListStart
->bufferstate
= PENDING
;
1746 ALBufferListStart
->flag
= 0;
1747 ALBufferListStart
->next
= NULL
;
1750 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1754 DataSize
+= BufferSize
;
1756 // Increment reference counter for buffer
1758 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1760 ALBufferList
= ALBufferListStart
;
1762 for (i
= 1; i
< n
; i
++)
1764 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1765 ALBufferList
->next
->buffer
= buffers
[i
];
1766 ALBufferList
->next
->bufferstate
= PENDING
;
1767 ALBufferList
->next
->flag
= 0;
1768 ALBufferList
->next
->next
= NULL
;
1771 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1775 DataSize
+= BufferSize
;
1777 // Increment reference counter for buffer
1779 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1781 ALBufferList
= ALBufferList
->next
;
1784 if (ALSource
->queue
== NULL
)
1786 ALSource
->queue
= ALBufferListStart
;
1787 // Update Current Buffer
1788 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1792 // Find end of queue
1793 ALBufferList
= ALSource
->queue
;
1794 while (ALBufferList
->next
!= NULL
)
1796 ALBufferList
= ALBufferList
->next
;
1799 ALBufferList
->next
= ALBufferListStart
;
1802 // Update number of buffers in queue
1803 ALSource
->BuffersInQueue
+= n
;
1808 // Invalid Source Type (can't queue on a Static Source)
1809 alSetError(AL_INVALID_OPERATION
);
1814 // Invalid Source Name
1815 alSetError(AL_INVALID_NAME
);
1818 ProcessContext(Context
);
1823 alSetError(AL_INVALID_OPERATION
);
1830 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1831 // an array of buffer IDs that are to be filled with the names of the buffers removed
1832 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1834 ALCcontext
*Context
;
1837 ALbufferlistitem
*ALBufferList
;
1841 ALboolean bBuffersProcessed
;
1848 bBuffersProcessed
= AL_TRUE
;
1850 Context
=alcGetCurrentContext();
1853 SuspendContext(Context
);
1855 if (alIsSource(source
))
1857 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1859 // Check that all 'n' buffers have been processed
1860 ALBufferList
= ALSource
->queue
;
1861 for (i
= 0; i
< n
; i
++)
1863 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1865 ALBufferList
= ALBufferList
->next
;
1869 bBuffersProcessed
= AL_FALSE
;
1874 // If all 'n' buffers have been processed, remove them from the queue
1875 if (bBuffersProcessed
)
1877 for (i
= 0; i
< n
; i
++)
1879 ALBufferList
= ALSource
->queue
;
1881 ALSource
->queue
= ALBufferList
->next
;
1882 // Record name of buffer
1883 buffers
[i
] = ALBufferList
->buffer
;
1884 // Decrement buffer reference counter
1885 if (ALBufferList
->buffer
)
1886 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1887 // Record size of buffer
1888 if (ALBufferList
->buffer
)
1889 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1893 DataSize
+= BufferSize
;
1894 // Release memory for buffer list item
1896 ALSource
->BuffersInQueue
--;
1897 ALSource
->BuffersProcessed
--;
1900 if (ALSource
->state
!= AL_PLAYING
)
1902 if (ALSource
->queue
)
1903 BufferID
= ALSource
->queue
->buffer
;
1907 ALSource
->ulBufferID
= BufferID
;
1910 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1912 ALSource
->BuffersPlayed
= 0;
1913 ALSource
->BufferPosition
= 0;
1916 ALSource
->BuffersPlayed
-= n
;
1920 // Some buffers can't be unqueue because they have not been processed
1921 alSetError(AL_INVALID_VALUE
);
1926 // Invalid Source Name
1927 alSetError(AL_INVALID_NAME
);
1930 ProcessContext(Context
);
1935 alSetError(AL_INVALID_OPERATION
);
1942 static ALvoid
InitSourceParams(ALsource
*pSource
)
1944 pSource
->flInnerAngle
= 360.0f
;
1945 pSource
->flOuterAngle
= 360.0f
;
1946 pSource
->flPitch
= 1.0f
;
1947 pSource
->vPosition
[0] = 0.0f
;
1948 pSource
->vPosition
[1] = 0.0f
;
1949 pSource
->vPosition
[2] = 0.0f
;
1950 pSource
->vOrientation
[0] = 0.0f
;
1951 pSource
->vOrientation
[1] = 0.0f
;
1952 pSource
->vOrientation
[2] = 0.0f
;
1953 pSource
->vVelocity
[0] = 0.0f
;
1954 pSource
->vVelocity
[1] = 0.0f
;
1955 pSource
->vVelocity
[2] = 0.0f
;
1956 pSource
->flRefDistance
= 1.0f
;
1957 pSource
->flMaxDistance
= FLT_MAX
;
1958 pSource
->flRollOffFactor
= 1.0f
;
1959 pSource
->bLooping
= AL_FALSE
;
1960 pSource
->flGain
= 1.0f
;
1961 pSource
->flMinGain
= 0.0f
;
1962 pSource
->flMaxGain
= 1.0f
;
1963 pSource
->flOuterGain
= 0.0f
;
1965 pSource
->DryGainHFAuto
= AL_TRUE
;
1966 pSource
->WetGainAuto
= AL_TRUE
;
1967 pSource
->WetGainHFAuto
= AL_TRUE
;
1968 pSource
->AirAbsorptionFactor
= 0.0f
;
1970 pSource
->state
= AL_INITIAL
;
1971 pSource
->lSourceType
= AL_UNDETERMINED
;
1973 pSource
->ulBufferID
= 0;
1980 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1981 The offset is relative to the start of the queue (not the start of the current buffer)
1983 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
1985 ALbufferlistitem
*pBufferList
;
1986 ALfloat flBufferFreq
;
1987 ALint lBytesPlayed
, lChannels
;
1988 ALenum eOriginalFormat
;
1989 ALboolean bReturn
= AL_TRUE
;
1990 ALint lTotalBufferDataSize
;
1992 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
1994 // Get Current Buffer Size and frequency (in milliseconds)
1995 flBufferFreq
= (ALfloat
)(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
))->frequency
);
1996 eOriginalFormat
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
))->eOriginalFormat
;
1997 lChannels
= ((((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
))->format
== AL_FORMAT_MONO16
)?1:2);
1999 // Get Current BytesPlayed
2000 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2001 // Add byte length of any processed buffers in the queue
2002 pBufferList
= pSource
->queue
;
2003 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2005 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2006 pBufferList
= pBufferList
->next
;
2009 lTotalBufferDataSize
= 0;
2010 pBufferList
= pSource
->queue
;
2013 if (pBufferList
->buffer
)
2014 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2015 pBufferList
= pBufferList
->next
;
2018 if (pSource
->bLooping
)
2020 if (lBytesPlayed
< 0)
2023 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
2027 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2028 if(lBytesPlayed
< 0)
2030 if(lBytesPlayed
> lTotalBufferDataSize
)
2031 lBytesPlayed
= lTotalBufferDataSize
;
2037 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
2039 case AL_SAMPLE_OFFSET
:
2040 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
2042 case AL_BYTE_OFFSET
:
2043 // Take into account the original format of the Buffer
2044 if ((eOriginalFormat
== AL_FORMAT_MONO8
) || (eOriginalFormat
== AL_FORMAT_STEREO8
))
2046 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2048 else if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) || (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2050 // Compression rate of the ADPCM supported is 3.6111 to 1
2051 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
2052 // Round down to nearest ADPCM block
2053 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
2057 *pflOffset
= (ALfloat
)lBytesPlayed
;
2074 Apply a playback offset to the Source. This function will update the queue (to correctly
2075 mark buffers as 'pending' or 'processed' depending upon the new offset.
2077 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2079 ALbufferlistitem
*pBufferList
;
2080 ALint lBufferSize
, lTotalBufferSize
;
2083 // Get true byte offset
2084 lByteOffset
= GetByteOffset(pSource
);
2086 // If this is a valid offset apply it
2087 if (lByteOffset
!= -1)
2089 // Sort out the queue (pending and processed states)
2090 pBufferList
= pSource
->queue
;
2091 lTotalBufferSize
= 0;
2092 pSource
->BuffersPlayed
= 0;
2093 pSource
->BuffersProcessed
= 0;
2096 lBufferSize
= pBufferList
->buffer
? ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
: 0;
2098 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2100 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2101 // update the state to PROCESSED
2102 pSource
->BuffersPlayed
++;
2104 if (!pSource
->bLooping
)
2106 pBufferList
->bufferstate
= PROCESSED
;
2107 pSource
->BuffersProcessed
++;
2110 else if (lTotalBufferSize
<= lByteOffset
)
2112 // Offset is within this buffer
2113 pBufferList
->bufferstate
= PENDING
;
2115 // Set Current Buffer ID
2116 pSource
->ulBufferID
= pBufferList
->buffer
;
2118 // Set current position in this buffer
2119 pSource
->BufferPosition
= lByteOffset
- lTotalBufferSize
;
2121 // Set Total Bytes Played to Offset
2122 pSource
->lBytesPlayed
= lByteOffset
;
2124 // SW Mixer Positions are in Samples
2125 pSource
->position
= pSource
->BufferPosition
/ ((((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->format
== AL_FORMAT_MONO16
)?2:4);
2129 // Offset is before this buffer, so mark as pending
2130 pBufferList
->bufferstate
= PENDING
;
2133 // Increment the TotalBufferSize
2134 lTotalBufferSize
+= lBufferSize
;
2136 // Move on to next buffer in the Queue
2137 pBufferList
= pBufferList
->next
;
2143 alSetError(AL_INVALID_VALUE
);
2147 pSource
->lOffset
= 0;
2154 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2155 offset supplied by the application). This takes into account the fact that the buffer format
2156 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2158 static ALint
GetByteOffset(ALsource
*pSource
)
2160 ALbuffer
*pBuffer
= NULL
;
2161 ALbufferlistitem
*pBufferList
;
2162 ALfloat flBufferFreq
;
2164 ALint lByteOffset
= -1;
2165 ALint lTotalBufferDataSize
;
2167 // Find the first non-NULL Buffer in the Queue
2168 pBufferList
= pSource
->queue
;
2171 if (pBufferList
->buffer
)
2173 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2176 pBufferList
= pBufferList
->next
;
2181 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2182 lChannels
= (pBuffer
->format
== AL_FORMAT_MONO16
)?1:2;
2184 // Determine the ByteOffset (and ensure it is block aligned)
2185 switch (pSource
->lOffsetType
)
2187 case AL_BYTE_OFFSET
:
2188 // Take into consideration the original format
2189 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO8
) || (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO8
))
2191 lByteOffset
= pSource
->lOffset
* 2;
2192 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2194 else if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) || (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2196 // Round down to nearest ADPCM block
2197 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2198 // Multiply by compression rate
2199 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2200 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2204 lByteOffset
= pSource
->lOffset
;
2205 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2209 case AL_SAMPLE_OFFSET
:
2210 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2214 // Note - lOffset is internally stored as Milliseconds
2215 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2216 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2220 lTotalBufferDataSize
= 0;
2221 pBufferList
= pSource
->queue
;
2224 if (pBufferList
->buffer
)
2225 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2226 pBufferList
= pBufferList
->next
;
2229 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2230 if (lByteOffset
>= lTotalBufferDataSize
)