2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
30 static ALvoid
InitSourceParams(ALsource
*pSource
);
31 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
);
32 static ALvoid
ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
);
33 static ALint
GetByteOffset(ALsource
*pSource
);
35 ALAPI ALvoid ALAPIENTRY
alGenSources(ALsizei n
,ALuint
*sources
)
41 Context
= alcGetCurrentContext();
44 SuspendContext(Context
);
48 Device
= alcGetContextsDevice(Context
);
52 // Check that enough memory has been allocted in the 'sources' array for n Sources
53 if (!IsBadWritePtr((void*)sources
, n
* sizeof(ALuint
)))
55 // Check that the requested number of sources can be generated
56 if ((Context
->SourceCount
+ n
) <= Device
->MaxNoOfSources
)
58 ALsource
**list
= &Context
->Source
;
60 list
= &(*list
)->next
;
62 // Add additional sources to the list (Source->next points to the location for the next Source structure)
65 *list
= calloc(1, sizeof(ALsource
));
68 sources
[i
]=(ALuint
)ALTHUNK_ADDENTRY(*list
);
69 (*list
)->source
= sources
[i
];
71 InitSourceParams(*list
);
72 Context
->SourceCount
++;
75 list
= &(*list
)->next
;
79 // If we didn't create all the Sources, we must have run out or memory
81 alSetError(AL_OUT_OF_MEMORY
);
85 // Not enough resources to create the Sources
86 alSetError(AL_INVALID_VALUE
);
92 alSetError(AL_INVALID_VALUE
);
97 // No Device created, or attached to Context
98 alSetError(AL_INVALID_OPERATION
);
102 ProcessContext(Context
);
107 alSetError(AL_INVALID_OPERATION
);
114 ALAPI ALvoid ALAPIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
121 ALbufferlistitem
*ALBufferList
;
122 ALboolean bSourcesValid
= AL_TRUE
;
124 Context
= alcGetCurrentContext();
127 SuspendContext(Context
);
131 Device
= alcGetContextsDevice(Context
);
135 if ((ALuint
)n
<= Context
->SourceCount
)
137 // Check that all Sources are valid (and can therefore be deleted)
138 for (i
= 0; i
< n
; i
++)
140 if (!alIsSource(sources
[i
]))
142 alSetError(AL_INVALID_NAME
);
143 bSourcesValid
= AL_FALSE
;
150 // All Sources are valid, and can be deleted
151 for (i
= 0; i
< n
; i
++)
153 // Recheck that the Source is valid, because there could be duplicated Source names
154 if (alIsSource(sources
[i
]))
156 ALSource
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
157 alSourceStop((ALuint
)ALSource
->source
);
159 // For each buffer in the source's queue, decrement its reference counter and remove it
160 while (ALSource
->queue
!= NULL
)
162 ALBufferList
= ALSource
->queue
;
163 // Decrement buffer's reference counter
164 if (ALBufferList
->buffer
!= 0)
165 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
166 // Update queue to point to next element in list
167 ALSource
->queue
= ALBufferList
->next
;
168 // Release memory allocated for buffer list item
172 // Decrement Source count
173 Context
->SourceCount
--;
175 // Remove Source from list of Sources
176 list
= &Context
->Source
;
177 while(*list
&& *list
!= ALSource
)
178 list
= &(*list
)->next
;
181 *list
= (*list
)->next
;
182 ALTHUNK_REMOVEENTRY(ALSource
->source
);
184 memset(ALSource
,0,sizeof(ALsource
));
193 // Trying to delete more Sources than have been generated
194 alSetError(AL_INVALID_NAME
);
199 // No Device created, or attached to Context
200 alSetError(AL_INVALID_OPERATION
);
204 alSetError(AL_INVALID_VALUE
);
206 ProcessContext(Context
);
211 alSetError(AL_INVALID_OPERATION
);
218 ALAPI ALboolean ALAPIENTRY
alIsSource(ALuint source
)
220 ALboolean result
=AL_FALSE
;
224 Context
=alcGetCurrentContext();
227 SuspendContext(Context
);
229 // To determine if this is a valid Source name, look through the list of generated Sources
230 Source
= Context
->Source
;
233 if (Source
== (ALsource
*)ALTHUNK_LOOKUPENTRY(source
))
239 Source
= Source
->next
;
242 ProcessContext(Context
);
247 alSetError(AL_INVALID_OPERATION
);
254 ALAPI ALvoid ALAPIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
256 ALCcontext
*pContext
;
259 pContext
= alcGetCurrentContext();
262 SuspendContext(pContext
);
264 if (alIsSource(source
))
266 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
273 pSource
->flPitch
= flValue
;
274 if(pSource
->flPitch
< 0.001f
)
275 pSource
->flPitch
= 0.001f
;
278 alSetError(AL_INVALID_VALUE
);
281 case AL_CONE_INNER_ANGLE
:
282 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
283 pSource
->flInnerAngle
= flValue
;
285 alSetError(AL_INVALID_VALUE
);
288 case AL_CONE_OUTER_ANGLE
:
289 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
290 pSource
->flOuterAngle
= flValue
;
292 alSetError(AL_INVALID_VALUE
);
297 pSource
->flGain
= flValue
;
299 alSetError(AL_INVALID_VALUE
);
302 case AL_MAX_DISTANCE
:
304 pSource
->flMaxDistance
= flValue
;
306 alSetError(AL_INVALID_VALUE
);
309 case AL_ROLLOFF_FACTOR
:
311 pSource
->flRollOffFactor
= flValue
;
313 alSetError(AL_INVALID_VALUE
);
316 case AL_REFERENCE_DISTANCE
:
318 pSource
->flRefDistance
= flValue
;
320 alSetError(AL_INVALID_VALUE
);
324 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
325 pSource
->flMinGain
= flValue
;
327 alSetError(AL_INVALID_VALUE
);
331 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
332 pSource
->flMaxGain
= flValue
;
334 alSetError(AL_INVALID_VALUE
);
337 case AL_CONE_OUTER_GAIN
:
338 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
339 pSource
->flOuterGain
= flValue
;
341 alSetError(AL_INVALID_VALUE
);
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
;
443 pContext
= alcGetCurrentContext();
446 SuspendContext(pContext
);
450 if (alIsSource(source
))
455 case AL_CONE_INNER_ANGLE
:
456 case AL_CONE_OUTER_ANGLE
:
458 case AL_MAX_DISTANCE
:
459 case AL_ROLLOFF_FACTOR
:
460 case AL_REFERENCE_DISTANCE
:
463 case AL_CONE_OUTER_GAIN
:
465 case AL_SAMPLE_OFFSET
:
467 alSourcef(source
, eParam
, pflValues
[0]);
473 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
477 alSetError(AL_INVALID_ENUM
);
482 alSetError(AL_INVALID_NAME
);
485 alSetError(AL_INVALID_VALUE
);
487 ProcessContext(pContext
);
490 alSetError(AL_INVALID_OPERATION
);
496 ALAPI ALvoid ALAPIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
498 ALCcontext
*pContext
;
500 ALbufferlistitem
*pALBufferListItem
;
505 pContext
= alcGetCurrentContext();
508 SuspendContext(pContext
);
510 if (alIsSource(source
))
512 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
516 case AL_MAX_DISTANCE
:
517 case AL_ROLLOFF_FACTOR
:
518 case AL_REFERENCE_DISTANCE
:
519 alSourcef(source
, eParam
, (ALfloat
)lValue
);
522 case AL_SOURCE_RELATIVE
:
523 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
524 pSource
->bHeadRelative
= (ALboolean
)lValue
;
526 alSetError(AL_INVALID_VALUE
);
529 case AL_CONE_INNER_ANGLE
:
530 if ((lValue
>= 0) && (lValue
<= 360))
531 pSource
->flInnerAngle
= (float)lValue
;
533 alSetError(AL_INVALID_VALUE
);
536 case AL_CONE_OUTER_ANGLE
:
537 if ((lValue
>= 0) && (lValue
<= 360))
538 pSource
->flOuterAngle
= (float)lValue
;
540 alSetError(AL_INVALID_VALUE
);
544 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
545 pSource
->bLooping
= (ALboolean
)lValue
;
547 alSetError(AL_INVALID_VALUE
);
551 if ((pSource
->state
== AL_STOPPED
) || (pSource
->state
== AL_INITIAL
))
553 if (alIsBuffer(lValue
))
555 // Remove all elements in the queue
556 while (pSource
->queue
!= NULL
)
558 pALBufferListItem
= pSource
->queue
;
559 pSource
->queue
= pALBufferListItem
->next
;
560 // Decrement reference counter for buffer
561 if (pALBufferListItem
->buffer
)
562 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
)))->refcount
--;
563 // Record size of buffer
564 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
))->size
;
565 DataSize
+= BufferSize
;
566 // Increment the number of buffers removed from queue
568 // Release memory for buffer list item
569 free(pALBufferListItem
);
570 // Decrement the number of buffers in the queue
571 pSource
->BuffersInQueue
--;
574 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
577 // Source is now in STATIC mode
578 pSource
->lSourceType
= AL_STATIC
;
580 // Add the selected buffer to the queue
581 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
582 pALBufferListItem
->buffer
= lValue
;
583 pALBufferListItem
->bufferstate
= PENDING
;
584 pALBufferListItem
->flag
= 0;
585 pALBufferListItem
->next
= NULL
;
587 pSource
->queue
= pALBufferListItem
;
588 pSource
->BuffersInQueue
= 1;
590 DataSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(lValue
))->size
;
592 // Increment reference counter for buffer
593 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(lValue
)))->refcount
++;
597 // Source is now in UNDETERMINED mode
598 pSource
->lSourceType
= AL_UNDETERMINED
;
601 // Set Buffers Processed
602 pSource
->BuffersProcessed
= 0;
604 // Update AL_BUFFER parameter
605 pSource
->ulBufferID
= lValue
;
608 alSetError(AL_INVALID_VALUE
);
611 alSetError(AL_INVALID_OPERATION
);
614 case AL_SOURCE_STATE
:
616 alSetError(AL_INVALID_OPERATION
);
620 case AL_SAMPLE_OFFSET
:
624 pSource
->lOffsetType
= eParam
;
626 // Store Offset (convert Seconds into Milliseconds)
627 if (eParam
== AL_SEC_OFFSET
)
628 pSource
->lOffset
= lValue
* 1000;
630 pSource
->lOffset
= lValue
;
632 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
633 ApplyOffset(pSource
, AL_TRUE
);
636 alSetError(AL_INVALID_VALUE
);
640 alSetError(AL_INVALID_ENUM
);
645 alSetError(AL_INVALID_NAME
);
647 ProcessContext(pContext
);
650 alSetError(AL_INVALID_OPERATION
);
656 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
658 ALCcontext
*pContext
;
660 pContext
= alcGetCurrentContext();
663 SuspendContext(pContext
);
665 if (alIsSource(source
))
672 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
676 alSetError(AL_INVALID_ENUM
);
681 alSetError(AL_INVALID_NAME
);
683 ProcessContext(pContext
);
686 alSetError(AL_INVALID_OPERATION
);
692 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
694 ALCcontext
*pContext
;
696 pContext
= alcGetCurrentContext();
699 SuspendContext(pContext
);
703 if (alIsSource(source
))
707 case AL_SOURCE_RELATIVE
:
708 case AL_CONE_INNER_ANGLE
:
709 case AL_CONE_OUTER_ANGLE
:
712 case AL_SOURCE_STATE
:
714 case AL_SAMPLE_OFFSET
:
716 case AL_MAX_DISTANCE
:
717 case AL_ROLLOFF_FACTOR
:
718 case AL_REFERENCE_DISTANCE
:
719 alSourcei(source
, eParam
, plValues
[0]);
725 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
729 alSetError(AL_INVALID_ENUM
);
734 alSetError(AL_INVALID_NAME
);
737 alSetError(AL_INVALID_VALUE
);
739 ProcessContext(pContext
);
742 alSetError(AL_INVALID_OPERATION
);
748 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
750 ALCcontext
*pContext
;
754 pContext
= alcGetCurrentContext();
757 SuspendContext(pContext
);
761 if (alIsSource(source
))
763 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
768 *pflValue
= pSource
->flPitch
;
772 *pflValue
= pSource
->flGain
;
776 *pflValue
= pSource
->flMinGain
;
780 *pflValue
= pSource
->flMaxGain
;
783 case AL_MAX_DISTANCE
:
784 *pflValue
= pSource
->flMaxDistance
;
787 case AL_ROLLOFF_FACTOR
:
788 *pflValue
= pSource
->flRollOffFactor
;
791 case AL_CONE_OUTER_GAIN
:
792 *pflValue
= pSource
->flOuterGain
;
796 case AL_SAMPLE_OFFSET
:
798 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
799 *pflValue
= flOffset
;
801 alSetError(AL_INVALID_OPERATION
);
804 case AL_CONE_INNER_ANGLE
:
805 *pflValue
= pSource
->flInnerAngle
;
808 case AL_CONE_OUTER_ANGLE
:
809 *pflValue
= pSource
->flOuterAngle
;
812 case AL_REFERENCE_DISTANCE
:
813 *pflValue
= pSource
->flRefDistance
;
817 alSetError(AL_INVALID_ENUM
);
822 alSetError(AL_INVALID_NAME
);
825 alSetError(AL_INVALID_VALUE
);
827 ProcessContext(pContext
);
830 alSetError(AL_INVALID_OPERATION
);
836 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
838 ALCcontext
*pContext
;
841 pContext
= alcGetCurrentContext();
844 SuspendContext(pContext
);
846 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
848 if (alIsSource(source
))
850 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
855 *pflValue1
= pSource
->vPosition
[0];
856 *pflValue2
= pSource
->vPosition
[1];
857 *pflValue3
= pSource
->vPosition
[2];
861 *pflValue1
= pSource
->vVelocity
[0];
862 *pflValue2
= pSource
->vVelocity
[1];
863 *pflValue3
= pSource
->vVelocity
[2];
867 *pflValue1
= pSource
->vOrientation
[0];
868 *pflValue2
= pSource
->vOrientation
[1];
869 *pflValue3
= pSource
->vOrientation
[2];
873 alSetError(AL_INVALID_ENUM
);
878 alSetError(AL_INVALID_NAME
);
881 alSetError(AL_INVALID_VALUE
);
883 ProcessContext(pContext
);
886 alSetError(AL_INVALID_OPERATION
);
892 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
894 ALCcontext
*pContext
;
897 pContext
= alcGetCurrentContext();
900 SuspendContext(pContext
);
904 if (alIsSource(source
))
906 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
914 case AL_MAX_DISTANCE
:
915 case AL_ROLLOFF_FACTOR
:
916 case AL_CONE_OUTER_GAIN
:
918 case AL_SAMPLE_OFFSET
:
920 case AL_CONE_INNER_ANGLE
:
921 case AL_CONE_OUTER_ANGLE
:
922 case AL_REFERENCE_DISTANCE
:
923 alGetSourcef(source
, eParam
, pflValues
);
927 pflValues
[0] = pSource
->vPosition
[0];
928 pflValues
[1] = pSource
->vPosition
[1];
929 pflValues
[2] = pSource
->vPosition
[2];
933 pflValues
[0] = pSource
->vVelocity
[0];
934 pflValues
[1] = pSource
->vVelocity
[1];
935 pflValues
[2] = pSource
->vVelocity
[2];
939 pflValues
[0] = pSource
->vOrientation
[0];
940 pflValues
[1] = pSource
->vOrientation
[1];
941 pflValues
[2] = pSource
->vOrientation
[2];
945 alSetError(AL_INVALID_ENUM
);
950 alSetError(AL_INVALID_NAME
);
953 alSetError(AL_INVALID_VALUE
);
955 ProcessContext(pContext
);
958 alSetError(AL_INVALID_OPERATION
);
964 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
966 ALCcontext
*pContext
;
970 pContext
= alcGetCurrentContext();
973 SuspendContext(pContext
);
977 if (alIsSource(source
))
979 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
983 case AL_MAX_DISTANCE
:
984 *plValue
= (ALint
)pSource
->flMaxDistance
;
987 case AL_ROLLOFF_FACTOR
:
988 *plValue
= (ALint
)pSource
->flRollOffFactor
;
991 case AL_REFERENCE_DISTANCE
:
992 *plValue
= (ALint
)pSource
->flRefDistance
;
995 case AL_SOURCE_RELATIVE
:
996 *plValue
= pSource
->bHeadRelative
;
999 case AL_CONE_INNER_ANGLE
:
1000 *plValue
= (ALint
)pSource
->flInnerAngle
;
1003 case AL_CONE_OUTER_ANGLE
:
1004 *plValue
= (ALint
)pSource
->flOuterAngle
;
1008 *plValue
= pSource
->bLooping
;
1012 *plValue
= pSource
->ulBufferID
;
1015 case AL_SOURCE_STATE
:
1016 *plValue
= pSource
->state
;
1019 case AL_BUFFERS_QUEUED
:
1020 *plValue
= pSource
->BuffersInQueue
;
1023 case AL_BUFFERS_PROCESSED
:
1024 if(pSource
->bLooping
)
1026 /* Buffers on a looping source are in a perpetual state
1027 * of PENDING, so don't report any as PROCESSED */
1031 *plValue
= pSource
->BuffersProcessed
;
1034 case AL_SOURCE_TYPE
:
1035 *plValue
= pSource
->lSourceType
;
1039 case AL_SAMPLE_OFFSET
:
1040 case AL_BYTE_OFFSET
:
1041 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
1042 *plValue
= (ALint
)flOffset
;
1044 alSetError(AL_INVALID_OPERATION
);
1048 alSetError(AL_INVALID_ENUM
);
1053 alSetError(AL_INVALID_NAME
);
1056 alSetError(AL_INVALID_VALUE
);
1058 ProcessContext(pContext
);
1061 alSetError(AL_INVALID_OPERATION
);
1067 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1069 ALCcontext
*pContext
;
1072 pContext
= alcGetCurrentContext();
1075 SuspendContext(pContext
);
1077 if ((plValue1
) && (plValue2
) && (plValue3
))
1079 if (alIsSource(source
))
1081 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1086 *plValue1
= (ALint
)pSource
->vPosition
[0];
1087 *plValue2
= (ALint
)pSource
->vPosition
[1];
1088 *plValue3
= (ALint
)pSource
->vPosition
[2];
1092 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1093 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1094 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1098 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1099 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1100 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1104 alSetError(AL_INVALID_ENUM
);
1109 alSetError(AL_INVALID_NAME
);
1112 alSetError(AL_INVALID_VALUE
);
1114 ProcessContext(pContext
);
1117 alSetError(AL_INVALID_OPERATION
);
1123 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1125 ALCcontext
*pContext
;
1128 pContext
= alcGetCurrentContext();
1131 SuspendContext(pContext
);
1135 if (alIsSource(source
))
1137 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1141 case AL_SOURCE_RELATIVE
:
1142 case AL_CONE_INNER_ANGLE
:
1143 case AL_CONE_OUTER_ANGLE
:
1146 case AL_SOURCE_STATE
:
1147 case AL_BUFFERS_QUEUED
:
1148 case AL_BUFFERS_PROCESSED
:
1150 case AL_SAMPLE_OFFSET
:
1151 case AL_BYTE_OFFSET
:
1152 case AL_MAX_DISTANCE
:
1153 case AL_ROLLOFF_FACTOR
:
1154 case AL_REFERENCE_DISTANCE
:
1155 case AL_SOURCE_TYPE
:
1156 alGetSourcei(source
, eParam
, plValues
);
1160 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1161 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1162 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1166 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1167 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1168 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1172 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1173 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1174 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
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 ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1199 alSourcePlayv(1, &source
);
1203 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1205 ALCcontext
*pContext
;
1207 ALbufferlistitem
*ALBufferList
;
1208 ALboolean bSourcesValid
= AL_TRUE
;
1212 pContext
= alcGetCurrentContext();
1215 SuspendContext(pContext
);
1219 // Check that all the Sources are valid
1220 for (i
= 0; i
< n
; i
++)
1222 if (!alIsSource(pSourceList
[i
]))
1224 alSetError(AL_INVALID_NAME
);
1225 bSourcesValid
= AL_FALSE
;
1232 for (i
= 0; i
< n
; i
++)
1234 // Assume Source won't need to play
1237 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1239 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1240 ALBufferList
= pSource
->queue
;
1241 while (ALBufferList
)
1243 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1248 ALBufferList
= ALBufferList
->next
;
1253 if (pSource
->state
!= AL_PAUSED
)
1255 pSource
->state
= AL_PLAYING
;
1256 pSource
->inuse
= AL_TRUE
;
1257 pSource
->play
= AL_TRUE
;
1258 pSource
->position
= 0;
1259 pSource
->position_fraction
= 0;
1260 pSource
->BuffersProcessed
= 0;
1261 pSource
->BuffersPlayed
= 0;
1262 pSource
->BufferPosition
= 0;
1263 pSource
->lBytesPlayed
= 0;
1265 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1267 // Make sure all the Buffers in the queue are marked as PENDING
1268 ALBufferList
= pSource
->queue
;
1269 while (ALBufferList
)
1271 ALBufferList
->bufferstate
= PENDING
;
1272 ALBufferList
= ALBufferList
->next
;
1277 pSource
->state
= AL_PLAYING
;
1278 pSource
->inuse
= AL_TRUE
;
1279 pSource
->play
= AL_TRUE
;
1282 // Check if an Offset has been set
1283 if (pSource
->lOffset
)
1284 ApplyOffset(pSource
, AL_FALSE
);
1288 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1289 ALBufferList
= pSource
->queue
;
1290 while (ALBufferList
)
1292 ALBufferList
->bufferstate
= PROCESSED
;
1293 ALBufferList
= ALBufferList
->next
;
1296 pSource
->BuffersPlayed
= pSource
->BuffersProcessed
= pSource
->BuffersInQueue
;
1303 // sources is a NULL pointer
1304 alSetError(AL_INVALID_VALUE
);
1307 ProcessContext(pContext
);
1312 alSetError(AL_INVALID_OPERATION
);
1318 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1320 alSourcePausev(1, &source
);
1324 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1326 ALCcontext
*Context
;
1329 ALboolean bSourcesValid
= AL_TRUE
;
1331 Context
=alcGetCurrentContext();
1334 SuspendContext(Context
);
1338 // Check all the Sources are valid
1341 if (!alIsSource(sources
[i
]))
1343 alSetError(AL_INVALID_NAME
);
1344 bSourcesValid
= AL_FALSE
;
1353 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1354 if (Source
->state
==AL_PLAYING
)
1356 Source
->state
=AL_PAUSED
;
1357 Source
->inuse
=AL_FALSE
;
1364 // sources is a NULL pointer
1365 alSetError(AL_INVALID_VALUE
);
1368 ProcessContext(Context
);
1373 alSetError(AL_INVALID_OPERATION
);
1379 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1381 alSourceStopv(1, &source
);
1385 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1387 ALCcontext
*Context
;
1390 ALbufferlistitem
*ALBufferListItem
;
1391 ALboolean bSourcesValid
= AL_TRUE
;
1393 Context
=alcGetCurrentContext();
1396 SuspendContext(Context
);
1400 // Check all the Sources are valid
1403 if (!alIsSource(sources
[i
]))
1405 alSetError(AL_INVALID_NAME
);
1406 bSourcesValid
= AL_FALSE
;
1415 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1416 if (Source
->state
!=AL_INITIAL
)
1418 Source
->state
=AL_STOPPED
;
1419 Source
->inuse
=AL_FALSE
;
1420 Source
->BuffersPlayed
= Source
->BuffersProcessed
= Source
->BuffersInQueue
;
1421 ALBufferListItem
= Source
->queue
;
1422 while (ALBufferListItem
!= NULL
)
1424 ALBufferListItem
->bufferstate
= PROCESSED
;
1425 ALBufferListItem
= ALBufferListItem
->next
;
1428 Source
->lOffset
= 0;
1434 // sources is a NULL pointer
1435 alSetError(AL_INVALID_VALUE
);
1438 ProcessContext(Context
);
1443 alSetError(AL_INVALID_OPERATION
);
1449 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1451 alSourceRewindv(1, &source
);
1455 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1457 ALCcontext
*Context
;
1460 ALbufferlistitem
*ALBufferListItem
;
1461 ALboolean bSourcesValid
= AL_TRUE
;
1463 Context
=alcGetCurrentContext();
1466 SuspendContext(Context
);
1470 // Check all the Sources are valid
1473 if (!alIsSource(sources
[i
]))
1475 alSetError(AL_INVALID_NAME
);
1476 bSourcesValid
= AL_FALSE
;
1485 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1486 if (Source
->state
!=AL_INITIAL
)
1488 Source
->state
=AL_INITIAL
;
1489 Source
->inuse
=AL_FALSE
;
1491 Source
->position_fraction
=0;
1492 Source
->BuffersProcessed
= 0;
1493 ALBufferListItem
= Source
->queue
;
1494 while (ALBufferListItem
!= NULL
)
1496 ALBufferListItem
->bufferstate
= PENDING
;
1497 ALBufferListItem
= ALBufferListItem
->next
;
1500 Source
->ulBufferID
= Source
->queue
->buffer
;
1502 Source
->lOffset
= 0;
1508 // sources is a NULL pointer
1509 alSetError(AL_INVALID_VALUE
);
1512 ProcessContext(Context
);
1517 alSetError(AL_INVALID_OPERATION
);
1524 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1526 ALCcontext
*Context
;
1529 ALbufferlistitem
*ALBufferList
;
1530 ALbufferlistitem
*ALBufferListStart
;
1535 ALboolean bBuffersValid
= AL_TRUE
;
1540 Context
=alcGetCurrentContext();
1543 SuspendContext(Context
);
1548 // Check that all buffers are valid or zero and that the source is valid
1550 // Check that this is a valid source
1551 if (alIsSource(source
))
1553 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1555 // Check that this is not a STATIC Source
1556 if (ALSource
->lSourceType
!= AL_STATIC
)
1561 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1562 ALBufferList
= ALSource
->queue
;
1563 while (ALBufferList
)
1565 if (ALBufferList
->buffer
)
1567 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1568 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1571 ALBufferList
= ALBufferList
->next
;
1574 for (i
= 0; i
< n
; i
++)
1576 if (alIsBuffer(buffers
[i
]))
1580 if ((iFrequency
== -1) && (iFormat
== -1))
1582 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1583 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1587 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1588 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1590 alSetError(AL_INVALID_OPERATION
);
1591 bBuffersValid
= AL_FALSE
;
1599 alSetError(AL_INVALID_NAME
);
1600 bBuffersValid
= AL_FALSE
;
1607 // Change Source Type
1608 ALSource
->lSourceType
= AL_STREAMING
;
1610 // All buffers are valid - so add them to the list
1611 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1612 ALBufferListStart
->buffer
= buffers
[0];
1613 ALBufferListStart
->bufferstate
= PENDING
;
1614 ALBufferListStart
->flag
= 0;
1615 ALBufferListStart
->next
= NULL
;
1618 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1622 DataSize
+= BufferSize
;
1624 // Increment reference counter for buffer
1626 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1628 ALBufferList
= ALBufferListStart
;
1630 for (i
= 1; i
< n
; i
++)
1632 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1633 ALBufferList
->next
->buffer
= buffers
[i
];
1634 ALBufferList
->next
->bufferstate
= PENDING
;
1635 ALBufferList
->next
->flag
= 0;
1636 ALBufferList
->next
->next
= NULL
;
1639 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1643 DataSize
+= BufferSize
;
1645 // Increment reference counter for buffer
1647 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1649 ALBufferList
= ALBufferList
->next
;
1652 if (ALSource
->queue
== NULL
)
1654 ALSource
->queue
= ALBufferListStart
;
1655 // Update Current Buffer
1656 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1660 // Find end of queue
1661 ALBufferList
= ALSource
->queue
;
1662 while (ALBufferList
->next
!= NULL
)
1664 ALBufferList
= ALBufferList
->next
;
1667 ALBufferList
->next
= ALBufferListStart
;
1670 // Update number of buffers in queue
1671 ALSource
->BuffersInQueue
+= n
;
1676 // Invalid Source Type (can't queue on a Static Source)
1677 alSetError(AL_INVALID_OPERATION
);
1682 // Invalid Source Name
1683 alSetError(AL_INVALID_NAME
);
1686 ProcessContext(Context
);
1691 alSetError(AL_INVALID_OPERATION
);
1698 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1699 // an array of buffer IDs that are to be filled with the names of the buffers removed
1700 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1702 ALCcontext
*Context
;
1705 ALbufferlistitem
*ALBufferList
;
1709 ALboolean bBuffersProcessed
;
1716 bBuffersProcessed
= AL_TRUE
;
1718 Context
=alcGetCurrentContext();
1721 SuspendContext(Context
);
1723 if (alIsSource(source
))
1725 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1727 // Check that all 'n' buffers have been processed
1728 ALBufferList
= ALSource
->queue
;
1729 for (i
= 0; i
< n
; i
++)
1731 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1733 ALBufferList
= ALBufferList
->next
;
1737 bBuffersProcessed
= AL_FALSE
;
1742 // If all 'n' buffers have been processed, remove them from the queue
1743 if (bBuffersProcessed
)
1745 for (i
= 0; i
< n
; i
++)
1747 ALBufferList
= ALSource
->queue
;
1749 ALSource
->queue
= ALBufferList
->next
;
1750 // Record name of buffer
1751 buffers
[i
] = ALBufferList
->buffer
;
1752 // Decrement buffer reference counter
1753 if (ALBufferList
->buffer
)
1754 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1755 // Record size of buffer
1756 if (ALBufferList
->buffer
)
1757 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1761 DataSize
+= BufferSize
;
1762 // Release memory for buffer list item
1764 ALSource
->BuffersInQueue
--;
1765 ALSource
->BuffersProcessed
--;
1768 if (ALSource
->state
!= AL_PLAYING
)
1770 if (ALSource
->queue
)
1771 BufferID
= ALSource
->queue
->buffer
;
1775 ALSource
->ulBufferID
= BufferID
;
1778 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1780 ALSource
->BuffersPlayed
= 0;
1781 ALSource
->BufferPosition
= 0;
1784 ALSource
->BuffersPlayed
-= n
;
1788 // Some buffers can't be unqueue because they have not been processed
1789 alSetError(AL_INVALID_VALUE
);
1794 // Invalid Source Name
1795 alSetError(AL_INVALID_NAME
);
1798 ProcessContext(Context
);
1803 alSetError(AL_INVALID_OPERATION
);
1810 static ALvoid
InitSourceParams(ALsource
*pSource
)
1812 pSource
->flInnerAngle
= 360.0f
;
1813 pSource
->flOuterAngle
= 360.0f
;
1814 pSource
->flPitch
= 1.0f
;
1815 pSource
->vPosition
[0] = 0.0f
;
1816 pSource
->vPosition
[1] = 0.0f
;
1817 pSource
->vPosition
[2] = 0.0f
;
1818 pSource
->vOrientation
[0] = 0.0f
;
1819 pSource
->vOrientation
[1] = 0.0f
;
1820 pSource
->vOrientation
[2] = 0.0f
;
1821 pSource
->vVelocity
[0] = 0.0f
;
1822 pSource
->vVelocity
[1] = 0.0f
;
1823 pSource
->vVelocity
[2] = 0.0f
;
1824 pSource
->flRefDistance
= 1.0f
;
1825 pSource
->flMaxDistance
= FLT_MAX
;
1826 pSource
->flRollOffFactor
= 1.0f
;
1827 pSource
->bLooping
= AL_FALSE
;
1828 pSource
->flGain
= 1.0f
;
1829 pSource
->flMinGain
= 0.0f
;
1830 pSource
->flMaxGain
= 1.0f
;
1831 pSource
->flOuterGain
= 0.0f
;
1833 pSource
->state
= AL_INITIAL
;
1834 pSource
->lSourceType
= AL_UNDETERMINED
;
1836 pSource
->ulBufferID
= 0;
1843 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1844 The offset is relative to the start of the queue (not the start of the current buffer)
1846 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
1848 ALbufferlistitem
*pBufferList
;
1849 ALfloat flBufferFreq
;
1850 ALint lBytesPlayed
, lChannels
;
1851 ALenum eOriginalFormat
;
1852 ALboolean bReturn
= AL_TRUE
;
1853 ALint lTotalBufferDataSize
;
1855 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
1857 // Get Current Buffer Size and frequency (in milliseconds)
1858 flBufferFreq
= (ALfloat
)(((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
))->frequency
);
1859 eOriginalFormat
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
))->eOriginalFormat
;
1860 lChannels
= ((((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
))->format
== AL_FORMAT_MONO16
)?1:2);
1862 // Get Current BytesPlayed
1863 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
1864 // Add byte length of any processed buffers in the queue
1865 pBufferList
= pSource
->queue
;
1866 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
1868 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
1869 pBufferList
= pBufferList
->next
;
1872 lTotalBufferDataSize
= 0;
1873 pBufferList
= pSource
->queue
;
1876 if (pBufferList
->buffer
)
1877 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
1878 pBufferList
= pBufferList
->next
;
1881 if (pSource
->bLooping
)
1883 if (lBytesPlayed
< 0)
1886 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
1890 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
1891 if(lBytesPlayed
< 0)
1893 if(lBytesPlayed
> lTotalBufferDataSize
)
1894 lBytesPlayed
= lTotalBufferDataSize
;
1900 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
1902 case AL_SAMPLE_OFFSET
:
1903 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
1905 case AL_BYTE_OFFSET
:
1906 // Take into account the original format of the Buffer
1907 if ((eOriginalFormat
== AL_FORMAT_MONO8
) || (eOriginalFormat
== AL_FORMAT_STEREO8
))
1909 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
1911 else if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) || (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
1913 // Compression rate of the ADPCM supported is 3.6111 to 1
1914 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
1915 // Round down to nearest ADPCM block
1916 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
1920 *pflOffset
= (ALfloat
)lBytesPlayed
;
1937 Apply a playback offset to the Source. This function will update the queue (to correctly
1938 mark buffers as 'pending' or 'processed' depending upon the new offset.
1940 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
1942 ALbufferlistitem
*pBufferList
;
1943 ALint lBufferSize
, lTotalBufferSize
;
1946 // Get true byte offset
1947 lByteOffset
= GetByteOffset(pSource
);
1949 // If this is a valid offset apply it
1950 if (lByteOffset
!= -1)
1952 // Sort out the queue (pending and processed states)
1953 pBufferList
= pSource
->queue
;
1954 lTotalBufferSize
= 0;
1955 pSource
->BuffersPlayed
= 0;
1956 pSource
->BuffersProcessed
= 0;
1959 lBufferSize
= pBufferList
->buffer
? ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
: 0;
1961 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
1963 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
1964 // update the state to PROCESSED
1965 pSource
->BuffersPlayed
++;
1967 if (!pSource
->bLooping
)
1969 pBufferList
->bufferstate
= PROCESSED
;
1970 pSource
->BuffersProcessed
++;
1973 else if (lTotalBufferSize
<= lByteOffset
)
1975 // Offset is within this buffer
1976 pBufferList
->bufferstate
= PENDING
;
1978 // Set Current Buffer ID
1979 pSource
->ulBufferID
= pBufferList
->buffer
;
1981 // Set current position in this buffer
1982 pSource
->BufferPosition
= lByteOffset
- lTotalBufferSize
;
1984 // Set Total Bytes Played to Offset
1985 pSource
->lBytesPlayed
= lByteOffset
;
1987 // SW Mixer Positions are in Samples
1988 pSource
->position
= pSource
->BufferPosition
/ ((((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->format
== AL_FORMAT_MONO16
)?2:4);
1992 // Offset is before this buffer, so mark as pending
1993 pBufferList
->bufferstate
= PENDING
;
1996 // Increment the TotalBufferSize
1997 lTotalBufferSize
+= lBufferSize
;
1999 // Move on to next buffer in the Queue
2000 pBufferList
= pBufferList
->next
;
2006 alSetError(AL_INVALID_VALUE
);
2010 pSource
->lOffset
= 0;
2017 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2018 offset supplied by the application). This takes into account the fact that the buffer format
2019 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2021 static ALint
GetByteOffset(ALsource
*pSource
)
2023 ALbuffer
*pBuffer
= NULL
;
2024 ALbufferlistitem
*pBufferList
;
2025 ALfloat flBufferFreq
;
2027 ALint lByteOffset
= -1;
2028 ALint lTotalBufferDataSize
;
2030 // Find the first non-NULL Buffer in the Queue
2031 pBufferList
= pSource
->queue
;
2034 if (pBufferList
->buffer
)
2036 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2039 pBufferList
= pBufferList
->next
;
2044 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2045 lChannels
= (pBuffer
->format
== AL_FORMAT_MONO16
)?1:2;
2047 // Determine the ByteOffset (and ensure it is block aligned)
2048 switch (pSource
->lOffsetType
)
2050 case AL_BYTE_OFFSET
:
2051 // Take into consideration the original format
2052 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO8
) || (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO8
))
2054 lByteOffset
= pSource
->lOffset
* 2;
2055 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2057 else if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) || (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2059 // Round down to nearest ADPCM block
2060 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2061 // Multiply by compression rate
2062 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2063 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2067 lByteOffset
= pSource
->lOffset
;
2068 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2072 case AL_SAMPLE_OFFSET
:
2073 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2077 // Note - lOffset is internally stored as Milliseconds
2078 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2079 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2083 lTotalBufferDataSize
= 0;
2084 pBufferList
= pSource
->queue
;
2087 if (pBufferList
->buffer
)
2088 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2089 pBufferList
= pBufferList
->next
;
2092 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2093 if (lByteOffset
>= lTotalBufferDataSize
)