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
33 #include "alAuxEffectSlot.h"
35 static ALvoid
InitSourceParams(ALsource
*pSource
);
36 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
);
37 static ALvoid
ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
);
38 static ALint
GetByteOffset(ALsource
*pSource
);
40 ALAPI ALvoid ALAPIENTRY
alGenSources(ALsizei n
,ALuint
*sources
)
46 Context
= alcGetCurrentContext();
49 SuspendContext(Context
);
53 Device
= alcGetContextsDevice(Context
);
57 // Check that enough memory has been allocted in the 'sources' array for n Sources
58 if (!IsBadWritePtr((void*)sources
, n
* sizeof(ALuint
)))
60 // Check that the requested number of sources can be generated
61 if ((Context
->SourceCount
+ n
) <= Device
->MaxNoOfSources
)
63 ALsource
**list
= &Context
->Source
;
65 list
= &(*list
)->next
;
67 // Add additional sources to the list (Source->next points to the location for the next Source structure)
70 *list
= calloc(1, sizeof(ALsource
));
73 alDeleteSources(i
, sources
);
74 alSetError(AL_OUT_OF_MEMORY
);
78 sources
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
79 (*list
)->source
= sources
[i
];
81 InitSourceParams(*list
);
82 Context
->SourceCount
++;
85 list
= &(*list
)->next
;
90 // Not enough resources to create the Sources
91 alSetError(AL_INVALID_VALUE
);
97 alSetError(AL_INVALID_VALUE
);
102 // No Device created, or attached to Context
103 alSetError(AL_INVALID_OPERATION
);
107 ProcessContext(Context
);
112 alSetError(AL_INVALID_OPERATION
);
119 ALAPI ALvoid ALAPIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
126 ALbufferlistitem
*ALBufferList
;
127 ALboolean bSourcesValid
= AL_TRUE
;
129 Context
= alcGetCurrentContext();
132 SuspendContext(Context
);
136 Device
= alcGetContextsDevice(Context
);
140 // Check that all Sources are valid (and can therefore be deleted)
141 for (i
= 0; i
< n
; i
++)
143 if (!alIsSource(sources
[i
]))
145 alSetError(AL_INVALID_NAME
);
146 bSourcesValid
= AL_FALSE
;
153 // All Sources are valid, and can be deleted
154 for (i
= 0; i
< n
; i
++)
156 // Recheck that the Source is valid, because there could be duplicated Source names
157 if (alIsSource(sources
[i
]))
159 ALSource
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
160 alSourceStop((ALuint
)ALSource
->source
);
162 // For each buffer in the source's queue, decrement its reference counter and remove it
163 while (ALSource
->queue
!= NULL
)
165 ALBufferList
= ALSource
->queue
;
166 // Decrement buffer's reference counter
167 if (ALBufferList
->buffer
!= 0)
168 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
169 // Update queue to point to next element in list
170 ALSource
->queue
= ALBufferList
->next
;
171 // Release memory allocated for buffer list item
175 for(j
= 0;j
< MAX_SENDS
;++j
)
177 if(ALSource
->Send
[j
].Slot
)
178 ALSource
->Send
[j
].Slot
->refcount
--;
179 ALSource
->Send
[j
].Slot
= NULL
;
182 // Decrement Source count
183 Context
->SourceCount
--;
185 // Remove Source from list of Sources
186 list
= &Context
->Source
;
187 while(*list
&& *list
!= ALSource
)
188 list
= &(*list
)->next
;
191 *list
= (*list
)->next
;
192 ALTHUNK_REMOVEENTRY(ALSource
->source
);
194 memset(ALSource
,0,sizeof(ALsource
));
202 // No Device created, or attached to Context
203 alSetError(AL_INVALID_OPERATION
);
207 alSetError(AL_INVALID_VALUE
);
209 ProcessContext(Context
);
214 alSetError(AL_INVALID_OPERATION
);
221 ALAPI ALboolean ALAPIENTRY
alIsSource(ALuint source
)
223 ALboolean result
=AL_FALSE
;
227 Context
=alcGetCurrentContext();
230 SuspendContext(Context
);
232 // To determine if this is a valid Source name, look through the list of generated Sources
233 Source
= Context
->Source
;
236 if (Source
== (ALsource
*)ALTHUNK_LOOKUPENTRY(source
))
242 Source
= Source
->next
;
245 ProcessContext(Context
);
250 alSetError(AL_INVALID_OPERATION
);
257 ALAPI ALvoid ALAPIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
259 ALCcontext
*pContext
;
262 pContext
= alcGetCurrentContext();
265 SuspendContext(pContext
);
267 if (alIsSource(source
))
269 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
276 pSource
->flPitch
= flValue
;
277 if(pSource
->flPitch
< 0.001f
)
278 pSource
->flPitch
= 0.001f
;
281 alSetError(AL_INVALID_VALUE
);
284 case AL_CONE_INNER_ANGLE
:
285 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
286 pSource
->flInnerAngle
= flValue
;
288 alSetError(AL_INVALID_VALUE
);
291 case AL_CONE_OUTER_ANGLE
:
292 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
293 pSource
->flOuterAngle
= flValue
;
295 alSetError(AL_INVALID_VALUE
);
300 pSource
->flGain
= flValue
;
302 alSetError(AL_INVALID_VALUE
);
305 case AL_MAX_DISTANCE
:
307 pSource
->flMaxDistance
= flValue
;
309 alSetError(AL_INVALID_VALUE
);
312 case AL_ROLLOFF_FACTOR
:
314 pSource
->flRollOffFactor
= flValue
;
316 alSetError(AL_INVALID_VALUE
);
319 case AL_REFERENCE_DISTANCE
:
321 pSource
->flRefDistance
= flValue
;
323 alSetError(AL_INVALID_VALUE
);
327 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
328 pSource
->flMinGain
= flValue
;
330 alSetError(AL_INVALID_VALUE
);
334 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
335 pSource
->flMaxGain
= flValue
;
337 alSetError(AL_INVALID_VALUE
);
340 case AL_CONE_OUTER_GAIN
:
341 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
342 pSource
->flOuterGain
= flValue
;
344 alSetError(AL_INVALID_VALUE
);
347 case AL_CONE_OUTER_GAINHF
:
348 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
349 pSource
->OuterGainHF
= flValue
;
351 alSetError(AL_INVALID_VALUE
);
354 case AL_AIR_ABSORPTION_FACTOR
:
355 if (flValue
>= 0.0f
&& flValue
<= 10.0f
)
356 pSource
->AirAbsorptionFactor
= flValue
;
358 alSetError(AL_INVALID_VALUE
);
361 case AL_ROOM_ROLLOFF_FACTOR
:
362 if (flValue
>= 0.0f
&& flValue
<= 1.0f
)
363 pSource
->RoomRolloffFactor
= flValue
;
365 alSetError(AL_INVALID_VALUE
);
369 case AL_SAMPLE_OFFSET
:
373 pSource
->lOffsetType
= eParam
;
375 // Store Offset (convert Seconds into Milliseconds)
376 if (eParam
== AL_SEC_OFFSET
)
377 pSource
->lOffset
= (ALint
)(flValue
* 1000.0f
);
379 pSource
->lOffset
= (ALint
)flValue
;
381 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
382 ApplyOffset(pSource
, AL_TRUE
);
385 alSetError(AL_INVALID_VALUE
);
389 alSetError(AL_INVALID_ENUM
);
395 // Invalid Source Name
396 alSetError(AL_INVALID_NAME
);
399 ProcessContext(pContext
);
404 alSetError(AL_INVALID_OPERATION
);
411 ALAPI ALvoid ALAPIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
413 ALCcontext
*pContext
;
416 pContext
= alcGetCurrentContext();
419 SuspendContext(pContext
);
421 if (alIsSource(source
))
423 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
427 pSource
->vPosition
[0] = flValue1
;
428 pSource
->vPosition
[1] = flValue2
;
429 pSource
->vPosition
[2] = flValue3
;
433 pSource
->vVelocity
[0] = flValue1
;
434 pSource
->vVelocity
[1] = flValue2
;
435 pSource
->vVelocity
[2] = flValue3
;
439 pSource
->vOrientation
[0] = flValue1
;
440 pSource
->vOrientation
[1] = flValue2
;
441 pSource
->vOrientation
[2] = flValue3
;
445 alSetError(AL_INVALID_ENUM
);
450 alSetError(AL_INVALID_NAME
);
452 ProcessContext(pContext
);
456 alSetError(AL_INVALID_OPERATION
);
463 ALAPI ALvoid ALAPIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
465 ALCcontext
*pContext
;
467 pContext
= alcGetCurrentContext();
470 SuspendContext(pContext
);
474 if (alIsSource(source
))
479 case AL_CONE_INNER_ANGLE
:
480 case AL_CONE_OUTER_ANGLE
:
482 case AL_MAX_DISTANCE
:
483 case AL_ROLLOFF_FACTOR
:
484 case AL_REFERENCE_DISTANCE
:
487 case AL_CONE_OUTER_GAIN
:
488 case AL_CONE_OUTER_GAINHF
:
490 case AL_SAMPLE_OFFSET
:
492 case AL_AIR_ABSORPTION_FACTOR
:
493 case AL_ROOM_ROLLOFF_FACTOR
:
494 alSourcef(source
, eParam
, pflValues
[0]);
500 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
504 alSetError(AL_INVALID_ENUM
);
509 alSetError(AL_INVALID_NAME
);
512 alSetError(AL_INVALID_VALUE
);
514 ProcessContext(pContext
);
517 alSetError(AL_INVALID_OPERATION
);
523 ALAPI ALvoid ALAPIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
525 ALCcontext
*pContext
;
527 ALbufferlistitem
*pALBufferListItem
;
532 pContext
= alcGetCurrentContext();
535 SuspendContext(pContext
);
537 if (alIsSource(source
))
539 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
543 case AL_MAX_DISTANCE
:
544 case AL_ROLLOFF_FACTOR
:
545 case AL_REFERENCE_DISTANCE
:
546 alSourcef(source
, eParam
, (ALfloat
)lValue
);
549 case AL_SOURCE_RELATIVE
:
550 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
551 pSource
->bHeadRelative
= (ALboolean
)lValue
;
553 alSetError(AL_INVALID_VALUE
);
556 case AL_CONE_INNER_ANGLE
:
557 if ((lValue
>= 0) && (lValue
<= 360))
558 pSource
->flInnerAngle
= (float)lValue
;
560 alSetError(AL_INVALID_VALUE
);
563 case AL_CONE_OUTER_ANGLE
:
564 if ((lValue
>= 0) && (lValue
<= 360))
565 pSource
->flOuterAngle
= (float)lValue
;
567 alSetError(AL_INVALID_VALUE
);
571 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
572 pSource
->bLooping
= (ALboolean
)lValue
;
574 alSetError(AL_INVALID_VALUE
);
578 if ((pSource
->state
== AL_STOPPED
) || (pSource
->state
== AL_INITIAL
))
580 if (alIsBuffer(lValue
))
582 // Remove all elements in the queue
583 while (pSource
->queue
!= NULL
)
585 pALBufferListItem
= pSource
->queue
;
586 pSource
->queue
= pALBufferListItem
->next
;
587 // Decrement reference counter for buffer
588 if (pALBufferListItem
->buffer
)
589 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
)))->refcount
--;
590 // Record size of buffer
591 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
))->size
;
592 DataSize
+= BufferSize
;
593 // Increment the number of buffers removed from queue
595 // Release memory for buffer list item
596 free(pALBufferListItem
);
597 // Decrement the number of buffers in the queue
598 pSource
->BuffersInQueue
--;
601 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
604 // Source is now in STATIC mode
605 pSource
->lSourceType
= AL_STATIC
;
607 // Add the selected buffer to the queue
608 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
609 pALBufferListItem
->buffer
= lValue
;
610 pALBufferListItem
->bufferstate
= PENDING
;
611 pALBufferListItem
->flag
= 0;
612 pALBufferListItem
->next
= NULL
;
614 pSource
->queue
= pALBufferListItem
;
615 pSource
->BuffersInQueue
= 1;
617 DataSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(lValue
))->size
;
619 // Increment reference counter for buffer
620 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(lValue
)))->refcount
++;
624 // Source is now in UNDETERMINED mode
625 pSource
->lSourceType
= AL_UNDETERMINED
;
628 // Set Buffers Processed
629 pSource
->BuffersProcessed
= 0;
631 // Update AL_BUFFER parameter
632 pSource
->ulBufferID
= lValue
;
635 alSetError(AL_INVALID_VALUE
);
638 alSetError(AL_INVALID_OPERATION
);
641 case AL_SOURCE_STATE
:
643 alSetError(AL_INVALID_OPERATION
);
647 case AL_SAMPLE_OFFSET
:
651 pSource
->lOffsetType
= eParam
;
653 // Store Offset (convert Seconds into Milliseconds)
654 if (eParam
== AL_SEC_OFFSET
)
655 pSource
->lOffset
= lValue
* 1000;
657 pSource
->lOffset
= lValue
;
659 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
660 ApplyOffset(pSource
, AL_TRUE
);
663 alSetError(AL_INVALID_VALUE
);
666 case AL_DIRECT_FILTER
:
667 if(alIsFilter(lValue
))
669 ALfilter
*filter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue
);
672 pSource
->DirectFilter
.type
= AL_FILTER_NULL
;
673 pSource
->DirectFilter
.filter
= 0;
676 memcpy(&pSource
->DirectFilter
, filter
, sizeof(*filter
));
679 alSetError(AL_INVALID_VALUE
);
682 case AL_DIRECT_FILTER_GAINHF_AUTO
:
683 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
684 pSource
->DryGainHFAuto
= lValue
;
686 alSetError(AL_INVALID_VALUE
);
689 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
690 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
691 pSource
->WetGainAuto
= lValue
;
693 alSetError(AL_INVALID_VALUE
);
696 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
697 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
698 pSource
->WetGainHFAuto
= lValue
;
700 alSetError(AL_INVALID_VALUE
);
704 alSetError(AL_INVALID_ENUM
);
709 alSetError(AL_INVALID_NAME
);
711 ProcessContext(pContext
);
714 alSetError(AL_INVALID_OPERATION
);
720 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
722 ALCcontext
*pContext
;
724 pContext
= alcGetCurrentContext();
727 SuspendContext(pContext
);
729 if (alIsSource(source
))
731 ALsource
*pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
738 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
741 case AL_AUXILIARY_SEND_FILTER
:
742 if(lValue2
>= 0 && lValue2
< MAX_SENDS
&&
743 (alIsAuxiliaryEffectSlot(lValue1
) || lValue1
== 0) &&
746 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(lValue1
);
747 ALfilter
*ALFilter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue3
);
749 /* Release refcount on the previous slot, and add one for
751 if(pSource
->Send
[lValue2
].Slot
)
752 pSource
->Send
[lValue2
].Slot
->refcount
--;
753 pSource
->Send
[lValue2
].Slot
= ALEffectSlot
;
754 if(pSource
->Send
[lValue2
].Slot
)
755 pSource
->Send
[lValue2
].Slot
->refcount
++;
760 pSource
->Send
[lValue2
].WetFilter
.type
= 0;
761 pSource
->Send
[lValue2
].WetFilter
.filter
= 0;
764 memcpy(&pSource
->Send
[lValue2
].WetFilter
, ALFilter
, sizeof(*ALFilter
));
767 alSetError(AL_INVALID_VALUE
);
771 alSetError(AL_INVALID_ENUM
);
776 alSetError(AL_INVALID_NAME
);
778 ProcessContext(pContext
);
781 alSetError(AL_INVALID_OPERATION
);
787 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
789 ALCcontext
*pContext
;
791 pContext
= alcGetCurrentContext();
794 SuspendContext(pContext
);
798 if (alIsSource(source
))
802 case AL_SOURCE_RELATIVE
:
803 case AL_CONE_INNER_ANGLE
:
804 case AL_CONE_OUTER_ANGLE
:
807 case AL_SOURCE_STATE
:
809 case AL_SAMPLE_OFFSET
:
811 case AL_MAX_DISTANCE
:
812 case AL_ROLLOFF_FACTOR
:
813 case AL_REFERENCE_DISTANCE
:
814 case AL_DIRECT_FILTER
:
815 case AL_DIRECT_FILTER_GAINHF_AUTO
:
816 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
817 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
818 alSourcei(source
, eParam
, plValues
[0]);
824 case AL_AUXILIARY_SEND_FILTER
:
825 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
829 alSetError(AL_INVALID_ENUM
);
834 alSetError(AL_INVALID_NAME
);
837 alSetError(AL_INVALID_VALUE
);
839 ProcessContext(pContext
);
842 alSetError(AL_INVALID_OPERATION
);
848 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
850 ALCcontext
*pContext
;
854 pContext
= alcGetCurrentContext();
857 SuspendContext(pContext
);
861 if (alIsSource(source
))
863 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
868 *pflValue
= pSource
->flPitch
;
872 *pflValue
= pSource
->flGain
;
876 *pflValue
= pSource
->flMinGain
;
880 *pflValue
= pSource
->flMaxGain
;
883 case AL_MAX_DISTANCE
:
884 *pflValue
= pSource
->flMaxDistance
;
887 case AL_ROLLOFF_FACTOR
:
888 *pflValue
= pSource
->flRollOffFactor
;
891 case AL_CONE_OUTER_GAIN
:
892 *pflValue
= pSource
->flOuterGain
;
895 case AL_CONE_OUTER_GAINHF
:
896 *pflValue
= pSource
->OuterGainHF
;
900 case AL_SAMPLE_OFFSET
:
902 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
903 *pflValue
= flOffset
;
905 alSetError(AL_INVALID_OPERATION
);
908 case AL_CONE_INNER_ANGLE
:
909 *pflValue
= pSource
->flInnerAngle
;
912 case AL_CONE_OUTER_ANGLE
:
913 *pflValue
= pSource
->flOuterAngle
;
916 case AL_REFERENCE_DISTANCE
:
917 *pflValue
= pSource
->flRefDistance
;
920 case AL_AIR_ABSORPTION_FACTOR
:
921 *pflValue
= pSource
->AirAbsorptionFactor
;
924 case AL_ROOM_ROLLOFF_FACTOR
:
925 *pflValue
= pSource
->RoomRolloffFactor
;
928 case AL_DOPPLER_FACTOR
:
929 *pflValue
= pSource
->DopplerFactor
;
933 alSetError(AL_INVALID_ENUM
);
938 alSetError(AL_INVALID_NAME
);
941 alSetError(AL_INVALID_VALUE
);
943 ProcessContext(pContext
);
946 alSetError(AL_INVALID_OPERATION
);
952 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
954 ALCcontext
*pContext
;
957 pContext
= alcGetCurrentContext();
960 SuspendContext(pContext
);
962 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
964 if (alIsSource(source
))
966 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
971 *pflValue1
= pSource
->vPosition
[0];
972 *pflValue2
= pSource
->vPosition
[1];
973 *pflValue3
= pSource
->vPosition
[2];
977 *pflValue1
= pSource
->vVelocity
[0];
978 *pflValue2
= pSource
->vVelocity
[1];
979 *pflValue3
= pSource
->vVelocity
[2];
983 *pflValue1
= pSource
->vOrientation
[0];
984 *pflValue2
= pSource
->vOrientation
[1];
985 *pflValue3
= pSource
->vOrientation
[2];
989 alSetError(AL_INVALID_ENUM
);
994 alSetError(AL_INVALID_NAME
);
997 alSetError(AL_INVALID_VALUE
);
999 ProcessContext(pContext
);
1002 alSetError(AL_INVALID_OPERATION
);
1008 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1010 ALCcontext
*pContext
;
1013 pContext
= alcGetCurrentContext();
1016 SuspendContext(pContext
);
1020 if (alIsSource(source
))
1022 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1030 case AL_MAX_DISTANCE
:
1031 case AL_ROLLOFF_FACTOR
:
1032 case AL_DOPPLER_FACTOR
:
1033 case AL_CONE_OUTER_GAIN
:
1035 case AL_SAMPLE_OFFSET
:
1036 case AL_BYTE_OFFSET
:
1037 case AL_CONE_INNER_ANGLE
:
1038 case AL_CONE_OUTER_ANGLE
:
1039 case AL_REFERENCE_DISTANCE
:
1040 case AL_CONE_OUTER_GAINHF
:
1041 case AL_AIR_ABSORPTION_FACTOR
:
1042 case AL_ROOM_ROLLOFF_FACTOR
:
1043 alGetSourcef(source
, eParam
, pflValues
);
1047 pflValues
[0] = pSource
->vPosition
[0];
1048 pflValues
[1] = pSource
->vPosition
[1];
1049 pflValues
[2] = pSource
->vPosition
[2];
1053 pflValues
[0] = pSource
->vVelocity
[0];
1054 pflValues
[1] = pSource
->vVelocity
[1];
1055 pflValues
[2] = pSource
->vVelocity
[2];
1059 pflValues
[0] = pSource
->vOrientation
[0];
1060 pflValues
[1] = pSource
->vOrientation
[1];
1061 pflValues
[2] = pSource
->vOrientation
[2];
1065 alSetError(AL_INVALID_ENUM
);
1070 alSetError(AL_INVALID_NAME
);
1073 alSetError(AL_INVALID_VALUE
);
1075 ProcessContext(pContext
);
1078 alSetError(AL_INVALID_OPERATION
);
1084 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1086 ALCcontext
*pContext
;
1090 pContext
= alcGetCurrentContext();
1093 SuspendContext(pContext
);
1097 if (alIsSource(source
))
1099 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1103 case AL_MAX_DISTANCE
:
1104 *plValue
= (ALint
)pSource
->flMaxDistance
;
1107 case AL_ROLLOFF_FACTOR
:
1108 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1111 case AL_REFERENCE_DISTANCE
:
1112 *plValue
= (ALint
)pSource
->flRefDistance
;
1115 case AL_SOURCE_RELATIVE
:
1116 *plValue
= pSource
->bHeadRelative
;
1119 case AL_CONE_INNER_ANGLE
:
1120 *plValue
= (ALint
)pSource
->flInnerAngle
;
1123 case AL_CONE_OUTER_ANGLE
:
1124 *plValue
= (ALint
)pSource
->flOuterAngle
;
1128 *plValue
= pSource
->bLooping
;
1132 *plValue
= pSource
->ulBufferID
;
1135 case AL_SOURCE_STATE
:
1136 *plValue
= pSource
->state
;
1139 case AL_BUFFERS_QUEUED
:
1140 *plValue
= pSource
->BuffersInQueue
;
1143 case AL_BUFFERS_PROCESSED
:
1144 if(pSource
->bLooping
)
1146 /* Buffers on a looping source are in a perpetual state
1147 * of PENDING, so don't report any as PROCESSED */
1151 *plValue
= pSource
->BuffersProcessed
;
1154 case AL_SOURCE_TYPE
:
1155 *plValue
= pSource
->lSourceType
;
1159 case AL_SAMPLE_OFFSET
:
1160 case AL_BYTE_OFFSET
:
1161 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
1162 *plValue
= (ALint
)flOffset
;
1164 alSetError(AL_INVALID_OPERATION
);
1167 case AL_DIRECT_FILTER
:
1168 *plValue
= pSource
->DirectFilter
.filter
;
1171 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1172 *plValue
= pSource
->DryGainHFAuto
;
1175 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1176 *plValue
= pSource
->WetGainAuto
;
1179 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1180 *plValue
= pSource
->WetGainHFAuto
;
1183 case AL_DOPPLER_FACTOR
:
1184 *plValue
= (ALint
)pSource
->DopplerFactor
;
1188 alSetError(AL_INVALID_ENUM
);
1193 alSetError(AL_INVALID_NAME
);
1196 alSetError(AL_INVALID_VALUE
);
1198 ProcessContext(pContext
);
1201 alSetError(AL_INVALID_OPERATION
);
1207 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1209 ALCcontext
*pContext
;
1212 pContext
= alcGetCurrentContext();
1215 SuspendContext(pContext
);
1217 if ((plValue1
) && (plValue2
) && (plValue3
))
1219 if (alIsSource(source
))
1221 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1226 *plValue1
= (ALint
)pSource
->vPosition
[0];
1227 *plValue2
= (ALint
)pSource
->vPosition
[1];
1228 *plValue3
= (ALint
)pSource
->vPosition
[2];
1232 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1233 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1234 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1238 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1239 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1240 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1244 alSetError(AL_INVALID_ENUM
);
1249 alSetError(AL_INVALID_NAME
);
1252 alSetError(AL_INVALID_VALUE
);
1254 ProcessContext(pContext
);
1257 alSetError(AL_INVALID_OPERATION
);
1263 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1265 ALCcontext
*pContext
;
1268 pContext
= alcGetCurrentContext();
1271 SuspendContext(pContext
);
1275 if (alIsSource(source
))
1277 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1281 case AL_SOURCE_RELATIVE
:
1282 case AL_CONE_INNER_ANGLE
:
1283 case AL_CONE_OUTER_ANGLE
:
1286 case AL_SOURCE_STATE
:
1287 case AL_BUFFERS_QUEUED
:
1288 case AL_BUFFERS_PROCESSED
:
1290 case AL_SAMPLE_OFFSET
:
1291 case AL_BYTE_OFFSET
:
1292 case AL_MAX_DISTANCE
:
1293 case AL_ROLLOFF_FACTOR
:
1294 case AL_DOPPLER_FACTOR
:
1295 case AL_REFERENCE_DISTANCE
:
1296 case AL_SOURCE_TYPE
:
1297 case AL_DIRECT_FILTER
:
1298 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1299 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1300 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1301 alGetSourcei(source
, eParam
, plValues
);
1305 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1306 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1307 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1311 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1312 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1313 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1317 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1318 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1319 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1323 alSetError(AL_INVALID_ENUM
);
1328 alSetError(AL_INVALID_NAME
);
1331 alSetError(AL_INVALID_VALUE
);
1333 ProcessContext(pContext
);
1336 alSetError(AL_INVALID_OPERATION
);
1342 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1344 alSourcePlayv(1, &source
);
1348 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1350 ALCcontext
*pContext
;
1352 ALbufferlistitem
*ALBufferList
;
1353 ALboolean bSourcesValid
= AL_TRUE
;
1357 pContext
= alcGetCurrentContext();
1360 SuspendContext(pContext
);
1364 // Check that all the Sources are valid
1365 for (i
= 0; i
< n
; i
++)
1367 if (!alIsSource(pSourceList
[i
]))
1369 alSetError(AL_INVALID_NAME
);
1370 bSourcesValid
= AL_FALSE
;
1377 for (i
= 0; i
< n
; i
++)
1379 // Assume Source won't need to play
1382 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1384 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1385 ALBufferList
= pSource
->queue
;
1386 while (ALBufferList
)
1388 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1393 ALBufferList
= ALBufferList
->next
;
1398 if (pSource
->state
!= AL_PAUSED
)
1400 pSource
->state
= AL_PLAYING
;
1401 pSource
->inuse
= AL_TRUE
;
1402 pSource
->play
= AL_TRUE
;
1403 pSource
->position
= 0;
1404 pSource
->position_fraction
= 0;
1405 pSource
->BuffersProcessed
= 0;
1406 pSource
->BuffersPlayed
= 0;
1407 pSource
->BufferPosition
= 0;
1408 pSource
->lBytesPlayed
= 0;
1410 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1412 // Make sure all the Buffers in the queue are marked as PENDING
1413 ALBufferList
= pSource
->queue
;
1414 while (ALBufferList
)
1416 ALBufferList
->bufferstate
= PENDING
;
1417 ALBufferList
= ALBufferList
->next
;
1422 pSource
->state
= AL_PLAYING
;
1423 pSource
->inuse
= AL_TRUE
;
1424 pSource
->play
= AL_TRUE
;
1427 // Check if an Offset has been set
1428 if (pSource
->lOffset
)
1429 ApplyOffset(pSource
, AL_FALSE
);
1433 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1434 ALBufferList
= pSource
->queue
;
1435 while (ALBufferList
)
1437 ALBufferList
->bufferstate
= PROCESSED
;
1438 ALBufferList
= ALBufferList
->next
;
1441 pSource
->BuffersPlayed
= pSource
->BuffersProcessed
= pSource
->BuffersInQueue
;
1448 // sources is a NULL pointer
1449 alSetError(AL_INVALID_VALUE
);
1452 ProcessContext(pContext
);
1457 alSetError(AL_INVALID_OPERATION
);
1463 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1465 alSourcePausev(1, &source
);
1469 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1471 ALCcontext
*Context
;
1474 ALboolean bSourcesValid
= AL_TRUE
;
1476 Context
=alcGetCurrentContext();
1479 SuspendContext(Context
);
1483 // Check all the Sources are valid
1486 if (!alIsSource(sources
[i
]))
1488 alSetError(AL_INVALID_NAME
);
1489 bSourcesValid
= AL_FALSE
;
1498 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1499 if (Source
->state
==AL_PLAYING
)
1501 Source
->state
=AL_PAUSED
;
1502 Source
->inuse
=AL_FALSE
;
1509 // sources is a NULL pointer
1510 alSetError(AL_INVALID_VALUE
);
1513 ProcessContext(Context
);
1518 alSetError(AL_INVALID_OPERATION
);
1524 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1526 alSourceStopv(1, &source
);
1530 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1532 ALCcontext
*Context
;
1535 ALbufferlistitem
*ALBufferListItem
;
1536 ALboolean bSourcesValid
= AL_TRUE
;
1538 Context
=alcGetCurrentContext();
1541 SuspendContext(Context
);
1545 // Check all the Sources are valid
1548 if (!alIsSource(sources
[i
]))
1550 alSetError(AL_INVALID_NAME
);
1551 bSourcesValid
= AL_FALSE
;
1560 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1561 if (Source
->state
!=AL_INITIAL
)
1563 Source
->state
=AL_STOPPED
;
1564 Source
->inuse
=AL_FALSE
;
1565 Source
->BuffersPlayed
= Source
->BuffersProcessed
= Source
->BuffersInQueue
;
1566 ALBufferListItem
= Source
->queue
;
1567 while (ALBufferListItem
!= NULL
)
1569 ALBufferListItem
->bufferstate
= PROCESSED
;
1570 ALBufferListItem
= ALBufferListItem
->next
;
1573 Source
->lOffset
= 0;
1579 // sources is a NULL pointer
1580 alSetError(AL_INVALID_VALUE
);
1583 ProcessContext(Context
);
1588 alSetError(AL_INVALID_OPERATION
);
1594 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1596 alSourceRewindv(1, &source
);
1600 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1602 ALCcontext
*Context
;
1605 ALbufferlistitem
*ALBufferListItem
;
1606 ALboolean bSourcesValid
= AL_TRUE
;
1608 Context
=alcGetCurrentContext();
1611 SuspendContext(Context
);
1615 // Check all the Sources are valid
1618 if (!alIsSource(sources
[i
]))
1620 alSetError(AL_INVALID_NAME
);
1621 bSourcesValid
= AL_FALSE
;
1630 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1631 if (Source
->state
!=AL_INITIAL
)
1633 Source
->state
=AL_INITIAL
;
1634 Source
->inuse
=AL_FALSE
;
1636 Source
->position_fraction
=0;
1637 Source
->BuffersProcessed
= 0;
1638 ALBufferListItem
= Source
->queue
;
1639 while (ALBufferListItem
!= NULL
)
1641 ALBufferListItem
->bufferstate
= PENDING
;
1642 ALBufferListItem
= ALBufferListItem
->next
;
1645 Source
->ulBufferID
= Source
->queue
->buffer
;
1647 Source
->lOffset
= 0;
1653 // sources is a NULL pointer
1654 alSetError(AL_INVALID_VALUE
);
1657 ProcessContext(Context
);
1662 alSetError(AL_INVALID_OPERATION
);
1669 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1671 ALCcontext
*Context
;
1674 ALbufferlistitem
*ALBufferList
;
1675 ALbufferlistitem
*ALBufferListStart
;
1680 ALboolean bBuffersValid
= AL_TRUE
;
1685 Context
=alcGetCurrentContext();
1688 SuspendContext(Context
);
1693 // Check that all buffers are valid or zero and that the source is valid
1695 // Check that this is a valid source
1696 if (alIsSource(source
))
1698 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1700 // Check that this is not a STATIC Source
1701 if (ALSource
->lSourceType
!= AL_STATIC
)
1706 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1707 ALBufferList
= ALSource
->queue
;
1708 while (ALBufferList
)
1710 if (ALBufferList
->buffer
)
1712 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1713 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1716 ALBufferList
= ALBufferList
->next
;
1719 for (i
= 0; i
< n
; i
++)
1721 if (alIsBuffer(buffers
[i
]))
1725 if ((iFrequency
== -1) && (iFormat
== -1))
1727 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1728 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1732 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1733 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1735 alSetError(AL_INVALID_OPERATION
);
1736 bBuffersValid
= AL_FALSE
;
1744 alSetError(AL_INVALID_NAME
);
1745 bBuffersValid
= AL_FALSE
;
1752 // Change Source Type
1753 ALSource
->lSourceType
= AL_STREAMING
;
1755 // All buffers are valid - so add them to the list
1756 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1757 ALBufferListStart
->buffer
= buffers
[0];
1758 ALBufferListStart
->bufferstate
= PENDING
;
1759 ALBufferListStart
->flag
= 0;
1760 ALBufferListStart
->next
= NULL
;
1763 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1767 DataSize
+= BufferSize
;
1769 // Increment reference counter for buffer
1771 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1773 ALBufferList
= ALBufferListStart
;
1775 for (i
= 1; i
< n
; i
++)
1777 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1778 ALBufferList
->next
->buffer
= buffers
[i
];
1779 ALBufferList
->next
->bufferstate
= PENDING
;
1780 ALBufferList
->next
->flag
= 0;
1781 ALBufferList
->next
->next
= NULL
;
1784 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1788 DataSize
+= BufferSize
;
1790 // Increment reference counter for buffer
1792 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1794 ALBufferList
= ALBufferList
->next
;
1797 if (ALSource
->queue
== NULL
)
1799 ALSource
->queue
= ALBufferListStart
;
1800 // Update Current Buffer
1801 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1805 // Find end of queue
1806 ALBufferList
= ALSource
->queue
;
1807 while (ALBufferList
->next
!= NULL
)
1809 ALBufferList
= ALBufferList
->next
;
1812 ALBufferList
->next
= ALBufferListStart
;
1815 // Update number of buffers in queue
1816 ALSource
->BuffersInQueue
+= n
;
1821 // Invalid Source Type (can't queue on a Static Source)
1822 alSetError(AL_INVALID_OPERATION
);
1827 // Invalid Source Name
1828 alSetError(AL_INVALID_NAME
);
1831 ProcessContext(Context
);
1836 alSetError(AL_INVALID_OPERATION
);
1843 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1844 // an array of buffer IDs that are to be filled with the names of the buffers removed
1845 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1847 ALCcontext
*Context
;
1850 ALbufferlistitem
*ALBufferList
;
1854 ALboolean bBuffersProcessed
;
1861 bBuffersProcessed
= AL_TRUE
;
1863 Context
=alcGetCurrentContext();
1866 SuspendContext(Context
);
1868 if (alIsSource(source
))
1870 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1872 // Check that all 'n' buffers have been processed
1873 ALBufferList
= ALSource
->queue
;
1874 for (i
= 0; i
< n
; i
++)
1876 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1878 ALBufferList
= ALBufferList
->next
;
1882 bBuffersProcessed
= AL_FALSE
;
1887 // If all 'n' buffers have been processed, remove them from the queue
1888 if (bBuffersProcessed
)
1890 for (i
= 0; i
< n
; i
++)
1892 ALBufferList
= ALSource
->queue
;
1894 ALSource
->queue
= ALBufferList
->next
;
1895 // Record name of buffer
1896 buffers
[i
] = ALBufferList
->buffer
;
1897 // Decrement buffer reference counter
1898 if (ALBufferList
->buffer
)
1899 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1900 // Record size of buffer
1901 if (ALBufferList
->buffer
)
1902 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1906 DataSize
+= BufferSize
;
1907 // Release memory for buffer list item
1909 ALSource
->BuffersInQueue
--;
1910 ALSource
->BuffersProcessed
--;
1913 if (ALSource
->state
!= AL_PLAYING
)
1915 if (ALSource
->queue
)
1916 BufferID
= ALSource
->queue
->buffer
;
1920 ALSource
->ulBufferID
= BufferID
;
1923 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1925 ALSource
->BuffersPlayed
= 0;
1926 ALSource
->BufferPosition
= 0;
1929 ALSource
->BuffersPlayed
-= n
;
1933 // Some buffers can't be unqueue because they have not been processed
1934 alSetError(AL_INVALID_VALUE
);
1939 // Invalid Source Name
1940 alSetError(AL_INVALID_NAME
);
1943 ProcessContext(Context
);
1948 alSetError(AL_INVALID_OPERATION
);
1955 static ALvoid
InitSourceParams(ALsource
*pSource
)
1957 pSource
->flInnerAngle
= 360.0f
;
1958 pSource
->flOuterAngle
= 360.0f
;
1959 pSource
->flPitch
= 1.0f
;
1960 pSource
->vPosition
[0] = 0.0f
;
1961 pSource
->vPosition
[1] = 0.0f
;
1962 pSource
->vPosition
[2] = 0.0f
;
1963 pSource
->vOrientation
[0] = 0.0f
;
1964 pSource
->vOrientation
[1] = 0.0f
;
1965 pSource
->vOrientation
[2] = 0.0f
;
1966 pSource
->vVelocity
[0] = 0.0f
;
1967 pSource
->vVelocity
[1] = 0.0f
;
1968 pSource
->vVelocity
[2] = 0.0f
;
1969 pSource
->flRefDistance
= 1.0f
;
1970 pSource
->flMaxDistance
= FLT_MAX
;
1971 pSource
->flRollOffFactor
= 1.0f
;
1972 pSource
->bLooping
= AL_FALSE
;
1973 pSource
->flGain
= 1.0f
;
1974 pSource
->flMinGain
= 0.0f
;
1975 pSource
->flMaxGain
= 1.0f
;
1976 pSource
->flOuterGain
= 0.0f
;
1977 pSource
->OuterGainHF
= 1.0f
;
1979 pSource
->DryGainHFAuto
= AL_TRUE
;
1980 pSource
->WetGainAuto
= AL_TRUE
;
1981 pSource
->WetGainHFAuto
= AL_TRUE
;
1982 pSource
->AirAbsorptionFactor
= 0.0f
;
1983 pSource
->RoomRolloffFactor
= 0.0f
;
1984 pSource
->DopplerFactor
= 1.0f
;
1986 pSource
->state
= AL_INITIAL
;
1987 pSource
->lSourceType
= AL_UNDETERMINED
;
1989 pSource
->ulBufferID
= 0;
1996 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1997 The offset is relative to the start of the queue (not the start of the current buffer)
1999 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
2001 ALbufferlistitem
*pBufferList
;
2003 ALfloat flBufferFreq
;
2004 ALint lBytesPlayed
, lChannels
;
2005 ALenum eOriginalFormat
;
2006 ALboolean bReturn
= AL_TRUE
;
2007 ALint lTotalBufferDataSize
;
2009 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
2011 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
2012 // Get Current Buffer Size and frequency (in milliseconds)
2013 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
2014 eOriginalFormat
= pBuffer
->eOriginalFormat
;
2015 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2017 // Get Current BytesPlayed
2018 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2019 // Add byte length of any processed buffers in the queue
2020 pBufferList
= pSource
->queue
;
2021 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2023 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2024 pBufferList
= pBufferList
->next
;
2027 lTotalBufferDataSize
= 0;
2028 pBufferList
= pSource
->queue
;
2031 if (pBufferList
->buffer
)
2032 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2033 pBufferList
= pBufferList
->next
;
2036 if (pSource
->bLooping
)
2038 if (lBytesPlayed
< 0)
2041 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
2045 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2046 if(lBytesPlayed
< 0)
2048 if(lBytesPlayed
> lTotalBufferDataSize
)
2049 lBytesPlayed
= lTotalBufferDataSize
;
2055 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
2057 case AL_SAMPLE_OFFSET
:
2058 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
2060 case AL_BYTE_OFFSET
:
2061 // Take into account the original format of the Buffer
2062 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2063 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2065 // Compression rate of the ADPCM supported is 3.6111 to 1
2066 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
2067 // Round down to nearest ADPCM block
2068 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
2070 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2072 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 2);
2074 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2076 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2078 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2080 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2082 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2084 *pflOffset
= (ALfloat
)(lBytesPlayed
<< 1);
2088 *pflOffset
= (ALfloat
)lBytesPlayed
;
2105 Apply a playback offset to the Source. This function will update the queue (to correctly
2106 mark buffers as 'pending' or 'processed' depending upon the new offset.
2108 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2110 ALbufferlistitem
*pBufferList
;
2112 ALint lBufferSize
, lTotalBufferSize
;
2115 // Get true byte offset
2116 lByteOffset
= GetByteOffset(pSource
);
2118 // If this is a valid offset apply it
2119 if (lByteOffset
!= -1)
2121 // Sort out the queue (pending and processed states)
2122 pBufferList
= pSource
->queue
;
2123 lTotalBufferSize
= 0;
2124 pSource
->BuffersPlayed
= 0;
2125 pSource
->BuffersProcessed
= 0;
2128 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2129 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2131 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2133 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2134 // update the state to PROCESSED
2135 pSource
->BuffersPlayed
++;
2137 if (!pSource
->bLooping
)
2139 pBufferList
->bufferstate
= PROCESSED
;
2140 pSource
->BuffersProcessed
++;
2143 else if (lTotalBufferSize
<= lByteOffset
)
2145 // Offset is within this buffer
2146 pBufferList
->bufferstate
= PENDING
;
2148 // Set Current Buffer ID
2149 pSource
->ulBufferID
= pBufferList
->buffer
;
2151 // Set current position in this buffer
2152 pSource
->BufferPosition
= lByteOffset
- lTotalBufferSize
;
2154 // Set Total Bytes Played to Offset
2155 pSource
->lBytesPlayed
= lByteOffset
;
2157 // SW Mixer Positions are in Samples
2158 pSource
->position
= pSource
->BufferPosition
/
2159 aluBytesFromFormat(pBuffer
->format
) /
2160 aluChannelsFromFormat(pBuffer
->format
);
2164 // Offset is before this buffer, so mark as pending
2165 pBufferList
->bufferstate
= PENDING
;
2168 // Increment the TotalBufferSize
2169 lTotalBufferSize
+= lBufferSize
;
2171 // Move on to next buffer in the Queue
2172 pBufferList
= pBufferList
->next
;
2178 alSetError(AL_INVALID_VALUE
);
2182 pSource
->lOffset
= 0;
2189 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2190 offset supplied by the application). This takes into account the fact that the buffer format
2191 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2193 static ALint
GetByteOffset(ALsource
*pSource
)
2195 ALbuffer
*pBuffer
= NULL
;
2196 ALbufferlistitem
*pBufferList
;
2197 ALfloat flBufferFreq
;
2199 ALint lByteOffset
= -1;
2200 ALint lTotalBufferDataSize
;
2202 // Find the first non-NULL Buffer in the Queue
2203 pBufferList
= pSource
->queue
;
2206 if (pBufferList
->buffer
)
2208 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2211 pBufferList
= pBufferList
->next
;
2216 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2217 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2219 // Determine the ByteOffset (and ensure it is block aligned)
2220 switch (pSource
->lOffsetType
)
2222 case AL_BYTE_OFFSET
:
2223 // Take into consideration the original format
2224 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2225 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2227 // Round down to nearest ADPCM block
2228 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2229 // Multiply by compression rate
2230 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2231 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2233 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2235 lByteOffset
= pSource
->lOffset
* 4;
2236 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2238 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2240 lByteOffset
= pSource
->lOffset
* 2;
2241 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2243 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2245 lByteOffset
= pSource
->lOffset
* 2;
2246 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2248 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2250 lByteOffset
= pSource
->lOffset
/ 2;
2251 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2255 lByteOffset
= pSource
->lOffset
;
2256 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2260 case AL_SAMPLE_OFFSET
:
2261 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2265 // Note - lOffset is internally stored as Milliseconds
2266 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2267 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2271 lTotalBufferDataSize
= 0;
2272 pBufferList
= pSource
->queue
;
2275 if (pBufferList
->buffer
)
2276 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2277 pBufferList
= pBufferList
->next
;
2280 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2281 if (lByteOffset
>= lTotalBufferDataSize
)
2289 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2292 if(Context
->SourceCount
> 0)
2293 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", Context
->SourceCount
);
2296 while(Context
->Source
)
2298 ALsource
*temp
= Context
->Source
;
2299 Context
->Source
= Context
->Source
->next
;
2301 // Release source structure
2302 ALTHUNK_REMOVEENTRY(temp
->source
);
2303 memset(temp
, 0, sizeof(ALsource
));
2306 Context
->SourceCount
= 0;