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(ALCcontext
*Context
, ALsource
*pSource
);
36 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
, ALuint updateSize
);
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
= GetContextSuspended();
51 Device
= Context
->Device
;
53 // Check that enough memory has been allocted in the 'sources' array for n Sources
54 if(!IsBadWritePtr((void*)sources
, n
* sizeof(ALuint
)))
56 // Check that the requested number of sources can be generated
57 if((Context
->SourceCount
+ n
) <= Device
->MaxNoOfSources
)
59 ALsource
**list
= &Context
->Source
;
61 list
= &(*list
)->next
;
63 // Add additional sources to the list (Source->next points to the location for the next Source structure)
66 *list
= calloc(1, sizeof(ALsource
));
69 alDeleteSources(i
, sources
);
70 alSetError(AL_OUT_OF_MEMORY
);
74 sources
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
75 (*list
)->source
= sources
[i
];
77 InitSourceParams(Context
, *list
);
78 Context
->SourceCount
++;
81 list
= &(*list
)->next
;
86 // Not enough resources to create the Sources
87 alSetError(AL_INVALID_VALUE
);
93 alSetError(AL_INVALID_VALUE
);
97 ProcessContext(Context
);
101 ALAPI ALvoid ALAPIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
108 ALbufferlistitem
*ALBufferList
;
109 ALboolean bSourcesValid
= AL_TRUE
;
111 Context
= GetContextSuspended();
116 Device
= Context
->Device
;
118 // Check that all Sources are valid (and can therefore be deleted)
119 for (i
= 0; i
< n
; i
++)
121 if (!alIsSource(sources
[i
]))
123 alSetError(AL_INVALID_NAME
);
124 bSourcesValid
= AL_FALSE
;
131 // All Sources are valid, and can be deleted
132 for(i
= 0; i
< n
; i
++)
134 // Recheck that the Source is valid, because there could be duplicated Source names
135 if(alIsSource(sources
[i
]))
137 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]);
138 alSourceStop((ALuint
)ALSource
->source
);
140 // For each buffer in the source's queue, decrement its reference counter and remove it
141 while (ALSource
->queue
!= NULL
)
143 ALBufferList
= ALSource
->queue
;
144 // Decrement buffer's reference counter
145 if(ALBufferList
->buffer
!= 0)
146 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
147 // Update queue to point to next element in list
148 ALSource
->queue
= ALBufferList
->next
;
149 // Release memory allocated for buffer list item
153 for(j
= 0;j
< MAX_SENDS
;++j
)
155 if(ALSource
->Send
[j
].Slot
)
156 ALSource
->Send
[j
].Slot
->refcount
--;
157 ALSource
->Send
[j
].Slot
= NULL
;
160 // Decrement Source count
161 Context
->SourceCount
--;
163 // Remove Source from list of Sources
164 list
= &Context
->Source
;
165 while(*list
&& *list
!= ALSource
)
166 list
= &(*list
)->next
;
169 *list
= (*list
)->next
;
170 ALTHUNK_REMOVEENTRY(ALSource
->source
);
172 memset(ALSource
,0,sizeof(ALsource
));
179 alSetError(AL_INVALID_VALUE
);
181 ProcessContext(Context
);
185 ALAPI ALboolean ALAPIENTRY
alIsSource(ALuint source
)
187 ALboolean result
=AL_FALSE
;
191 Context
= GetContextSuspended();
192 if(!Context
) return AL_FALSE
;
194 // To determine if this is a valid Source name, look through the list of generated Sources
195 Source
= Context
->Source
;
198 if(Source
->source
== source
)
204 Source
= Source
->next
;
207 ProcessContext(Context
);
213 ALAPI ALvoid ALAPIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
215 ALCcontext
*pContext
;
218 pContext
= GetContextSuspended();
219 if(!pContext
) return;
221 if(alIsSource(source
))
223 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
230 pSource
->flPitch
= flValue
;
231 if(pSource
->flPitch
< 0.001f
)
232 pSource
->flPitch
= 0.001f
;
235 alSetError(AL_INVALID_VALUE
);
238 case AL_CONE_INNER_ANGLE
:
239 if(flValue
>= 0.0f
&& flValue
<= 360.0f
)
240 pSource
->flInnerAngle
= flValue
;
242 alSetError(AL_INVALID_VALUE
);
245 case AL_CONE_OUTER_ANGLE
:
246 if(flValue
>= 0.0f
&& flValue
<= 360.0f
)
247 pSource
->flOuterAngle
= flValue
;
249 alSetError(AL_INVALID_VALUE
);
254 pSource
->flGain
= flValue
;
256 alSetError(AL_INVALID_VALUE
);
259 case AL_MAX_DISTANCE
:
261 pSource
->flMaxDistance
= flValue
;
263 alSetError(AL_INVALID_VALUE
);
266 case AL_ROLLOFF_FACTOR
:
268 pSource
->flRollOffFactor
= flValue
;
270 alSetError(AL_INVALID_VALUE
);
273 case AL_REFERENCE_DISTANCE
:
275 pSource
->flRefDistance
= flValue
;
277 alSetError(AL_INVALID_VALUE
);
281 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
282 pSource
->flMinGain
= flValue
;
284 alSetError(AL_INVALID_VALUE
);
288 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
289 pSource
->flMaxGain
= flValue
;
291 alSetError(AL_INVALID_VALUE
);
294 case AL_CONE_OUTER_GAIN
:
295 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
296 pSource
->flOuterGain
= flValue
;
298 alSetError(AL_INVALID_VALUE
);
301 case AL_CONE_OUTER_GAINHF
:
302 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
303 pSource
->OuterGainHF
= flValue
;
305 alSetError(AL_INVALID_VALUE
);
308 case AL_AIR_ABSORPTION_FACTOR
:
309 if(flValue
>= 0.0f
&& flValue
<= 10.0f
)
310 pSource
->AirAbsorptionFactor
= flValue
;
312 alSetError(AL_INVALID_VALUE
);
315 case AL_ROOM_ROLLOFF_FACTOR
:
316 if(flValue
>= 0.0f
&& flValue
<= 10.0f
)
317 pSource
->RoomRolloffFactor
= flValue
;
319 alSetError(AL_INVALID_VALUE
);
322 case AL_DOPPLER_FACTOR
:
323 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
324 pSource
->DopplerFactor
= flValue
;
326 alSetError(AL_INVALID_VALUE
);
330 case AL_SAMPLE_OFFSET
:
334 pSource
->lOffsetType
= eParam
;
336 // Store Offset (convert Seconds into Milliseconds)
337 if(eParam
== AL_SEC_OFFSET
)
338 pSource
->lOffset
= (ALint
)(flValue
* 1000.0f
);
340 pSource
->lOffset
= (ALint
)flValue
;
342 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
343 ApplyOffset(pSource
, AL_TRUE
);
346 alSetError(AL_INVALID_VALUE
);
350 alSetError(AL_INVALID_ENUM
);
356 // Invalid Source Name
357 alSetError(AL_INVALID_NAME
);
360 ProcessContext(pContext
);
364 ALAPI ALvoid ALAPIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
366 ALCcontext
*pContext
;
369 pContext
= GetContextSuspended();
370 if(!pContext
) return;
372 if(alIsSource(source
))
374 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
378 pSource
->vPosition
[0] = flValue1
;
379 pSource
->vPosition
[1] = flValue2
;
380 pSource
->vPosition
[2] = flValue3
;
384 pSource
->vVelocity
[0] = flValue1
;
385 pSource
->vVelocity
[1] = flValue2
;
386 pSource
->vVelocity
[2] = flValue3
;
390 pSource
->vOrientation
[0] = flValue1
;
391 pSource
->vOrientation
[1] = flValue2
;
392 pSource
->vOrientation
[2] = flValue3
;
396 alSetError(AL_INVALID_ENUM
);
401 alSetError(AL_INVALID_NAME
);
403 ProcessContext(pContext
);
407 ALAPI ALvoid ALAPIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
409 ALCcontext
*pContext
;
411 pContext
= GetContextSuspended();
412 if(!pContext
) return;
416 if(alIsSource(source
))
421 case AL_CONE_INNER_ANGLE
:
422 case AL_CONE_OUTER_ANGLE
:
424 case AL_MAX_DISTANCE
:
425 case AL_ROLLOFF_FACTOR
:
426 case AL_REFERENCE_DISTANCE
:
429 case AL_CONE_OUTER_GAIN
:
430 case AL_CONE_OUTER_GAINHF
:
432 case AL_SAMPLE_OFFSET
:
434 case AL_AIR_ABSORPTION_FACTOR
:
435 case AL_ROOM_ROLLOFF_FACTOR
:
436 alSourcef(source
, eParam
, pflValues
[0]);
442 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
446 alSetError(AL_INVALID_ENUM
);
451 alSetError(AL_INVALID_NAME
);
454 alSetError(AL_INVALID_VALUE
);
456 ProcessContext(pContext
);
460 ALAPI ALvoid ALAPIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
462 ALCcontext
*pContext
;
464 ALbufferlistitem
*pALBufferListItem
;
467 pContext
= GetContextSuspended();
468 if(!pContext
) return;
470 if(alIsSource(source
))
472 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
476 case AL_MAX_DISTANCE
:
477 case AL_ROLLOFF_FACTOR
:
478 case AL_REFERENCE_DISTANCE
:
479 alSourcef(source
, eParam
, (ALfloat
)lValue
);
482 case AL_SOURCE_RELATIVE
:
483 if(lValue
== AL_FALSE
|| lValue
== AL_TRUE
)
484 pSource
->bHeadRelative
= (ALboolean
)lValue
;
486 alSetError(AL_INVALID_VALUE
);
489 case AL_CONE_INNER_ANGLE
:
490 if(lValue
>= 0 && lValue
<= 360)
491 pSource
->flInnerAngle
= (float)lValue
;
493 alSetError(AL_INVALID_VALUE
);
496 case AL_CONE_OUTER_ANGLE
:
497 if(lValue
>= 0 && lValue
<= 360)
498 pSource
->flOuterAngle
= (float)lValue
;
500 alSetError(AL_INVALID_VALUE
);
504 if(lValue
== AL_FALSE
|| lValue
== AL_TRUE
)
506 pSource
->bLooping
= (ALboolean
)lValue
;
508 pALBufferListItem
= pSource
->queue
;
509 for(i
= 0;pALBufferListItem
!= NULL
;i
++)
511 if(lValue
== AL_FALSE
&& i
<= pSource
->BuffersPlayed
)
512 pALBufferListItem
->bufferstate
= PROCESSED
;
514 pALBufferListItem
->bufferstate
= PENDING
;
515 pALBufferListItem
= pALBufferListItem
->next
;
519 alSetError(AL_INVALID_VALUE
);
523 if(pSource
->state
== AL_STOPPED
|| pSource
->state
== AL_INITIAL
)
525 if(alIsBuffer(lValue
))
527 // Remove all elements in the queue
528 while(pSource
->queue
!= NULL
)
530 pALBufferListItem
= pSource
->queue
;
531 pSource
->queue
= pALBufferListItem
->next
;
532 // Decrement reference counter for buffer
533 if (pALBufferListItem
->buffer
)
534 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(pALBufferListItem
->buffer
)))->refcount
--;
535 // Release memory for buffer list item
536 free(pALBufferListItem
);
537 // Decrement the number of buffers in the queue
538 pSource
->BuffersInQueue
--;
541 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
544 // Source is now in STATIC mode
545 pSource
->lSourceType
= AL_STATIC
;
547 // Add the selected buffer to the queue
548 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
549 pALBufferListItem
->buffer
= lValue
;
550 pALBufferListItem
->bufferstate
= PENDING
;
551 pALBufferListItem
->flag
= 0;
552 pALBufferListItem
->next
= NULL
;
554 pSource
->queue
= pALBufferListItem
;
555 pSource
->BuffersInQueue
= 1;
557 // Increment reference counter for buffer
558 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(lValue
)))->refcount
++;
562 // Source is now in UNDETERMINED mode
563 pSource
->lSourceType
= AL_UNDETERMINED
;
564 pSource
->BuffersPlayed
= 0;
567 // Update AL_BUFFER parameter
568 pSource
->ulBufferID
= lValue
;
571 alSetError(AL_INVALID_VALUE
);
574 alSetError(AL_INVALID_OPERATION
);
577 case AL_SOURCE_STATE
:
579 alSetError(AL_INVALID_OPERATION
);
583 case AL_SAMPLE_OFFSET
:
587 pSource
->lOffsetType
= eParam
;
589 // Store Offset (convert Seconds into Milliseconds)
590 if(eParam
== AL_SEC_OFFSET
)
591 pSource
->lOffset
= lValue
* 1000;
593 pSource
->lOffset
= lValue
;
595 if(pSource
->state
== AL_PLAYING
|| pSource
->state
== AL_PAUSED
)
596 ApplyOffset(pSource
, AL_TRUE
);
599 alSetError(AL_INVALID_VALUE
);
602 case AL_DIRECT_FILTER
:
603 if(alIsFilter(lValue
))
605 ALfilter
*filter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue
);
608 pSource
->DirectFilter
.type
= AL_FILTER_NULL
;
609 pSource
->DirectFilter
.filter
= 0;
612 memcpy(&pSource
->DirectFilter
, filter
, sizeof(*filter
));
615 alSetError(AL_INVALID_VALUE
);
618 case AL_DIRECT_FILTER_GAINHF_AUTO
:
619 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
620 pSource
->DryGainHFAuto
= lValue
;
622 alSetError(AL_INVALID_VALUE
);
625 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
626 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
627 pSource
->WetGainAuto
= lValue
;
629 alSetError(AL_INVALID_VALUE
);
632 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
633 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
634 pSource
->WetGainHFAuto
= lValue
;
636 alSetError(AL_INVALID_VALUE
);
639 case AL_DISTANCE_MODEL
:
640 if(lValue
== AL_NONE
||
641 lValue
== AL_INVERSE_DISTANCE
||
642 lValue
== AL_INVERSE_DISTANCE_CLAMPED
||
643 lValue
== AL_LINEAR_DISTANCE
||
644 lValue
== AL_LINEAR_DISTANCE_CLAMPED
||
645 lValue
== AL_EXPONENT_DISTANCE
||
646 lValue
== AL_EXPONENT_DISTANCE_CLAMPED
)
647 pSource
->DistanceModel
= lValue
;
649 alSetError(AL_INVALID_VALUE
);
653 alSetError(AL_INVALID_ENUM
);
658 alSetError(AL_INVALID_NAME
);
660 ProcessContext(pContext
);
664 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
666 ALCcontext
*pContext
;
668 pContext
= GetContextSuspended();
669 if(!pContext
) return;
671 if(alIsSource(source
))
673 ALsource
*pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
674 ALCdevice
*Device
= pContext
->Device
;
681 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
684 case AL_AUXILIARY_SEND_FILTER
:
685 if((ALuint
)lValue2
< Device
->NumAuxSends
&&
686 (lValue1
== 0 || alIsAuxiliaryEffectSlot(lValue1
)) &&
689 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(lValue1
);
690 ALfilter
*ALFilter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue3
);
692 /* Release refcount on the previous slot, and add one for
694 if(pSource
->Send
[lValue2
].Slot
)
695 pSource
->Send
[lValue2
].Slot
->refcount
--;
696 pSource
->Send
[lValue2
].Slot
= ALEffectSlot
;
697 if(pSource
->Send
[lValue2
].Slot
)
698 pSource
->Send
[lValue2
].Slot
->refcount
++;
703 pSource
->Send
[lValue2
].WetFilter
.type
= 0;
704 pSource
->Send
[lValue2
].WetFilter
.filter
= 0;
707 memcpy(&pSource
->Send
[lValue2
].WetFilter
, ALFilter
, sizeof(*ALFilter
));
710 alSetError(AL_INVALID_VALUE
);
714 alSetError(AL_INVALID_ENUM
);
719 alSetError(AL_INVALID_NAME
);
721 ProcessContext(pContext
);
725 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
727 ALCcontext
*pContext
;
729 pContext
= GetContextSuspended();
730 if(!pContext
) return;
734 if(alIsSource(source
))
738 case AL_SOURCE_RELATIVE
:
739 case AL_CONE_INNER_ANGLE
:
740 case AL_CONE_OUTER_ANGLE
:
743 case AL_SOURCE_STATE
:
745 case AL_SAMPLE_OFFSET
:
747 case AL_MAX_DISTANCE
:
748 case AL_ROLLOFF_FACTOR
:
749 case AL_REFERENCE_DISTANCE
:
750 case AL_DIRECT_FILTER
:
751 case AL_DIRECT_FILTER_GAINHF_AUTO
:
752 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
753 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
754 case AL_DISTANCE_MODEL
:
755 alSourcei(source
, eParam
, plValues
[0]);
761 case AL_AUXILIARY_SEND_FILTER
:
762 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
766 alSetError(AL_INVALID_ENUM
);
771 alSetError(AL_INVALID_NAME
);
774 alSetError(AL_INVALID_VALUE
);
776 ProcessContext(pContext
);
780 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
782 ALCcontext
*pContext
;
786 pContext
= GetContextSuspended();
787 if(!pContext
) return;
791 if(alIsSource(source
))
793 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
798 *pflValue
= pSource
->flPitch
;
802 *pflValue
= pSource
->flGain
;
806 *pflValue
= pSource
->flMinGain
;
810 *pflValue
= pSource
->flMaxGain
;
813 case AL_MAX_DISTANCE
:
814 *pflValue
= pSource
->flMaxDistance
;
817 case AL_ROLLOFF_FACTOR
:
818 *pflValue
= pSource
->flRollOffFactor
;
821 case AL_CONE_OUTER_GAIN
:
822 *pflValue
= pSource
->flOuterGain
;
825 case AL_CONE_OUTER_GAINHF
:
826 *pflValue
= pSource
->OuterGainHF
;
830 case AL_SAMPLE_OFFSET
:
832 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
833 *pflValue
= flOffset
[0];
835 alSetError(AL_INVALID_OPERATION
);
838 case AL_SEC_RW_OFFSETS_EXT
:
839 case AL_SAMPLE_RW_OFFSETS_EXT
:
840 case AL_BYTE_RW_OFFSETS_EXT
:
841 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
843 pflValue
[0] = flOffset
[0];
844 pflValue
[1] = flOffset
[1];
847 alSetError(AL_INVALID_OPERATION
);
850 case AL_CONE_INNER_ANGLE
:
851 *pflValue
= pSource
->flInnerAngle
;
854 case AL_CONE_OUTER_ANGLE
:
855 *pflValue
= pSource
->flOuterAngle
;
858 case AL_REFERENCE_DISTANCE
:
859 *pflValue
= pSource
->flRefDistance
;
862 case AL_AIR_ABSORPTION_FACTOR
:
863 *pflValue
= pSource
->AirAbsorptionFactor
;
866 case AL_ROOM_ROLLOFF_FACTOR
:
867 *pflValue
= pSource
->RoomRolloffFactor
;
870 case AL_DOPPLER_FACTOR
:
871 *pflValue
= pSource
->DopplerFactor
;
875 alSetError(AL_INVALID_ENUM
);
880 alSetError(AL_INVALID_NAME
);
883 alSetError(AL_INVALID_VALUE
);
885 ProcessContext(pContext
);
889 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
891 ALCcontext
*pContext
;
894 pContext
= GetContextSuspended();
895 if(!pContext
) return;
897 if(pflValue1
&& pflValue2
&& pflValue3
)
899 if(alIsSource(source
))
901 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
906 *pflValue1
= pSource
->vPosition
[0];
907 *pflValue2
= pSource
->vPosition
[1];
908 *pflValue3
= pSource
->vPosition
[2];
912 *pflValue1
= pSource
->vVelocity
[0];
913 *pflValue2
= pSource
->vVelocity
[1];
914 *pflValue3
= pSource
->vVelocity
[2];
918 *pflValue1
= pSource
->vOrientation
[0];
919 *pflValue2
= pSource
->vOrientation
[1];
920 *pflValue3
= pSource
->vOrientation
[2];
924 alSetError(AL_INVALID_ENUM
);
929 alSetError(AL_INVALID_NAME
);
932 alSetError(AL_INVALID_VALUE
);
934 ProcessContext(pContext
);
938 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
940 ALCcontext
*pContext
;
943 pContext
= GetContextSuspended();
944 if(!pContext
) return;
948 if(alIsSource(source
))
950 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
958 case AL_MAX_DISTANCE
:
959 case AL_ROLLOFF_FACTOR
:
960 case AL_DOPPLER_FACTOR
:
961 case AL_CONE_OUTER_GAIN
:
963 case AL_SAMPLE_OFFSET
:
965 case AL_CONE_INNER_ANGLE
:
966 case AL_CONE_OUTER_ANGLE
:
967 case AL_REFERENCE_DISTANCE
:
968 case AL_CONE_OUTER_GAINHF
:
969 case AL_AIR_ABSORPTION_FACTOR
:
970 case AL_ROOM_ROLLOFF_FACTOR
:
971 alGetSourcef(source
, eParam
, pflValues
);
975 pflValues
[0] = pSource
->vPosition
[0];
976 pflValues
[1] = pSource
->vPosition
[1];
977 pflValues
[2] = pSource
->vPosition
[2];
981 pflValues
[0] = pSource
->vVelocity
[0];
982 pflValues
[1] = pSource
->vVelocity
[1];
983 pflValues
[2] = pSource
->vVelocity
[2];
987 pflValues
[0] = pSource
->vOrientation
[0];
988 pflValues
[1] = pSource
->vOrientation
[1];
989 pflValues
[2] = pSource
->vOrientation
[2];
993 alSetError(AL_INVALID_ENUM
);
998 alSetError(AL_INVALID_NAME
);
1001 alSetError(AL_INVALID_VALUE
);
1003 ProcessContext(pContext
);
1007 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1009 ALCcontext
*pContext
;
1011 ALfloat flOffset
[2];
1013 pContext
= GetContextSuspended();
1014 if(!pContext
) return;
1018 if(alIsSource(source
))
1020 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1024 case AL_MAX_DISTANCE
:
1025 *plValue
= (ALint
)pSource
->flMaxDistance
;
1028 case AL_ROLLOFF_FACTOR
:
1029 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1032 case AL_REFERENCE_DISTANCE
:
1033 *plValue
= (ALint
)pSource
->flRefDistance
;
1036 case AL_SOURCE_RELATIVE
:
1037 *plValue
= pSource
->bHeadRelative
;
1040 case AL_CONE_INNER_ANGLE
:
1041 *plValue
= (ALint
)pSource
->flInnerAngle
;
1044 case AL_CONE_OUTER_ANGLE
:
1045 *plValue
= (ALint
)pSource
->flOuterAngle
;
1049 *plValue
= pSource
->bLooping
;
1053 *plValue
= pSource
->ulBufferID
;
1056 case AL_SOURCE_STATE
:
1057 *plValue
= pSource
->state
;
1060 case AL_BUFFERS_QUEUED
:
1061 *plValue
= pSource
->BuffersInQueue
;
1064 case AL_BUFFERS_PROCESSED
:
1065 if(pSource
->bLooping
)
1067 /* Buffers on a looping source are in a perpetual state
1068 * of PENDING, so don't report any as PROCESSED */
1072 *plValue
= pSource
->BuffersPlayed
;
1075 case AL_SOURCE_TYPE
:
1076 *plValue
= pSource
->lSourceType
;
1080 case AL_SAMPLE_OFFSET
:
1081 case AL_BYTE_OFFSET
:
1082 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
1083 *plValue
= (ALint
)flOffset
[0];
1085 alSetError(AL_INVALID_OPERATION
);
1088 case AL_SEC_RW_OFFSETS_EXT
:
1089 case AL_SAMPLE_RW_OFFSETS_EXT
:
1090 case AL_BYTE_RW_OFFSETS_EXT
:
1091 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
1093 plValue
[0] = (ALint
)flOffset
[0];
1094 plValue
[1] = (ALint
)flOffset
[1];
1097 alSetError(AL_INVALID_OPERATION
);
1100 case AL_DIRECT_FILTER
:
1101 *plValue
= pSource
->DirectFilter
.filter
;
1104 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1105 *plValue
= pSource
->DryGainHFAuto
;
1108 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1109 *plValue
= pSource
->WetGainAuto
;
1112 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1113 *plValue
= pSource
->WetGainHFAuto
;
1116 case AL_DOPPLER_FACTOR
:
1117 *plValue
= (ALint
)pSource
->DopplerFactor
;
1120 case AL_DISTANCE_MODEL
:
1121 *plValue
= pSource
->DistanceModel
;
1125 alSetError(AL_INVALID_ENUM
);
1130 alSetError(AL_INVALID_NAME
);
1133 alSetError(AL_INVALID_VALUE
);
1135 ProcessContext(pContext
);
1139 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1141 ALCcontext
*pContext
;
1144 pContext
= GetContextSuspended();
1145 if(!pContext
) return;
1147 if(plValue1
&& plValue2
&& plValue3
)
1149 if(alIsSource(source
))
1151 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1156 *plValue1
= (ALint
)pSource
->vPosition
[0];
1157 *plValue2
= (ALint
)pSource
->vPosition
[1];
1158 *plValue3
= (ALint
)pSource
->vPosition
[2];
1162 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1163 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1164 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1168 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1169 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1170 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1174 alSetError(AL_INVALID_ENUM
);
1179 alSetError(AL_INVALID_NAME
);
1182 alSetError(AL_INVALID_VALUE
);
1184 ProcessContext(pContext
);
1188 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1190 ALCcontext
*pContext
;
1193 pContext
= GetContextSuspended();
1194 if(!pContext
) return;
1198 if(alIsSource(source
))
1200 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1204 case AL_SOURCE_RELATIVE
:
1205 case AL_CONE_INNER_ANGLE
:
1206 case AL_CONE_OUTER_ANGLE
:
1209 case AL_SOURCE_STATE
:
1210 case AL_BUFFERS_QUEUED
:
1211 case AL_BUFFERS_PROCESSED
:
1213 case AL_SAMPLE_OFFSET
:
1214 case AL_BYTE_OFFSET
:
1215 case AL_MAX_DISTANCE
:
1216 case AL_ROLLOFF_FACTOR
:
1217 case AL_DOPPLER_FACTOR
:
1218 case AL_REFERENCE_DISTANCE
:
1219 case AL_SOURCE_TYPE
:
1220 case AL_DIRECT_FILTER
:
1221 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1222 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1223 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1224 case AL_DISTANCE_MODEL
:
1225 alGetSourcei(source
, eParam
, plValues
);
1229 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1230 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1231 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1235 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1236 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1237 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1241 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1242 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1243 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1247 alSetError(AL_INVALID_ENUM
);
1252 alSetError(AL_INVALID_NAME
);
1255 alSetError(AL_INVALID_VALUE
);
1257 ProcessContext(pContext
);
1261 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1263 alSourcePlayv(1, &source
);
1267 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1269 ALCcontext
*pContext
;
1271 ALbufferlistitem
*ALBufferList
;
1272 ALboolean bSourcesValid
= AL_TRUE
;
1276 pContext
= GetContextSuspended();
1277 if(!pContext
) return;
1281 // Check that all the Sources are valid
1282 for(i
= 0; i
< n
; i
++)
1284 if(!alIsSource(pSourceList
[i
]))
1286 alSetError(AL_INVALID_NAME
);
1287 bSourcesValid
= AL_FALSE
;
1294 for(i
= 0; i
< n
; i
++)
1296 // Assume Source won't need to play
1299 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]);
1301 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1302 ALBufferList
= pSource
->queue
;
1305 if(ALBufferList
->buffer
!= 0 && ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
))->size
)
1310 ALBufferList
= ALBufferList
->next
;
1315 for(j
= 0;j
< OUTPUTCHANNELS
;j
++)
1316 pSource
->DryGains
[j
] = 0.0f
;
1317 for(j
= 0;j
< MAX_SENDS
;j
++)
1318 pSource
->WetGains
[j
] = 0.0f
;
1320 if(pSource
->state
!= AL_PAUSED
)
1322 pSource
->state
= AL_PLAYING
;
1323 pSource
->inuse
= AL_TRUE
;
1324 pSource
->play
= AL_TRUE
;
1325 pSource
->position
= 0;
1326 pSource
->position_fraction
= 0;
1327 pSource
->BuffersPlayed
= 0;
1328 pSource
->FirstStart
= AL_TRUE
;
1330 pSource
->ulBufferID
= pSource
->queue
->buffer
;
1332 // Make sure all the Buffers in the queue are marked as PENDING
1333 ALBufferList
= pSource
->queue
;
1336 ALBufferList
->bufferstate
= PENDING
;
1337 ALBufferList
= ALBufferList
->next
;
1342 pSource
->state
= AL_PLAYING
;
1343 pSource
->inuse
= AL_TRUE
;
1344 pSource
->play
= AL_TRUE
;
1345 pSource
->FirstStart
= AL_FALSE
;
1348 // Check if an Offset has been set
1349 if(pSource
->lOffset
)
1350 ApplyOffset(pSource
, AL_FALSE
);
1352 // If device is disconnected, go right to stopped
1353 if(!pContext
->Device
->Connected
)
1355 pSource
->state
= AL_STOPPED
;
1356 pSource
->inuse
= AL_FALSE
;
1357 pSource
->BuffersPlayed
= pSource
->BuffersInQueue
;
1358 ALBufferList
= pSource
->queue
;
1359 while(ALBufferList
!= NULL
)
1361 ALBufferList
->bufferstate
= PROCESSED
;
1362 ALBufferList
= ALBufferList
->next
;
1364 pSource
->position
= 0;
1365 pSource
->position_fraction
= 0;
1370 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1371 ALBufferList
= pSource
->queue
;
1374 ALBufferList
->bufferstate
= PROCESSED
;
1375 ALBufferList
= ALBufferList
->next
;
1378 pSource
->BuffersPlayed
= pSource
->BuffersInQueue
;
1385 // sources is a NULL pointer
1386 alSetError(AL_INVALID_VALUE
);
1389 ProcessContext(pContext
);
1392 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1394 alSourcePausev(1, &source
);
1398 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1400 ALCcontext
*Context
;
1403 ALboolean bSourcesValid
= AL_TRUE
;
1405 Context
= GetContextSuspended();
1406 if(!Context
) return;
1410 // Check all the Sources are valid
1413 if(!alIsSource(sources
[i
]))
1415 alSetError(AL_INVALID_NAME
);
1416 bSourcesValid
= AL_FALSE
;
1423 for(i
= 0;i
< n
;i
++)
1425 Source
= (ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]);
1426 if(Source
->state
== AL_PLAYING
)
1428 Source
->state
= AL_PAUSED
;
1429 Source
->inuse
= AL_FALSE
;
1436 // sources is a NULL pointer
1437 alSetError(AL_INVALID_VALUE
);
1440 ProcessContext(Context
);
1443 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1445 alSourceStopv(1, &source
);
1449 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1451 ALCcontext
*Context
;
1454 ALbufferlistitem
*ALBufferListItem
;
1455 ALboolean bSourcesValid
= AL_TRUE
;
1457 Context
= GetContextSuspended();
1458 if(!Context
) return;
1462 // Check all the Sources are valid
1463 for(i
= 0;i
< n
;i
++)
1465 if(!alIsSource(sources
[i
]))
1467 alSetError(AL_INVALID_NAME
);
1468 bSourcesValid
= AL_FALSE
;
1475 for(i
= 0;i
< n
;i
++)
1477 Source
= (ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]);
1478 if(Source
->state
!= AL_INITIAL
)
1480 Source
->state
= AL_STOPPED
;
1481 Source
->inuse
= AL_FALSE
;
1482 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1483 ALBufferListItem
= Source
->queue
;
1484 while(ALBufferListItem
!= NULL
)
1486 ALBufferListItem
->bufferstate
= PROCESSED
;
1487 ALBufferListItem
= ALBufferListItem
->next
;
1490 Source
->lOffset
= 0;
1496 // sources is a NULL pointer
1497 alSetError(AL_INVALID_VALUE
);
1500 ProcessContext(Context
);
1503 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1505 alSourceRewindv(1, &source
);
1509 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1511 ALCcontext
*Context
;
1514 ALbufferlistitem
*ALBufferListItem
;
1515 ALboolean bSourcesValid
= AL_TRUE
;
1517 Context
= GetContextSuspended();
1518 if(!Context
) return;
1522 // Check all the Sources are valid
1523 for(i
= 0;i
< n
;i
++)
1525 if(!alIsSource(sources
[i
]))
1527 alSetError(AL_INVALID_NAME
);
1528 bSourcesValid
= AL_FALSE
;
1535 for(i
= 0;i
< n
;i
++)
1537 Source
= (ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]);
1538 if(Source
->state
!= AL_INITIAL
)
1540 Source
->state
= AL_INITIAL
;
1541 Source
->inuse
= AL_FALSE
;
1542 Source
->position
= 0;
1543 Source
->position_fraction
= 0;
1544 Source
->BuffersPlayed
= 0;
1545 ALBufferListItem
= Source
->queue
;
1546 while(ALBufferListItem
!= NULL
)
1548 ALBufferListItem
->bufferstate
= PENDING
;
1549 ALBufferListItem
= ALBufferListItem
->next
;
1552 Source
->ulBufferID
= Source
->queue
->buffer
;
1554 Source
->lOffset
= 0;
1560 // sources is a NULL pointer
1561 alSetError(AL_INVALID_VALUE
);
1564 ProcessContext(Context
);
1568 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1570 ALCcontext
*Context
;
1573 ALbufferlistitem
*ALBufferList
;
1574 ALbufferlistitem
*ALBufferListStart
;
1577 ALboolean bBuffersValid
= AL_TRUE
;
1582 Context
= GetContextSuspended();
1583 if(!Context
) return;
1585 // Check that all buffers are valid or zero and that the source is valid
1587 // Check that this is a valid source
1588 if(alIsSource(source
))
1590 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1592 // Check that this is not a STATIC Source
1593 if(ALSource
->lSourceType
!= AL_STATIC
)
1598 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1599 ALBufferList
= ALSource
->queue
;
1602 if (ALBufferList
->buffer
)
1604 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->frequency
;
1605 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->format
;
1608 ALBufferList
= ALBufferList
->next
;
1611 for(i
= 0; i
< n
; i
++)
1613 if(alIsBuffer(buffers
[i
]))
1617 if((iFrequency
== -1) && (iFormat
== -1))
1619 iFrequency
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
;
1620 iFormat
= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
;
1624 if((iFrequency
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->frequency
) ||
1625 (iFormat
!= ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->format
))
1627 alSetError(AL_INVALID_OPERATION
);
1628 bBuffersValid
= AL_FALSE
;
1636 alSetError(AL_INVALID_NAME
);
1637 bBuffersValid
= AL_FALSE
;
1644 // Change Source Type
1645 ALSource
->lSourceType
= AL_STREAMING
;
1647 // All buffers are valid - so add them to the list
1648 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1649 ALBufferListStart
->buffer
= buffers
[0];
1650 ALBufferListStart
->bufferstate
= PENDING
;
1651 ALBufferListStart
->flag
= 0;
1652 ALBufferListStart
->next
= NULL
;
1654 // Increment reference counter for buffer
1656 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[0])))->refcount
++;
1658 ALBufferList
= ALBufferListStart
;
1660 for(i
= 1; i
< n
; i
++)
1662 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1663 ALBufferList
->next
->buffer
= buffers
[i
];
1664 ALBufferList
->next
->bufferstate
= PENDING
;
1665 ALBufferList
->next
->flag
= 0;
1666 ALBufferList
->next
->next
= NULL
;
1668 // Increment reference counter for buffer
1670 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(buffers
[i
])))->refcount
++;
1672 ALBufferList
= ALBufferList
->next
;
1675 if(ALSource
->queue
== NULL
)
1677 ALSource
->queue
= ALBufferListStart
;
1678 // Update Current Buffer
1679 ALSource
->ulBufferID
= ALBufferListStart
->buffer
;
1683 // Find end of queue
1684 ALBufferList
= ALSource
->queue
;
1685 while(ALBufferList
->next
!= NULL
)
1686 ALBufferList
= ALBufferList
->next
;
1688 ALBufferList
->next
= ALBufferListStart
;
1691 // Update number of buffers in queue
1692 ALSource
->BuffersInQueue
+= n
;
1697 // Invalid Source Type (can't queue on a Static Source)
1698 alSetError(AL_INVALID_OPERATION
);
1703 // Invalid Source Name
1704 alSetError(AL_INVALID_NAME
);
1707 ProcessContext(Context
);
1711 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1712 // an array of buffer IDs that are to be filled with the names of the buffers removed
1713 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1715 ALCcontext
*Context
;
1718 ALbufferlistitem
*ALBufferList
;
1720 ALboolean bBuffersProcessed
;
1725 bBuffersProcessed
= AL_TRUE
;
1727 Context
= GetContextSuspended();
1728 if(!Context
) return;
1730 if(alIsSource(source
))
1732 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1734 // Check that all 'n' buffers have been processed
1735 ALBufferList
= ALSource
->queue
;
1736 for(i
= 0; i
< n
; i
++)
1738 if(ALBufferList
!= NULL
&& ALBufferList
->bufferstate
== PROCESSED
)
1740 ALBufferList
= ALBufferList
->next
;
1744 bBuffersProcessed
= AL_FALSE
;
1749 // If all 'n' buffers have been processed, remove them from the queue
1750 if(bBuffersProcessed
)
1752 for(i
= 0; i
< n
; i
++)
1754 ALBufferList
= ALSource
->queue
;
1756 ALSource
->queue
= ALBufferList
->next
;
1757 // Record name of buffer
1758 buffers
[i
] = ALBufferList
->buffer
;
1759 // Decrement buffer reference counter
1760 if(ALBufferList
->buffer
)
1761 ((ALbuffer
*)(ALTHUNK_LOOKUPENTRY(ALBufferList
->buffer
)))->refcount
--;
1763 // Release memory for buffer list item
1765 ALSource
->BuffersInQueue
--;
1768 if(ALSource
->state
!= AL_PLAYING
)
1770 if (ALSource
->queue
)
1771 BufferID
= ALSource
->queue
->buffer
;
1775 ALSource
->ulBufferID
= BufferID
;
1778 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1779 ALSource
->BuffersPlayed
= 0;
1781 ALSource
->BuffersPlayed
-= n
;
1785 // Some buffers can't be unqueue because they have not been processed
1786 alSetError(AL_INVALID_VALUE
);
1791 // Invalid Source Name
1792 alSetError(AL_INVALID_NAME
);
1795 ProcessContext(Context
);
1799 static ALvoid
InitSourceParams(ALCcontext
*Context
, ALsource
*pSource
)
1801 pSource
->flInnerAngle
= 360.0f
;
1802 pSource
->flOuterAngle
= 360.0f
;
1803 pSource
->flPitch
= 1.0f
;
1804 pSource
->vPosition
[0] = 0.0f
;
1805 pSource
->vPosition
[1] = 0.0f
;
1806 pSource
->vPosition
[2] = 0.0f
;
1807 pSource
->vOrientation
[0] = 0.0f
;
1808 pSource
->vOrientation
[1] = 0.0f
;
1809 pSource
->vOrientation
[2] = 0.0f
;
1810 pSource
->vVelocity
[0] = 0.0f
;
1811 pSource
->vVelocity
[1] = 0.0f
;
1812 pSource
->vVelocity
[2] = 0.0f
;
1813 pSource
->flRefDistance
= 1.0f
;
1814 pSource
->flMaxDistance
= FLT_MAX
;
1815 pSource
->flRollOffFactor
= 1.0f
;
1816 pSource
->bLooping
= AL_FALSE
;
1817 pSource
->flGain
= 1.0f
;
1818 pSource
->flMinGain
= 0.0f
;
1819 pSource
->flMaxGain
= 1.0f
;
1820 pSource
->flOuterGain
= 0.0f
;
1821 pSource
->OuterGainHF
= 1.0f
;
1823 pSource
->DryGainHFAuto
= AL_TRUE
;
1824 pSource
->WetGainAuto
= AL_TRUE
;
1825 pSource
->WetGainHFAuto
= AL_TRUE
;
1826 pSource
->AirAbsorptionFactor
= 0.0f
;
1827 pSource
->RoomRolloffFactor
= 0.0f
;
1828 pSource
->DopplerFactor
= 1.0f
;
1830 pSource
->DistanceModel
= Context
->DistanceModel
;
1832 pSource
->state
= AL_INITIAL
;
1833 pSource
->lSourceType
= AL_UNDETERMINED
;
1835 pSource
->ulBufferID
= 0;
1842 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1843 The offset is relative to the start of the queue (not the start of the current buffer)
1845 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
, ALuint updateSize
)
1847 ALbufferlistitem
*pBufferList
;
1849 ALfloat flBufferFreq
;
1851 ALint readPos
, writePos
;
1852 ALenum eOriginalFormat
;
1853 ALboolean bReturn
= AL_TRUE
;
1854 ALint lTotalBufferDataSize
;
1856 if (((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
)) && (pSource
->ulBufferID
))
1858 pBuffer
= ALTHUNK_LOOKUPENTRY(pSource
->ulBufferID
);
1859 // Get Current Buffer Size and frequency (in milliseconds)
1860 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
1861 eOriginalFormat
= pBuffer
->eOriginalFormat
;
1862 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
1864 // Get Current BytesPlayed
1865 readPos
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
1866 // Add byte length of any processed buffers in the queue
1867 pBufferList
= pSource
->queue
;
1868 while ((pBufferList
) && (pBufferList
->bufferstate
== PROCESSED
))
1870 readPos
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
1871 pBufferList
= pBufferList
->next
;
1874 if(pSource
->state
== AL_PLAYING
)
1875 writePos
= readPos
+ (updateSize
* lChannels
* 2);
1879 lTotalBufferDataSize
= 0;
1880 pBufferList
= pSource
->queue
;
1883 if (pBufferList
->buffer
)
1884 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
1885 pBufferList
= pBufferList
->next
;
1888 if (pSource
->bLooping
)
1893 readPos
%= lTotalBufferDataSize
;
1897 writePos
%= lTotalBufferDataSize
;
1901 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
1904 else if(readPos
> lTotalBufferDataSize
)
1905 readPos
= lTotalBufferDataSize
;
1908 else if(writePos
> lTotalBufferDataSize
)
1909 writePos
= lTotalBufferDataSize
;
1915 case AL_SEC_RW_OFFSETS_EXT
:
1916 pflOffset
[0] = (ALfloat
)readPos
/ (lChannels
* 2.0f
* flBufferFreq
);
1917 pflOffset
[1] = (ALfloat
)writePos
/ (lChannels
* 2.0f
* flBufferFreq
);
1919 case AL_SAMPLE_OFFSET
:
1920 case AL_SAMPLE_RW_OFFSETS_EXT
:
1921 pflOffset
[0] = (ALfloat
)(readPos
/ (lChannels
* 2));
1922 pflOffset
[1] = (ALfloat
)(writePos
/ (lChannels
* 2));
1924 case AL_BYTE_OFFSET
:
1925 case AL_BYTE_RW_OFFSETS_EXT
:
1926 // Take into account the original format of the Buffer
1927 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
1928 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
1930 // Round down to nearest ADPCM block
1931 pflOffset
[0] = (ALfloat
)((readPos
/ (65 * 2 * lChannels
)) * 36 * lChannels
);
1932 if(pSource
->state
== AL_PLAYING
)
1934 // Round up to nearest ADPCM block
1935 pflOffset
[1] = (ALfloat
)(((writePos
+ (65 * 2 * lChannels
) - 1) / (65 * 2 * lChannels
)) * 36 * lChannels
);
1938 pflOffset
[1] = pflOffset
[0];
1940 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
1942 pflOffset
[0] = (ALfloat
)(readPos
>> 2);
1943 pflOffset
[1] = (ALfloat
)(writePos
>> 2);
1945 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
1947 pflOffset
[0] = (ALfloat
)(readPos
>> 1);
1948 pflOffset
[1] = (ALfloat
)(writePos
>> 1);
1950 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
1952 pflOffset
[0] = (ALfloat
)(readPos
>> 1);
1953 pflOffset
[1] = (ALfloat
)(writePos
>> 1);
1955 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
1957 pflOffset
[0] = (ALfloat
)(readPos
<< 1);
1958 pflOffset
[1] = (ALfloat
)(writePos
<< 1);
1962 pflOffset
[0] = (ALfloat
)readPos
;
1963 pflOffset
[1] = (ALfloat
)writePos
;
1970 pflOffset
[0] = 0.0f
;
1971 pflOffset
[1] = 0.0f
;
1981 Apply a playback offset to the Source. This function will update the queue (to correctly
1982 mark buffers as 'pending' or 'processed' depending upon the new offset.
1984 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
1986 ALbufferlistitem
*pBufferList
;
1988 ALint lBufferSize
, lTotalBufferSize
;
1991 // Get true byte offset
1992 lByteOffset
= GetByteOffset(pSource
);
1994 // If this is a valid offset apply it
1995 if (lByteOffset
!= -1)
1997 // Sort out the queue (pending and processed states)
1998 pBufferList
= pSource
->queue
;
1999 lTotalBufferSize
= 0;
2000 pSource
->BuffersPlayed
= 0;
2003 pBuffer
= ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2004 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2006 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2008 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2009 // update the state to PROCESSED
2010 pSource
->BuffersPlayed
++;
2012 if (!pSource
->bLooping
)
2013 pBufferList
->bufferstate
= PROCESSED
;
2015 else if (lTotalBufferSize
<= lByteOffset
)
2017 // Offset is within this buffer
2018 pBufferList
->bufferstate
= PENDING
;
2020 // Set Current Buffer ID
2021 pSource
->ulBufferID
= pBufferList
->buffer
;
2023 // SW Mixer Positions are in Samples
2024 pSource
->position
= (lByteOffset
- lTotalBufferSize
) /
2025 aluBytesFromFormat(pBuffer
->format
) /
2026 aluChannelsFromFormat(pBuffer
->format
);
2030 // Offset is before this buffer, so mark as pending
2031 pBufferList
->bufferstate
= PENDING
;
2034 // Increment the TotalBufferSize
2035 lTotalBufferSize
+= lBufferSize
;
2037 // Move on to next buffer in the Queue
2038 pBufferList
= pBufferList
->next
;
2044 alSetError(AL_INVALID_VALUE
);
2048 pSource
->lOffset
= 0;
2055 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2056 offset supplied by the application). This takes into account the fact that the buffer format
2057 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2059 static ALint
GetByteOffset(ALsource
*pSource
)
2061 ALbuffer
*pBuffer
= NULL
;
2062 ALbufferlistitem
*pBufferList
;
2063 ALfloat flBufferFreq
;
2065 ALint lByteOffset
= -1;
2066 ALint lTotalBufferDataSize
;
2068 // Find the first non-NULL Buffer in the Queue
2069 pBufferList
= pSource
->queue
;
2072 if (pBufferList
->buffer
)
2074 pBuffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
);
2077 pBufferList
= pBufferList
->next
;
2082 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2083 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2085 // Determine the ByteOffset (and ensure it is block aligned)
2086 switch (pSource
->lOffsetType
)
2088 case AL_BYTE_OFFSET
:
2089 // Take into consideration the original format
2090 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2091 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2093 // Round down to nearest ADPCM block
2094 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2095 // Multiply by compression rate
2096 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2097 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2099 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2101 lByteOffset
= pSource
->lOffset
* 4;
2102 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2104 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2106 lByteOffset
= pSource
->lOffset
* 2;
2107 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2109 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2111 lByteOffset
= pSource
->lOffset
* 2;
2112 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2114 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2116 lByteOffset
= pSource
->lOffset
/ 2;
2117 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2121 lByteOffset
= pSource
->lOffset
;
2122 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2126 case AL_SAMPLE_OFFSET
:
2127 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2131 // Note - lOffset is internally stored as Milliseconds
2132 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2133 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2137 lTotalBufferDataSize
= 0;
2138 pBufferList
= pSource
->queue
;
2141 if (pBufferList
->buffer
)
2142 lTotalBufferDataSize
+= ((ALbuffer
*)ALTHUNK_LOOKUPENTRY(pBufferList
->buffer
))->size
;
2143 pBufferList
= pBufferList
->next
;
2146 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2147 if (lByteOffset
>= lTotalBufferDataSize
)
2155 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2157 while(Context
->Source
)
2159 ALsource
*temp
= Context
->Source
;
2160 Context
->Source
= Context
->Source
->next
;
2162 // Release source structure
2163 ALTHUNK_REMOVEENTRY(temp
->source
);
2164 memset(temp
, 0, sizeof(ALsource
));
2167 Context
->SourceCount
= 0;