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 ALvoid
InitSourceParams(ALsource
*pSource
);
31 ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
);
32 ALvoid
ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
);
33 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
);
345 case AL_SAMPLE_OFFSET
:
349 pSource
->lOffsetType
= eParam
;
351 // Store Offset (convert Seconds into Milliseconds)
352 if (eParam
== AL_SEC_OFFSET
)
353 pSource
->lOffset
= (ALint
)(flValue
* 1000.0f
);
355 pSource
->lOffset
= (ALint
)flValue
;
357 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
358 ApplyOffset(pSource
, AL_TRUE
);
361 alSetError(AL_INVALID_VALUE
);
365 alSetError(AL_INVALID_ENUM
);
371 // Invalid Source Name
372 alSetError(AL_INVALID_NAME
);
375 ProcessContext(pContext
);
380 alSetError(AL_INVALID_OPERATION
);
387 ALAPI ALvoid ALAPIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
389 ALCcontext
*pContext
;
392 pContext
= alcGetCurrentContext();
395 SuspendContext(pContext
);
397 if (alIsSource(source
))
399 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
403 pSource
->vPosition
[0] = flValue1
;
404 pSource
->vPosition
[1] = flValue2
;
405 pSource
->vPosition
[2] = flValue3
;
409 pSource
->vVelocity
[0] = flValue1
;
410 pSource
->vVelocity
[1] = flValue2
;
411 pSource
->vVelocity
[2] = flValue3
;
415 pSource
->vOrientation
[0] = flValue1
;
416 pSource
->vOrientation
[1] = flValue2
;
417 pSource
->vOrientation
[2] = flValue3
;
421 alSetError(AL_INVALID_ENUM
);
426 alSetError(AL_INVALID_NAME
);
428 ProcessContext(pContext
);
432 alSetError(AL_INVALID_OPERATION
);
439 ALAPI ALvoid ALAPIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
441 ALCcontext
*pContext
;
444 pContext
= alcGetCurrentContext();
447 SuspendContext(pContext
);
451 if (alIsSource(source
))
453 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
458 case AL_CONE_INNER_ANGLE
:
459 case AL_CONE_OUTER_ANGLE
:
461 case AL_MAX_DISTANCE
:
462 case AL_ROLLOFF_FACTOR
:
463 case AL_REFERENCE_DISTANCE
:
466 case AL_CONE_OUTER_GAIN
:
468 case AL_SAMPLE_OFFSET
:
470 alSourcef(source
, eParam
, pflValues
[0]);
476 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
480 alSetError(AL_INVALID_ENUM
);
485 alSetError(AL_INVALID_NAME
);
488 alSetError(AL_INVALID_VALUE
);
490 ProcessContext(pContext
);
493 alSetError(AL_INVALID_OPERATION
);
499 ALAPI ALvoid ALAPIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
501 ALCcontext
*pContext
;
503 ALbufferlistitem
*pALBufferListItem
;
508 pContext
= alcGetCurrentContext();
511 SuspendContext(pContext
);
513 if (alIsSource(source
))
515 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
519 case AL_MAX_DISTANCE
:
520 case AL_ROLLOFF_FACTOR
:
521 case AL_REFERENCE_DISTANCE
:
522 alSourcef(source
, eParam
, (ALfloat
)lValue
);
525 case AL_SOURCE_RELATIVE
:
526 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
527 pSource
->bHeadRelative
= (ALboolean
)lValue
;
529 alSetError(AL_INVALID_VALUE
);
532 case AL_CONE_INNER_ANGLE
:
533 if ((lValue
>= 0) && (lValue
<= 360))
534 pSource
->flInnerAngle
= (float)lValue
;
536 alSetError(AL_INVALID_VALUE
);
539 case AL_CONE_OUTER_ANGLE
:
540 if ((lValue
>= 0) && (lValue
<= 360))
541 pSource
->flOuterAngle
= (float)lValue
;
543 alSetError(AL_INVALID_VALUE
);
547 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
548 pSource
->bLooping
= (ALboolean
)lValue
;
550 alSetError(AL_INVALID_VALUE
);
554 if ((pSource
->state
== AL_STOPPED
) || (pSource
->state
== AL_INITIAL
))
556 if (alIsBuffer(lValue
))
558 // Remove all elements in the queue
559 while (pSource
->queue
!= NULL
)
561 pALBufferListItem
= pSource
->queue
;
562 pSource
->queue
= pALBufferListItem
->next
;
563 // Decrement reference counter for buffer
564 if (pALBufferListItem
->buffer
)
565 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
)))->refcount
--;
566 // Record size of buffer
567 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
))->size
;
568 DataSize
+= BufferSize
;
569 // Increment the number of buffers removed from queue
571 // Release memory for buffer list item
572 free(pALBufferListItem
);
573 // Decrement the number of buffers in the queue
574 pSource
->BuffersInQueue
--;
577 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
580 // Source is now in STATIC mode
581 pSource
->lSourceType
= AL_STATIC
;
583 // Add the selected buffer to the queue
584 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
585 pALBufferListItem
->buffer
= lValue
;
586 pALBufferListItem
->bufferstate
= PENDING
;
587 pALBufferListItem
->flag
= 0;
588 pALBufferListItem
->next
= NULL
;
590 pSource
->queue
= pALBufferListItem
;
591 pSource
->BuffersInQueue
= 1;
593 DataSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(lValue
))->size
;
595 // Increment reference counter for buffer
596 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(lValue
)))->refcount
++;
600 // Source is now in UNDETERMINED mode
601 pSource
->lSourceType
= AL_UNDETERMINED
;
604 // Set Buffers Processed
605 pSource
->BuffersProcessed
= 0;
607 // Update AL_BUFFER parameter
608 pSource
->ulBufferID
= lValue
;
611 alSetError(AL_INVALID_VALUE
);
614 alSetError(AL_INVALID_OPERATION
);
617 case AL_SOURCE_STATE
:
619 alSetError(AL_INVALID_OPERATION
);
623 case AL_SAMPLE_OFFSET
:
627 pSource
->lOffsetType
= eParam
;
629 // Store Offset (convert Seconds into Milliseconds)
630 if (eParam
== AL_SEC_OFFSET
)
631 pSource
->lOffset
= lValue
* 1000;
633 pSource
->lOffset
= lValue
;
635 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
636 ApplyOffset(pSource
, AL_TRUE
);
639 alSetError(AL_INVALID_VALUE
);
643 alSetError(AL_INVALID_ENUM
);
648 alSetError(AL_INVALID_NAME
);
650 ProcessContext(pContext
);
653 alSetError(AL_INVALID_OPERATION
);
659 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
661 ALCcontext
*pContext
;
664 pContext
= alcGetCurrentContext();
667 SuspendContext(pContext
);
669 if (alIsSource(source
))
671 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
678 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
682 alSetError(AL_INVALID_ENUM
);
687 alSetError(AL_INVALID_NAME
);
689 ProcessContext(pContext
);
692 alSetError(AL_INVALID_OPERATION
);
698 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
700 ALCcontext
*pContext
;
703 pContext
= alcGetCurrentContext();
706 SuspendContext(pContext
);
710 if (alIsSource(source
))
712 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
716 case AL_SOURCE_RELATIVE
:
717 case AL_CONE_INNER_ANGLE
:
718 case AL_CONE_OUTER_ANGLE
:
721 case AL_SOURCE_STATE
:
723 case AL_SAMPLE_OFFSET
:
725 case AL_MAX_DISTANCE
:
726 case AL_ROLLOFF_FACTOR
:
727 case AL_REFERENCE_DISTANCE
:
728 alSourcei(source
, eParam
, plValues
[0]);
734 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
738 alSetError(AL_INVALID_ENUM
);
743 alSetError(AL_INVALID_NAME
);
746 alSetError(AL_INVALID_VALUE
);
748 ProcessContext(pContext
);
751 alSetError(AL_INVALID_OPERATION
);
757 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
759 ALCcontext
*pContext
;
763 pContext
= alcGetCurrentContext();
766 SuspendContext(pContext
);
770 if (alIsSource(source
))
772 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
777 *pflValue
= pSource
->flPitch
;
781 *pflValue
= pSource
->flGain
;
785 *pflValue
= pSource
->flMinGain
;
789 *pflValue
= pSource
->flMaxGain
;
792 case AL_MAX_DISTANCE
:
793 *pflValue
= pSource
->flMaxDistance
;
796 case AL_ROLLOFF_FACTOR
:
797 *pflValue
= pSource
->flRollOffFactor
;
800 case AL_CONE_OUTER_GAIN
:
801 *pflValue
= pSource
->flOuterGain
;
805 case AL_SAMPLE_OFFSET
:
807 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
808 *pflValue
= flOffset
;
810 alSetError(AL_INVALID_OPERATION
);
813 case AL_CONE_INNER_ANGLE
:
814 *pflValue
= pSource
->flInnerAngle
;
817 case AL_CONE_OUTER_ANGLE
:
818 *pflValue
= pSource
->flOuterAngle
;
821 case AL_REFERENCE_DISTANCE
:
822 *pflValue
= pSource
->flRefDistance
;
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
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
847 ALCcontext
*pContext
;
850 pContext
= alcGetCurrentContext();
853 SuspendContext(pContext
);
855 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
857 if (alIsSource(source
))
859 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
864 *pflValue1
= pSource
->vPosition
[0];
865 *pflValue2
= pSource
->vPosition
[1];
866 *pflValue3
= pSource
->vPosition
[2];
870 *pflValue1
= pSource
->vVelocity
[0];
871 *pflValue2
= pSource
->vVelocity
[1];
872 *pflValue3
= pSource
->vVelocity
[2];
876 *pflValue1
= pSource
->vOrientation
[0];
877 *pflValue2
= pSource
->vOrientation
[1];
878 *pflValue3
= pSource
->vOrientation
[2];
882 alSetError(AL_INVALID_ENUM
);
887 alSetError(AL_INVALID_NAME
);
890 alSetError(AL_INVALID_VALUE
);
892 ProcessContext(pContext
);
895 alSetError(AL_INVALID_OPERATION
);
901 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
903 ALCcontext
*pContext
;
906 pContext
= alcGetCurrentContext();
909 SuspendContext(pContext
);
913 if (alIsSource(source
))
915 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
923 case AL_MAX_DISTANCE
:
924 case AL_ROLLOFF_FACTOR
:
925 case AL_CONE_OUTER_GAIN
:
927 case AL_SAMPLE_OFFSET
:
929 case AL_CONE_INNER_ANGLE
:
930 case AL_CONE_OUTER_ANGLE
:
931 case AL_REFERENCE_DISTANCE
:
932 alGetSourcef(source
, eParam
, pflValues
);
936 pflValues
[0] = pSource
->vPosition
[0];
937 pflValues
[1] = pSource
->vPosition
[1];
938 pflValues
[2] = pSource
->vPosition
[2];
942 pflValues
[0] = pSource
->vVelocity
[0];
943 pflValues
[1] = pSource
->vVelocity
[1];
944 pflValues
[2] = pSource
->vVelocity
[2];
948 pflValues
[0] = pSource
->vOrientation
[0];
949 pflValues
[1] = pSource
->vOrientation
[1];
950 pflValues
[2] = pSource
->vOrientation
[2];
954 alSetError(AL_INVALID_ENUM
);
959 alSetError(AL_INVALID_NAME
);
962 alSetError(AL_INVALID_VALUE
);
964 ProcessContext(pContext
);
967 alSetError(AL_INVALID_OPERATION
);
973 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
975 ALCcontext
*pContext
;
979 pContext
= alcGetCurrentContext();
982 SuspendContext(pContext
);
986 if (alIsSource(source
))
988 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
992 case AL_MAX_DISTANCE
:
993 *plValue
= (ALint
)pSource
->flMaxDistance
;
996 case AL_ROLLOFF_FACTOR
:
997 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1000 case AL_REFERENCE_DISTANCE
:
1001 *plValue
= (ALint
)pSource
->flRefDistance
;
1004 case AL_SOURCE_RELATIVE
:
1005 *plValue
= pSource
->bHeadRelative
;
1008 case AL_CONE_INNER_ANGLE
:
1009 *plValue
= (ALint
)pSource
->flInnerAngle
;
1012 case AL_CONE_OUTER_ANGLE
:
1013 *plValue
= (ALint
)pSource
->flOuterAngle
;
1017 *plValue
= pSource
->bLooping
;
1021 *plValue
= pSource
->ulBufferID
;
1024 case AL_SOURCE_STATE
:
1025 *plValue
= pSource
->state
;
1028 case AL_BUFFERS_QUEUED
:
1029 *plValue
= pSource
->BuffersInQueue
;
1032 case AL_BUFFERS_PROCESSED
:
1033 if(pSource
->bLooping
)
1035 /* Buffers on a looping source are in a perpetual state
1036 * of PENDING, so don't report any as PROCESSED */
1040 *plValue
= pSource
->BuffersProcessed
;
1043 case AL_SOURCE_TYPE
:
1044 *plValue
= pSource
->lSourceType
;
1048 case AL_SAMPLE_OFFSET
:
1049 case AL_BYTE_OFFSET
:
1050 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
1051 *plValue
= (ALint
)flOffset
;
1053 alSetError(AL_INVALID_OPERATION
);
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
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1078 ALCcontext
*pContext
;
1081 pContext
= alcGetCurrentContext();
1084 SuspendContext(pContext
);
1086 if ((plValue1
) && (plValue2
) && (plValue3
))
1088 if (alIsSource(source
))
1090 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1095 *plValue1
= (ALint
)pSource
->vPosition
[0];
1096 *plValue2
= (ALint
)pSource
->vPosition
[1];
1097 *plValue3
= (ALint
)pSource
->vPosition
[2];
1101 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1102 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1103 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1107 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1108 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1109 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1113 alSetError(AL_INVALID_ENUM
);
1118 alSetError(AL_INVALID_NAME
);
1121 alSetError(AL_INVALID_VALUE
);
1123 ProcessContext(pContext
);
1126 alSetError(AL_INVALID_OPERATION
);
1132 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1134 ALCcontext
*pContext
;
1137 pContext
= alcGetCurrentContext();
1140 SuspendContext(pContext
);
1144 if (alIsSource(source
))
1146 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1150 case AL_SOURCE_RELATIVE
:
1151 case AL_CONE_INNER_ANGLE
:
1152 case AL_CONE_OUTER_ANGLE
:
1155 case AL_SOURCE_STATE
:
1156 case AL_BUFFERS_QUEUED
:
1157 case AL_BUFFERS_PROCESSED
:
1159 case AL_SAMPLE_OFFSET
:
1160 case AL_BYTE_OFFSET
:
1161 case AL_MAX_DISTANCE
:
1162 case AL_ROLLOFF_FACTOR
:
1163 case AL_REFERENCE_DISTANCE
:
1164 case AL_SOURCE_TYPE
:
1165 alGetSourcei(source
, eParam
, plValues
);
1169 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1170 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1171 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1175 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1176 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1177 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1181 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1182 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1183 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1187 alSetError(AL_INVALID_ENUM
);
1192 alSetError(AL_INVALID_NAME
);
1195 alSetError(AL_INVALID_VALUE
);
1197 ProcessContext(pContext
);
1200 alSetError(AL_INVALID_OPERATION
);
1206 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1208 alSourcePlayv(1, &source
);
1212 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1214 ALCcontext
*pContext
;
1216 ALbufferlistitem
*ALBufferList
;
1217 ALboolean bSourcesValid
= AL_TRUE
;
1221 pContext
= alcGetCurrentContext();
1224 SuspendContext(pContext
);
1228 // Check that all the Sources are valid
1229 for (i
= 0; i
< n
; i
++)
1231 if (!alIsSource(pSourceList
[i
]))
1233 alSetError(AL_INVALID_NAME
);
1234 bSourcesValid
= AL_FALSE
;
1241 for (i
= 0; i
< n
; i
++)
1243 // Assume Source won't need to play
1246 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1248 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1249 ALBufferList
= pSource
->queue
;
1250 while (ALBufferList
)
1252 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1257 ALBufferList
= ALBufferList
->next
;
1262 if (pSource
->state
!= AL_PAUSED
)
1264 pSource
->state
= AL_PLAYING
;
1265 pSource
->inuse
= AL_TRUE
;
1266 pSource
->play
= AL_TRUE
;
1267 pSource
->position
= 0;
1268 pSource
->position_fraction
= 0;
1269 pSource
->BuffersProcessed
= 0;
1270 pSource
->BuffersPlayed
= 0;
1271 pSource
->BufferPosition
= 0;
1272 pSource
->lBytesPlayed
= 0;
1274 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1276 // Make sure all the Buffers in the queue are marked as PENDING
1277 ALBufferList
= pSource
->queue
;
1278 while (ALBufferList
)
1280 ALBufferList
->bufferstate
= PENDING
;
1281 ALBufferList
= ALBufferList
->next
;
1286 pSource
->state
= AL_PLAYING
;
1287 pSource
->inuse
= AL_TRUE
;
1288 pSource
->play
= AL_TRUE
;
1291 // Check if an Offset has been set
1292 if (pSource
->lOffset
)
1293 ApplyOffset(pSource
, AL_FALSE
);
1297 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1298 ALBufferList
= pSource
->queue
;
1299 while (ALBufferList
)
1301 ALBufferList
->bufferstate
= PROCESSED
;
1302 ALBufferList
= ALBufferList
->next
;
1305 pSource
->BuffersPlayed
= pSource
->BuffersProcessed
= pSource
->BuffersInQueue
;
1312 // sources is a NULL pointer
1313 alSetError(AL_INVALID_VALUE
);
1316 ProcessContext(pContext
);
1321 alSetError(AL_INVALID_OPERATION
);
1327 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1329 alSourcePausev(1, &source
);
1333 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1335 ALCcontext
*Context
;
1338 ALboolean bSourcesValid
= AL_TRUE
;
1340 Context
=alcGetCurrentContext();
1343 SuspendContext(Context
);
1347 // Check all the Sources are valid
1350 if (!alIsSource(sources
[i
]))
1352 alSetError(AL_INVALID_NAME
);
1353 bSourcesValid
= AL_FALSE
;
1362 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1363 if (Source
->state
==AL_PLAYING
)
1365 Source
->state
=AL_PAUSED
;
1366 Source
->inuse
=AL_FALSE
;
1373 // sources is a NULL pointer
1374 alSetError(AL_INVALID_VALUE
);
1377 ProcessContext(Context
);
1382 alSetError(AL_INVALID_OPERATION
);
1388 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1390 alSourceStopv(1, &source
);
1394 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1396 ALCcontext
*Context
;
1399 ALbufferlistitem
*ALBufferListItem
;
1400 ALboolean bSourcesValid
= AL_TRUE
;
1402 Context
=alcGetCurrentContext();
1405 SuspendContext(Context
);
1409 // Check all the Sources are valid
1412 if (!alIsSource(sources
[i
]))
1414 alSetError(AL_INVALID_NAME
);
1415 bSourcesValid
= AL_FALSE
;
1424 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1425 if (Source
->state
!=AL_INITIAL
)
1427 Source
->state
=AL_STOPPED
;
1428 Source
->inuse
=AL_FALSE
;
1429 Source
->BuffersPlayed
= Source
->BuffersProcessed
= Source
->BuffersInQueue
;
1430 ALBufferListItem
= Source
->queue
;
1431 while (ALBufferListItem
!= NULL
)
1433 ALBufferListItem
->bufferstate
= PROCESSED
;
1434 ALBufferListItem
= ALBufferListItem
->next
;
1437 Source
->lOffset
= 0;
1443 // sources is a NULL pointer
1444 alSetError(AL_INVALID_VALUE
);
1447 ProcessContext(Context
);
1452 alSetError(AL_INVALID_OPERATION
);
1458 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1460 alSourceRewindv(1, &source
);
1464 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1466 ALCcontext
*Context
;
1469 ALbufferlistitem
*ALBufferListItem
;
1470 ALboolean bSourcesValid
= AL_TRUE
;
1472 Context
=alcGetCurrentContext();
1475 SuspendContext(Context
);
1479 // Check all the Sources are valid
1482 if (!alIsSource(sources
[i
]))
1484 alSetError(AL_INVALID_NAME
);
1485 bSourcesValid
= AL_FALSE
;
1494 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1495 if (Source
->state
!=AL_INITIAL
)
1497 Source
->state
=AL_INITIAL
;
1498 Source
->inuse
=AL_FALSE
;
1500 Source
->position_fraction
=0;
1501 Source
->BuffersProcessed
= 0;
1502 ALBufferListItem
= Source
->queue
;
1503 while (ALBufferListItem
!= NULL
)
1505 ALBufferListItem
->bufferstate
= PENDING
;
1506 ALBufferListItem
= ALBufferListItem
->next
;
1509 Source
->ulBufferID
= Source
->queue
->buffer
;
1511 Source
->lOffset
= 0;
1517 // sources is a NULL pointer
1518 alSetError(AL_INVALID_VALUE
);
1521 ProcessContext(Context
);
1526 alSetError(AL_INVALID_OPERATION
);
1533 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1535 ALCcontext
*Context
;
1538 ALbufferlistitem
*ALBufferList
;
1539 ALbufferlistitem
*ALBufferListStart
;
1544 ALboolean bBuffersValid
= AL_TRUE
;
1549 Context
=alcGetCurrentContext();
1552 SuspendContext(Context
);
1557 // Check that all buffers are valid or zero and that the source is valid
1559 // Check that this is a valid source
1560 if (alIsSource(source
))
1562 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1564 // Check that this is not a STATIC Source
1565 if (ALSource
->lSourceType
!= AL_STATIC
)
1570 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1571 ALBufferList
= ALSource
->queue
;
1572 while (ALBufferList
)
1574 if (ALBufferList
->buffer
)
1576 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1577 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1580 ALBufferList
= ALBufferList
->next
;
1583 for (i
= 0; i
< n
; i
++)
1585 if (alIsBuffer(buffers
[i
]))
1589 if ((iFrequency
== -1) && (iFormat
== -1))
1591 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1592 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1596 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1597 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1599 alSetError(AL_INVALID_OPERATION
);
1600 bBuffersValid
= AL_FALSE
;
1608 alSetError(AL_INVALID_NAME
);
1609 bBuffersValid
= AL_FALSE
;
1616 // Change Source Type
1617 ALSource
->lSourceType
= AL_STREAMING
;
1619 // All buffers are valid - so add them to the list
1620 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1621 ALBufferListStart
->buffer
= buffers
[0];
1622 ALBufferListStart
->bufferstate
= PENDING
;
1623 ALBufferListStart
->flag
= 0;
1624 ALBufferListStart
->next
= NULL
;
1627 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1631 DataSize
+= BufferSize
;
1633 // Increment reference counter for buffer
1635 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1637 ALBufferList
= ALBufferListStart
;
1639 for (i
= 1; i
< n
; i
++)
1641 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1642 ALBufferList
->next
->buffer
= buffers
[i
];
1643 ALBufferList
->next
->bufferstate
= PENDING
;
1644 ALBufferList
->next
->flag
= 0;
1645 ALBufferList
->next
->next
= NULL
;
1648 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1652 DataSize
+= BufferSize
;
1654 // Increment reference counter for buffer
1656 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1658 ALBufferList
= ALBufferList
->next
;
1661 if (ALSource
->queue
== NULL
)
1663 ALSource
->queue
= ALBufferListStart
;
1664 // Update Current Buffer
1665 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1669 // Find end of queue
1670 ALBufferList
= ALSource
->queue
;
1671 while (ALBufferList
->next
!= NULL
)
1673 ALBufferList
= ALBufferList
->next
;
1676 ALBufferList
->next
= ALBufferListStart
;
1679 // Update number of buffers in queue
1680 ALSource
->BuffersInQueue
+= n
;
1685 // Invalid Source Type (can't queue on a Static Source)
1686 alSetError(AL_INVALID_OPERATION
);
1691 // Invalid Source Name
1692 alSetError(AL_INVALID_NAME
);
1695 ProcessContext(Context
);
1700 alSetError(AL_INVALID_OPERATION
);
1707 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1708 // an array of buffer IDs that are to be filled with the names of the buffers removed
1709 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1711 ALCcontext
*Context
;
1714 ALbufferlistitem
*ALBufferList
;
1718 ALboolean bBuffersProcessed
;
1725 bBuffersProcessed
= AL_TRUE
;
1727 Context
=alcGetCurrentContext();
1730 SuspendContext(Context
);
1732 if (alIsSource(source
))
1734 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1736 // Check that all 'n' buffers have been processed
1737 ALBufferList
= ALSource
->queue
;
1738 for (i
= 0; i
< n
; i
++)
1740 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1742 ALBufferList
= ALBufferList
->next
;
1746 bBuffersProcessed
= AL_FALSE
;
1751 // If all 'n' buffers have been processed, remove them from the queue
1752 if (bBuffersProcessed
)
1754 for (i
= 0; i
< n
; i
++)
1756 ALBufferList
= ALSource
->queue
;
1758 ALSource
->queue
= ALBufferList
->next
;
1759 // Record name of buffer
1760 buffers
[i
] = ALBufferList
->buffer
;
1761 // Decrement buffer reference counter
1762 if (ALBufferList
->buffer
)
1763 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1764 // Record size of buffer
1765 if (ALBufferList
->buffer
)
1766 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1770 DataSize
+= BufferSize
;
1771 // Release memory for buffer list item
1773 ALSource
->BuffersInQueue
--;
1774 ALSource
->BuffersProcessed
--;
1777 if (ALSource
->state
!= AL_PLAYING
)
1779 if (ALSource
->queue
)
1780 BufferID
= ALSource
->queue
->buffer
;
1784 ALSource
->ulBufferID
= BufferID
;
1787 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1789 ALSource
->BuffersPlayed
= 0;
1790 ALSource
->BufferPosition
= 0;
1793 ALSource
->BuffersPlayed
-= n
;
1797 // Some buffers can't be unqueue because they have not been processed
1798 alSetError(AL_INVALID_VALUE
);
1803 // Invalid Source Name
1804 alSetError(AL_INVALID_NAME
);
1807 ProcessContext(Context
);
1812 alSetError(AL_INVALID_OPERATION
);
1819 ALvoid
InitSourceParams(ALsource
*pSource
)
1821 pSource
->flInnerAngle
= 360.0f
;
1822 pSource
->flOuterAngle
= 360.0f
;
1823 pSource
->flPitch
= 1.0f
;
1824 pSource
->vPosition
[0] = 0.0f
;
1825 pSource
->vPosition
[1] = 0.0f
;
1826 pSource
->vPosition
[2] = 0.0f
;
1827 pSource
->vOrientation
[0] = 0.0f
;
1828 pSource
->vOrientation
[1] = 0.0f
;
1829 pSource
->vOrientation
[2] = 0.0f
;
1830 pSource
->vVelocity
[0] = 0.0f
;
1831 pSource
->vVelocity
[1] = 0.0f
;
1832 pSource
->vVelocity
[2] = 0.0f
;
1833 pSource
->flRefDistance
= 1.0f
;
1834 pSource
->flMaxDistance
= FLT_MAX
;
1835 pSource
->flRollOffFactor
= 1.0f
;
1836 pSource
->bLooping
= AL_FALSE
;
1837 pSource
->flGain
= 1.0f
;
1838 pSource
->flMinGain
= 0.0f
;
1839 pSource
->flMaxGain
= 1.0f
;
1840 pSource
->flOuterGain
= 0.0f
;
1842 pSource
->state
= AL_INITIAL
;
1843 pSource
->lSourceType
= AL_UNDETERMINED
;
1845 pSource
->ulBufferID
= 0;
1852 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1853 The offset is relative to the start of the queue (not the start of the current buffer)
1855 ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
1857 ALbufferlistitem
*pBufferList
;
1858 ALfloat flBufferFreq
;
1859 ALint lBufferSize
, lBytesPlayed
, lChannels
;
1860 ALenum eOriginalFormat
;
1861 ALboolean bReturn
= AL_TRUE
;
1862 ALint lTotalBufferDataSize
;
1864 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
1866 // Get Current Buffer Size and frequency (in milliseconds)
1867 lBufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
))->size
;
1868 flBufferFreq
= (ALfloat
)(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
))->frequency
);
1869 eOriginalFormat
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
))->eOriginalFormat
;
1870 lChannels
= ((((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
))->format
== AL_FORMAT_MONO16
)?1:2);
1872 // Get Current BytesPlayed
1873 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
1874 // Add byte length of any processed buffers in the queue
1875 pBufferList
= pSource
->queue
;
1876 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
1878 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
1879 pBufferList
= pBufferList
->next
;
1882 lTotalBufferDataSize
= 0;
1883 pBufferList
= pSource
->queue
;
1886 if (pBufferList
->buffer
)
1887 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
1888 pBufferList
= pBufferList
->next
;
1891 if (pSource
->bLooping
)
1893 if (lBytesPlayed
< 0)
1896 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
1900 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
1901 if(lBytesPlayed
< 0)
1903 if(lBytesPlayed
> lTotalBufferDataSize
)
1904 lBytesPlayed
= lTotalBufferDataSize
;
1910 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
1912 case AL_SAMPLE_OFFSET
:
1913 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
1915 case AL_BYTE_OFFSET
:
1916 // Take into account the original format of the Buffer
1917 if ((eOriginalFormat
== AL_FORMAT_MONO8
) || (eOriginalFormat
== AL_FORMAT_STEREO8
))
1919 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
1921 else if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) || (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
1923 // Compression rate of the ADPCM supported is 3.6111 to 1
1924 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
1925 // Round down to nearest ADPCM block
1926 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
1930 *pflOffset
= (ALfloat
)lBytesPlayed
;
1947 Apply a playback offset to the Source. This function will update the queue (to correctly
1948 mark buffers as 'pending' or 'processed' depending upon the new offset.
1950 void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
1952 ALbufferlistitem
*pBufferList
;
1953 ALint lBufferSize
, lTotalBufferSize
;
1956 // Get true byte offset
1957 lByteOffset
= GetByteOffset(pSource
);
1959 // If this is a valid offset apply it
1960 if (lByteOffset
!= -1)
1962 // Sort out the queue (pending and processed states)
1963 pBufferList
= pSource
->queue
;
1964 lTotalBufferSize
= 0;
1965 pSource
->BuffersPlayed
= 0;
1966 pSource
->BuffersProcessed
= 0;
1969 lBufferSize
= pBufferList
->buffer
? ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
: 0;
1971 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
1973 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
1974 // update the state to PROCESSED
1975 pSource
->BuffersPlayed
++;
1977 if (!pSource
->bLooping
)
1979 pBufferList
->bufferstate
= PROCESSED
;
1980 pSource
->BuffersProcessed
++;
1983 else if (lTotalBufferSize
<= lByteOffset
)
1985 // Offset is within this buffer
1986 pBufferList
->bufferstate
= PENDING
;
1988 // Set Current Buffer ID
1989 pSource
->ulBufferID
= pBufferList
->buffer
;
1991 // Set current position in this buffer
1992 pSource
->BufferPosition
= lByteOffset
- lTotalBufferSize
;
1994 // Set Total Bytes Played to Offset
1995 pSource
->lBytesPlayed
= lByteOffset
;
1997 // SW Mixer Positions are in Samples
1998 pSource
->position
= pSource
->BufferPosition
/ ((((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->format
== AL_FORMAT_MONO16
)?2:4);
2002 // Offset is before this buffer, so mark as pending
2003 pBufferList
->bufferstate
= PENDING
;
2006 // Increment the TotalBufferSize
2007 lTotalBufferSize
+= lBufferSize
;
2009 // Move on to next buffer in the Queue
2010 pBufferList
= pBufferList
->next
;
2016 alSetError(AL_INVALID_VALUE
);
2020 pSource
->lOffset
= 0;
2027 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2028 offset supplied by the application). This takes into account the fact that the buffer format
2029 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2031 ALint
GetByteOffset(ALsource
*pSource
)
2033 ALbuffer
*pBuffer
= NULL
;
2034 ALbufferlistitem
*pBufferList
;
2035 ALfloat flBufferFreq
;
2037 ALint lByteOffset
= -1;
2038 ALint lTotalBufferDataSize
;
2040 // Find the first non-NULL Buffer in the Queue
2041 pBufferList
= pSource
->queue
;
2044 if (pBufferList
->buffer
)
2046 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2049 pBufferList
= pBufferList
->next
;
2054 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2055 lChannels
= (pBuffer
->format
== AL_FORMAT_MONO16
)?1:2;
2057 // Determine the ByteOffset (and ensure it is block aligned)
2058 switch (pSource
->lOffsetType
)
2060 case AL_BYTE_OFFSET
:
2061 // Take into consideration the original format
2062 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO8
) || (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO8
))
2064 lByteOffset
= pSource
->lOffset
* 2;
2065 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2067 else if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) || (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2069 // Round down to nearest ADPCM block
2070 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2071 // Multiply by compression rate
2072 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2073 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2077 lByteOffset
= pSource
->lOffset
;
2078 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2082 case AL_SAMPLE_OFFSET
:
2083 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2087 // Note - lOffset is internally stored as Milliseconds
2088 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2089 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2093 lTotalBufferDataSize
= 0;
2094 pBufferList
= pSource
->queue
;
2097 if (pBufferList
->buffer
)
2098 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2099 pBufferList
= pBufferList
->next
;
2102 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2103 if (lByteOffset
>= lTotalBufferDataSize
)