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 alDeleteSources(i
, sources
);
71 alSetError(AL_OUT_OF_MEMORY
);
75 sources
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
76 (*list
)->source
= sources
[i
];
78 InitSourceParams(*list
);
79 Context
->SourceCount
++;
82 list
= &(*list
)->next
;
87 // Not enough resources to create the Sources
88 alSetError(AL_INVALID_VALUE
);
94 alSetError(AL_INVALID_VALUE
);
99 // No Device created, or attached to Context
100 alSetError(AL_INVALID_OPERATION
);
104 ProcessContext(Context
);
109 alSetError(AL_INVALID_OPERATION
);
116 ALAPI ALvoid ALAPIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
123 ALbufferlistitem
*ALBufferList
;
124 ALboolean bSourcesValid
= AL_TRUE
;
126 Context
= alcGetCurrentContext();
129 SuspendContext(Context
);
133 Device
= alcGetContextsDevice(Context
);
137 if ((ALuint
)n
<= Context
->SourceCount
)
139 // Check that all Sources are valid (and can therefore be deleted)
140 for (i
= 0; i
< n
; i
++)
142 if (!alIsSource(sources
[i
]))
144 alSetError(AL_INVALID_NAME
);
145 bSourcesValid
= AL_FALSE
;
152 // All Sources are valid, and can be deleted
153 for (i
= 0; i
< n
; i
++)
155 // Recheck that the Source is valid, because there could be duplicated Source names
156 if (alIsSource(sources
[i
]))
158 ALSource
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
159 alSourceStop((ALuint
)ALSource
->source
);
161 // For each buffer in the source's queue, decrement its reference counter and remove it
162 while (ALSource
->queue
!= NULL
)
164 ALBufferList
= ALSource
->queue
;
165 // Decrement buffer's reference counter
166 if (ALBufferList
->buffer
!= 0)
167 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
168 // Update queue to point to next element in list
169 ALSource
->queue
= ALBufferList
->next
;
170 // Release memory allocated for buffer list item
174 // Decrement Source count
175 Context
->SourceCount
--;
177 // Remove Source from list of Sources
178 list
= &Context
->Source
;
179 while(*list
&& *list
!= ALSource
)
180 list
= &(*list
)->next
;
183 *list
= (*list
)->next
;
184 ALTHUNK_REMOVEENTRY(ALSource
->source
);
186 memset(ALSource
,0,sizeof(ALsource
));
195 // Trying to delete more Sources than have been generated
196 alSetError(AL_INVALID_NAME
);
201 // No Device created, or attached to Context
202 alSetError(AL_INVALID_OPERATION
);
206 alSetError(AL_INVALID_VALUE
);
208 ProcessContext(Context
);
213 alSetError(AL_INVALID_OPERATION
);
220 ALAPI ALboolean ALAPIENTRY
alIsSource(ALuint source
)
222 ALboolean result
=AL_FALSE
;
226 Context
=alcGetCurrentContext();
229 SuspendContext(Context
);
231 // To determine if this is a valid Source name, look through the list of generated Sources
232 Source
= Context
->Source
;
235 if (Source
== (ALsource
*)ALTHUNK_LOOKUPENTRY(source
))
241 Source
= Source
->next
;
244 ProcessContext(Context
);
249 alSetError(AL_INVALID_OPERATION
);
256 ALAPI ALvoid ALAPIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
258 ALCcontext
*pContext
;
261 pContext
= alcGetCurrentContext();
264 SuspendContext(pContext
);
266 if (alIsSource(source
))
268 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
275 pSource
->flPitch
= flValue
;
276 if(pSource
->flPitch
< 0.001f
)
277 pSource
->flPitch
= 0.001f
;
280 alSetError(AL_INVALID_VALUE
);
283 case AL_CONE_INNER_ANGLE
:
284 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
285 pSource
->flInnerAngle
= flValue
;
287 alSetError(AL_INVALID_VALUE
);
290 case AL_CONE_OUTER_ANGLE
:
291 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
292 pSource
->flOuterAngle
= flValue
;
294 alSetError(AL_INVALID_VALUE
);
299 pSource
->flGain
= flValue
;
301 alSetError(AL_INVALID_VALUE
);
304 case AL_MAX_DISTANCE
:
306 pSource
->flMaxDistance
= flValue
;
308 alSetError(AL_INVALID_VALUE
);
311 case AL_ROLLOFF_FACTOR
:
313 pSource
->flRollOffFactor
= flValue
;
315 alSetError(AL_INVALID_VALUE
);
318 case AL_REFERENCE_DISTANCE
:
320 pSource
->flRefDistance
= flValue
;
322 alSetError(AL_INVALID_VALUE
);
326 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
327 pSource
->flMinGain
= flValue
;
329 alSetError(AL_INVALID_VALUE
);
333 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
334 pSource
->flMaxGain
= flValue
;
336 alSetError(AL_INVALID_VALUE
);
339 case AL_CONE_OUTER_GAIN
:
340 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
341 pSource
->flOuterGain
= flValue
;
343 alSetError(AL_INVALID_VALUE
);
346 case AL_CONE_OUTER_GAINHF
:
347 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
348 pSource
->OuterGainHF
= flValue
;
350 alSetError(AL_INVALID_VALUE
);
353 case AL_AIR_ABSORPTION_FACTOR
:
354 if (flValue
>= 0.0f
&& flValue
<= 10.0f
)
355 pSource
->AirAbsorptionFactor
= flValue
;
357 alSetError(AL_INVALID_VALUE
);
360 case AL_ROOM_ROLLOFF_FACTOR
:
361 if (flValue
>= 0.0f
&& flValue
<= 1.0f
)
362 pSource
->RoomRolloffFactor
= flValue
;
364 alSetError(AL_INVALID_VALUE
);
368 case AL_SAMPLE_OFFSET
:
372 pSource
->lOffsetType
= eParam
;
374 // Store Offset (convert Seconds into Milliseconds)
375 if (eParam
== AL_SEC_OFFSET
)
376 pSource
->lOffset
= (ALint
)(flValue
* 1000.0f
);
378 pSource
->lOffset
= (ALint
)flValue
;
380 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
381 ApplyOffset(pSource
, AL_TRUE
);
384 alSetError(AL_INVALID_VALUE
);
388 alSetError(AL_INVALID_ENUM
);
394 // Invalid Source Name
395 alSetError(AL_INVALID_NAME
);
398 ProcessContext(pContext
);
403 alSetError(AL_INVALID_OPERATION
);
410 ALAPI ALvoid ALAPIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
412 ALCcontext
*pContext
;
415 pContext
= alcGetCurrentContext();
418 SuspendContext(pContext
);
420 if (alIsSource(source
))
422 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
426 pSource
->vPosition
[0] = flValue1
;
427 pSource
->vPosition
[1] = flValue2
;
428 pSource
->vPosition
[2] = flValue3
;
432 pSource
->vVelocity
[0] = flValue1
;
433 pSource
->vVelocity
[1] = flValue2
;
434 pSource
->vVelocity
[2] = flValue3
;
438 pSource
->vOrientation
[0] = flValue1
;
439 pSource
->vOrientation
[1] = flValue2
;
440 pSource
->vOrientation
[2] = flValue3
;
444 alSetError(AL_INVALID_ENUM
);
449 alSetError(AL_INVALID_NAME
);
451 ProcessContext(pContext
);
455 alSetError(AL_INVALID_OPERATION
);
462 ALAPI ALvoid ALAPIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
464 ALCcontext
*pContext
;
466 pContext
= alcGetCurrentContext();
469 SuspendContext(pContext
);
473 if (alIsSource(source
))
478 case AL_CONE_INNER_ANGLE
:
479 case AL_CONE_OUTER_ANGLE
:
481 case AL_MAX_DISTANCE
:
482 case AL_ROLLOFF_FACTOR
:
483 case AL_REFERENCE_DISTANCE
:
486 case AL_CONE_OUTER_GAIN
:
487 case AL_CONE_OUTER_GAINHF
:
489 case AL_SAMPLE_OFFSET
:
491 case AL_AIR_ABSORPTION_FACTOR
:
492 case AL_ROOM_ROLLOFF_FACTOR
:
493 alSourcef(source
, eParam
, pflValues
[0]);
499 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
503 alSetError(AL_INVALID_ENUM
);
508 alSetError(AL_INVALID_NAME
);
511 alSetError(AL_INVALID_VALUE
);
513 ProcessContext(pContext
);
516 alSetError(AL_INVALID_OPERATION
);
522 ALAPI ALvoid ALAPIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
524 ALCcontext
*pContext
;
526 ALbufferlistitem
*pALBufferListItem
;
531 pContext
= alcGetCurrentContext();
534 SuspendContext(pContext
);
536 if (alIsSource(source
))
538 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
542 case AL_MAX_DISTANCE
:
543 case AL_ROLLOFF_FACTOR
:
544 case AL_REFERENCE_DISTANCE
:
545 alSourcef(source
, eParam
, (ALfloat
)lValue
);
548 case AL_SOURCE_RELATIVE
:
549 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
550 pSource
->bHeadRelative
= (ALboolean
)lValue
;
552 alSetError(AL_INVALID_VALUE
);
555 case AL_CONE_INNER_ANGLE
:
556 if ((lValue
>= 0) && (lValue
<= 360))
557 pSource
->flInnerAngle
= (float)lValue
;
559 alSetError(AL_INVALID_VALUE
);
562 case AL_CONE_OUTER_ANGLE
:
563 if ((lValue
>= 0) && (lValue
<= 360))
564 pSource
->flOuterAngle
= (float)lValue
;
566 alSetError(AL_INVALID_VALUE
);
570 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
571 pSource
->bLooping
= (ALboolean
)lValue
;
573 alSetError(AL_INVALID_VALUE
);
577 if ((pSource
->state
== AL_STOPPED
) || (pSource
->state
== AL_INITIAL
))
579 if (alIsBuffer(lValue
))
581 // Remove all elements in the queue
582 while (pSource
->queue
!= NULL
)
584 pALBufferListItem
= pSource
->queue
;
585 pSource
->queue
= pALBufferListItem
->next
;
586 // Decrement reference counter for buffer
587 if (pALBufferListItem
->buffer
)
588 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
)))->refcount
--;
589 // Record size of buffer
590 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
))->size
;
591 DataSize
+= BufferSize
;
592 // Increment the number of buffers removed from queue
594 // Release memory for buffer list item
595 free(pALBufferListItem
);
596 // Decrement the number of buffers in the queue
597 pSource
->BuffersInQueue
--;
600 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
603 // Source is now in STATIC mode
604 pSource
->lSourceType
= AL_STATIC
;
606 // Add the selected buffer to the queue
607 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
608 pALBufferListItem
->buffer
= lValue
;
609 pALBufferListItem
->bufferstate
= PENDING
;
610 pALBufferListItem
->flag
= 0;
611 pALBufferListItem
->next
= NULL
;
613 pSource
->queue
= pALBufferListItem
;
614 pSource
->BuffersInQueue
= 1;
616 DataSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(lValue
))->size
;
618 // Increment reference counter for buffer
619 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(lValue
)))->refcount
++;
623 // Source is now in UNDETERMINED mode
624 pSource
->lSourceType
= AL_UNDETERMINED
;
627 // Set Buffers Processed
628 pSource
->BuffersProcessed
= 0;
630 // Update AL_BUFFER parameter
631 pSource
->ulBufferID
= lValue
;
634 alSetError(AL_INVALID_VALUE
);
637 alSetError(AL_INVALID_OPERATION
);
640 case AL_SOURCE_STATE
:
642 alSetError(AL_INVALID_OPERATION
);
646 case AL_SAMPLE_OFFSET
:
650 pSource
->lOffsetType
= eParam
;
652 // Store Offset (convert Seconds into Milliseconds)
653 if (eParam
== AL_SEC_OFFSET
)
654 pSource
->lOffset
= lValue
* 1000;
656 pSource
->lOffset
= lValue
;
658 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
659 ApplyOffset(pSource
, AL_TRUE
);
662 alSetError(AL_INVALID_VALUE
);
665 case AL_DIRECT_FILTER
:
666 if(alIsFilter(lValue
))
668 ALfilter
*filter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue
);
671 pSource
->DirectFilter
.type
= AL_FILTER_NULL
;
672 pSource
->DirectFilter
.filter
= 0;
675 memcpy(&pSource
->DirectFilter
, filter
, sizeof(*filter
));
678 alSetError(AL_INVALID_VALUE
);
681 case AL_DIRECT_FILTER_GAINHF_AUTO
:
682 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
683 pSource
->DryGainHFAuto
= lValue
;
685 alSetError(AL_INVALID_VALUE
);
688 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
689 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
690 pSource
->WetGainAuto
= lValue
;
692 alSetError(AL_INVALID_VALUE
);
695 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
696 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
697 pSource
->WetGainHFAuto
= lValue
;
699 alSetError(AL_INVALID_VALUE
);
703 alSetError(AL_INVALID_ENUM
);
708 alSetError(AL_INVALID_NAME
);
710 ProcessContext(pContext
);
713 alSetError(AL_INVALID_OPERATION
);
719 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
721 ALCcontext
*pContext
;
723 pContext
= alcGetCurrentContext();
726 SuspendContext(pContext
);
728 if (alIsSource(source
))
730 ALsource
*pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
737 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
740 case AL_AUXILIARY_SEND_FILTER
:
741 if(lValue2
>= 0 && lValue2
< MAX_SENDS
&&
742 (alIsAuxiliaryEffectSlot(lValue1
) || lValue1
== 0) &&
745 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(lValue1
);
746 ALfilter
*ALFilter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue3
);
748 pSource
->Send
[lValue2
].Slot
= ALEffectSlot
;
753 pSource
->Send
[lValue2
].WetFilter
.type
= 0;
754 pSource
->Send
[lValue2
].WetFilter
.filter
= 0;
757 memcpy(&pSource
->Send
[lValue2
].WetFilter
, ALFilter
, sizeof(*ALFilter
));
760 alSetError(AL_INVALID_VALUE
);
764 alSetError(AL_INVALID_ENUM
);
769 alSetError(AL_INVALID_NAME
);
771 ProcessContext(pContext
);
774 alSetError(AL_INVALID_OPERATION
);
780 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
782 ALCcontext
*pContext
;
784 pContext
= alcGetCurrentContext();
787 SuspendContext(pContext
);
791 if (alIsSource(source
))
795 case AL_SOURCE_RELATIVE
:
796 case AL_CONE_INNER_ANGLE
:
797 case AL_CONE_OUTER_ANGLE
:
800 case AL_SOURCE_STATE
:
802 case AL_SAMPLE_OFFSET
:
804 case AL_MAX_DISTANCE
:
805 case AL_ROLLOFF_FACTOR
:
806 case AL_REFERENCE_DISTANCE
:
807 case AL_DIRECT_FILTER
:
808 case AL_DIRECT_FILTER_GAINHF_AUTO
:
809 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
810 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
811 alSourcei(source
, eParam
, plValues
[0]);
817 case AL_AUXILIARY_SEND_FILTER
:
818 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
822 alSetError(AL_INVALID_ENUM
);
827 alSetError(AL_INVALID_NAME
);
830 alSetError(AL_INVALID_VALUE
);
832 ProcessContext(pContext
);
835 alSetError(AL_INVALID_OPERATION
);
841 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
843 ALCcontext
*pContext
;
847 pContext
= alcGetCurrentContext();
850 SuspendContext(pContext
);
854 if (alIsSource(source
))
856 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
861 *pflValue
= pSource
->flPitch
;
865 *pflValue
= pSource
->flGain
;
869 *pflValue
= pSource
->flMinGain
;
873 *pflValue
= pSource
->flMaxGain
;
876 case AL_MAX_DISTANCE
:
877 *pflValue
= pSource
->flMaxDistance
;
880 case AL_ROLLOFF_FACTOR
:
881 *pflValue
= pSource
->flRollOffFactor
;
884 case AL_CONE_OUTER_GAIN
:
885 *pflValue
= pSource
->flOuterGain
;
888 case AL_CONE_OUTER_GAINHF
:
889 *pflValue
= pSource
->OuterGainHF
;
893 case AL_SAMPLE_OFFSET
:
895 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
896 *pflValue
= flOffset
;
898 alSetError(AL_INVALID_OPERATION
);
901 case AL_CONE_INNER_ANGLE
:
902 *pflValue
= pSource
->flInnerAngle
;
905 case AL_CONE_OUTER_ANGLE
:
906 *pflValue
= pSource
->flOuterAngle
;
909 case AL_REFERENCE_DISTANCE
:
910 *pflValue
= pSource
->flRefDistance
;
913 case AL_AIR_ABSORPTION_FACTOR
:
914 *pflValue
= pSource
->AirAbsorptionFactor
;
917 case AL_ROOM_ROLLOFF_FACTOR
:
918 *pflValue
= pSource
->RoomRolloffFactor
;
922 alSetError(AL_INVALID_ENUM
);
927 alSetError(AL_INVALID_NAME
);
930 alSetError(AL_INVALID_VALUE
);
932 ProcessContext(pContext
);
935 alSetError(AL_INVALID_OPERATION
);
941 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
943 ALCcontext
*pContext
;
946 pContext
= alcGetCurrentContext();
949 SuspendContext(pContext
);
951 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
953 if (alIsSource(source
))
955 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
960 *pflValue1
= pSource
->vPosition
[0];
961 *pflValue2
= pSource
->vPosition
[1];
962 *pflValue3
= pSource
->vPosition
[2];
966 *pflValue1
= pSource
->vVelocity
[0];
967 *pflValue2
= pSource
->vVelocity
[1];
968 *pflValue3
= pSource
->vVelocity
[2];
972 *pflValue1
= pSource
->vOrientation
[0];
973 *pflValue2
= pSource
->vOrientation
[1];
974 *pflValue3
= pSource
->vOrientation
[2];
978 alSetError(AL_INVALID_ENUM
);
983 alSetError(AL_INVALID_NAME
);
986 alSetError(AL_INVALID_VALUE
);
988 ProcessContext(pContext
);
991 alSetError(AL_INVALID_OPERATION
);
997 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
999 ALCcontext
*pContext
;
1002 pContext
= alcGetCurrentContext();
1005 SuspendContext(pContext
);
1009 if (alIsSource(source
))
1011 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1019 case AL_MAX_DISTANCE
:
1020 case AL_ROLLOFF_FACTOR
:
1021 case AL_CONE_OUTER_GAIN
:
1023 case AL_SAMPLE_OFFSET
:
1024 case AL_BYTE_OFFSET
:
1025 case AL_CONE_INNER_ANGLE
:
1026 case AL_CONE_OUTER_ANGLE
:
1027 case AL_REFERENCE_DISTANCE
:
1028 case AL_CONE_OUTER_GAINHF
:
1029 case AL_AIR_ABSORPTION_FACTOR
:
1030 case AL_ROOM_ROLLOFF_FACTOR
:
1031 alGetSourcef(source
, eParam
, pflValues
);
1035 pflValues
[0] = pSource
->vPosition
[0];
1036 pflValues
[1] = pSource
->vPosition
[1];
1037 pflValues
[2] = pSource
->vPosition
[2];
1041 pflValues
[0] = pSource
->vVelocity
[0];
1042 pflValues
[1] = pSource
->vVelocity
[1];
1043 pflValues
[2] = pSource
->vVelocity
[2];
1047 pflValues
[0] = pSource
->vOrientation
[0];
1048 pflValues
[1] = pSource
->vOrientation
[1];
1049 pflValues
[2] = pSource
->vOrientation
[2];
1053 alSetError(AL_INVALID_ENUM
);
1058 alSetError(AL_INVALID_NAME
);
1061 alSetError(AL_INVALID_VALUE
);
1063 ProcessContext(pContext
);
1066 alSetError(AL_INVALID_OPERATION
);
1072 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1074 ALCcontext
*pContext
;
1078 pContext
= alcGetCurrentContext();
1081 SuspendContext(pContext
);
1085 if (alIsSource(source
))
1087 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1091 case AL_MAX_DISTANCE
:
1092 *plValue
= (ALint
)pSource
->flMaxDistance
;
1095 case AL_ROLLOFF_FACTOR
:
1096 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1099 case AL_REFERENCE_DISTANCE
:
1100 *plValue
= (ALint
)pSource
->flRefDistance
;
1103 case AL_SOURCE_RELATIVE
:
1104 *plValue
= pSource
->bHeadRelative
;
1107 case AL_CONE_INNER_ANGLE
:
1108 *plValue
= (ALint
)pSource
->flInnerAngle
;
1111 case AL_CONE_OUTER_ANGLE
:
1112 *plValue
= (ALint
)pSource
->flOuterAngle
;
1116 *plValue
= pSource
->bLooping
;
1120 *plValue
= pSource
->ulBufferID
;
1123 case AL_SOURCE_STATE
:
1124 *plValue
= pSource
->state
;
1127 case AL_BUFFERS_QUEUED
:
1128 *plValue
= pSource
->BuffersInQueue
;
1131 case AL_BUFFERS_PROCESSED
:
1132 if(pSource
->bLooping
)
1134 /* Buffers on a looping source are in a perpetual state
1135 * of PENDING, so don't report any as PROCESSED */
1139 *plValue
= pSource
->BuffersProcessed
;
1142 case AL_SOURCE_TYPE
:
1143 *plValue
= pSource
->lSourceType
;
1147 case AL_SAMPLE_OFFSET
:
1148 case AL_BYTE_OFFSET
:
1149 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
1150 *plValue
= (ALint
)flOffset
;
1152 alSetError(AL_INVALID_OPERATION
);
1155 case AL_DIRECT_FILTER
:
1156 *plValue
= pSource
->DirectFilter
.filter
;
1159 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1160 *plValue
= pSource
->DryGainHFAuto
;
1163 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1164 *plValue
= pSource
->WetGainAuto
;
1167 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1168 *plValue
= pSource
->WetGainHFAuto
;
1172 alSetError(AL_INVALID_ENUM
);
1177 alSetError(AL_INVALID_NAME
);
1180 alSetError(AL_INVALID_VALUE
);
1182 ProcessContext(pContext
);
1185 alSetError(AL_INVALID_OPERATION
);
1191 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1193 ALCcontext
*pContext
;
1196 pContext
= alcGetCurrentContext();
1199 SuspendContext(pContext
);
1201 if ((plValue1
) && (plValue2
) && (plValue3
))
1203 if (alIsSource(source
))
1205 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1210 *plValue1
= (ALint
)pSource
->vPosition
[0];
1211 *plValue2
= (ALint
)pSource
->vPosition
[1];
1212 *plValue3
= (ALint
)pSource
->vPosition
[2];
1216 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1217 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1218 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1222 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1223 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1224 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1228 alSetError(AL_INVALID_ENUM
);
1233 alSetError(AL_INVALID_NAME
);
1236 alSetError(AL_INVALID_VALUE
);
1238 ProcessContext(pContext
);
1241 alSetError(AL_INVALID_OPERATION
);
1247 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1249 ALCcontext
*pContext
;
1252 pContext
= alcGetCurrentContext();
1255 SuspendContext(pContext
);
1259 if (alIsSource(source
))
1261 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1265 case AL_SOURCE_RELATIVE
:
1266 case AL_CONE_INNER_ANGLE
:
1267 case AL_CONE_OUTER_ANGLE
:
1270 case AL_SOURCE_STATE
:
1271 case AL_BUFFERS_QUEUED
:
1272 case AL_BUFFERS_PROCESSED
:
1274 case AL_SAMPLE_OFFSET
:
1275 case AL_BYTE_OFFSET
:
1276 case AL_MAX_DISTANCE
:
1277 case AL_ROLLOFF_FACTOR
:
1278 case AL_REFERENCE_DISTANCE
:
1279 case AL_SOURCE_TYPE
:
1280 case AL_DIRECT_FILTER
:
1281 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1282 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1283 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1284 alGetSourcei(source
, eParam
, plValues
);
1288 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1289 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1290 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1294 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1295 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1296 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1300 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1301 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1302 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1306 alSetError(AL_INVALID_ENUM
);
1311 alSetError(AL_INVALID_NAME
);
1314 alSetError(AL_INVALID_VALUE
);
1316 ProcessContext(pContext
);
1319 alSetError(AL_INVALID_OPERATION
);
1325 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1327 alSourcePlayv(1, &source
);
1331 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1333 ALCcontext
*pContext
;
1335 ALbufferlistitem
*ALBufferList
;
1336 ALboolean bSourcesValid
= AL_TRUE
;
1340 pContext
= alcGetCurrentContext();
1343 SuspendContext(pContext
);
1347 // Check that all the Sources are valid
1348 for (i
= 0; i
< n
; i
++)
1350 if (!alIsSource(pSourceList
[i
]))
1352 alSetError(AL_INVALID_NAME
);
1353 bSourcesValid
= AL_FALSE
;
1360 for (i
= 0; i
< n
; i
++)
1362 // Assume Source won't need to play
1365 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1367 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1368 ALBufferList
= pSource
->queue
;
1369 while (ALBufferList
)
1371 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1376 ALBufferList
= ALBufferList
->next
;
1381 if (pSource
->state
!= AL_PAUSED
)
1383 pSource
->state
= AL_PLAYING
;
1384 pSource
->inuse
= AL_TRUE
;
1385 pSource
->play
= AL_TRUE
;
1386 pSource
->position
= 0;
1387 pSource
->position_fraction
= 0;
1388 pSource
->BuffersProcessed
= 0;
1389 pSource
->BuffersPlayed
= 0;
1390 pSource
->BufferPosition
= 0;
1391 pSource
->lBytesPlayed
= 0;
1393 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1395 // Make sure all the Buffers in the queue are marked as PENDING
1396 ALBufferList
= pSource
->queue
;
1397 while (ALBufferList
)
1399 ALBufferList
->bufferstate
= PENDING
;
1400 ALBufferList
= ALBufferList
->next
;
1405 pSource
->state
= AL_PLAYING
;
1406 pSource
->inuse
= AL_TRUE
;
1407 pSource
->play
= AL_TRUE
;
1410 // Check if an Offset has been set
1411 if (pSource
->lOffset
)
1412 ApplyOffset(pSource
, AL_FALSE
);
1416 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1417 ALBufferList
= pSource
->queue
;
1418 while (ALBufferList
)
1420 ALBufferList
->bufferstate
= PROCESSED
;
1421 ALBufferList
= ALBufferList
->next
;
1424 pSource
->BuffersPlayed
= pSource
->BuffersProcessed
= pSource
->BuffersInQueue
;
1431 // sources is a NULL pointer
1432 alSetError(AL_INVALID_VALUE
);
1435 ProcessContext(pContext
);
1440 alSetError(AL_INVALID_OPERATION
);
1446 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1448 alSourcePausev(1, &source
);
1452 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1454 ALCcontext
*Context
;
1457 ALboolean bSourcesValid
= AL_TRUE
;
1459 Context
=alcGetCurrentContext();
1462 SuspendContext(Context
);
1466 // Check all the Sources are valid
1469 if (!alIsSource(sources
[i
]))
1471 alSetError(AL_INVALID_NAME
);
1472 bSourcesValid
= AL_FALSE
;
1481 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1482 if (Source
->state
==AL_PLAYING
)
1484 Source
->state
=AL_PAUSED
;
1485 Source
->inuse
=AL_FALSE
;
1492 // sources is a NULL pointer
1493 alSetError(AL_INVALID_VALUE
);
1496 ProcessContext(Context
);
1501 alSetError(AL_INVALID_OPERATION
);
1507 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1509 alSourceStopv(1, &source
);
1513 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1515 ALCcontext
*Context
;
1518 ALbufferlistitem
*ALBufferListItem
;
1519 ALboolean bSourcesValid
= AL_TRUE
;
1521 Context
=alcGetCurrentContext();
1524 SuspendContext(Context
);
1528 // Check all the Sources are valid
1531 if (!alIsSource(sources
[i
]))
1533 alSetError(AL_INVALID_NAME
);
1534 bSourcesValid
= AL_FALSE
;
1543 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1544 if (Source
->state
!=AL_INITIAL
)
1546 Source
->state
=AL_STOPPED
;
1547 Source
->inuse
=AL_FALSE
;
1548 Source
->BuffersPlayed
= Source
->BuffersProcessed
= Source
->BuffersInQueue
;
1549 ALBufferListItem
= Source
->queue
;
1550 while (ALBufferListItem
!= NULL
)
1552 ALBufferListItem
->bufferstate
= PROCESSED
;
1553 ALBufferListItem
= ALBufferListItem
->next
;
1556 Source
->lOffset
= 0;
1562 // sources is a NULL pointer
1563 alSetError(AL_INVALID_VALUE
);
1566 ProcessContext(Context
);
1571 alSetError(AL_INVALID_OPERATION
);
1577 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1579 alSourceRewindv(1, &source
);
1583 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1585 ALCcontext
*Context
;
1588 ALbufferlistitem
*ALBufferListItem
;
1589 ALboolean bSourcesValid
= AL_TRUE
;
1591 Context
=alcGetCurrentContext();
1594 SuspendContext(Context
);
1598 // Check all the Sources are valid
1601 if (!alIsSource(sources
[i
]))
1603 alSetError(AL_INVALID_NAME
);
1604 bSourcesValid
= AL_FALSE
;
1613 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1614 if (Source
->state
!=AL_INITIAL
)
1616 Source
->state
=AL_INITIAL
;
1617 Source
->inuse
=AL_FALSE
;
1619 Source
->position_fraction
=0;
1620 Source
->BuffersProcessed
= 0;
1621 ALBufferListItem
= Source
->queue
;
1622 while (ALBufferListItem
!= NULL
)
1624 ALBufferListItem
->bufferstate
= PENDING
;
1625 ALBufferListItem
= ALBufferListItem
->next
;
1628 Source
->ulBufferID
= Source
->queue
->buffer
;
1630 Source
->lOffset
= 0;
1636 // sources is a NULL pointer
1637 alSetError(AL_INVALID_VALUE
);
1640 ProcessContext(Context
);
1645 alSetError(AL_INVALID_OPERATION
);
1652 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1654 ALCcontext
*Context
;
1657 ALbufferlistitem
*ALBufferList
;
1658 ALbufferlistitem
*ALBufferListStart
;
1663 ALboolean bBuffersValid
= AL_TRUE
;
1668 Context
=alcGetCurrentContext();
1671 SuspendContext(Context
);
1676 // Check that all buffers are valid or zero and that the source is valid
1678 // Check that this is a valid source
1679 if (alIsSource(source
))
1681 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1683 // Check that this is not a STATIC Source
1684 if (ALSource
->lSourceType
!= AL_STATIC
)
1689 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1690 ALBufferList
= ALSource
->queue
;
1691 while (ALBufferList
)
1693 if (ALBufferList
->buffer
)
1695 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1696 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1699 ALBufferList
= ALBufferList
->next
;
1702 for (i
= 0; i
< n
; i
++)
1704 if (alIsBuffer(buffers
[i
]))
1708 if ((iFrequency
== -1) && (iFormat
== -1))
1710 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1711 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1715 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1716 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1718 alSetError(AL_INVALID_OPERATION
);
1719 bBuffersValid
= AL_FALSE
;
1727 alSetError(AL_INVALID_NAME
);
1728 bBuffersValid
= AL_FALSE
;
1735 // Change Source Type
1736 ALSource
->lSourceType
= AL_STREAMING
;
1738 // All buffers are valid - so add them to the list
1739 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1740 ALBufferListStart
->buffer
= buffers
[0];
1741 ALBufferListStart
->bufferstate
= PENDING
;
1742 ALBufferListStart
->flag
= 0;
1743 ALBufferListStart
->next
= NULL
;
1746 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1750 DataSize
+= BufferSize
;
1752 // Increment reference counter for buffer
1754 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1756 ALBufferList
= ALBufferListStart
;
1758 for (i
= 1; i
< n
; i
++)
1760 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1761 ALBufferList
->next
->buffer
= buffers
[i
];
1762 ALBufferList
->next
->bufferstate
= PENDING
;
1763 ALBufferList
->next
->flag
= 0;
1764 ALBufferList
->next
->next
= NULL
;
1767 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1771 DataSize
+= BufferSize
;
1773 // Increment reference counter for buffer
1775 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1777 ALBufferList
= ALBufferList
->next
;
1780 if (ALSource
->queue
== NULL
)
1782 ALSource
->queue
= ALBufferListStart
;
1783 // Update Current Buffer
1784 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1788 // Find end of queue
1789 ALBufferList
= ALSource
->queue
;
1790 while (ALBufferList
->next
!= NULL
)
1792 ALBufferList
= ALBufferList
->next
;
1795 ALBufferList
->next
= ALBufferListStart
;
1798 // Update number of buffers in queue
1799 ALSource
->BuffersInQueue
+= n
;
1804 // Invalid Source Type (can't queue on a Static Source)
1805 alSetError(AL_INVALID_OPERATION
);
1810 // Invalid Source Name
1811 alSetError(AL_INVALID_NAME
);
1814 ProcessContext(Context
);
1819 alSetError(AL_INVALID_OPERATION
);
1826 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1827 // an array of buffer IDs that are to be filled with the names of the buffers removed
1828 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1830 ALCcontext
*Context
;
1833 ALbufferlistitem
*ALBufferList
;
1837 ALboolean bBuffersProcessed
;
1844 bBuffersProcessed
= AL_TRUE
;
1846 Context
=alcGetCurrentContext();
1849 SuspendContext(Context
);
1851 if (alIsSource(source
))
1853 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1855 // Check that all 'n' buffers have been processed
1856 ALBufferList
= ALSource
->queue
;
1857 for (i
= 0; i
< n
; i
++)
1859 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1861 ALBufferList
= ALBufferList
->next
;
1865 bBuffersProcessed
= AL_FALSE
;
1870 // If all 'n' buffers have been processed, remove them from the queue
1871 if (bBuffersProcessed
)
1873 for (i
= 0; i
< n
; i
++)
1875 ALBufferList
= ALSource
->queue
;
1877 ALSource
->queue
= ALBufferList
->next
;
1878 // Record name of buffer
1879 buffers
[i
] = ALBufferList
->buffer
;
1880 // Decrement buffer reference counter
1881 if (ALBufferList
->buffer
)
1882 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1883 // Record size of buffer
1884 if (ALBufferList
->buffer
)
1885 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1889 DataSize
+= BufferSize
;
1890 // Release memory for buffer list item
1892 ALSource
->BuffersInQueue
--;
1893 ALSource
->BuffersProcessed
--;
1896 if (ALSource
->state
!= AL_PLAYING
)
1898 if (ALSource
->queue
)
1899 BufferID
= ALSource
->queue
->buffer
;
1903 ALSource
->ulBufferID
= BufferID
;
1906 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1908 ALSource
->BuffersPlayed
= 0;
1909 ALSource
->BufferPosition
= 0;
1912 ALSource
->BuffersPlayed
-= n
;
1916 // Some buffers can't be unqueue because they have not been processed
1917 alSetError(AL_INVALID_VALUE
);
1922 // Invalid Source Name
1923 alSetError(AL_INVALID_NAME
);
1926 ProcessContext(Context
);
1931 alSetError(AL_INVALID_OPERATION
);
1938 static ALvoid
InitSourceParams(ALsource
*pSource
)
1940 pSource
->flInnerAngle
= 360.0f
;
1941 pSource
->flOuterAngle
= 360.0f
;
1942 pSource
->flPitch
= 1.0f
;
1943 pSource
->vPosition
[0] = 0.0f
;
1944 pSource
->vPosition
[1] = 0.0f
;
1945 pSource
->vPosition
[2] = 0.0f
;
1946 pSource
->vOrientation
[0] = 0.0f
;
1947 pSource
->vOrientation
[1] = 0.0f
;
1948 pSource
->vOrientation
[2] = 0.0f
;
1949 pSource
->vVelocity
[0] = 0.0f
;
1950 pSource
->vVelocity
[1] = 0.0f
;
1951 pSource
->vVelocity
[2] = 0.0f
;
1952 pSource
->flRefDistance
= 1.0f
;
1953 pSource
->flMaxDistance
= FLT_MAX
;
1954 pSource
->flRollOffFactor
= 1.0f
;
1955 pSource
->bLooping
= AL_FALSE
;
1956 pSource
->flGain
= 1.0f
;
1957 pSource
->flMinGain
= 0.0f
;
1958 pSource
->flMaxGain
= 1.0f
;
1959 pSource
->flOuterGain
= 0.0f
;
1960 pSource
->OuterGainHF
= 1.0f
;
1962 pSource
->DryGainHFAuto
= AL_TRUE
;
1963 pSource
->WetGainAuto
= AL_TRUE
;
1964 pSource
->WetGainHFAuto
= AL_TRUE
;
1965 pSource
->AirAbsorptionFactor
= 0.0f
;
1966 pSource
->RoomRolloffFactor
= 0.0f
;
1968 pSource
->state
= AL_INITIAL
;
1969 pSource
->lSourceType
= AL_UNDETERMINED
;
1971 pSource
->ulBufferID
= 0;
1978 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1979 The offset is relative to the start of the queue (not the start of the current buffer)
1981 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
1983 ALbufferlistitem
*pBufferList
;
1985 ALfloat flBufferFreq
;
1986 ALint lBytesPlayed
, lChannels
;
1987 ALenum eOriginalFormat
;
1988 ALboolean bReturn
= AL_TRUE
;
1989 ALint lTotalBufferDataSize
;
1991 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
1993 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
1994 // Get Current Buffer Size and frequency (in milliseconds)
1995 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
1996 eOriginalFormat
= pBuffer
->eOriginalFormat
;
1997 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
1999 // Get Current BytesPlayed
2000 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2001 // Add byte length of any processed buffers in the queue
2002 pBufferList
= pSource
->queue
;
2003 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2005 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2006 pBufferList
= pBufferList
->next
;
2009 lTotalBufferDataSize
= 0;
2010 pBufferList
= pSource
->queue
;
2013 if (pBufferList
->buffer
)
2014 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2015 pBufferList
= pBufferList
->next
;
2018 if (pSource
->bLooping
)
2020 if (lBytesPlayed
< 0)
2023 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
2027 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2028 if(lBytesPlayed
< 0)
2030 if(lBytesPlayed
> lTotalBufferDataSize
)
2031 lBytesPlayed
= lTotalBufferDataSize
;
2037 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
2039 case AL_SAMPLE_OFFSET
:
2040 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
2042 case AL_BYTE_OFFSET
:
2043 // Take into account the original format of the Buffer
2044 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2045 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2047 // Compression rate of the ADPCM supported is 3.6111 to 1
2048 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
2049 // Round down to nearest ADPCM block
2050 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
2052 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2054 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 2);
2056 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2058 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2060 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2062 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2064 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2066 *pflOffset
= (ALfloat
)(lBytesPlayed
<< 1);
2070 *pflOffset
= (ALfloat
)lBytesPlayed
;
2087 Apply a playback offset to the Source. This function will update the queue (to correctly
2088 mark buffers as 'pending' or 'processed' depending upon the new offset.
2090 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2092 ALbufferlistitem
*pBufferList
;
2094 ALint lBufferSize
, lTotalBufferSize
;
2097 // Get true byte offset
2098 lByteOffset
= GetByteOffset(pSource
);
2100 // If this is a valid offset apply it
2101 if (lByteOffset
!= -1)
2103 // Sort out the queue (pending and processed states)
2104 pBufferList
= pSource
->queue
;
2105 lTotalBufferSize
= 0;
2106 pSource
->BuffersPlayed
= 0;
2107 pSource
->BuffersProcessed
= 0;
2110 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2111 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2113 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2115 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2116 // update the state to PROCESSED
2117 pSource
->BuffersPlayed
++;
2119 if (!pSource
->bLooping
)
2121 pBufferList
->bufferstate
= PROCESSED
;
2122 pSource
->BuffersProcessed
++;
2125 else if (lTotalBufferSize
<= lByteOffset
)
2127 // Offset is within this buffer
2128 pBufferList
->bufferstate
= PENDING
;
2130 // Set Current Buffer ID
2131 pSource
->ulBufferID
= pBufferList
->buffer
;
2133 // Set current position in this buffer
2134 pSource
->BufferPosition
= lByteOffset
- lTotalBufferSize
;
2136 // Set Total Bytes Played to Offset
2137 pSource
->lBytesPlayed
= lByteOffset
;
2139 // SW Mixer Positions are in Samples
2140 pSource
->position
= pSource
->BufferPosition
/
2141 aluBytesFromFormat(pBuffer
->format
) /
2142 aluChannelsFromFormat(pBuffer
->format
);
2146 // Offset is before this buffer, so mark as pending
2147 pBufferList
->bufferstate
= PENDING
;
2150 // Increment the TotalBufferSize
2151 lTotalBufferSize
+= lBufferSize
;
2153 // Move on to next buffer in the Queue
2154 pBufferList
= pBufferList
->next
;
2160 alSetError(AL_INVALID_VALUE
);
2164 pSource
->lOffset
= 0;
2171 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2172 offset supplied by the application). This takes into account the fact that the buffer format
2173 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2175 static ALint
GetByteOffset(ALsource
*pSource
)
2177 ALbuffer
*pBuffer
= NULL
;
2178 ALbufferlistitem
*pBufferList
;
2179 ALfloat flBufferFreq
;
2181 ALint lByteOffset
= -1;
2182 ALint lTotalBufferDataSize
;
2184 // Find the first non-NULL Buffer in the Queue
2185 pBufferList
= pSource
->queue
;
2188 if (pBufferList
->buffer
)
2190 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2193 pBufferList
= pBufferList
->next
;
2198 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2199 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2201 // Determine the ByteOffset (and ensure it is block aligned)
2202 switch (pSource
->lOffsetType
)
2204 case AL_BYTE_OFFSET
:
2205 // Take into consideration the original format
2206 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2207 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2209 // Round down to nearest ADPCM block
2210 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2211 // Multiply by compression rate
2212 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2213 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2215 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2217 lByteOffset
= pSource
->lOffset
* 4;
2218 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2220 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2222 lByteOffset
= pSource
->lOffset
* 2;
2223 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2225 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2227 lByteOffset
= pSource
->lOffset
* 2;
2228 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2230 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2232 lByteOffset
= pSource
->lOffset
/ 2;
2233 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2237 lByteOffset
= pSource
->lOffset
;
2238 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2242 case AL_SAMPLE_OFFSET
:
2243 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2247 // Note - lOffset is internally stored as Milliseconds
2248 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2249 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2253 lTotalBufferDataSize
= 0;
2254 pBufferList
= pSource
->queue
;
2257 if (pBufferList
->buffer
)
2258 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2259 pBufferList
= pBufferList
->next
;
2262 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2263 if (lByteOffset
>= lTotalBufferDataSize
)