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 InitLowPassFilter(Context
, &(*list
)->iirFilter
);
80 sources
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
81 (*list
)->source
= sources
[i
];
83 InitSourceParams(*list
);
84 Context
->SourceCount
++;
87 list
= &(*list
)->next
;
92 // Not enough resources to create the Sources
93 alSetError(AL_INVALID_VALUE
);
99 alSetError(AL_INVALID_VALUE
);
104 // No Device created, or attached to Context
105 alSetError(AL_INVALID_OPERATION
);
109 ProcessContext(Context
);
114 alSetError(AL_INVALID_OPERATION
);
121 ALAPI ALvoid ALAPIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
128 ALbufferlistitem
*ALBufferList
;
129 ALboolean bSourcesValid
= AL_TRUE
;
131 Context
= alcGetCurrentContext();
134 SuspendContext(Context
);
138 Device
= alcGetContextsDevice(Context
);
142 // Check that all Sources are valid (and can therefore be deleted)
143 for (i
= 0; i
< n
; i
++)
145 if (!alIsSource(sources
[i
]))
147 alSetError(AL_INVALID_NAME
);
148 bSourcesValid
= AL_FALSE
;
155 // All Sources are valid, and can be deleted
156 for (i
= 0; i
< n
; i
++)
158 // Recheck that the Source is valid, because there could be duplicated Source names
159 if (alIsSource(sources
[i
]))
161 ALSource
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
162 alSourceStop((ALuint
)ALSource
->source
);
164 // For each buffer in the source's queue, decrement its reference counter and remove it
165 while (ALSource
->queue
!= NULL
)
167 ALBufferList
= ALSource
->queue
;
168 // Decrement buffer's reference counter
169 if (ALBufferList
->buffer
!= 0)
170 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
171 // Update queue to point to next element in list
172 ALSource
->queue
= ALBufferList
->next
;
173 // Release memory allocated for buffer list item
177 for(j
= 0;j
< MAX_SENDS
;++j
)
179 if(ALSource
->Send
[j
].Slot
)
180 ALSource
->Send
[j
].Slot
->refcount
--;
181 ALSource
->Send
[j
].Slot
= NULL
;
184 free(ALSource
->iirFilter
.coef
);
185 free(ALSource
->iirFilter
.history
);
187 // Decrement Source count
188 Context
->SourceCount
--;
190 // Remove Source from list of Sources
191 list
= &Context
->Source
;
192 while(*list
&& *list
!= ALSource
)
193 list
= &(*list
)->next
;
196 *list
= (*list
)->next
;
197 ALTHUNK_REMOVEENTRY(ALSource
->source
);
199 memset(ALSource
,0,sizeof(ALsource
));
207 // No Device created, or attached to Context
208 alSetError(AL_INVALID_OPERATION
);
212 alSetError(AL_INVALID_VALUE
);
214 ProcessContext(Context
);
219 alSetError(AL_INVALID_OPERATION
);
226 ALAPI ALboolean ALAPIENTRY
alIsSource(ALuint source
)
228 ALboolean result
=AL_FALSE
;
232 Context
=alcGetCurrentContext();
235 SuspendContext(Context
);
237 // To determine if this is a valid Source name, look through the list of generated Sources
238 Source
= Context
->Source
;
241 if (Source
== (ALsource
*)ALTHUNK_LOOKUPENTRY(source
))
247 Source
= Source
->next
;
250 ProcessContext(Context
);
255 alSetError(AL_INVALID_OPERATION
);
262 ALAPI ALvoid ALAPIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
264 ALCcontext
*pContext
;
267 pContext
= alcGetCurrentContext();
270 SuspendContext(pContext
);
272 if (alIsSource(source
))
274 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
281 pSource
->flPitch
= flValue
;
282 if(pSource
->flPitch
< 0.001f
)
283 pSource
->flPitch
= 0.001f
;
286 alSetError(AL_INVALID_VALUE
);
289 case AL_CONE_INNER_ANGLE
:
290 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
291 pSource
->flInnerAngle
= flValue
;
293 alSetError(AL_INVALID_VALUE
);
296 case AL_CONE_OUTER_ANGLE
:
297 if ((flValue
>= 0.0f
) && (flValue
<= 360.0f
))
298 pSource
->flOuterAngle
= flValue
;
300 alSetError(AL_INVALID_VALUE
);
305 pSource
->flGain
= flValue
;
307 alSetError(AL_INVALID_VALUE
);
310 case AL_MAX_DISTANCE
:
312 pSource
->flMaxDistance
= flValue
;
314 alSetError(AL_INVALID_VALUE
);
317 case AL_ROLLOFF_FACTOR
:
319 pSource
->flRollOffFactor
= flValue
;
321 alSetError(AL_INVALID_VALUE
);
324 case AL_REFERENCE_DISTANCE
:
326 pSource
->flRefDistance
= flValue
;
328 alSetError(AL_INVALID_VALUE
);
332 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
333 pSource
->flMinGain
= flValue
;
335 alSetError(AL_INVALID_VALUE
);
339 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
340 pSource
->flMaxGain
= flValue
;
342 alSetError(AL_INVALID_VALUE
);
345 case AL_CONE_OUTER_GAIN
:
346 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
347 pSource
->flOuterGain
= flValue
;
349 alSetError(AL_INVALID_VALUE
);
352 case AL_CONE_OUTER_GAINHF
:
353 if ((flValue
>= 0.0f
) && (flValue
<= 1.0f
))
354 pSource
->OuterGainHF
= flValue
;
356 alSetError(AL_INVALID_VALUE
);
359 case AL_AIR_ABSORPTION_FACTOR
:
360 if (flValue
>= 0.0f
&& flValue
<= 10.0f
)
361 pSource
->AirAbsorptionFactor
= flValue
;
363 alSetError(AL_INVALID_VALUE
);
366 case AL_ROOM_ROLLOFF_FACTOR
:
367 if (flValue
>= 0.0f
&& flValue
<= 1.0f
)
368 pSource
->RoomRolloffFactor
= flValue
;
370 alSetError(AL_INVALID_VALUE
);
374 case AL_SAMPLE_OFFSET
:
378 pSource
->lOffsetType
= eParam
;
380 // Store Offset (convert Seconds into Milliseconds)
381 if (eParam
== AL_SEC_OFFSET
)
382 pSource
->lOffset
= (ALint
)(flValue
* 1000.0f
);
384 pSource
->lOffset
= (ALint
)flValue
;
386 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
387 ApplyOffset(pSource
, AL_TRUE
);
390 alSetError(AL_INVALID_VALUE
);
394 alSetError(AL_INVALID_ENUM
);
400 // Invalid Source Name
401 alSetError(AL_INVALID_NAME
);
404 ProcessContext(pContext
);
409 alSetError(AL_INVALID_OPERATION
);
416 ALAPI ALvoid ALAPIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
418 ALCcontext
*pContext
;
421 pContext
= alcGetCurrentContext();
424 SuspendContext(pContext
);
426 if (alIsSource(source
))
428 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
432 pSource
->vPosition
[0] = flValue1
;
433 pSource
->vPosition
[1] = flValue2
;
434 pSource
->vPosition
[2] = flValue3
;
438 pSource
->vVelocity
[0] = flValue1
;
439 pSource
->vVelocity
[1] = flValue2
;
440 pSource
->vVelocity
[2] = flValue3
;
444 pSource
->vOrientation
[0] = flValue1
;
445 pSource
->vOrientation
[1] = flValue2
;
446 pSource
->vOrientation
[2] = flValue3
;
450 alSetError(AL_INVALID_ENUM
);
455 alSetError(AL_INVALID_NAME
);
457 ProcessContext(pContext
);
461 alSetError(AL_INVALID_OPERATION
);
468 ALAPI ALvoid ALAPIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
470 ALCcontext
*pContext
;
472 pContext
= alcGetCurrentContext();
475 SuspendContext(pContext
);
479 if (alIsSource(source
))
484 case AL_CONE_INNER_ANGLE
:
485 case AL_CONE_OUTER_ANGLE
:
487 case AL_MAX_DISTANCE
:
488 case AL_ROLLOFF_FACTOR
:
489 case AL_REFERENCE_DISTANCE
:
492 case AL_CONE_OUTER_GAIN
:
493 case AL_CONE_OUTER_GAINHF
:
495 case AL_SAMPLE_OFFSET
:
497 case AL_AIR_ABSORPTION_FACTOR
:
498 case AL_ROOM_ROLLOFF_FACTOR
:
499 alSourcef(source
, eParam
, pflValues
[0]);
505 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
509 alSetError(AL_INVALID_ENUM
);
514 alSetError(AL_INVALID_NAME
);
517 alSetError(AL_INVALID_VALUE
);
519 ProcessContext(pContext
);
522 alSetError(AL_INVALID_OPERATION
);
528 ALAPI ALvoid ALAPIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
530 ALCcontext
*pContext
;
532 ALbufferlistitem
*pALBufferListItem
;
537 pContext
= alcGetCurrentContext();
540 SuspendContext(pContext
);
542 if (alIsSource(source
))
544 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
548 case AL_MAX_DISTANCE
:
549 case AL_ROLLOFF_FACTOR
:
550 case AL_REFERENCE_DISTANCE
:
551 alSourcef(source
, eParam
, (ALfloat
)lValue
);
554 case AL_SOURCE_RELATIVE
:
555 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
556 pSource
->bHeadRelative
= (ALboolean
)lValue
;
558 alSetError(AL_INVALID_VALUE
);
561 case AL_CONE_INNER_ANGLE
:
562 if ((lValue
>= 0) && (lValue
<= 360))
563 pSource
->flInnerAngle
= (float)lValue
;
565 alSetError(AL_INVALID_VALUE
);
568 case AL_CONE_OUTER_ANGLE
:
569 if ((lValue
>= 0) && (lValue
<= 360))
570 pSource
->flOuterAngle
= (float)lValue
;
572 alSetError(AL_INVALID_VALUE
);
576 if ((lValue
== AL_FALSE
) || (lValue
== AL_TRUE
))
577 pSource
->bLooping
= (ALboolean
)lValue
;
579 alSetError(AL_INVALID_VALUE
);
583 if ((pSource
->state
== AL_STOPPED
) || (pSource
->state
== AL_INITIAL
))
585 if (alIsBuffer(lValue
))
587 // Remove all elements in the queue
588 while (pSource
->queue
!= NULL
)
590 pALBufferListItem
= pSource
->queue
;
591 pSource
->queue
= pALBufferListItem
->next
;
592 // Decrement reference counter for buffer
593 if (pALBufferListItem
->buffer
)
594 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
)))->refcount
--;
595 // Record size of buffer
596 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
))->size
;
597 DataSize
+= BufferSize
;
598 // Increment the number of buffers removed from queue
600 // Release memory for buffer list item
601 free(pALBufferListItem
);
602 // Decrement the number of buffers in the queue
603 pSource
->BuffersInQueue
--;
606 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
609 // Source is now in STATIC mode
610 pSource
->lSourceType
= AL_STATIC
;
612 // Add the selected buffer to the queue
613 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
614 pALBufferListItem
->buffer
= lValue
;
615 pALBufferListItem
->bufferstate
= PENDING
;
616 pALBufferListItem
->flag
= 0;
617 pALBufferListItem
->next
= NULL
;
619 pSource
->queue
= pALBufferListItem
;
620 pSource
->BuffersInQueue
= 1;
622 DataSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(lValue
))->size
;
624 // Increment reference counter for buffer
625 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(lValue
)))->refcount
++;
629 // Source is now in UNDETERMINED mode
630 pSource
->lSourceType
= AL_UNDETERMINED
;
633 // Set Buffers Processed
634 pSource
->BuffersProcessed
= 0;
636 // Update AL_BUFFER parameter
637 pSource
->ulBufferID
= lValue
;
640 alSetError(AL_INVALID_VALUE
);
643 alSetError(AL_INVALID_OPERATION
);
646 case AL_SOURCE_STATE
:
648 alSetError(AL_INVALID_OPERATION
);
652 case AL_SAMPLE_OFFSET
:
656 pSource
->lOffsetType
= eParam
;
658 // Store Offset (convert Seconds into Milliseconds)
659 if (eParam
== AL_SEC_OFFSET
)
660 pSource
->lOffset
= lValue
* 1000;
662 pSource
->lOffset
= lValue
;
664 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
665 ApplyOffset(pSource
, AL_TRUE
);
668 alSetError(AL_INVALID_VALUE
);
671 case AL_DIRECT_FILTER
:
672 if(alIsFilter(lValue
))
674 ALfilter
*filter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue
);
677 pSource
->DirectFilter
.type
= AL_FILTER_NULL
;
678 pSource
->DirectFilter
.filter
= 0;
681 memcpy(&pSource
->DirectFilter
, filter
, sizeof(*filter
));
684 alSetError(AL_INVALID_VALUE
);
687 case AL_DIRECT_FILTER_GAINHF_AUTO
:
688 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
689 pSource
->DryGainHFAuto
= lValue
;
691 alSetError(AL_INVALID_VALUE
);
694 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
695 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
696 pSource
->WetGainAuto
= lValue
;
698 alSetError(AL_INVALID_VALUE
);
701 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
702 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
703 pSource
->WetGainHFAuto
= lValue
;
705 alSetError(AL_INVALID_VALUE
);
709 alSetError(AL_INVALID_ENUM
);
714 alSetError(AL_INVALID_NAME
);
716 ProcessContext(pContext
);
719 alSetError(AL_INVALID_OPERATION
);
725 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
727 ALCcontext
*pContext
;
729 pContext
= alcGetCurrentContext();
732 SuspendContext(pContext
);
734 if (alIsSource(source
))
736 ALsource
*pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
743 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
746 case AL_AUXILIARY_SEND_FILTER
:
747 if(lValue2
>= 0 && lValue2
< MAX_SENDS
&&
748 (alIsAuxiliaryEffectSlot(lValue1
) || lValue1
== 0) &&
751 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(lValue1
);
752 ALfilter
*ALFilter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue3
);
754 /* Release refcount on the previous slot, and add one for
756 if(pSource
->Send
[lValue2
].Slot
)
757 pSource
->Send
[lValue2
].Slot
->refcount
--;
758 pSource
->Send
[lValue2
].Slot
= ALEffectSlot
;
759 if(pSource
->Send
[lValue2
].Slot
)
760 pSource
->Send
[lValue2
].Slot
->refcount
++;
765 pSource
->Send
[lValue2
].WetFilter
.type
= 0;
766 pSource
->Send
[lValue2
].WetFilter
.filter
= 0;
769 memcpy(&pSource
->Send
[lValue2
].WetFilter
, ALFilter
, sizeof(*ALFilter
));
772 alSetError(AL_INVALID_VALUE
);
776 alSetError(AL_INVALID_ENUM
);
781 alSetError(AL_INVALID_NAME
);
783 ProcessContext(pContext
);
786 alSetError(AL_INVALID_OPERATION
);
792 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
794 ALCcontext
*pContext
;
796 pContext
= alcGetCurrentContext();
799 SuspendContext(pContext
);
803 if (alIsSource(source
))
807 case AL_SOURCE_RELATIVE
:
808 case AL_CONE_INNER_ANGLE
:
809 case AL_CONE_OUTER_ANGLE
:
812 case AL_SOURCE_STATE
:
814 case AL_SAMPLE_OFFSET
:
816 case AL_MAX_DISTANCE
:
817 case AL_ROLLOFF_FACTOR
:
818 case AL_REFERENCE_DISTANCE
:
819 case AL_DIRECT_FILTER
:
820 case AL_DIRECT_FILTER_GAINHF_AUTO
:
821 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
822 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
823 alSourcei(source
, eParam
, plValues
[0]);
829 case AL_AUXILIARY_SEND_FILTER
:
830 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
834 alSetError(AL_INVALID_ENUM
);
839 alSetError(AL_INVALID_NAME
);
842 alSetError(AL_INVALID_VALUE
);
844 ProcessContext(pContext
);
847 alSetError(AL_INVALID_OPERATION
);
853 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
855 ALCcontext
*pContext
;
859 pContext
= alcGetCurrentContext();
862 SuspendContext(pContext
);
866 if (alIsSource(source
))
868 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
873 *pflValue
= pSource
->flPitch
;
877 *pflValue
= pSource
->flGain
;
881 *pflValue
= pSource
->flMinGain
;
885 *pflValue
= pSource
->flMaxGain
;
888 case AL_MAX_DISTANCE
:
889 *pflValue
= pSource
->flMaxDistance
;
892 case AL_ROLLOFF_FACTOR
:
893 *pflValue
= pSource
->flRollOffFactor
;
896 case AL_CONE_OUTER_GAIN
:
897 *pflValue
= pSource
->flOuterGain
;
900 case AL_CONE_OUTER_GAINHF
:
901 *pflValue
= pSource
->OuterGainHF
;
905 case AL_SAMPLE_OFFSET
:
907 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
908 *pflValue
= flOffset
;
910 alSetError(AL_INVALID_OPERATION
);
913 case AL_CONE_INNER_ANGLE
:
914 *pflValue
= pSource
->flInnerAngle
;
917 case AL_CONE_OUTER_ANGLE
:
918 *pflValue
= pSource
->flOuterAngle
;
921 case AL_REFERENCE_DISTANCE
:
922 *pflValue
= pSource
->flRefDistance
;
925 case AL_AIR_ABSORPTION_FACTOR
:
926 *pflValue
= pSource
->AirAbsorptionFactor
;
929 case AL_ROOM_ROLLOFF_FACTOR
:
930 *pflValue
= pSource
->RoomRolloffFactor
;
933 case AL_DOPPLER_FACTOR
:
934 *pflValue
= pSource
->DopplerFactor
;
938 alSetError(AL_INVALID_ENUM
);
943 alSetError(AL_INVALID_NAME
);
946 alSetError(AL_INVALID_VALUE
);
948 ProcessContext(pContext
);
951 alSetError(AL_INVALID_OPERATION
);
957 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
959 ALCcontext
*pContext
;
962 pContext
= alcGetCurrentContext();
965 SuspendContext(pContext
);
967 if ((pflValue1
) && (pflValue2
) && (pflValue3
))
969 if (alIsSource(source
))
971 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
976 *pflValue1
= pSource
->vPosition
[0];
977 *pflValue2
= pSource
->vPosition
[1];
978 *pflValue3
= pSource
->vPosition
[2];
982 *pflValue1
= pSource
->vVelocity
[0];
983 *pflValue2
= pSource
->vVelocity
[1];
984 *pflValue3
= pSource
->vVelocity
[2];
988 *pflValue1
= pSource
->vOrientation
[0];
989 *pflValue2
= pSource
->vOrientation
[1];
990 *pflValue3
= pSource
->vOrientation
[2];
994 alSetError(AL_INVALID_ENUM
);
999 alSetError(AL_INVALID_NAME
);
1002 alSetError(AL_INVALID_VALUE
);
1004 ProcessContext(pContext
);
1007 alSetError(AL_INVALID_OPERATION
);
1013 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1015 ALCcontext
*pContext
;
1018 pContext
= alcGetCurrentContext();
1021 SuspendContext(pContext
);
1025 if (alIsSource(source
))
1027 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1035 case AL_MAX_DISTANCE
:
1036 case AL_ROLLOFF_FACTOR
:
1037 case AL_DOPPLER_FACTOR
:
1038 case AL_CONE_OUTER_GAIN
:
1040 case AL_SAMPLE_OFFSET
:
1041 case AL_BYTE_OFFSET
:
1042 case AL_CONE_INNER_ANGLE
:
1043 case AL_CONE_OUTER_ANGLE
:
1044 case AL_REFERENCE_DISTANCE
:
1045 case AL_CONE_OUTER_GAINHF
:
1046 case AL_AIR_ABSORPTION_FACTOR
:
1047 case AL_ROOM_ROLLOFF_FACTOR
:
1048 alGetSourcef(source
, eParam
, pflValues
);
1052 pflValues
[0] = pSource
->vPosition
[0];
1053 pflValues
[1] = pSource
->vPosition
[1];
1054 pflValues
[2] = pSource
->vPosition
[2];
1058 pflValues
[0] = pSource
->vVelocity
[0];
1059 pflValues
[1] = pSource
->vVelocity
[1];
1060 pflValues
[2] = pSource
->vVelocity
[2];
1064 pflValues
[0] = pSource
->vOrientation
[0];
1065 pflValues
[1] = pSource
->vOrientation
[1];
1066 pflValues
[2] = pSource
->vOrientation
[2];
1070 alSetError(AL_INVALID_ENUM
);
1075 alSetError(AL_INVALID_NAME
);
1078 alSetError(AL_INVALID_VALUE
);
1080 ProcessContext(pContext
);
1083 alSetError(AL_INVALID_OPERATION
);
1089 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1091 ALCcontext
*pContext
;
1095 pContext
= alcGetCurrentContext();
1098 SuspendContext(pContext
);
1102 if (alIsSource(source
))
1104 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1108 case AL_MAX_DISTANCE
:
1109 *plValue
= (ALint
)pSource
->flMaxDistance
;
1112 case AL_ROLLOFF_FACTOR
:
1113 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1116 case AL_REFERENCE_DISTANCE
:
1117 *plValue
= (ALint
)pSource
->flRefDistance
;
1120 case AL_SOURCE_RELATIVE
:
1121 *plValue
= pSource
->bHeadRelative
;
1124 case AL_CONE_INNER_ANGLE
:
1125 *plValue
= (ALint
)pSource
->flInnerAngle
;
1128 case AL_CONE_OUTER_ANGLE
:
1129 *plValue
= (ALint
)pSource
->flOuterAngle
;
1133 *plValue
= pSource
->bLooping
;
1137 *plValue
= pSource
->ulBufferID
;
1140 case AL_SOURCE_STATE
:
1141 *plValue
= pSource
->state
;
1144 case AL_BUFFERS_QUEUED
:
1145 *plValue
= pSource
->BuffersInQueue
;
1148 case AL_BUFFERS_PROCESSED
:
1149 if(pSource
->bLooping
)
1151 /* Buffers on a looping source are in a perpetual state
1152 * of PENDING, so don't report any as PROCESSED */
1156 *plValue
= pSource
->BuffersProcessed
;
1159 case AL_SOURCE_TYPE
:
1160 *plValue
= pSource
->lSourceType
;
1164 case AL_SAMPLE_OFFSET
:
1165 case AL_BYTE_OFFSET
:
1166 if (GetSourceOffset(pSource
, eParam
, &flOffset
))
1167 *plValue
= (ALint
)flOffset
;
1169 alSetError(AL_INVALID_OPERATION
);
1172 case AL_DIRECT_FILTER
:
1173 *plValue
= pSource
->DirectFilter
.filter
;
1176 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1177 *plValue
= pSource
->DryGainHFAuto
;
1180 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1181 *plValue
= pSource
->WetGainAuto
;
1184 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1185 *plValue
= pSource
->WetGainHFAuto
;
1188 case AL_DOPPLER_FACTOR
:
1189 *plValue
= (ALint
)pSource
->DopplerFactor
;
1193 alSetError(AL_INVALID_ENUM
);
1198 alSetError(AL_INVALID_NAME
);
1201 alSetError(AL_INVALID_VALUE
);
1203 ProcessContext(pContext
);
1206 alSetError(AL_INVALID_OPERATION
);
1212 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1214 ALCcontext
*pContext
;
1217 pContext
= alcGetCurrentContext();
1220 SuspendContext(pContext
);
1222 if ((plValue1
) && (plValue2
) && (plValue3
))
1224 if (alIsSource(source
))
1226 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1231 *plValue1
= (ALint
)pSource
->vPosition
[0];
1232 *plValue2
= (ALint
)pSource
->vPosition
[1];
1233 *plValue3
= (ALint
)pSource
->vPosition
[2];
1237 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1238 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1239 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1243 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1244 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1245 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1249 alSetError(AL_INVALID_ENUM
);
1254 alSetError(AL_INVALID_NAME
);
1257 alSetError(AL_INVALID_VALUE
);
1259 ProcessContext(pContext
);
1262 alSetError(AL_INVALID_OPERATION
);
1268 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1270 ALCcontext
*pContext
;
1273 pContext
= alcGetCurrentContext();
1276 SuspendContext(pContext
);
1280 if (alIsSource(source
))
1282 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(source
));
1286 case AL_SOURCE_RELATIVE
:
1287 case AL_CONE_INNER_ANGLE
:
1288 case AL_CONE_OUTER_ANGLE
:
1291 case AL_SOURCE_STATE
:
1292 case AL_BUFFERS_QUEUED
:
1293 case AL_BUFFERS_PROCESSED
:
1295 case AL_SAMPLE_OFFSET
:
1296 case AL_BYTE_OFFSET
:
1297 case AL_MAX_DISTANCE
:
1298 case AL_ROLLOFF_FACTOR
:
1299 case AL_DOPPLER_FACTOR
:
1300 case AL_REFERENCE_DISTANCE
:
1301 case AL_SOURCE_TYPE
:
1302 case AL_DIRECT_FILTER
:
1303 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1304 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1305 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1306 alGetSourcei(source
, eParam
, plValues
);
1310 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1311 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1312 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1316 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1317 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1318 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1322 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1323 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1324 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1328 alSetError(AL_INVALID_ENUM
);
1333 alSetError(AL_INVALID_NAME
);
1336 alSetError(AL_INVALID_VALUE
);
1338 ProcessContext(pContext
);
1341 alSetError(AL_INVALID_OPERATION
);
1347 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1349 alSourcePlayv(1, &source
);
1353 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1355 ALCcontext
*pContext
;
1357 ALbufferlistitem
*ALBufferList
;
1358 ALboolean bSourcesValid
= AL_TRUE
;
1362 pContext
= alcGetCurrentContext();
1365 SuspendContext(pContext
);
1369 // Check that all the Sources are valid
1370 for (i
= 0; i
< n
; i
++)
1372 if (!alIsSource(pSourceList
[i
]))
1374 alSetError(AL_INVALID_NAME
);
1375 bSourcesValid
= AL_FALSE
;
1382 for (i
= 0; i
< n
; i
++)
1384 // Assume Source won't need to play
1387 pSource
= ((ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]));
1389 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1390 ALBufferList
= pSource
->queue
;
1391 while (ALBufferList
)
1393 if ((ALBufferList
->buffer
!= 0) && (((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
))
1398 ALBufferList
= ALBufferList
->next
;
1403 if (pSource
->state
!= AL_PAUSED
)
1405 pSource
->state
= AL_PLAYING
;
1406 pSource
->inuse
= AL_TRUE
;
1407 pSource
->play
= AL_TRUE
;
1408 pSource
->position
= 0;
1409 pSource
->position_fraction
= 0;
1410 pSource
->BuffersProcessed
= 0;
1411 pSource
->BuffersPlayed
= 0;
1412 pSource
->BufferPosition
= 0;
1413 pSource
->lBytesPlayed
= 0;
1415 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1417 // Make sure all the Buffers in the queue are marked as PENDING
1418 ALBufferList
= pSource
->queue
;
1419 while (ALBufferList
)
1421 ALBufferList
->bufferstate
= PENDING
;
1422 ALBufferList
= ALBufferList
->next
;
1427 pSource
->state
= AL_PLAYING
;
1428 pSource
->inuse
= AL_TRUE
;
1429 pSource
->play
= AL_TRUE
;
1432 // Check if an Offset has been set
1433 if (pSource
->lOffset
)
1434 ApplyOffset(pSource
, AL_FALSE
);
1438 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1439 ALBufferList
= pSource
->queue
;
1440 while (ALBufferList
)
1442 ALBufferList
->bufferstate
= PROCESSED
;
1443 ALBufferList
= ALBufferList
->next
;
1446 pSource
->BuffersPlayed
= pSource
->BuffersProcessed
= pSource
->BuffersInQueue
;
1453 // sources is a NULL pointer
1454 alSetError(AL_INVALID_VALUE
);
1457 ProcessContext(pContext
);
1462 alSetError(AL_INVALID_OPERATION
);
1468 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1470 alSourcePausev(1, &source
);
1474 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1476 ALCcontext
*Context
;
1479 ALboolean bSourcesValid
= AL_TRUE
;
1481 Context
=alcGetCurrentContext();
1484 SuspendContext(Context
);
1488 // Check all the Sources are valid
1491 if (!alIsSource(sources
[i
]))
1493 alSetError(AL_INVALID_NAME
);
1494 bSourcesValid
= AL_FALSE
;
1503 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1504 if (Source
->state
==AL_PLAYING
)
1506 Source
->state
=AL_PAUSED
;
1507 Source
->inuse
=AL_FALSE
;
1514 // sources is a NULL pointer
1515 alSetError(AL_INVALID_VALUE
);
1518 ProcessContext(Context
);
1523 alSetError(AL_INVALID_OPERATION
);
1529 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1531 alSourceStopv(1, &source
);
1535 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1537 ALCcontext
*Context
;
1540 ALbufferlistitem
*ALBufferListItem
;
1541 ALboolean bSourcesValid
= AL_TRUE
;
1543 Context
=alcGetCurrentContext();
1546 SuspendContext(Context
);
1550 // Check all the Sources are valid
1553 if (!alIsSource(sources
[i
]))
1555 alSetError(AL_INVALID_NAME
);
1556 bSourcesValid
= AL_FALSE
;
1565 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1566 if (Source
->state
!=AL_INITIAL
)
1568 Source
->state
=AL_STOPPED
;
1569 Source
->inuse
=AL_FALSE
;
1570 Source
->BuffersPlayed
= Source
->BuffersProcessed
= Source
->BuffersInQueue
;
1571 ALBufferListItem
= Source
->queue
;
1572 while (ALBufferListItem
!= NULL
)
1574 ALBufferListItem
->bufferstate
= PROCESSED
;
1575 ALBufferListItem
= ALBufferListItem
->next
;
1578 Source
->lOffset
= 0;
1584 // sources is a NULL pointer
1585 alSetError(AL_INVALID_VALUE
);
1588 ProcessContext(Context
);
1593 alSetError(AL_INVALID_OPERATION
);
1599 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1601 alSourceRewindv(1, &source
);
1605 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1607 ALCcontext
*Context
;
1610 ALbufferlistitem
*ALBufferListItem
;
1611 ALboolean bSourcesValid
= AL_TRUE
;
1613 Context
=alcGetCurrentContext();
1616 SuspendContext(Context
);
1620 // Check all the Sources are valid
1623 if (!alIsSource(sources
[i
]))
1625 alSetError(AL_INVALID_NAME
);
1626 bSourcesValid
= AL_FALSE
;
1635 Source
=((ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]));
1636 if (Source
->state
!=AL_INITIAL
)
1638 Source
->state
=AL_INITIAL
;
1639 Source
->inuse
=AL_FALSE
;
1641 Source
->position_fraction
=0;
1642 Source
->BuffersProcessed
= 0;
1643 ALBufferListItem
= Source
->queue
;
1644 while (ALBufferListItem
!= NULL
)
1646 ALBufferListItem
->bufferstate
= PENDING
;
1647 ALBufferListItem
= ALBufferListItem
->next
;
1650 Source
->ulBufferID
= Source
->queue
->buffer
;
1652 Source
->lOffset
= 0;
1658 // sources is a NULL pointer
1659 alSetError(AL_INVALID_VALUE
);
1662 ProcessContext(Context
);
1667 alSetError(AL_INVALID_OPERATION
);
1674 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1676 ALCcontext
*Context
;
1679 ALbufferlistitem
*ALBufferList
;
1680 ALbufferlistitem
*ALBufferListStart
;
1685 ALboolean bBuffersValid
= AL_TRUE
;
1690 Context
=alcGetCurrentContext();
1693 SuspendContext(Context
);
1698 // Check that all buffers are valid or zero and that the source is valid
1700 // Check that this is a valid source
1701 if (alIsSource(source
))
1703 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1705 // Check that this is not a STATIC Source
1706 if (ALSource
->lSourceType
!= AL_STATIC
)
1711 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1712 ALBufferList
= ALSource
->queue
;
1713 while (ALBufferList
)
1715 if (ALBufferList
->buffer
)
1717 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1718 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1721 ALBufferList
= ALBufferList
->next
;
1724 for (i
= 0; i
< n
; i
++)
1726 if (alIsBuffer(buffers
[i
]))
1730 if ((iFrequency
== -1) && (iFormat
== -1))
1732 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1733 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1737 if ((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1738 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1740 alSetError(AL_INVALID_OPERATION
);
1741 bBuffersValid
= AL_FALSE
;
1749 alSetError(AL_INVALID_NAME
);
1750 bBuffersValid
= AL_FALSE
;
1757 // Change Source Type
1758 ALSource
->lSourceType
= AL_STREAMING
;
1760 // All buffers are valid - so add them to the list
1761 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1762 ALBufferListStart
->buffer
= buffers
[0];
1763 ALBufferListStart
->bufferstate
= PENDING
;
1764 ALBufferListStart
->flag
= 0;
1765 ALBufferListStart
->next
= NULL
;
1768 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]))->size
;
1772 DataSize
+= BufferSize
;
1774 // Increment reference counter for buffer
1776 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1778 ALBufferList
= ALBufferListStart
;
1780 for (i
= 1; i
< n
; i
++)
1782 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1783 ALBufferList
->next
->buffer
= buffers
[i
];
1784 ALBufferList
->next
->bufferstate
= PENDING
;
1785 ALBufferList
->next
->flag
= 0;
1786 ALBufferList
->next
->next
= NULL
;
1789 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]))->size
;
1793 DataSize
+= BufferSize
;
1795 // Increment reference counter for buffer
1797 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1799 ALBufferList
= ALBufferList
->next
;
1802 if (ALSource
->queue
== NULL
)
1804 ALSource
->queue
= ALBufferListStart
;
1805 // Update Current Buffer
1806 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1810 // Find end of queue
1811 ALBufferList
= ALSource
->queue
;
1812 while (ALBufferList
->next
!= NULL
)
1814 ALBufferList
= ALBufferList
->next
;
1817 ALBufferList
->next
= ALBufferListStart
;
1820 // Update number of buffers in queue
1821 ALSource
->BuffersInQueue
+= n
;
1826 // Invalid Source Type (can't queue on a Static Source)
1827 alSetError(AL_INVALID_OPERATION
);
1832 // Invalid Source Name
1833 alSetError(AL_INVALID_NAME
);
1836 ProcessContext(Context
);
1841 alSetError(AL_INVALID_OPERATION
);
1848 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1849 // an array of buffer IDs that are to be filled with the names of the buffers removed
1850 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1852 ALCcontext
*Context
;
1855 ALbufferlistitem
*ALBufferList
;
1859 ALboolean bBuffersProcessed
;
1866 bBuffersProcessed
= AL_TRUE
;
1868 Context
=alcGetCurrentContext();
1871 SuspendContext(Context
);
1873 if (alIsSource(source
))
1875 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1877 // Check that all 'n' buffers have been processed
1878 ALBufferList
= ALSource
->queue
;
1879 for (i
= 0; i
< n
; i
++)
1881 if ((ALBufferList
!= NULL
) && (ALBufferList
->bufferstate
== PROCESSED
))
1883 ALBufferList
= ALBufferList
->next
;
1887 bBuffersProcessed
= AL_FALSE
;
1892 // If all 'n' buffers have been processed, remove them from the queue
1893 if (bBuffersProcessed
)
1895 for (i
= 0; i
< n
; i
++)
1897 ALBufferList
= ALSource
->queue
;
1899 ALSource
->queue
= ALBufferList
->next
;
1900 // Record name of buffer
1901 buffers
[i
] = ALBufferList
->buffer
;
1902 // Decrement buffer reference counter
1903 if (ALBufferList
->buffer
)
1904 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1905 // Record size of buffer
1906 if (ALBufferList
->buffer
)
1907 BufferSize
= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
;
1911 DataSize
+= BufferSize
;
1912 // Release memory for buffer list item
1914 ALSource
->BuffersInQueue
--;
1915 ALSource
->BuffersProcessed
--;
1918 if (ALSource
->state
!= AL_PLAYING
)
1920 if (ALSource
->queue
)
1921 BufferID
= ALSource
->queue
->buffer
;
1925 ALSource
->ulBufferID
= BufferID
;
1928 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1930 ALSource
->BuffersPlayed
= 0;
1931 ALSource
->BufferPosition
= 0;
1934 ALSource
->BuffersPlayed
-= n
;
1938 // Some buffers can't be unqueue because they have not been processed
1939 alSetError(AL_INVALID_VALUE
);
1944 // Invalid Source Name
1945 alSetError(AL_INVALID_NAME
);
1948 ProcessContext(Context
);
1953 alSetError(AL_INVALID_OPERATION
);
1960 static ALvoid
InitSourceParams(ALsource
*pSource
)
1962 pSource
->flInnerAngle
= 360.0f
;
1963 pSource
->flOuterAngle
= 360.0f
;
1964 pSource
->flPitch
= 1.0f
;
1965 pSource
->vPosition
[0] = 0.0f
;
1966 pSource
->vPosition
[1] = 0.0f
;
1967 pSource
->vPosition
[2] = 0.0f
;
1968 pSource
->vOrientation
[0] = 0.0f
;
1969 pSource
->vOrientation
[1] = 0.0f
;
1970 pSource
->vOrientation
[2] = 0.0f
;
1971 pSource
->vVelocity
[0] = 0.0f
;
1972 pSource
->vVelocity
[1] = 0.0f
;
1973 pSource
->vVelocity
[2] = 0.0f
;
1974 pSource
->flRefDistance
= 1.0f
;
1975 pSource
->flMaxDistance
= FLT_MAX
;
1976 pSource
->flRollOffFactor
= 1.0f
;
1977 pSource
->bLooping
= AL_FALSE
;
1978 pSource
->flGain
= 1.0f
;
1979 pSource
->flMinGain
= 0.0f
;
1980 pSource
->flMaxGain
= 1.0f
;
1981 pSource
->flOuterGain
= 0.0f
;
1982 pSource
->OuterGainHF
= 1.0f
;
1984 pSource
->DryGainHFAuto
= AL_TRUE
;
1985 pSource
->WetGainAuto
= AL_TRUE
;
1986 pSource
->WetGainHFAuto
= AL_TRUE
;
1987 pSource
->AirAbsorptionFactor
= 0.0f
;
1988 pSource
->RoomRolloffFactor
= 0.0f
;
1989 pSource
->DopplerFactor
= 1.0f
;
1991 pSource
->state
= AL_INITIAL
;
1992 pSource
->lSourceType
= AL_UNDETERMINED
;
1994 pSource
->ulBufferID
= 0;
2001 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
2002 The offset is relative to the start of the queue (not the start of the current buffer)
2004 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
)
2006 ALbufferlistitem
*pBufferList
;
2008 ALfloat flBufferFreq
;
2009 ALint lBytesPlayed
, lChannels
;
2010 ALenum eOriginalFormat
;
2011 ALboolean bReturn
= AL_TRUE
;
2012 ALint lTotalBufferDataSize
;
2014 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
2016 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
2017 // Get Current Buffer Size and frequency (in milliseconds)
2018 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
2019 eOriginalFormat
= pBuffer
->eOriginalFormat
;
2020 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2022 // Get Current BytesPlayed
2023 lBytesPlayed
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
2024 // Add byte length of any processed buffers in the queue
2025 pBufferList
= pSource
->queue
;
2026 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
2028 lBytesPlayed
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2029 pBufferList
= pBufferList
->next
;
2032 lTotalBufferDataSize
= 0;
2033 pBufferList
= pSource
->queue
;
2036 if (pBufferList
->buffer
)
2037 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2038 pBufferList
= pBufferList
->next
;
2041 if (pSource
->bLooping
)
2043 if (lBytesPlayed
< 0)
2046 lBytesPlayed
= lBytesPlayed
% lTotalBufferDataSize
;
2050 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
2051 if(lBytesPlayed
< 0)
2053 if(lBytesPlayed
> lTotalBufferDataSize
)
2054 lBytesPlayed
= lTotalBufferDataSize
;
2060 *pflOffset
= ((ALfloat
)lBytesPlayed
/ (lChannels
* 2.0f
* flBufferFreq
));
2062 case AL_SAMPLE_OFFSET
:
2063 *pflOffset
= (ALfloat
)(lBytesPlayed
/ (lChannels
* 2));
2065 case AL_BYTE_OFFSET
:
2066 // Take into account the original format of the Buffer
2067 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2068 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2070 // Compression rate of the ADPCM supported is 3.6111 to 1
2071 lBytesPlayed
= (ALint
)((ALfloat
)lBytesPlayed
/ 3.6111f
);
2072 // Round down to nearest ADPCM block
2073 *pflOffset
= (ALfloat
)((lBytesPlayed
/ (36 * lChannels
)) * 36 * lChannels
);
2075 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
2077 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 2);
2079 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
2081 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2083 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
2085 *pflOffset
= (ALfloat
)(lBytesPlayed
>> 1);
2087 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
2089 *pflOffset
= (ALfloat
)(lBytesPlayed
<< 1);
2093 *pflOffset
= (ALfloat
)lBytesPlayed
;
2110 Apply a playback offset to the Source. This function will update the queue (to correctly
2111 mark buffers as 'pending' or 'processed' depending upon the new offset.
2113 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
2115 ALbufferlistitem
*pBufferList
;
2117 ALint lBufferSize
, lTotalBufferSize
;
2120 // Get true byte offset
2121 lByteOffset
= GetByteOffset(pSource
);
2123 // If this is a valid offset apply it
2124 if (lByteOffset
!= -1)
2126 // Sort out the queue (pending and processed states)
2127 pBufferList
= pSource
->queue
;
2128 lTotalBufferSize
= 0;
2129 pSource
->BuffersPlayed
= 0;
2130 pSource
->BuffersProcessed
= 0;
2133 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2134 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2136 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2138 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2139 // update the state to PROCESSED
2140 pSource
->BuffersPlayed
++;
2142 if (!pSource
->bLooping
)
2144 pBufferList
->bufferstate
= PROCESSED
;
2145 pSource
->BuffersProcessed
++;
2148 else if (lTotalBufferSize
<= lByteOffset
)
2150 // Offset is within this buffer
2151 pBufferList
->bufferstate
= PENDING
;
2153 // Set Current Buffer ID
2154 pSource
->ulBufferID
= pBufferList
->buffer
;
2156 // Set current position in this buffer
2157 pSource
->BufferPosition
= lByteOffset
- lTotalBufferSize
;
2159 // Set Total Bytes Played to Offset
2160 pSource
->lBytesPlayed
= lByteOffset
;
2162 // SW Mixer Positions are in Samples
2163 pSource
->position
= pSource
->BufferPosition
/
2164 aluBytesFromFormat(pBuffer
->format
) /
2165 aluChannelsFromFormat(pBuffer
->format
);
2169 // Offset is before this buffer, so mark as pending
2170 pBufferList
->bufferstate
= PENDING
;
2173 // Increment the TotalBufferSize
2174 lTotalBufferSize
+= lBufferSize
;
2176 // Move on to next buffer in the Queue
2177 pBufferList
= pBufferList
->next
;
2183 alSetError(AL_INVALID_VALUE
);
2187 pSource
->lOffset
= 0;
2194 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2195 offset supplied by the application). This takes into account the fact that the buffer format
2196 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2198 static ALint
GetByteOffset(ALsource
*pSource
)
2200 ALbuffer
*pBuffer
= NULL
;
2201 ALbufferlistitem
*pBufferList
;
2202 ALfloat flBufferFreq
;
2204 ALint lByteOffset
= -1;
2205 ALint lTotalBufferDataSize
;
2207 // Find the first non-NULL Buffer in the Queue
2208 pBufferList
= pSource
->queue
;
2211 if (pBufferList
->buffer
)
2213 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2216 pBufferList
= pBufferList
->next
;
2221 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2222 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2224 // Determine the ByteOffset (and ensure it is block aligned)
2225 switch (pSource
->lOffsetType
)
2227 case AL_BYTE_OFFSET
:
2228 // Take into consideration the original format
2229 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2230 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2232 // Round down to nearest ADPCM block
2233 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2234 // Multiply by compression rate
2235 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2236 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2238 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2240 lByteOffset
= pSource
->lOffset
* 4;
2241 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2243 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2245 lByteOffset
= pSource
->lOffset
* 2;
2246 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2248 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2250 lByteOffset
= pSource
->lOffset
* 2;
2251 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2253 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2255 lByteOffset
= pSource
->lOffset
/ 2;
2256 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2260 lByteOffset
= pSource
->lOffset
;
2261 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2265 case AL_SAMPLE_OFFSET
:
2266 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2270 // Note - lOffset is internally stored as Milliseconds
2271 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2272 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2276 lTotalBufferDataSize
= 0;
2277 pBufferList
= pSource
->queue
;
2280 if (pBufferList
->buffer
)
2281 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2282 pBufferList
= pBufferList
->next
;
2285 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2286 if (lByteOffset
>= lTotalBufferDataSize
)
2294 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2297 if(Context
->SourceCount
> 0)
2298 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", Context
->SourceCount
);
2301 while(Context
->Source
)
2303 ALsource
*temp
= Context
->Source
;
2304 Context
->Source
= Context
->Source
->next
;
2306 // Release source structure
2307 ALTHUNK_REMOVEENTRY(temp
->source
);
2308 memset(temp
, 0, sizeof(ALsource
));
2311 Context
->SourceCount
= 0;