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
);
347 case AL_SAMPLE_OFFSET
:
351 pSource
->lOffsetType
= eParam
;
353 // Store Offset (convert Seconds into Milliseconds)
354 if (eParam
== AL_SEC_OFFSET
)
355 pSource
->lOffset
= (ALint
)(flValue
* 1000.0f
);
357 pSource
->lOffset
= (ALint
)flValue
;
359 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
360 ApplyOffset(pSource
, AL_TRUE
);
363 alSetError(AL_INVALID_VALUE
);
367 alSetError(AL_INVALID_ENUM
);
373 // Invalid Source Name
374 alSetError(AL_INVALID_NAME
);
377 ProcessContext(pContext
);
382 alSetError(AL_INVALID_OPERATION
);
389 ALAPI ALvoid ALAPIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
391 ALCcontext
*pContext
;
394 pContext
= alcGetCurrentContext();
397 SuspendContext(pContext
);
399 if (alIsSource(source
))
401 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
405 pSource
->vPosition
[0] = flValue1
;
406 pSource
->vPosition
[1] = flValue2
;
407 pSource
->vPosition
[2] = flValue3
;
411 pSource
->vVelocity
[0] = flValue1
;
412 pSource
->vVelocity
[1] = flValue2
;
413 pSource
->vVelocity
[2] = flValue3
;
417 pSource
->vOrientation
[0] = flValue1
;
418 pSource
->vOrientation
[1] = flValue2
;
419 pSource
->vOrientation
[2] = flValue3
;
423 alSetError(AL_INVALID_ENUM
);
428 alSetError(AL_INVALID_NAME
);
430 ProcessContext(pContext
);
434 alSetError(AL_INVALID_OPERATION
);
441 ALAPI ALvoid ALAPIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
443 ALCcontext
*pContext
;
445 pContext
= alcGetCurrentContext();
448 SuspendContext(pContext
);
452 if (alIsSource(source
))
457 case AL_CONE_INNER_ANGLE
:
458 case AL_CONE_OUTER_ANGLE
:
460 case AL_MAX_DISTANCE
:
461 case AL_ROLLOFF_FACTOR
:
462 case AL_REFERENCE_DISTANCE
:
465 case AL_CONE_OUTER_GAIN
:
467 case AL_SAMPLE_OFFSET
:
469 alSourcef(source
, eParam
, pflValues
[0]);
475 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
479 alSetError(AL_INVALID_ENUM
);
484 alSetError(AL_INVALID_NAME
);
487 alSetError(AL_INVALID_VALUE
);
489 ProcessContext(pContext
);
492 alSetError(AL_INVALID_OPERATION
);
498 ALAPI ALvoid ALAPIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
500 ALCcontext
*pContext
;
502 ALbufferlistitem
*pALBufferListItem
;
507 pContext
= alcGetCurrentContext();
510 SuspendContext(pContext
);
512 if (alIsSource(source
))
514 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
518 case AL_MAX_DISTANCE
:
519 case AL_ROLLOFF_FACTOR
:
520 case AL_REFERENCE_DISTANCE
:
521 alSourcef(source
, eParam
, (ALfloat
)lValue
);
524 case AL_SOURCE_RELATIVE
:
525 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
526 pSource
->bHeadRelative
= (ALboolean
)lValue
;
528 alSetError(AL_INVALID_VALUE
);
531 case AL_CONE_INNER_ANGLE
:
532 if ((lValue
>= 0) && (lValue
<= 360))
533 pSource
->flInnerAngle
= (float)lValue
;
535 alSetError(AL_INVALID_VALUE
);
538 case AL_CONE_OUTER_ANGLE
:
539 if ((lValue
>= 0) && (lValue
<= 360))
540 pSource
->flOuterAngle
= (float)lValue
;
542 alSetError(AL_INVALID_VALUE
);
546 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
547 pSource
->bLooping
= (ALboolean
)lValue
;
549 alSetError(AL_INVALID_VALUE
);
553 if ((pSource
->state
== AL_STOPPED
) || (pSource
->state
== AL_INITIAL
))
555 if (alIsBuffer(lValue
))
557 // Remove all elements in the queue
558 while (pSource
->queue
!= NULL
)
560 pALBufferListItem
= pSource
->queue
;
561 pSource
->queue
= pALBufferListItem
->next
;
562 // Decrement reference counter for buffer
563 if (pALBufferListItem
->buffer
)
564 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
)))->refcount
--;
565 // Record size of buffer
566 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
))->size
;
567 DataSize
+= BufferSize
;
568 // Increment the number of buffers removed from queue
570 // Release memory for buffer list item
571 free(pALBufferListItem
);
572 // Decrement the number of buffers in the queue
573 pSource
->BuffersInQueue
--;
576 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
579 // Source is now in STATIC mode
580 pSource
->lSourceType
= AL_STATIC
;
582 // Add the selected buffer to the queue
583 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
584 pALBufferListItem
->buffer
= lValue
;
585 pALBufferListItem
->bufferstate
= PENDING
;
586 pALBufferListItem
->flag
= 0;
587 pALBufferListItem
->next
= NULL
;
589 pSource
->queue
= pALBufferListItem
;
590 pSource
->BuffersInQueue
= 1;
592 DataSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(lValue
))->size
;
594 // Increment reference counter for buffer
595 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(lValue
)))->refcount
++;
599 // Source is now in UNDETERMINED mode
600 pSource
->lSourceType
= AL_UNDETERMINED
;
603 // Set Buffers Processed
604 pSource
->BuffersProcessed
= 0;
606 // Update AL_BUFFER parameter
607 pSource
->ulBufferID
= lValue
;
610 alSetError(AL_INVALID_VALUE
);
613 alSetError(AL_INVALID_OPERATION
);
616 case AL_SOURCE_STATE
:
618 alSetError(AL_INVALID_OPERATION
);
622 case AL_SAMPLE_OFFSET
:
626 pSource
->lOffsetType
= eParam
;
628 // Store Offset (convert Seconds into Milliseconds)
629 if (eParam
== AL_SEC_OFFSET
)
630 pSource
->lOffset
= lValue
* 1000;
632 pSource
->lOffset
= lValue
;
634 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
635 ApplyOffset(pSource
, AL_TRUE
);
638 alSetError(AL_INVALID_VALUE
);
642 alSetError(AL_INVALID_ENUM
);
647 alSetError(AL_INVALID_NAME
);
649 ProcessContext(pContext
);
652 alSetError(AL_INVALID_OPERATION
);
658 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
660 ALCcontext
*pContext
;
662 pContext
= alcGetCurrentContext();
665 SuspendContext(pContext
);
667 if (alIsSource(source
))
674 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
678 alSetError(AL_INVALID_ENUM
);
683 alSetError(AL_INVALID_NAME
);
685 ProcessContext(pContext
);
688 alSetError(AL_INVALID_OPERATION
);
694 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
696 ALCcontext
*pContext
;
698 pContext
= alcGetCurrentContext();
701 SuspendContext(pContext
);
705 if (alIsSource(source
))
709 case AL_SOURCE_RELATIVE
:
710 case AL_CONE_INNER_ANGLE
:
711 case AL_CONE_OUTER_ANGLE
:
714 case AL_SOURCE_STATE
:
716 case AL_SAMPLE_OFFSET
:
718 case AL_MAX_DISTANCE
:
719 case AL_ROLLOFF_FACTOR
:
720 case AL_REFERENCE_DISTANCE
:
721 alSourcei(source
, eParam
, plValues
[0]);
727 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
731 alSetError(AL_INVALID_ENUM
);
736 alSetError(AL_INVALID_NAME
);
739 alSetError(AL_INVALID_VALUE
);
741 ProcessContext(pContext
);
744 alSetError(AL_INVALID_OPERATION
);
750 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
752 ALCcontext
*pContext
;
756 pContext
= alcGetCurrentContext();
759 SuspendContext(pContext
);
763 if (alIsSource(source
))
765 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
770 *pflValue
= pSource
->flPitch
;
774 *pflValue
= pSource
->flGain
;
778 *pflValue
= pSource
->flMinGain
;
782 *pflValue
= pSource
->flMaxGain
;
785 case AL_MAX_DISTANCE
:
786 *pflValue
= pSource
->flMaxDistance
;
789 case AL_ROLLOFF_FACTOR
:
790 *pflValue
= pSource
->flRollOffFactor
;
793 case AL_CONE_OUTER_GAIN
:
794 *pflValue
= pSource
->flOuterGain
;
798 case AL_SAMPLE_OFFSET
:
800 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
801 *pflValue
= flOffset
;
803 alSetError(AL_INVALID_OPERATION
);
806 case AL_CONE_INNER_ANGLE
:
807 *pflValue
= pSource
->flInnerAngle
;
810 case AL_CONE_OUTER_ANGLE
:
811 *pflValue
= pSource
->flOuterAngle
;
814 case AL_REFERENCE_DISTANCE
:
815 *pflValue
= pSource
->flRefDistance
;
819 alSetError(AL_INVALID_ENUM
);
824 alSetError(AL_INVALID_NAME
);
827 alSetError(AL_INVALID_VALUE
);
829 ProcessContext(pContext
);
832 alSetError(AL_INVALID_OPERATION
);
838 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
840 ALCcontext
*pContext
;
843 pContext
= alcGetCurrentContext();
846 SuspendContext(pContext
);
848 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
850 if (alIsSource(source
))
852 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
857 *pflValue1
= pSource
->vPosition
[0];
858 *pflValue2
= pSource
->vPosition
[1];
859 *pflValue3
= pSource
->vPosition
[2];
863 *pflValue1
= pSource
->vVelocity
[0];
864 *pflValue2
= pSource
->vVelocity
[1];
865 *pflValue3
= pSource
->vVelocity
[2];
869 *pflValue1
= pSource
->vOrientation
[0];
870 *pflValue2
= pSource
->vOrientation
[1];
871 *pflValue3
= pSource
->vOrientation
[2];
875 alSetError(AL_INVALID_ENUM
);
880 alSetError(AL_INVALID_NAME
);
883 alSetError(AL_INVALID_VALUE
);
885 ProcessContext(pContext
);
888 alSetError(AL_INVALID_OPERATION
);
894 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
896 ALCcontext
*pContext
;
899 pContext
= alcGetCurrentContext();
902 SuspendContext(pContext
);
906 if (alIsSource(source
))
908 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
916 case AL_MAX_DISTANCE
:
917 case AL_ROLLOFF_FACTOR
:
918 case AL_CONE_OUTER_GAIN
:
920 case AL_SAMPLE_OFFSET
:
922 case AL_CONE_INNER_ANGLE
:
923 case AL_CONE_OUTER_ANGLE
:
924 case AL_REFERENCE_DISTANCE
:
925 alGetSourcef(source
, eParam
, pflValues
);
929 pflValues
[0] = pSource
->vPosition
[0];
930 pflValues
[1] = pSource
->vPosition
[1];
931 pflValues
[2] = pSource
->vPosition
[2];
935 pflValues
[0] = pSource
->vVelocity
[0];
936 pflValues
[1] = pSource
->vVelocity
[1];
937 pflValues
[2] = pSource
->vVelocity
[2];
941 pflValues
[0] = pSource
->vOrientation
[0];
942 pflValues
[1] = pSource
->vOrientation
[1];
943 pflValues
[2] = pSource
->vOrientation
[2];
947 alSetError(AL_INVALID_ENUM
);
952 alSetError(AL_INVALID_NAME
);
955 alSetError(AL_INVALID_VALUE
);
957 ProcessContext(pContext
);
960 alSetError(AL_INVALID_OPERATION
);
966 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
968 ALCcontext
*pContext
;
972 pContext
= alcGetCurrentContext();
975 SuspendContext(pContext
);
979 if (alIsSource(source
))
981 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
985 case AL_MAX_DISTANCE
:
986 *plValue
= (ALint
)pSource
->flMaxDistance
;
989 case AL_ROLLOFF_FACTOR
:
990 *plValue
= (ALint
)pSource
->flRollOffFactor
;
993 case AL_REFERENCE_DISTANCE
:
994 *plValue
= (ALint
)pSource
->flRefDistance
;
997 case AL_SOURCE_RELATIVE
:
998 *plValue
= pSource
->bHeadRelative
;
1001 case AL_CONE_INNER_ANGLE
:
1002 *plValue
= (ALint
)pSource
->flInnerAngle
;
1005 case AL_CONE_OUTER_ANGLE
:
1006 *plValue
= (ALint
)pSource
->flOuterAngle
;
1010 *plValue
= pSource
->bLooping
;
1014 *plValue
= pSource
->ulBufferID
;
1017 case AL_SOURCE_STATE
:
1018 *plValue
= pSource
->state
;
1021 case AL_BUFFERS_QUEUED
:
1022 *plValue
= pSource
->BuffersInQueue
;
1025 case AL_BUFFERS_PROCESSED
:
1026 if(pSource
->bLooping
)
1028 /* Buffers on a looping source are in a perpetual state
1029 * of PENDING, so don't report any as PROCESSED */
1033 *plValue
= pSource
->BuffersProcessed
;
1036 case AL_SOURCE_TYPE
:
1037 *plValue
= pSource
->lSourceType
;
1041 case AL_SAMPLE_OFFSET
:
1042 case AL_BYTE_OFFSET
:
1043 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
1044 *plValue
= (ALint
)flOffset
;
1046 alSetError(AL_INVALID_OPERATION
);
1050 alSetError(AL_INVALID_ENUM
);
1055 alSetError(AL_INVALID_NAME
);
1058 alSetError(AL_INVALID_VALUE
);
1060 ProcessContext(pContext
);
1063 alSetError(AL_INVALID_OPERATION
);
1069 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1071 ALCcontext
*pContext
;
1074 pContext
= alcGetCurrentContext();
1077 SuspendContext(pContext
);
1079 if ((plValue1
) && (plValue2
) && (plValue3
))
1081 if (alIsSource(source
))
1083 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1088 *plValue1
= (ALint
)pSource
->vPosition
[0];
1089 *plValue2
= (ALint
)pSource
->vPosition
[1];
1090 *plValue3
= (ALint
)pSource
->vPosition
[2];
1094 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1095 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1096 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1100 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1101 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1102 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1106 alSetError(AL_INVALID_ENUM
);
1111 alSetError(AL_INVALID_NAME
);
1114 alSetError(AL_INVALID_VALUE
);
1116 ProcessContext(pContext
);
1119 alSetError(AL_INVALID_OPERATION
);
1125 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1127 ALCcontext
*pContext
;
1130 pContext
= alcGetCurrentContext();
1133 SuspendContext(pContext
);
1137 if (alIsSource(source
))
1139 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1143 case AL_SOURCE_RELATIVE
:
1144 case AL_CONE_INNER_ANGLE
:
1145 case AL_CONE_OUTER_ANGLE
:
1148 case AL_SOURCE_STATE
:
1149 case AL_BUFFERS_QUEUED
:
1150 case AL_BUFFERS_PROCESSED
:
1152 case AL_SAMPLE_OFFSET
:
1153 case AL_BYTE_OFFSET
:
1154 case AL_MAX_DISTANCE
:
1155 case AL_ROLLOFF_FACTOR
:
1156 case AL_REFERENCE_DISTANCE
:
1157 case AL_SOURCE_TYPE
:
1158 alGetSourcei(source
, eParam
, plValues
);
1162 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1163 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1164 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1168 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1169 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1170 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1174 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1175 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1176 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1180 alSetError(AL_INVALID_ENUM
);
1185 alSetError(AL_INVALID_NAME
);
1188 alSetError(AL_INVALID_VALUE
);
1190 ProcessContext(pContext
);
1193 alSetError(AL_INVALID_OPERATION
);
1199 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1201 alSourcePlayv(1, &source
);
1205 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1207 ALCcontext
*pContext
;
1209 ALbufferlistitem
*ALBufferList
;
1210 ALboolean bSourcesValid
= AL_TRUE
;
1214 pContext
= alcGetCurrentContext();
1217 SuspendContext(pContext
);
1221 // Check that all the Sources are valid
1222 for (i
= 0; i
< n
; i
++)
1224 if (!alIsSource(pSourceList
[i
]))
1226 alSetError(AL_INVALID_NAME
);
1227 bSourcesValid
= AL_FALSE
;
1234 for (i
= 0; i
< n
; i
++)
1236 // Assume Source won't need to play
1239 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1241 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1242 ALBufferList
= pSource
->queue
;
1243 while (ALBufferList
)
1245 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1250 ALBufferList
= ALBufferList
->next
;
1255 if (pSource
->state
!= AL_PAUSED
)
1257 pSource
->state
= AL_PLAYING
;
1258 pSource
->inuse
= AL_TRUE
;
1259 pSource
->play
= AL_TRUE
;
1260 pSource
->position
= 0;
1261 pSource
->position_fraction
= 0;
1262 pSource
->BuffersProcessed
= 0;
1263 pSource
->BuffersPlayed
= 0;
1264 pSource
->BufferPosition
= 0;
1265 pSource
->lBytesPlayed
= 0;
1267 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1269 // Make sure all the Buffers in the queue are marked as PENDING
1270 ALBufferList
= pSource
->queue
;
1271 while (ALBufferList
)
1273 ALBufferList
->bufferstate
= PENDING
;
1274 ALBufferList
= ALBufferList
->next
;
1279 pSource
->state
= AL_PLAYING
;
1280 pSource
->inuse
= AL_TRUE
;
1281 pSource
->play
= AL_TRUE
;
1284 // Check if an Offset has been set
1285 if (pSource
->lOffset
)
1286 ApplyOffset(pSource
, AL_FALSE
);
1290 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1291 ALBufferList
= pSource
->queue
;
1292 while (ALBufferList
)
1294 ALBufferList
->bufferstate
= PROCESSED
;
1295 ALBufferList
= ALBufferList
->next
;
1298 pSource
->BuffersPlayed
= pSource
->BuffersProcessed
= pSource
->BuffersInQueue
;
1305 // sources is a NULL pointer
1306 alSetError(AL_INVALID_VALUE
);
1309 ProcessContext(pContext
);
1314 alSetError(AL_INVALID_OPERATION
);
1320 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1322 alSourcePausev(1, &source
);
1326 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1328 ALCcontext
*Context
;
1331 ALboolean bSourcesValid
= AL_TRUE
;
1333 Context
=alcGetCurrentContext();
1336 SuspendContext(Context
);
1340 // Check all the Sources are valid
1343 if (!alIsSource(sources
[i
]))
1345 alSetError(AL_INVALID_NAME
);
1346 bSourcesValid
= AL_FALSE
;
1355 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1356 if (Source
->state
==AL_PLAYING
)
1358 Source
->state
=AL_PAUSED
;
1359 Source
->inuse
=AL_FALSE
;
1366 // sources is a NULL pointer
1367 alSetError(AL_INVALID_VALUE
);
1370 ProcessContext(Context
);
1375 alSetError(AL_INVALID_OPERATION
);
1381 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1383 alSourceStopv(1, &source
);
1387 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1389 ALCcontext
*Context
;
1392 ALbufferlistitem
*ALBufferListItem
;
1393 ALboolean bSourcesValid
= AL_TRUE
;
1395 Context
=alcGetCurrentContext();
1398 SuspendContext(Context
);
1402 // Check all the Sources are valid
1405 if (!alIsSource(sources
[i
]))
1407 alSetError(AL_INVALID_NAME
);
1408 bSourcesValid
= AL_FALSE
;
1417 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1418 if (Source
->state
!=AL_INITIAL
)
1420 Source
->state
=AL_STOPPED
;
1421 Source
->inuse
=AL_FALSE
;
1422 Source
->BuffersPlayed
= Source
->BuffersProcessed
= Source
->BuffersInQueue
;
1423 ALBufferListItem
= Source
->queue
;
1424 while (ALBufferListItem
!= NULL
)
1426 ALBufferListItem
->bufferstate
= PROCESSED
;
1427 ALBufferListItem
= ALBufferListItem
->next
;
1430 Source
->lOffset
= 0;
1436 // sources is a NULL pointer
1437 alSetError(AL_INVALID_VALUE
);
1440 ProcessContext(Context
);
1445 alSetError(AL_INVALID_OPERATION
);
1451 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1453 alSourceRewindv(1, &source
);
1457 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1459 ALCcontext
*Context
;
1462 ALbufferlistitem
*ALBufferListItem
;
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_INITIAL
)
1490 Source
->state
=AL_INITIAL
;
1491 Source
->inuse
=AL_FALSE
;
1493 Source
->position_fraction
=0;
1494 Source
->BuffersProcessed
= 0;
1495 ALBufferListItem
= Source
->queue
;
1496 while (ALBufferListItem
!= NULL
)
1498 ALBufferListItem
->bufferstate
= PENDING
;
1499 ALBufferListItem
= ALBufferListItem
->next
;
1502 Source
->ulBufferID
= Source
->queue
->buffer
;
1504 Source
->lOffset
= 0;
1510 // sources is a NULL pointer
1511 alSetError(AL_INVALID_VALUE
);
1514 ProcessContext(Context
);
1519 alSetError(AL_INVALID_OPERATION
);
1526 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1528 ALCcontext
*Context
;
1531 ALbufferlistitem
*ALBufferList
;
1532 ALbufferlistitem
*ALBufferListStart
;
1537 ALboolean bBuffersValid
= AL_TRUE
;
1542 Context
=alcGetCurrentContext();
1545 SuspendContext(Context
);
1550 // Check that all buffers are valid or zero and that the source is valid
1552 // Check that this is a valid source
1553 if (alIsSource(source
))
1555 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1557 // Check that this is not a STATIC Source
1558 if (ALSource
->lSourceType
!= AL_STATIC
)
1563 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1564 ALBufferList
= ALSource
->queue
;
1565 while (ALBufferList
)
1567 if (ALBufferList
->buffer
)
1569 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1570 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1573 ALBufferList
= ALBufferList
->next
;
1576 for (i
= 0; i
< n
; i
++)
1578 if (alIsBuffer(buffers
[i
]))
1582 if ((iFrequency
== -1) && (iFormat
== -1))
1584 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1585 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1589 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1590 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1592 alSetError(AL_INVALID_OPERATION
);
1593 bBuffersValid
= AL_FALSE
;
1601 alSetError(AL_INVALID_NAME
);
1602 bBuffersValid
= AL_FALSE
;
1609 // Change Source Type
1610 ALSource
->lSourceType
= AL_STREAMING
;
1612 // All buffers are valid - so add them to the list
1613 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1614 ALBufferListStart
->buffer
= buffers
[0];
1615 ALBufferListStart
->bufferstate
= PENDING
;
1616 ALBufferListStart
->flag
= 0;
1617 ALBufferListStart
->next
= NULL
;
1620 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1624 DataSize
+= BufferSize
;
1626 // Increment reference counter for buffer
1628 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1630 ALBufferList
= ALBufferListStart
;
1632 for (i
= 1; i
< n
; i
++)
1634 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1635 ALBufferList
->next
->buffer
= buffers
[i
];
1636 ALBufferList
->next
->bufferstate
= PENDING
;
1637 ALBufferList
->next
->flag
= 0;
1638 ALBufferList
->next
->next
= NULL
;
1641 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1645 DataSize
+= BufferSize
;
1647 // Increment reference counter for buffer
1649 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1651 ALBufferList
= ALBufferList
->next
;
1654 if (ALSource
->queue
== NULL
)
1656 ALSource
->queue
= ALBufferListStart
;
1657 // Update Current Buffer
1658 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1662 // Find end of queue
1663 ALBufferList
= ALSource
->queue
;
1664 while (ALBufferList
->next
!= NULL
)
1666 ALBufferList
= ALBufferList
->next
;
1669 ALBufferList
->next
= ALBufferListStart
;
1672 // Update number of buffers in queue
1673 ALSource
->BuffersInQueue
+= n
;
1678 // Invalid Source Type (can't queue on a Static Source)
1679 alSetError(AL_INVALID_OPERATION
);
1684 // Invalid Source Name
1685 alSetError(AL_INVALID_NAME
);
1688 ProcessContext(Context
);
1693 alSetError(AL_INVALID_OPERATION
);
1700 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1701 // an array of buffer IDs that are to be filled with the names of the buffers removed
1702 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1704 ALCcontext
*Context
;
1707 ALbufferlistitem
*ALBufferList
;
1711 ALboolean bBuffersProcessed
;
1718 bBuffersProcessed
= AL_TRUE
;
1720 Context
=alcGetCurrentContext();
1723 SuspendContext(Context
);
1725 if (alIsSource(source
))
1727 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1729 // Check that all 'n' buffers have been processed
1730 ALBufferList
= ALSource
->queue
;
1731 for (i
= 0; i
< n
; i
++)
1733 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1735 ALBufferList
= ALBufferList
->next
;
1739 bBuffersProcessed
= AL_FALSE
;
1744 // If all 'n' buffers have been processed, remove them from the queue
1745 if (bBuffersProcessed
)
1747 for (i
= 0; i
< n
; i
++)
1749 ALBufferList
= ALSource
->queue
;
1751 ALSource
->queue
= ALBufferList
->next
;
1752 // Record name of buffer
1753 buffers
[i
] = ALBufferList
->buffer
;
1754 // Decrement buffer reference counter
1755 if (ALBufferList
->buffer
)
1756 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1757 // Record size of buffer
1758 if (ALBufferList
->buffer
)
1759 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1763 DataSize
+= BufferSize
;
1764 // Release memory for buffer list item
1766 ALSource
->BuffersInQueue
--;
1767 ALSource
->BuffersProcessed
--;
1770 if (ALSource
->state
!= AL_PLAYING
)
1772 if (ALSource
->queue
)
1773 BufferID
= ALSource
->queue
->buffer
;
1777 ALSource
->ulBufferID
= BufferID
;
1780 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1782 ALSource
->BuffersPlayed
= 0;
1783 ALSource
->BufferPosition
= 0;
1786 ALSource
->BuffersPlayed
-= n
;
1790 // Some buffers can't be unqueue because they have not been processed
1791 alSetError(AL_INVALID_VALUE
);
1796 // Invalid Source Name
1797 alSetError(AL_INVALID_NAME
);
1800 ProcessContext(Context
);
1805 alSetError(AL_INVALID_OPERATION
);
1812 static ALvoid
InitSourceParams(ALsource
*pSource
)
1814 pSource
->flInnerAngle
= 360.0f
;
1815 pSource
->flOuterAngle
= 360.0f
;
1816 pSource
->flPitch
= 1.0f
;
1817 pSource
->vPosition
[0] = 0.0f
;
1818 pSource
->vPosition
[1] = 0.0f
;
1819 pSource
->vPosition
[2] = 0.0f
;
1820 pSource
->vOrientation
[0] = 0.0f
;
1821 pSource
->vOrientation
[1] = 0.0f
;
1822 pSource
->vOrientation
[2] = 0.0f
;
1823 pSource
->vVelocity
[0] = 0.0f
;
1824 pSource
->vVelocity
[1] = 0.0f
;
1825 pSource
->vVelocity
[2] = 0.0f
;
1826 pSource
->flRefDistance
= 1.0f
;
1827 pSource
->flMaxDistance
= FLT_MAX
;
1828 pSource
->flRollOffFactor
= 1.0f
;
1829 pSource
->bLooping
= AL_FALSE
;
1830 pSource
->flGain
= 1.0f
;
1831 pSource
->flMinGain
= 0.0f
;
1832 pSource
->flMaxGain
= 1.0f
;
1833 pSource
->flOuterGain
= 0.0f
;
1835 pSource
->state
= AL_INITIAL
;
1836 pSource
->lSourceType
= AL_UNDETERMINED
;
1838 pSource
->ulBufferID
= 0;
1845 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1846 The offset is relative to the start of the queue (not the start of the current buffer)
1848 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
1850 ALbufferlistitem
*pBufferList
;
1852 ALfloat flBufferFreq
;
1853 ALint lBytesPlayed
, lChannels
;
1854 ALenum eOriginalFormat
;
1855 ALboolean bReturn
= AL_TRUE
;
1856 ALint lTotalBufferDataSize
;
1858 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
1860 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
1861 // Get Current Buffer Size and frequency (in milliseconds)
1862 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
1863 eOriginalFormat
= pBuffer
->eOriginalFormat
;
1864 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
1866 // Get Current BytesPlayed
1867 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
1868 // Add byte length of any processed buffers in the queue
1869 pBufferList
= pSource
->queue
;
1870 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
1872 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
1873 pBufferList
= pBufferList
->next
;
1876 lTotalBufferDataSize
= 0;
1877 pBufferList
= pSource
->queue
;
1880 if (pBufferList
->buffer
)
1881 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
1882 pBufferList
= pBufferList
->next
;
1885 if (pSource
->bLooping
)
1887 if (lBytesPlayed
< 0)
1890 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
1894 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
1895 if(lBytesPlayed
< 0)
1897 if(lBytesPlayed
> lTotalBufferDataSize
)
1898 lBytesPlayed
= lTotalBufferDataSize
;
1904 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
1906 case AL_SAMPLE_OFFSET
:
1907 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
1909 case AL_BYTE_OFFSET
:
1910 // Take into account the original format of the Buffer
1911 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
1912 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
1914 // Compression rate of the ADPCM supported is 3.6111 to 1
1915 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
1916 // Round down to nearest ADPCM block
1917 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
1919 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
1921 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 2);
1923 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
1925 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
1927 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
1929 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
1931 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
1933 *pflOffset
= (ALfloat
)(lBytesPlayed
<< 1);
1937 *pflOffset
= (ALfloat
)lBytesPlayed
;
1954 Apply a playback offset to the Source. This function will update the queue (to correctly
1955 mark buffers as 'pending' or 'processed' depending upon the new offset.
1957 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
1959 ALbufferlistitem
*pBufferList
;
1961 ALint lBufferSize
, lTotalBufferSize
;
1964 // Get true byte offset
1965 lByteOffset
= GetByteOffset(pSource
);
1967 // If this is a valid offset apply it
1968 if (lByteOffset
!= -1)
1970 // Sort out the queue (pending and processed states)
1971 pBufferList
= pSource
->queue
;
1972 lTotalBufferSize
= 0;
1973 pSource
->BuffersPlayed
= 0;
1974 pSource
->BuffersProcessed
= 0;
1977 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
1978 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
1980 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
1982 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
1983 // update the state to PROCESSED
1984 pSource
->BuffersPlayed
++;
1986 if (!pSource
->bLooping
)
1988 pBufferList
->bufferstate
= PROCESSED
;
1989 pSource
->BuffersProcessed
++;
1992 else if (lTotalBufferSize
<= lByteOffset
)
1994 // Offset is within this buffer
1995 pBufferList
->bufferstate
= PENDING
;
1997 // Set Current Buffer ID
1998 pSource
->ulBufferID
= pBufferList
->buffer
;
2000 // Set current position in this buffer
2001 pSource
->BufferPosition
= lByteOffset
- lTotalBufferSize
;
2003 // Set Total Bytes Played to Offset
2004 pSource
->lBytesPlayed
= lByteOffset
;
2006 // SW Mixer Positions are in Samples
2007 pSource
->position
= pSource
->BufferPosition
/
2008 aluBytesFromFormat(pBuffer
->format
) /
2009 aluChannelsFromFormat(pBuffer
->format
);
2013 // Offset is before this buffer, so mark as pending
2014 pBufferList
->bufferstate
= PENDING
;
2017 // Increment the TotalBufferSize
2018 lTotalBufferSize
+= lBufferSize
;
2020 // Move on to next buffer in the Queue
2021 pBufferList
= pBufferList
->next
;
2027 alSetError(AL_INVALID_VALUE
);
2031 pSource
->lOffset
= 0;
2038 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2039 offset supplied by the application). This takes into account the fact that the buffer format
2040 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2042 static ALint
GetByteOffset(ALsource
*pSource
)
2044 ALbuffer
*pBuffer
= NULL
;
2045 ALbufferlistitem
*pBufferList
;
2046 ALfloat flBufferFreq
;
2048 ALint lByteOffset
= -1;
2049 ALint lTotalBufferDataSize
;
2051 // Find the first non-NULL Buffer in the Queue
2052 pBufferList
= pSource
->queue
;
2055 if (pBufferList
->buffer
)
2057 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2060 pBufferList
= pBufferList
->next
;
2065 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2066 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2068 // Determine the ByteOffset (and ensure it is block aligned)
2069 switch (pSource
->lOffsetType
)
2071 case AL_BYTE_OFFSET
:
2072 // Take into consideration the original format
2073 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2074 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2076 // Round down to nearest ADPCM block
2077 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2078 // Multiply by compression rate
2079 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2080 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2082 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2084 lByteOffset
= pSource
->lOffset
* 4;
2085 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2087 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2089 lByteOffset
= pSource
->lOffset
* 2;
2090 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2092 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2094 lByteOffset
= pSource
->lOffset
* 2;
2095 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2097 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2099 lByteOffset
= pSource
->lOffset
/ 2;
2100 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2104 lByteOffset
= pSource
->lOffset
;
2105 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2109 case AL_SAMPLE_OFFSET
:
2110 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2114 // Note - lOffset is internally stored as Milliseconds
2115 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2116 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2120 lTotalBufferDataSize
= 0;
2121 pBufferList
= pSource
->queue
;
2124 if (pBufferList
->buffer
)
2125 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2126 pBufferList
= pBufferList
->next
;
2129 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2130 if (lByteOffset
>= lTotalBufferDataSize
)