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
32 static ALvoid
InitSourceParams(ALsource
*pSource
);
33 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
);
34 static ALvoid
ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
);
35 static ALint
GetByteOffset(ALsource
*pSource
);
37 ALAPI ALvoid ALAPIENTRY
alGenSources(ALsizei n
,ALuint
*sources
)
43 Context
= alcGetCurrentContext();
46 SuspendContext(Context
);
50 Device
= alcGetContextsDevice(Context
);
54 // Check that enough memory has been allocted in the 'sources' array for n Sources
55 if (!IsBadWritePtr((void*)sources
, n
* sizeof(ALuint
)))
57 // Check that the requested number of sources can be generated
58 if ((Context
->SourceCount
+ n
) <= Device
->MaxNoOfSources
)
60 ALsource
**list
= &Context
->Source
;
62 list
= &(*list
)->next
;
64 // Add additional sources to the list (Source->next points to the location for the next Source structure)
67 *list
= calloc(1, sizeof(ALsource
));
70 sources
[i
]=(ALuint
)ALTHUNK_ADDENTRY(*list
);
71 (*list
)->source
= sources
[i
];
73 InitSourceParams(*list
);
74 Context
->SourceCount
++;
77 list
= &(*list
)->next
;
81 // If we didn't create all the Sources, we must have run out or memory
83 alSetError(AL_OUT_OF_MEMORY
);
87 // Not enough resources to create the Sources
88 alSetError(AL_INVALID_VALUE
);
94 alSetError(AL_INVALID_VALUE
);
99 // No Device created, or attached to Context
100 alSetError(AL_INVALID_OPERATION
);
104 ProcessContext(Context
);
109 alSetError(AL_INVALID_OPERATION
);
116 ALAPI ALvoid ALAPIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
123 ALbufferlistitem
*ALBufferList
;
124 ALboolean bSourcesValid
= AL_TRUE
;
126 Context
= alcGetCurrentContext();
129 SuspendContext(Context
);
133 Device
= alcGetContextsDevice(Context
);
137 if ((ALuint
)n
<= Context
->SourceCount
)
139 // Check that all Sources are valid (and can therefore be deleted)
140 for (i
= 0; i
< n
; i
++)
142 if (!alIsSource(sources
[i
]))
144 alSetError(AL_INVALID_NAME
);
145 bSourcesValid
= AL_FALSE
;
152 // All Sources are valid, and can be deleted
153 for (i
= 0; i
< n
; i
++)
155 // Recheck that the Source is valid, because there could be duplicated Source names
156 if (alIsSource(sources
[i
]))
158 ALSource
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
159 alSourceStop((ALuint
)ALSource
->source
);
161 // For each buffer in the source's queue, decrement its reference counter and remove it
162 while (ALSource
->queue
!= NULL
)
164 ALBufferList
= ALSource
->queue
;
165 // Decrement buffer's reference counter
166 if (ALBufferList
->buffer
!= 0)
167 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
168 // Update queue to point to next element in list
169 ALSource
->queue
= ALBufferList
->next
;
170 // Release memory allocated for buffer list item
174 // Decrement Source count
175 Context
->SourceCount
--;
177 // Remove Source from list of Sources
178 list
= &Context
->Source
;
179 while(*list
&& *list
!= ALSource
)
180 list
= &(*list
)->next
;
183 *list
= (*list
)->next
;
184 ALTHUNK_REMOVEENTRY(ALSource
->source
);
186 memset(ALSource
,0,sizeof(ALsource
));
195 // Trying to delete more Sources than have been generated
196 alSetError(AL_INVALID_NAME
);
201 // No Device created, or attached to Context
202 alSetError(AL_INVALID_OPERATION
);
206 alSetError(AL_INVALID_VALUE
);
208 ProcessContext(Context
);
213 alSetError(AL_INVALID_OPERATION
);
220 ALAPI ALboolean ALAPIENTRY
alIsSource(ALuint source
)
222 ALboolean result
=AL_FALSE
;
226 Context
=alcGetCurrentContext();
229 SuspendContext(Context
);
231 // To determine if this is a valid Source name, look through the list of generated Sources
232 Source
= Context
->Source
;
235 if (Source
== (ALsource
*)ALTHUNK_LOOKUPENTRY(source
))
241 Source
= Source
->next
;
244 ProcessContext(Context
);
249 alSetError(AL_INVALID_OPERATION
);
256 ALAPI ALvoid ALAPIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
258 ALCcontext
*pContext
;
261 pContext
= alcGetCurrentContext();
264 SuspendContext(pContext
);
266 if (alIsSource(source
))
268 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
275 pSource
->flPitch
= flValue
;
276 if(pSource
->flPitch
< 0.001f
)
277 pSource
->flPitch
= 0.001f
;
280 alSetError(AL_INVALID_VALUE
);
283 case AL_CONE_INNER_ANGLE
:
284 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
285 pSource
->flInnerAngle
= flValue
;
287 alSetError(AL_INVALID_VALUE
);
290 case AL_CONE_OUTER_ANGLE
:
291 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
292 pSource
->flOuterAngle
= flValue
;
294 alSetError(AL_INVALID_VALUE
);
299 pSource
->flGain
= flValue
;
301 alSetError(AL_INVALID_VALUE
);
304 case AL_MAX_DISTANCE
:
306 pSource
->flMaxDistance
= flValue
;
308 alSetError(AL_INVALID_VALUE
);
311 case AL_ROLLOFF_FACTOR
:
313 pSource
->flRollOffFactor
= flValue
;
315 alSetError(AL_INVALID_VALUE
);
318 case AL_REFERENCE_DISTANCE
:
320 pSource
->flRefDistance
= flValue
;
322 alSetError(AL_INVALID_VALUE
);
326 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
327 pSource
->flMinGain
= flValue
;
329 alSetError(AL_INVALID_VALUE
);
333 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
334 pSource
->flMaxGain
= flValue
;
336 alSetError(AL_INVALID_VALUE
);
339 case AL_CONE_OUTER_GAIN
:
340 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
341 pSource
->flOuterGain
= flValue
;
343 alSetError(AL_INVALID_VALUE
);
346 case AL_CONE_OUTER_GAINHF
:
347 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
348 pSource
->OuterGainHF
= flValue
;
350 alSetError(AL_INVALID_VALUE
);
353 case AL_AIR_ABSORPTION_FACTOR
:
354 if (flValue
>= 0.0f
&& flValue
<= 10.0f
)
355 pSource
->AirAbsorptionFactor
= flValue
;
357 alSetError(AL_INVALID_VALUE
);
360 case AL_ROOM_ROLLOFF_FACTOR
:
361 if (flValue
>= 0.0f
&& flValue
<= 1.0f
)
362 pSource
->RoomRolloffFactor
= flValue
;
364 alSetError(AL_INVALID_VALUE
);
368 case AL_SAMPLE_OFFSET
:
372 pSource
->lOffsetType
= eParam
;
374 // Store Offset (convert Seconds into Milliseconds)
375 if (eParam
== AL_SEC_OFFSET
)
376 pSource
->lOffset
= (ALint
)(flValue
* 1000.0f
);
378 pSource
->lOffset
= (ALint
)flValue
;
380 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
381 ApplyOffset(pSource
, AL_TRUE
);
384 alSetError(AL_INVALID_VALUE
);
388 alSetError(AL_INVALID_ENUM
);
394 // Invalid Source Name
395 alSetError(AL_INVALID_NAME
);
398 ProcessContext(pContext
);
403 alSetError(AL_INVALID_OPERATION
);
410 ALAPI ALvoid ALAPIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
412 ALCcontext
*pContext
;
415 pContext
= alcGetCurrentContext();
418 SuspendContext(pContext
);
420 if (alIsSource(source
))
422 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
426 pSource
->vPosition
[0] = flValue1
;
427 pSource
->vPosition
[1] = flValue2
;
428 pSource
->vPosition
[2] = flValue3
;
432 pSource
->vVelocity
[0] = flValue1
;
433 pSource
->vVelocity
[1] = flValue2
;
434 pSource
->vVelocity
[2] = flValue3
;
438 pSource
->vOrientation
[0] = flValue1
;
439 pSource
->vOrientation
[1] = flValue2
;
440 pSource
->vOrientation
[2] = flValue3
;
444 alSetError(AL_INVALID_ENUM
);
449 alSetError(AL_INVALID_NAME
);
451 ProcessContext(pContext
);
455 alSetError(AL_INVALID_OPERATION
);
462 ALAPI ALvoid ALAPIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
464 ALCcontext
*pContext
;
466 pContext
= alcGetCurrentContext();
469 SuspendContext(pContext
);
473 if (alIsSource(source
))
478 case AL_CONE_INNER_ANGLE
:
479 case AL_CONE_OUTER_ANGLE
:
481 case AL_MAX_DISTANCE
:
482 case AL_ROLLOFF_FACTOR
:
483 case AL_REFERENCE_DISTANCE
:
486 case AL_CONE_OUTER_GAIN
:
487 case AL_CONE_OUTER_GAINHF
:
489 case AL_SAMPLE_OFFSET
:
491 case AL_AIR_ABSORPTION_FACTOR
:
492 case AL_ROOM_ROLLOFF_FACTOR
:
493 alSourcef(source
, eParam
, pflValues
[0]);
499 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
503 alSetError(AL_INVALID_ENUM
);
508 alSetError(AL_INVALID_NAME
);
511 alSetError(AL_INVALID_VALUE
);
513 ProcessContext(pContext
);
516 alSetError(AL_INVALID_OPERATION
);
522 ALAPI ALvoid ALAPIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
524 ALCcontext
*pContext
;
526 ALbufferlistitem
*pALBufferListItem
;
531 pContext
= alcGetCurrentContext();
534 SuspendContext(pContext
);
536 if (alIsSource(source
))
538 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
542 case AL_MAX_DISTANCE
:
543 case AL_ROLLOFF_FACTOR
:
544 case AL_REFERENCE_DISTANCE
:
545 alSourcef(source
, eParam
, (ALfloat
)lValue
);
548 case AL_SOURCE_RELATIVE
:
549 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
550 pSource
->bHeadRelative
= (ALboolean
)lValue
;
552 alSetError(AL_INVALID_VALUE
);
555 case AL_CONE_INNER_ANGLE
:
556 if ((lValue
>= 0) && (lValue
<= 360))
557 pSource
->flInnerAngle
= (float)lValue
;
559 alSetError(AL_INVALID_VALUE
);
562 case AL_CONE_OUTER_ANGLE
:
563 if ((lValue
>= 0) && (lValue
<= 360))
564 pSource
->flOuterAngle
= (float)lValue
;
566 alSetError(AL_INVALID_VALUE
);
570 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
571 pSource
->bLooping
= (ALboolean
)lValue
;
573 alSetError(AL_INVALID_VALUE
);
577 if ((pSource
->state
== AL_STOPPED
) || (pSource
->state
== AL_INITIAL
))
579 if (alIsBuffer(lValue
))
581 // Remove all elements in the queue
582 while (pSource
->queue
!= NULL
)
584 pALBufferListItem
= pSource
->queue
;
585 pSource
->queue
= pALBufferListItem
->next
;
586 // Decrement reference counter for buffer
587 if (pALBufferListItem
->buffer
)
588 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
)))->refcount
--;
589 // Record size of buffer
590 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
))->size
;
591 DataSize
+= BufferSize
;
592 // Increment the number of buffers removed from queue
594 // Release memory for buffer list item
595 free(pALBufferListItem
);
596 // Decrement the number of buffers in the queue
597 pSource
->BuffersInQueue
--;
600 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
603 // Source is now in STATIC mode
604 pSource
->lSourceType
= AL_STATIC
;
606 // Add the selected buffer to the queue
607 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
608 pALBufferListItem
->buffer
= lValue
;
609 pALBufferListItem
->bufferstate
= PENDING
;
610 pALBufferListItem
->flag
= 0;
611 pALBufferListItem
->next
= NULL
;
613 pSource
->queue
= pALBufferListItem
;
614 pSource
->BuffersInQueue
= 1;
616 DataSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(lValue
))->size
;
618 // Increment reference counter for buffer
619 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(lValue
)))->refcount
++;
623 // Source is now in UNDETERMINED mode
624 pSource
->lSourceType
= AL_UNDETERMINED
;
627 // Set Buffers Processed
628 pSource
->BuffersProcessed
= 0;
630 // Update AL_BUFFER parameter
631 pSource
->ulBufferID
= lValue
;
634 alSetError(AL_INVALID_VALUE
);
637 alSetError(AL_INVALID_OPERATION
);
640 case AL_SOURCE_STATE
:
642 alSetError(AL_INVALID_OPERATION
);
646 case AL_SAMPLE_OFFSET
:
650 pSource
->lOffsetType
= eParam
;
652 // Store Offset (convert Seconds into Milliseconds)
653 if (eParam
== AL_SEC_OFFSET
)
654 pSource
->lOffset
= lValue
* 1000;
656 pSource
->lOffset
= lValue
;
658 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
659 ApplyOffset(pSource
, AL_TRUE
);
662 alSetError(AL_INVALID_VALUE
);
665 case AL_DIRECT_FILTER
:
666 if(alIsFilter(lValue
))
668 ALfilter
*filter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue
);
671 pSource
->DirectFilter
.type
= AL_FILTER_NULL
;
672 pSource
->DirectFilter
.filter
= 0;
675 memcpy(&pSource
->DirectFilter
, filter
, sizeof(*filter
));
678 alSetError(AL_INVALID_VALUE
);
681 case AL_DIRECT_FILTER_GAINHF_AUTO
:
682 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
683 pSource
->DryGainHFAuto
= lValue
;
685 alSetError(AL_INVALID_VALUE
);
688 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
689 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
690 pSource
->WetGainAuto
= lValue
;
692 alSetError(AL_INVALID_VALUE
);
695 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
696 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
697 pSource
->WetGainHFAuto
= lValue
;
699 alSetError(AL_INVALID_VALUE
);
703 alSetError(AL_INVALID_ENUM
);
708 alSetError(AL_INVALID_NAME
);
710 ProcessContext(pContext
);
713 alSetError(AL_INVALID_OPERATION
);
719 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
721 ALCcontext
*pContext
;
723 pContext
= alcGetCurrentContext();
726 SuspendContext(pContext
);
728 if (alIsSource(source
))
730 ALsource
*pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
737 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
740 case AL_AUXILIARY_SEND_FILTER
:
741 if(lValue2
>= 0 && lValue2
< MAX_SENDS
&&
742 (alIsAuxiliaryEffectSlot(lValue1
) || lValue1
== 0) &&
745 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(lValue1
);
746 ALfilter
*ALFilter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue3
);
751 pSource
->Send
[lValue2
].Slot
.effectslot
= 0;
754 memcpy(&pSource
->Send
[lValue2
].Slot
, ALEffectSlot
, sizeof(*ALEffectSlot
));
759 pSource
->Send
[lValue2
].WetFilter
.type
= 0;
760 pSource
->Send
[lValue2
].WetFilter
.filter
= 0;
763 memcpy(&pSource
->Send
[lValue2
].WetFilter
, ALFilter
, sizeof(*ALFilter
));
766 alSetError(AL_INVALID_VALUE
);
770 alSetError(AL_INVALID_ENUM
);
775 alSetError(AL_INVALID_NAME
);
777 ProcessContext(pContext
);
780 alSetError(AL_INVALID_OPERATION
);
786 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
788 ALCcontext
*pContext
;
790 pContext
= alcGetCurrentContext();
793 SuspendContext(pContext
);
797 if (alIsSource(source
))
801 case AL_SOURCE_RELATIVE
:
802 case AL_CONE_INNER_ANGLE
:
803 case AL_CONE_OUTER_ANGLE
:
806 case AL_SOURCE_STATE
:
808 case AL_SAMPLE_OFFSET
:
810 case AL_MAX_DISTANCE
:
811 case AL_ROLLOFF_FACTOR
:
812 case AL_REFERENCE_DISTANCE
:
813 case AL_DIRECT_FILTER
:
814 case AL_DIRECT_FILTER_GAINHF_AUTO
:
815 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
816 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
817 alSourcei(source
, eParam
, plValues
[0]);
823 case AL_AUXILIARY_SEND_FILTER
:
824 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
828 alSetError(AL_INVALID_ENUM
);
833 alSetError(AL_INVALID_NAME
);
836 alSetError(AL_INVALID_VALUE
);
838 ProcessContext(pContext
);
841 alSetError(AL_INVALID_OPERATION
);
847 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
849 ALCcontext
*pContext
;
853 pContext
= alcGetCurrentContext();
856 SuspendContext(pContext
);
860 if (alIsSource(source
))
862 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
867 *pflValue
= pSource
->flPitch
;
871 *pflValue
= pSource
->flGain
;
875 *pflValue
= pSource
->flMinGain
;
879 *pflValue
= pSource
->flMaxGain
;
882 case AL_MAX_DISTANCE
:
883 *pflValue
= pSource
->flMaxDistance
;
886 case AL_ROLLOFF_FACTOR
:
887 *pflValue
= pSource
->flRollOffFactor
;
890 case AL_CONE_OUTER_GAIN
:
891 *pflValue
= pSource
->flOuterGain
;
894 case AL_CONE_OUTER_GAINHF
:
895 *pflValue
= pSource
->OuterGainHF
;
899 case AL_SAMPLE_OFFSET
:
901 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
902 *pflValue
= flOffset
;
904 alSetError(AL_INVALID_OPERATION
);
907 case AL_CONE_INNER_ANGLE
:
908 *pflValue
= pSource
->flInnerAngle
;
911 case AL_CONE_OUTER_ANGLE
:
912 *pflValue
= pSource
->flOuterAngle
;
915 case AL_REFERENCE_DISTANCE
:
916 *pflValue
= pSource
->flRefDistance
;
919 case AL_AIR_ABSORPTION_FACTOR
:
920 *pflValue
= pSource
->AirAbsorptionFactor
;
923 case AL_ROOM_ROLLOFF_FACTOR
:
924 *pflValue
= pSource
->RoomRolloffFactor
;
928 alSetError(AL_INVALID_ENUM
);
933 alSetError(AL_INVALID_NAME
);
936 alSetError(AL_INVALID_VALUE
);
938 ProcessContext(pContext
);
941 alSetError(AL_INVALID_OPERATION
);
947 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
949 ALCcontext
*pContext
;
952 pContext
= alcGetCurrentContext();
955 SuspendContext(pContext
);
957 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
959 if (alIsSource(source
))
961 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
966 *pflValue1
= pSource
->vPosition
[0];
967 *pflValue2
= pSource
->vPosition
[1];
968 *pflValue3
= pSource
->vPosition
[2];
972 *pflValue1
= pSource
->vVelocity
[0];
973 *pflValue2
= pSource
->vVelocity
[1];
974 *pflValue3
= pSource
->vVelocity
[2];
978 *pflValue1
= pSource
->vOrientation
[0];
979 *pflValue2
= pSource
->vOrientation
[1];
980 *pflValue3
= pSource
->vOrientation
[2];
984 alSetError(AL_INVALID_ENUM
);
989 alSetError(AL_INVALID_NAME
);
992 alSetError(AL_INVALID_VALUE
);
994 ProcessContext(pContext
);
997 alSetError(AL_INVALID_OPERATION
);
1003 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1005 ALCcontext
*pContext
;
1008 pContext
= alcGetCurrentContext();
1011 SuspendContext(pContext
);
1015 if (alIsSource(source
))
1017 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1025 case AL_MAX_DISTANCE
:
1026 case AL_ROLLOFF_FACTOR
:
1027 case AL_CONE_OUTER_GAIN
:
1029 case AL_SAMPLE_OFFSET
:
1030 case AL_BYTE_OFFSET
:
1031 case AL_CONE_INNER_ANGLE
:
1032 case AL_CONE_OUTER_ANGLE
:
1033 case AL_REFERENCE_DISTANCE
:
1034 case AL_CONE_OUTER_GAINHF
:
1035 case AL_AIR_ABSORPTION_FACTOR
:
1036 case AL_ROOM_ROLLOFF_FACTOR
:
1037 alGetSourcef(source
, eParam
, pflValues
);
1041 pflValues
[0] = pSource
->vPosition
[0];
1042 pflValues
[1] = pSource
->vPosition
[1];
1043 pflValues
[2] = pSource
->vPosition
[2];
1047 pflValues
[0] = pSource
->vVelocity
[0];
1048 pflValues
[1] = pSource
->vVelocity
[1];
1049 pflValues
[2] = pSource
->vVelocity
[2];
1053 pflValues
[0] = pSource
->vOrientation
[0];
1054 pflValues
[1] = pSource
->vOrientation
[1];
1055 pflValues
[2] = pSource
->vOrientation
[2];
1059 alSetError(AL_INVALID_ENUM
);
1064 alSetError(AL_INVALID_NAME
);
1067 alSetError(AL_INVALID_VALUE
);
1069 ProcessContext(pContext
);
1072 alSetError(AL_INVALID_OPERATION
);
1078 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1080 ALCcontext
*pContext
;
1084 pContext
= alcGetCurrentContext();
1087 SuspendContext(pContext
);
1091 if (alIsSource(source
))
1093 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1097 case AL_MAX_DISTANCE
:
1098 *plValue
= (ALint
)pSource
->flMaxDistance
;
1101 case AL_ROLLOFF_FACTOR
:
1102 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1105 case AL_REFERENCE_DISTANCE
:
1106 *plValue
= (ALint
)pSource
->flRefDistance
;
1109 case AL_SOURCE_RELATIVE
:
1110 *plValue
= pSource
->bHeadRelative
;
1113 case AL_CONE_INNER_ANGLE
:
1114 *plValue
= (ALint
)pSource
->flInnerAngle
;
1117 case AL_CONE_OUTER_ANGLE
:
1118 *plValue
= (ALint
)pSource
->flOuterAngle
;
1122 *plValue
= pSource
->bLooping
;
1126 *plValue
= pSource
->ulBufferID
;
1129 case AL_SOURCE_STATE
:
1130 *plValue
= pSource
->state
;
1133 case AL_BUFFERS_QUEUED
:
1134 *plValue
= pSource
->BuffersInQueue
;
1137 case AL_BUFFERS_PROCESSED
:
1138 if(pSource
->bLooping
)
1140 /* Buffers on a looping source are in a perpetual state
1141 * of PENDING, so don't report any as PROCESSED */
1145 *plValue
= pSource
->BuffersProcessed
;
1148 case AL_SOURCE_TYPE
:
1149 *plValue
= pSource
->lSourceType
;
1153 case AL_SAMPLE_OFFSET
:
1154 case AL_BYTE_OFFSET
:
1155 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
1156 *plValue
= (ALint
)flOffset
;
1158 alSetError(AL_INVALID_OPERATION
);
1161 case AL_DIRECT_FILTER
:
1162 *plValue
= pSource
->DirectFilter
.filter
;
1165 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1166 *plValue
= pSource
->DryGainHFAuto
;
1169 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1170 *plValue
= pSource
->WetGainAuto
;
1173 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1174 *plValue
= pSource
->WetGainHFAuto
;
1178 alSetError(AL_INVALID_ENUM
);
1183 alSetError(AL_INVALID_NAME
);
1186 alSetError(AL_INVALID_VALUE
);
1188 ProcessContext(pContext
);
1191 alSetError(AL_INVALID_OPERATION
);
1197 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1199 ALCcontext
*pContext
;
1202 pContext
= alcGetCurrentContext();
1205 SuspendContext(pContext
);
1207 if ((plValue1
) && (plValue2
) && (plValue3
))
1209 if (alIsSource(source
))
1211 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1216 *plValue1
= (ALint
)pSource
->vPosition
[0];
1217 *plValue2
= (ALint
)pSource
->vPosition
[1];
1218 *plValue3
= (ALint
)pSource
->vPosition
[2];
1222 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1223 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1224 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1228 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1229 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1230 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1234 alSetError(AL_INVALID_ENUM
);
1239 alSetError(AL_INVALID_NAME
);
1242 alSetError(AL_INVALID_VALUE
);
1244 ProcessContext(pContext
);
1247 alSetError(AL_INVALID_OPERATION
);
1253 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1255 ALCcontext
*pContext
;
1258 pContext
= alcGetCurrentContext();
1261 SuspendContext(pContext
);
1265 if (alIsSource(source
))
1267 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1271 case AL_SOURCE_RELATIVE
:
1272 case AL_CONE_INNER_ANGLE
:
1273 case AL_CONE_OUTER_ANGLE
:
1276 case AL_SOURCE_STATE
:
1277 case AL_BUFFERS_QUEUED
:
1278 case AL_BUFFERS_PROCESSED
:
1280 case AL_SAMPLE_OFFSET
:
1281 case AL_BYTE_OFFSET
:
1282 case AL_MAX_DISTANCE
:
1283 case AL_ROLLOFF_FACTOR
:
1284 case AL_REFERENCE_DISTANCE
:
1285 case AL_SOURCE_TYPE
:
1286 case AL_DIRECT_FILTER
:
1287 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1288 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1289 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1290 alGetSourcei(source
, eParam
, plValues
);
1294 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1295 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1296 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1300 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1301 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1302 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1306 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1307 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1308 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1312 alSetError(AL_INVALID_ENUM
);
1317 alSetError(AL_INVALID_NAME
);
1320 alSetError(AL_INVALID_VALUE
);
1322 ProcessContext(pContext
);
1325 alSetError(AL_INVALID_OPERATION
);
1331 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1333 alSourcePlayv(1, &source
);
1337 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1339 ALCcontext
*pContext
;
1341 ALbufferlistitem
*ALBufferList
;
1342 ALboolean bSourcesValid
= AL_TRUE
;
1346 pContext
= alcGetCurrentContext();
1349 SuspendContext(pContext
);
1353 // Check that all the Sources are valid
1354 for (i
= 0; i
< n
; i
++)
1356 if (!alIsSource(pSourceList
[i
]))
1358 alSetError(AL_INVALID_NAME
);
1359 bSourcesValid
= AL_FALSE
;
1366 for (i
= 0; i
< n
; i
++)
1368 // Assume Source won't need to play
1371 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1373 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1374 ALBufferList
= pSource
->queue
;
1375 while (ALBufferList
)
1377 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1382 ALBufferList
= ALBufferList
->next
;
1387 if (pSource
->state
!= AL_PAUSED
)
1389 pSource
->state
= AL_PLAYING
;
1390 pSource
->inuse
= AL_TRUE
;
1391 pSource
->play
= AL_TRUE
;
1392 pSource
->position
= 0;
1393 pSource
->position_fraction
= 0;
1394 pSource
->BuffersProcessed
= 0;
1395 pSource
->BuffersPlayed
= 0;
1396 pSource
->BufferPosition
= 0;
1397 pSource
->lBytesPlayed
= 0;
1399 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1401 // Make sure all the Buffers in the queue are marked as PENDING
1402 ALBufferList
= pSource
->queue
;
1403 while (ALBufferList
)
1405 ALBufferList
->bufferstate
= PENDING
;
1406 ALBufferList
= ALBufferList
->next
;
1411 pSource
->state
= AL_PLAYING
;
1412 pSource
->inuse
= AL_TRUE
;
1413 pSource
->play
= AL_TRUE
;
1416 // Check if an Offset has been set
1417 if (pSource
->lOffset
)
1418 ApplyOffset(pSource
, AL_FALSE
);
1422 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1423 ALBufferList
= pSource
->queue
;
1424 while (ALBufferList
)
1426 ALBufferList
->bufferstate
= PROCESSED
;
1427 ALBufferList
= ALBufferList
->next
;
1430 pSource
->BuffersPlayed
= pSource
->BuffersProcessed
= pSource
->BuffersInQueue
;
1437 // sources is a NULL pointer
1438 alSetError(AL_INVALID_VALUE
);
1441 ProcessContext(pContext
);
1446 alSetError(AL_INVALID_OPERATION
);
1452 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1454 alSourcePausev(1, &source
);
1458 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1460 ALCcontext
*Context
;
1463 ALboolean bSourcesValid
= AL_TRUE
;
1465 Context
=alcGetCurrentContext();
1468 SuspendContext(Context
);
1472 // Check all the Sources are valid
1475 if (!alIsSource(sources
[i
]))
1477 alSetError(AL_INVALID_NAME
);
1478 bSourcesValid
= AL_FALSE
;
1487 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1488 if (Source
->state
==AL_PLAYING
)
1490 Source
->state
=AL_PAUSED
;
1491 Source
->inuse
=AL_FALSE
;
1498 // sources is a NULL pointer
1499 alSetError(AL_INVALID_VALUE
);
1502 ProcessContext(Context
);
1507 alSetError(AL_INVALID_OPERATION
);
1513 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1515 alSourceStopv(1, &source
);
1519 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1521 ALCcontext
*Context
;
1524 ALbufferlistitem
*ALBufferListItem
;
1525 ALboolean bSourcesValid
= AL_TRUE
;
1527 Context
=alcGetCurrentContext();
1530 SuspendContext(Context
);
1534 // Check all the Sources are valid
1537 if (!alIsSource(sources
[i
]))
1539 alSetError(AL_INVALID_NAME
);
1540 bSourcesValid
= AL_FALSE
;
1549 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1550 if (Source
->state
!=AL_INITIAL
)
1552 Source
->state
=AL_STOPPED
;
1553 Source
->inuse
=AL_FALSE
;
1554 Source
->BuffersPlayed
= Source
->BuffersProcessed
= Source
->BuffersInQueue
;
1555 ALBufferListItem
= Source
->queue
;
1556 while (ALBufferListItem
!= NULL
)
1558 ALBufferListItem
->bufferstate
= PROCESSED
;
1559 ALBufferListItem
= ALBufferListItem
->next
;
1562 Source
->lOffset
= 0;
1568 // sources is a NULL pointer
1569 alSetError(AL_INVALID_VALUE
);
1572 ProcessContext(Context
);
1577 alSetError(AL_INVALID_OPERATION
);
1583 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1585 alSourceRewindv(1, &source
);
1589 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1591 ALCcontext
*Context
;
1594 ALbufferlistitem
*ALBufferListItem
;
1595 ALboolean bSourcesValid
= AL_TRUE
;
1597 Context
=alcGetCurrentContext();
1600 SuspendContext(Context
);
1604 // Check all the Sources are valid
1607 if (!alIsSource(sources
[i
]))
1609 alSetError(AL_INVALID_NAME
);
1610 bSourcesValid
= AL_FALSE
;
1619 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1620 if (Source
->state
!=AL_INITIAL
)
1622 Source
->state
=AL_INITIAL
;
1623 Source
->inuse
=AL_FALSE
;
1625 Source
->position_fraction
=0;
1626 Source
->BuffersProcessed
= 0;
1627 ALBufferListItem
= Source
->queue
;
1628 while (ALBufferListItem
!= NULL
)
1630 ALBufferListItem
->bufferstate
= PENDING
;
1631 ALBufferListItem
= ALBufferListItem
->next
;
1634 Source
->ulBufferID
= Source
->queue
->buffer
;
1636 Source
->lOffset
= 0;
1642 // sources is a NULL pointer
1643 alSetError(AL_INVALID_VALUE
);
1646 ProcessContext(Context
);
1651 alSetError(AL_INVALID_OPERATION
);
1658 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1660 ALCcontext
*Context
;
1663 ALbufferlistitem
*ALBufferList
;
1664 ALbufferlistitem
*ALBufferListStart
;
1669 ALboolean bBuffersValid
= AL_TRUE
;
1674 Context
=alcGetCurrentContext();
1677 SuspendContext(Context
);
1682 // Check that all buffers are valid or zero and that the source is valid
1684 // Check that this is a valid source
1685 if (alIsSource(source
))
1687 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1689 // Check that this is not a STATIC Source
1690 if (ALSource
->lSourceType
!= AL_STATIC
)
1695 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1696 ALBufferList
= ALSource
->queue
;
1697 while (ALBufferList
)
1699 if (ALBufferList
->buffer
)
1701 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1702 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1705 ALBufferList
= ALBufferList
->next
;
1708 for (i
= 0; i
< n
; i
++)
1710 if (alIsBuffer(buffers
[i
]))
1714 if ((iFrequency
== -1) && (iFormat
== -1))
1716 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1717 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1721 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1722 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1724 alSetError(AL_INVALID_OPERATION
);
1725 bBuffersValid
= AL_FALSE
;
1733 alSetError(AL_INVALID_NAME
);
1734 bBuffersValid
= AL_FALSE
;
1741 // Change Source Type
1742 ALSource
->lSourceType
= AL_STREAMING
;
1744 // All buffers are valid - so add them to the list
1745 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1746 ALBufferListStart
->buffer
= buffers
[0];
1747 ALBufferListStart
->bufferstate
= PENDING
;
1748 ALBufferListStart
->flag
= 0;
1749 ALBufferListStart
->next
= NULL
;
1752 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1756 DataSize
+= BufferSize
;
1758 // Increment reference counter for buffer
1760 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1762 ALBufferList
= ALBufferListStart
;
1764 for (i
= 1; i
< n
; i
++)
1766 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1767 ALBufferList
->next
->buffer
= buffers
[i
];
1768 ALBufferList
->next
->bufferstate
= PENDING
;
1769 ALBufferList
->next
->flag
= 0;
1770 ALBufferList
->next
->next
= NULL
;
1773 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1777 DataSize
+= BufferSize
;
1779 // Increment reference counter for buffer
1781 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1783 ALBufferList
= ALBufferList
->next
;
1786 if (ALSource
->queue
== NULL
)
1788 ALSource
->queue
= ALBufferListStart
;
1789 // Update Current Buffer
1790 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1794 // Find end of queue
1795 ALBufferList
= ALSource
->queue
;
1796 while (ALBufferList
->next
!= NULL
)
1798 ALBufferList
= ALBufferList
->next
;
1801 ALBufferList
->next
= ALBufferListStart
;
1804 // Update number of buffers in queue
1805 ALSource
->BuffersInQueue
+= n
;
1810 // Invalid Source Type (can't queue on a Static Source)
1811 alSetError(AL_INVALID_OPERATION
);
1816 // Invalid Source Name
1817 alSetError(AL_INVALID_NAME
);
1820 ProcessContext(Context
);
1825 alSetError(AL_INVALID_OPERATION
);
1832 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1833 // an array of buffer IDs that are to be filled with the names of the buffers removed
1834 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1836 ALCcontext
*Context
;
1839 ALbufferlistitem
*ALBufferList
;
1843 ALboolean bBuffersProcessed
;
1850 bBuffersProcessed
= AL_TRUE
;
1852 Context
=alcGetCurrentContext();
1855 SuspendContext(Context
);
1857 if (alIsSource(source
))
1859 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1861 // Check that all 'n' buffers have been processed
1862 ALBufferList
= ALSource
->queue
;
1863 for (i
= 0; i
< n
; i
++)
1865 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1867 ALBufferList
= ALBufferList
->next
;
1871 bBuffersProcessed
= AL_FALSE
;
1876 // If all 'n' buffers have been processed, remove them from the queue
1877 if (bBuffersProcessed
)
1879 for (i
= 0; i
< n
; i
++)
1881 ALBufferList
= ALSource
->queue
;
1883 ALSource
->queue
= ALBufferList
->next
;
1884 // Record name of buffer
1885 buffers
[i
] = ALBufferList
->buffer
;
1886 // Decrement buffer reference counter
1887 if (ALBufferList
->buffer
)
1888 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1889 // Record size of buffer
1890 if (ALBufferList
->buffer
)
1891 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1895 DataSize
+= BufferSize
;
1896 // Release memory for buffer list item
1898 ALSource
->BuffersInQueue
--;
1899 ALSource
->BuffersProcessed
--;
1902 if (ALSource
->state
!= AL_PLAYING
)
1904 if (ALSource
->queue
)
1905 BufferID
= ALSource
->queue
->buffer
;
1909 ALSource
->ulBufferID
= BufferID
;
1912 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1914 ALSource
->BuffersPlayed
= 0;
1915 ALSource
->BufferPosition
= 0;
1918 ALSource
->BuffersPlayed
-= n
;
1922 // Some buffers can't be unqueue because they have not been processed
1923 alSetError(AL_INVALID_VALUE
);
1928 // Invalid Source Name
1929 alSetError(AL_INVALID_NAME
);
1932 ProcessContext(Context
);
1937 alSetError(AL_INVALID_OPERATION
);
1944 static ALvoid
InitSourceParams(ALsource
*pSource
)
1946 pSource
->flInnerAngle
= 360.0f
;
1947 pSource
->flOuterAngle
= 360.0f
;
1948 pSource
->flPitch
= 1.0f
;
1949 pSource
->vPosition
[0] = 0.0f
;
1950 pSource
->vPosition
[1] = 0.0f
;
1951 pSource
->vPosition
[2] = 0.0f
;
1952 pSource
->vOrientation
[0] = 0.0f
;
1953 pSource
->vOrientation
[1] = 0.0f
;
1954 pSource
->vOrientation
[2] = 0.0f
;
1955 pSource
->vVelocity
[0] = 0.0f
;
1956 pSource
->vVelocity
[1] = 0.0f
;
1957 pSource
->vVelocity
[2] = 0.0f
;
1958 pSource
->flRefDistance
= 1.0f
;
1959 pSource
->flMaxDistance
= FLT_MAX
;
1960 pSource
->flRollOffFactor
= 1.0f
;
1961 pSource
->bLooping
= AL_FALSE
;
1962 pSource
->flGain
= 1.0f
;
1963 pSource
->flMinGain
= 0.0f
;
1964 pSource
->flMaxGain
= 1.0f
;
1965 pSource
->flOuterGain
= 0.0f
;
1967 pSource
->DryGainHFAuto
= AL_TRUE
;
1968 pSource
->WetGainAuto
= AL_TRUE
;
1969 pSource
->WetGainHFAuto
= AL_TRUE
;
1970 pSource
->AirAbsorptionFactor
= 0.0f
;
1972 pSource
->state
= AL_INITIAL
;
1973 pSource
->lSourceType
= AL_UNDETERMINED
;
1975 pSource
->ulBufferID
= 0;
1982 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1983 The offset is relative to the start of the queue (not the start of the current buffer)
1985 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
1987 ALbufferlistitem
*pBufferList
;
1989 ALfloat flBufferFreq
;
1990 ALint lBytesPlayed
, lChannels
;
1991 ALenum eOriginalFormat
;
1992 ALboolean bReturn
= AL_TRUE
;
1993 ALint lTotalBufferDataSize
;
1995 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
1997 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
1998 // Get Current Buffer Size and frequency (in milliseconds)
1999 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
2000 eOriginalFormat
= pBuffer
->eOriginalFormat
;
2001 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2003 // Get Current BytesPlayed
2004 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2005 // Add byte length of any processed buffers in the queue
2006 pBufferList
= pSource
->queue
;
2007 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2009 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2010 pBufferList
= pBufferList
->next
;
2013 lTotalBufferDataSize
= 0;
2014 pBufferList
= pSource
->queue
;
2017 if (pBufferList
->buffer
)
2018 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2019 pBufferList
= pBufferList
->next
;
2022 if (pSource
->bLooping
)
2024 if (lBytesPlayed
< 0)
2027 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
2031 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2032 if(lBytesPlayed
< 0)
2034 if(lBytesPlayed
> lTotalBufferDataSize
)
2035 lBytesPlayed
= lTotalBufferDataSize
;
2041 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
2043 case AL_SAMPLE_OFFSET
:
2044 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
2046 case AL_BYTE_OFFSET
:
2047 // Take into account the original format of the Buffer
2048 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2049 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2051 // Compression rate of the ADPCM supported is 3.6111 to 1
2052 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
2053 // Round down to nearest ADPCM block
2054 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
2056 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2058 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 2);
2060 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2062 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2064 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2066 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2068 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2070 *pflOffset
= (ALfloat
)(lBytesPlayed
<< 1);
2074 *pflOffset
= (ALfloat
)lBytesPlayed
;
2091 Apply a playback offset to the Source. This function will update the queue (to correctly
2092 mark buffers as 'pending' or 'processed' depending upon the new offset.
2094 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2096 ALbufferlistitem
*pBufferList
;
2098 ALint lBufferSize
, lTotalBufferSize
;
2101 // Get true byte offset
2102 lByteOffset
= GetByteOffset(pSource
);
2104 // If this is a valid offset apply it
2105 if (lByteOffset
!= -1)
2107 // Sort out the queue (pending and processed states)
2108 pBufferList
= pSource
->queue
;
2109 lTotalBufferSize
= 0;
2110 pSource
->BuffersPlayed
= 0;
2111 pSource
->BuffersProcessed
= 0;
2114 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2115 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2117 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2119 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2120 // update the state to PROCESSED
2121 pSource
->BuffersPlayed
++;
2123 if (!pSource
->bLooping
)
2125 pBufferList
->bufferstate
= PROCESSED
;
2126 pSource
->BuffersProcessed
++;
2129 else if (lTotalBufferSize
<= lByteOffset
)
2131 // Offset is within this buffer
2132 pBufferList
->bufferstate
= PENDING
;
2134 // Set Current Buffer ID
2135 pSource
->ulBufferID
= pBufferList
->buffer
;
2137 // Set current position in this buffer
2138 pSource
->BufferPosition
= lByteOffset
- lTotalBufferSize
;
2140 // Set Total Bytes Played to Offset
2141 pSource
->lBytesPlayed
= lByteOffset
;
2143 // SW Mixer Positions are in Samples
2144 pSource
->position
= pSource
->BufferPosition
/
2145 aluBytesFromFormat(pBuffer
->format
) /
2146 aluChannelsFromFormat(pBuffer
->format
);
2150 // Offset is before this buffer, so mark as pending
2151 pBufferList
->bufferstate
= PENDING
;
2154 // Increment the TotalBufferSize
2155 lTotalBufferSize
+= lBufferSize
;
2157 // Move on to next buffer in the Queue
2158 pBufferList
= pBufferList
->next
;
2164 alSetError(AL_INVALID_VALUE
);
2168 pSource
->lOffset
= 0;
2175 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2176 offset supplied by the application). This takes into account the fact that the buffer format
2177 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2179 static ALint
GetByteOffset(ALsource
*pSource
)
2181 ALbuffer
*pBuffer
= NULL
;
2182 ALbufferlistitem
*pBufferList
;
2183 ALfloat flBufferFreq
;
2185 ALint lByteOffset
= -1;
2186 ALint lTotalBufferDataSize
;
2188 // Find the first non-NULL Buffer in the Queue
2189 pBufferList
= pSource
->queue
;
2192 if (pBufferList
->buffer
)
2194 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2197 pBufferList
= pBufferList
->next
;
2202 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2203 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2205 // Determine the ByteOffset (and ensure it is block aligned)
2206 switch (pSource
->lOffsetType
)
2208 case AL_BYTE_OFFSET
:
2209 // Take into consideration the original format
2210 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2211 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2213 // Round down to nearest ADPCM block
2214 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2215 // Multiply by compression rate
2216 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2217 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2219 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2221 lByteOffset
= pSource
->lOffset
* 4;
2222 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2224 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2226 lByteOffset
= pSource
->lOffset
* 2;
2227 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2229 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2231 lByteOffset
= pSource
->lOffset
* 2;
2232 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2234 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2236 lByteOffset
= pSource
->lOffset
/ 2;
2237 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2241 lByteOffset
= pSource
->lOffset
;
2242 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2246 case AL_SAMPLE_OFFSET
:
2247 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2251 // Note - lOffset is internally stored as Milliseconds
2252 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2253 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2257 lTotalBufferDataSize
= 0;
2258 pBufferList
= pSource
->queue
;
2261 if (pBufferList
->buffer
)
2262 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2263 pBufferList
= pBufferList
->next
;
2266 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2267 if (lByteOffset
>= lTotalBufferDataSize
)