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
!= NULL
)
146 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 ALbuffer
*buffer
= NULL
;
529 // Remove all elements in the queue
530 while(pSource
->queue
!= NULL
)
532 pALBufferListItem
= pSource
->queue
;
533 pSource
->queue
= pALBufferListItem
->next
;
534 // Decrement reference counter for buffer
535 if(pALBufferListItem
->buffer
)
536 pALBufferListItem
->buffer
->refcount
--;
537 // Release memory for buffer list item
538 free(pALBufferListItem
);
539 // Decrement the number of buffers in the queue
540 pSource
->BuffersInQueue
--;
543 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
546 buffer
= (ALbuffer
*)(ALTHUNK_LOOKUPENTRY(lValue
));
548 // Source is now in STATIC mode
549 pSource
->lSourceType
= AL_STATIC
;
551 // Add the selected buffer to the queue
552 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
553 pALBufferListItem
->buffer
= buffer
;
554 pALBufferListItem
->bufferstate
= PENDING
;
555 pALBufferListItem
->flag
= 0;
556 pALBufferListItem
->next
= NULL
;
558 pSource
->queue
= pALBufferListItem
;
559 pSource
->BuffersInQueue
= 1;
561 // Increment reference counter for buffer
566 // Source is now in UNDETERMINED mode
567 pSource
->lSourceType
= AL_UNDETERMINED
;
568 pSource
->BuffersPlayed
= 0;
571 // Update AL_BUFFER parameter
572 pSource
->Buffer
= buffer
;
575 alSetError(AL_INVALID_VALUE
);
578 alSetError(AL_INVALID_OPERATION
);
581 case AL_SOURCE_STATE
:
583 alSetError(AL_INVALID_OPERATION
);
587 case AL_SAMPLE_OFFSET
:
591 pSource
->lOffsetType
= eParam
;
593 // Store Offset (convert Seconds into Milliseconds)
594 if(eParam
== AL_SEC_OFFSET
)
595 pSource
->lOffset
= lValue
* 1000;
597 pSource
->lOffset
= lValue
;
599 if(pSource
->state
== AL_PLAYING
|| pSource
->state
== AL_PAUSED
)
600 ApplyOffset(pSource
, AL_TRUE
);
603 alSetError(AL_INVALID_VALUE
);
606 case AL_DIRECT_FILTER
:
607 if(alIsFilter(lValue
))
609 ALfilter
*filter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue
);
612 pSource
->DirectFilter
.type
= AL_FILTER_NULL
;
613 pSource
->DirectFilter
.filter
= 0;
616 memcpy(&pSource
->DirectFilter
, filter
, sizeof(*filter
));
619 alSetError(AL_INVALID_VALUE
);
622 case AL_DIRECT_FILTER_GAINHF_AUTO
:
623 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
624 pSource
->DryGainHFAuto
= lValue
;
626 alSetError(AL_INVALID_VALUE
);
629 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
630 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
631 pSource
->WetGainAuto
= lValue
;
633 alSetError(AL_INVALID_VALUE
);
636 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
637 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
638 pSource
->WetGainHFAuto
= lValue
;
640 alSetError(AL_INVALID_VALUE
);
643 case AL_DISTANCE_MODEL
:
644 if(lValue
== AL_NONE
||
645 lValue
== AL_INVERSE_DISTANCE
||
646 lValue
== AL_INVERSE_DISTANCE_CLAMPED
||
647 lValue
== AL_LINEAR_DISTANCE
||
648 lValue
== AL_LINEAR_DISTANCE_CLAMPED
||
649 lValue
== AL_EXPONENT_DISTANCE
||
650 lValue
== AL_EXPONENT_DISTANCE_CLAMPED
)
651 pSource
->DistanceModel
= lValue
;
653 alSetError(AL_INVALID_VALUE
);
657 alSetError(AL_INVALID_ENUM
);
662 alSetError(AL_INVALID_NAME
);
664 ProcessContext(pContext
);
668 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
670 ALCcontext
*pContext
;
672 pContext
= GetContextSuspended();
673 if(!pContext
) return;
675 if(alIsSource(source
))
677 ALsource
*pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
678 ALCdevice
*Device
= pContext
->Device
;
685 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
688 case AL_AUXILIARY_SEND_FILTER
:
689 if((ALuint
)lValue2
< Device
->NumAuxSends
&&
690 (lValue1
== 0 || alIsAuxiliaryEffectSlot(lValue1
)) &&
693 ALeffectslot
*ALEffectSlot
= (ALeffectslot
*)ALTHUNK_LOOKUPENTRY(lValue1
);
694 ALfilter
*ALFilter
= (ALfilter
*)ALTHUNK_LOOKUPENTRY(lValue3
);
696 /* Release refcount on the previous slot, and add one for
698 if(pSource
->Send
[lValue2
].Slot
)
699 pSource
->Send
[lValue2
].Slot
->refcount
--;
700 pSource
->Send
[lValue2
].Slot
= ALEffectSlot
;
701 if(pSource
->Send
[lValue2
].Slot
)
702 pSource
->Send
[lValue2
].Slot
->refcount
++;
707 pSource
->Send
[lValue2
].WetFilter
.type
= 0;
708 pSource
->Send
[lValue2
].WetFilter
.filter
= 0;
711 memcpy(&pSource
->Send
[lValue2
].WetFilter
, ALFilter
, sizeof(*ALFilter
));
714 alSetError(AL_INVALID_VALUE
);
718 alSetError(AL_INVALID_ENUM
);
723 alSetError(AL_INVALID_NAME
);
725 ProcessContext(pContext
);
729 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
731 ALCcontext
*pContext
;
733 pContext
= GetContextSuspended();
734 if(!pContext
) return;
738 if(alIsSource(source
))
742 case AL_SOURCE_RELATIVE
:
743 case AL_CONE_INNER_ANGLE
:
744 case AL_CONE_OUTER_ANGLE
:
747 case AL_SOURCE_STATE
:
749 case AL_SAMPLE_OFFSET
:
751 case AL_MAX_DISTANCE
:
752 case AL_ROLLOFF_FACTOR
:
753 case AL_REFERENCE_DISTANCE
:
754 case AL_DIRECT_FILTER
:
755 case AL_DIRECT_FILTER_GAINHF_AUTO
:
756 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
757 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
758 case AL_DISTANCE_MODEL
:
759 alSourcei(source
, eParam
, plValues
[0]);
765 case AL_AUXILIARY_SEND_FILTER
:
766 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
770 alSetError(AL_INVALID_ENUM
);
775 alSetError(AL_INVALID_NAME
);
778 alSetError(AL_INVALID_VALUE
);
780 ProcessContext(pContext
);
784 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
786 ALCcontext
*pContext
;
790 pContext
= GetContextSuspended();
791 if(!pContext
) return;
795 if(alIsSource(source
))
797 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
802 *pflValue
= pSource
->flPitch
;
806 *pflValue
= pSource
->flGain
;
810 *pflValue
= pSource
->flMinGain
;
814 *pflValue
= pSource
->flMaxGain
;
817 case AL_MAX_DISTANCE
:
818 *pflValue
= pSource
->flMaxDistance
;
821 case AL_ROLLOFF_FACTOR
:
822 *pflValue
= pSource
->flRollOffFactor
;
825 case AL_CONE_OUTER_GAIN
:
826 *pflValue
= pSource
->flOuterGain
;
829 case AL_CONE_OUTER_GAINHF
:
830 *pflValue
= pSource
->OuterGainHF
;
834 case AL_SAMPLE_OFFSET
:
836 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
837 *pflValue
= flOffset
[0];
839 alSetError(AL_INVALID_OPERATION
);
842 case AL_SEC_RW_OFFSETS_EXT
:
843 case AL_SAMPLE_RW_OFFSETS_EXT
:
844 case AL_BYTE_RW_OFFSETS_EXT
:
845 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
847 pflValue
[0] = flOffset
[0];
848 pflValue
[1] = flOffset
[1];
851 alSetError(AL_INVALID_OPERATION
);
854 case AL_CONE_INNER_ANGLE
:
855 *pflValue
= pSource
->flInnerAngle
;
858 case AL_CONE_OUTER_ANGLE
:
859 *pflValue
= pSource
->flOuterAngle
;
862 case AL_REFERENCE_DISTANCE
:
863 *pflValue
= pSource
->flRefDistance
;
866 case AL_AIR_ABSORPTION_FACTOR
:
867 *pflValue
= pSource
->AirAbsorptionFactor
;
870 case AL_ROOM_ROLLOFF_FACTOR
:
871 *pflValue
= pSource
->RoomRolloffFactor
;
874 case AL_DOPPLER_FACTOR
:
875 *pflValue
= pSource
->DopplerFactor
;
879 alSetError(AL_INVALID_ENUM
);
884 alSetError(AL_INVALID_NAME
);
887 alSetError(AL_INVALID_VALUE
);
889 ProcessContext(pContext
);
893 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
895 ALCcontext
*pContext
;
898 pContext
= GetContextSuspended();
899 if(!pContext
) return;
901 if(pflValue1
&& pflValue2
&& pflValue3
)
903 if(alIsSource(source
))
905 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
910 *pflValue1
= pSource
->vPosition
[0];
911 *pflValue2
= pSource
->vPosition
[1];
912 *pflValue3
= pSource
->vPosition
[2];
916 *pflValue1
= pSource
->vVelocity
[0];
917 *pflValue2
= pSource
->vVelocity
[1];
918 *pflValue3
= pSource
->vVelocity
[2];
922 *pflValue1
= pSource
->vOrientation
[0];
923 *pflValue2
= pSource
->vOrientation
[1];
924 *pflValue3
= pSource
->vOrientation
[2];
928 alSetError(AL_INVALID_ENUM
);
933 alSetError(AL_INVALID_NAME
);
936 alSetError(AL_INVALID_VALUE
);
938 ProcessContext(pContext
);
942 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
944 ALCcontext
*pContext
;
947 pContext
= GetContextSuspended();
948 if(!pContext
) return;
952 if(alIsSource(source
))
954 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
962 case AL_MAX_DISTANCE
:
963 case AL_ROLLOFF_FACTOR
:
964 case AL_DOPPLER_FACTOR
:
965 case AL_CONE_OUTER_GAIN
:
967 case AL_SAMPLE_OFFSET
:
969 case AL_CONE_INNER_ANGLE
:
970 case AL_CONE_OUTER_ANGLE
:
971 case AL_REFERENCE_DISTANCE
:
972 case AL_CONE_OUTER_GAINHF
:
973 case AL_AIR_ABSORPTION_FACTOR
:
974 case AL_ROOM_ROLLOFF_FACTOR
:
975 alGetSourcef(source
, eParam
, pflValues
);
979 pflValues
[0] = pSource
->vPosition
[0];
980 pflValues
[1] = pSource
->vPosition
[1];
981 pflValues
[2] = pSource
->vPosition
[2];
985 pflValues
[0] = pSource
->vVelocity
[0];
986 pflValues
[1] = pSource
->vVelocity
[1];
987 pflValues
[2] = pSource
->vVelocity
[2];
991 pflValues
[0] = pSource
->vOrientation
[0];
992 pflValues
[1] = pSource
->vOrientation
[1];
993 pflValues
[2] = pSource
->vOrientation
[2];
997 alSetError(AL_INVALID_ENUM
);
1002 alSetError(AL_INVALID_NAME
);
1005 alSetError(AL_INVALID_VALUE
);
1007 ProcessContext(pContext
);
1011 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1013 ALCcontext
*pContext
;
1015 ALfloat flOffset
[2];
1017 pContext
= GetContextSuspended();
1018 if(!pContext
) return;
1022 if(alIsSource(source
))
1024 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1028 case AL_MAX_DISTANCE
:
1029 *plValue
= (ALint
)pSource
->flMaxDistance
;
1032 case AL_ROLLOFF_FACTOR
:
1033 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1036 case AL_REFERENCE_DISTANCE
:
1037 *plValue
= (ALint
)pSource
->flRefDistance
;
1040 case AL_SOURCE_RELATIVE
:
1041 *plValue
= pSource
->bHeadRelative
;
1044 case AL_CONE_INNER_ANGLE
:
1045 *plValue
= (ALint
)pSource
->flInnerAngle
;
1048 case AL_CONE_OUTER_ANGLE
:
1049 *plValue
= (ALint
)pSource
->flOuterAngle
;
1053 *plValue
= pSource
->bLooping
;
1057 *plValue
= (pSource
->Buffer
? pSource
->Buffer
->buffer
: 0);
1060 case AL_SOURCE_STATE
:
1061 *plValue
= pSource
->state
;
1064 case AL_BUFFERS_QUEUED
:
1065 *plValue
= pSource
->BuffersInQueue
;
1068 case AL_BUFFERS_PROCESSED
:
1069 if(pSource
->bLooping
)
1071 /* Buffers on a looping source are in a perpetual state
1072 * of PENDING, so don't report any as PROCESSED */
1076 *plValue
= pSource
->BuffersPlayed
;
1079 case AL_SOURCE_TYPE
:
1080 *plValue
= pSource
->lSourceType
;
1084 case AL_SAMPLE_OFFSET
:
1085 case AL_BYTE_OFFSET
:
1086 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
1087 *plValue
= (ALint
)flOffset
[0];
1089 alSetError(AL_INVALID_OPERATION
);
1092 case AL_SEC_RW_OFFSETS_EXT
:
1093 case AL_SAMPLE_RW_OFFSETS_EXT
:
1094 case AL_BYTE_RW_OFFSETS_EXT
:
1095 if(GetSourceOffset(pSource
, eParam
, flOffset
, pContext
->Device
->UpdateSize
))
1097 plValue
[0] = (ALint
)flOffset
[0];
1098 plValue
[1] = (ALint
)flOffset
[1];
1101 alSetError(AL_INVALID_OPERATION
);
1104 case AL_DIRECT_FILTER
:
1105 *plValue
= pSource
->DirectFilter
.filter
;
1108 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1109 *plValue
= pSource
->DryGainHFAuto
;
1112 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1113 *plValue
= pSource
->WetGainAuto
;
1116 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1117 *plValue
= pSource
->WetGainHFAuto
;
1120 case AL_DOPPLER_FACTOR
:
1121 *plValue
= (ALint
)pSource
->DopplerFactor
;
1124 case AL_DISTANCE_MODEL
:
1125 *plValue
= pSource
->DistanceModel
;
1129 alSetError(AL_INVALID_ENUM
);
1134 alSetError(AL_INVALID_NAME
);
1137 alSetError(AL_INVALID_VALUE
);
1139 ProcessContext(pContext
);
1143 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1145 ALCcontext
*pContext
;
1148 pContext
= GetContextSuspended();
1149 if(!pContext
) return;
1151 if(plValue1
&& plValue2
&& plValue3
)
1153 if(alIsSource(source
))
1155 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1160 *plValue1
= (ALint
)pSource
->vPosition
[0];
1161 *plValue2
= (ALint
)pSource
->vPosition
[1];
1162 *plValue3
= (ALint
)pSource
->vPosition
[2];
1166 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1167 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1168 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1172 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1173 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1174 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1178 alSetError(AL_INVALID_ENUM
);
1183 alSetError(AL_INVALID_NAME
);
1186 alSetError(AL_INVALID_VALUE
);
1188 ProcessContext(pContext
);
1192 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1194 ALCcontext
*pContext
;
1197 pContext
= GetContextSuspended();
1198 if(!pContext
) return;
1202 if(alIsSource(source
))
1204 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1208 case AL_SOURCE_RELATIVE
:
1209 case AL_CONE_INNER_ANGLE
:
1210 case AL_CONE_OUTER_ANGLE
:
1213 case AL_SOURCE_STATE
:
1214 case AL_BUFFERS_QUEUED
:
1215 case AL_BUFFERS_PROCESSED
:
1217 case AL_SAMPLE_OFFSET
:
1218 case AL_BYTE_OFFSET
:
1219 case AL_MAX_DISTANCE
:
1220 case AL_ROLLOFF_FACTOR
:
1221 case AL_DOPPLER_FACTOR
:
1222 case AL_REFERENCE_DISTANCE
:
1223 case AL_SOURCE_TYPE
:
1224 case AL_DIRECT_FILTER
:
1225 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1226 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1227 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1228 case AL_DISTANCE_MODEL
:
1229 alGetSourcei(source
, eParam
, plValues
);
1233 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1234 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1235 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1239 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1240 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1241 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1245 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1246 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1247 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1251 alSetError(AL_INVALID_ENUM
);
1256 alSetError(AL_INVALID_NAME
);
1259 alSetError(AL_INVALID_VALUE
);
1261 ProcessContext(pContext
);
1265 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1267 alSourcePlayv(1, &source
);
1271 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1273 ALCcontext
*pContext
;
1275 ALbufferlistitem
*ALBufferList
;
1276 ALboolean bSourcesValid
= AL_TRUE
;
1280 pContext
= GetContextSuspended();
1281 if(!pContext
) return;
1285 // Check that all the Sources are valid
1286 for(i
= 0; i
< n
; i
++)
1288 if(!alIsSource(pSourceList
[i
]))
1290 alSetError(AL_INVALID_NAME
);
1291 bSourcesValid
= AL_FALSE
;
1298 for(i
= 0; i
< n
; i
++)
1300 // Assume Source won't need to play
1303 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]);
1305 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1306 ALBufferList
= pSource
->queue
;
1309 if(ALBufferList
->buffer
!= NULL
&& ALBufferList
->buffer
->size
)
1314 ALBufferList
= ALBufferList
->next
;
1319 for(j
= 0;j
< OUTPUTCHANNELS
;j
++)
1320 pSource
->DryGains
[j
] = 0.0f
;
1321 for(j
= 0;j
< MAX_SENDS
;j
++)
1322 pSource
->WetGains
[j
] = 0.0f
;
1324 if(pSource
->state
!= AL_PAUSED
)
1326 pSource
->state
= AL_PLAYING
;
1327 pSource
->position
= 0;
1328 pSource
->position_fraction
= 0;
1329 pSource
->BuffersPlayed
= 0;
1331 pSource
->Buffer
= pSource
->queue
->buffer
;
1333 // Make sure all the Buffers in the queue are marked as PENDING
1334 ALBufferList
= pSource
->queue
;
1337 ALBufferList
->bufferstate
= PENDING
;
1338 ALBufferList
= ALBufferList
->next
;
1342 pSource
->state
= AL_PLAYING
;
1344 // Check if an Offset has been set
1345 if(pSource
->lOffset
)
1346 ApplyOffset(pSource
, AL_FALSE
);
1348 if(pSource
->BuffersPlayed
== 0 && pSource
->position
== 0 &&
1349 pSource
->position_fraction
== 0)
1350 pSource
->FirstStart
= AL_TRUE
;
1352 pSource
->FirstStart
= AL_FALSE
;
1354 // If device is disconnected, go right to stopped
1355 if(!pContext
->Device
->Connected
)
1357 pSource
->state
= AL_STOPPED
;
1358 pSource
->BuffersPlayed
= pSource
->BuffersInQueue
;
1359 ALBufferList
= pSource
->queue
;
1360 while(ALBufferList
!= NULL
)
1362 ALBufferList
->bufferstate
= PROCESSED
;
1363 ALBufferList
= ALBufferList
->next
;
1365 pSource
->position
= 0;
1366 pSource
->position_fraction
= 0;
1371 // If there is a queue (must all be NULL or Zero length Buffers) mark them all as processed
1372 ALBufferList
= pSource
->queue
;
1375 ALBufferList
->bufferstate
= PROCESSED
;
1376 ALBufferList
= ALBufferList
->next
;
1379 pSource
->BuffersPlayed
= pSource
->BuffersInQueue
;
1386 // sources is a NULL pointer
1387 alSetError(AL_INVALID_VALUE
);
1390 ProcessContext(pContext
);
1393 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1395 alSourcePausev(1, &source
);
1399 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1401 ALCcontext
*Context
;
1404 ALboolean bSourcesValid
= AL_TRUE
;
1406 Context
= GetContextSuspended();
1407 if(!Context
) return;
1411 // Check all the Sources are valid
1414 if(!alIsSource(sources
[i
]))
1416 alSetError(AL_INVALID_NAME
);
1417 bSourcesValid
= AL_FALSE
;
1424 for(i
= 0;i
< n
;i
++)
1426 Source
= (ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]);
1427 if(Source
->state
== AL_PLAYING
)
1428 Source
->state
= AL_PAUSED
;
1434 // sources is a NULL pointer
1435 alSetError(AL_INVALID_VALUE
);
1438 ProcessContext(Context
);
1441 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1443 alSourceStopv(1, &source
);
1447 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1449 ALCcontext
*Context
;
1452 ALbufferlistitem
*ALBufferListItem
;
1453 ALboolean bSourcesValid
= AL_TRUE
;
1455 Context
= GetContextSuspended();
1456 if(!Context
) return;
1460 // Check all the Sources are valid
1461 for(i
= 0;i
< n
;i
++)
1463 if(!alIsSource(sources
[i
]))
1465 alSetError(AL_INVALID_NAME
);
1466 bSourcesValid
= AL_FALSE
;
1473 for(i
= 0;i
< n
;i
++)
1475 Source
= (ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]);
1476 if(Source
->state
!= AL_INITIAL
)
1478 Source
->state
= AL_STOPPED
;
1479 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1480 ALBufferListItem
= Source
->queue
;
1481 while(ALBufferListItem
!= NULL
)
1483 ALBufferListItem
->bufferstate
= PROCESSED
;
1484 ALBufferListItem
= ALBufferListItem
->next
;
1487 Source
->lOffset
= 0;
1493 // sources is a NULL pointer
1494 alSetError(AL_INVALID_VALUE
);
1497 ProcessContext(Context
);
1500 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1502 alSourceRewindv(1, &source
);
1506 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1508 ALCcontext
*Context
;
1511 ALbufferlistitem
*ALBufferListItem
;
1512 ALboolean bSourcesValid
= AL_TRUE
;
1514 Context
= GetContextSuspended();
1515 if(!Context
) return;
1519 // Check all the Sources are valid
1520 for(i
= 0;i
< n
;i
++)
1522 if(!alIsSource(sources
[i
]))
1524 alSetError(AL_INVALID_NAME
);
1525 bSourcesValid
= AL_FALSE
;
1532 for(i
= 0;i
< n
;i
++)
1534 Source
= (ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]);
1535 if(Source
->state
!= AL_INITIAL
)
1537 Source
->state
= AL_INITIAL
;
1538 Source
->position
= 0;
1539 Source
->position_fraction
= 0;
1540 Source
->BuffersPlayed
= 0;
1541 ALBufferListItem
= Source
->queue
;
1542 while(ALBufferListItem
!= NULL
)
1544 ALBufferListItem
->bufferstate
= PENDING
;
1545 ALBufferListItem
= ALBufferListItem
->next
;
1548 Source
->Buffer
= Source
->queue
->buffer
;
1550 Source
->lOffset
= 0;
1556 // sources is a NULL pointer
1557 alSetError(AL_INVALID_VALUE
);
1560 ProcessContext(Context
);
1564 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1566 ALCcontext
*Context
;
1569 ALbufferlistitem
*ALBufferList
;
1570 ALbufferlistitem
*ALBufferListStart
;
1573 ALboolean bBuffersValid
= AL_TRUE
;
1578 Context
= GetContextSuspended();
1579 if(!Context
) return;
1581 // Check that all buffers are valid or zero and that the source is valid
1583 // Check that this is a valid source
1584 if(alIsSource(source
))
1586 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1588 // Check that this is not a STATIC Source
1589 if(ALSource
->lSourceType
!= AL_STATIC
)
1594 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1595 ALBufferList
= ALSource
->queue
;
1598 if (ALBufferList
->buffer
)
1600 iFrequency
= ALBufferList
->buffer
->frequency
;
1601 iFormat
= ALBufferList
->buffer
->format
;
1604 ALBufferList
= ALBufferList
->next
;
1607 for(i
= 0; i
< n
; i
++)
1611 if(!alIsBuffer(buffers
[i
]))
1613 alSetError(AL_INVALID_NAME
);
1614 bBuffersValid
= AL_FALSE
;
1620 buffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]);
1621 if(iFrequency
== -1 && iFormat
== -1)
1623 iFrequency
= buffer
->frequency
;
1624 iFormat
= buffer
->format
;
1626 else if(iFrequency
!= buffer
->frequency
||
1627 iFormat
!= buffer
->format
)
1629 alSetError(AL_INVALID_OPERATION
);
1630 bBuffersValid
= AL_FALSE
;
1637 ALbuffer
*buffer
= NULL
;
1639 // Change Source Type
1640 ALSource
->lSourceType
= AL_STREAMING
;
1643 buffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]);
1645 // All buffers are valid - so add them to the list
1646 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1647 ALBufferListStart
->buffer
= buffer
;
1648 ALBufferListStart
->bufferstate
= PENDING
;
1649 ALBufferListStart
->flag
= 0;
1650 ALBufferListStart
->next
= NULL
;
1652 // Increment reference counter for buffer
1653 if(buffer
) buffer
->refcount
++;
1655 ALBufferList
= ALBufferListStart
;
1657 for(i
= 1; i
< n
; i
++)
1660 buffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]);
1662 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1663 ALBufferList
->next
->buffer
= buffer
;
1664 ALBufferList
->next
->bufferstate
= PENDING
;
1665 ALBufferList
->next
->flag
= 0;
1666 ALBufferList
->next
->next
= NULL
;
1668 // Increment reference counter for buffer
1669 if(buffer
) buffer
->refcount
++;
1671 ALBufferList
= ALBufferList
->next
;
1674 if(ALSource
->queue
== NULL
)
1676 ALSource
->queue
= ALBufferListStart
;
1677 // Update Current Buffer
1678 ALSource
->Buffer
= ALBufferListStart
->buffer
;
1682 // Find end of queue
1683 ALBufferList
= ALSource
->queue
;
1684 while(ALBufferList
->next
!= NULL
)
1685 ALBufferList
= ALBufferList
->next
;
1687 ALBufferList
->next
= ALBufferListStart
;
1690 // Update number of buffers in queue
1691 ALSource
->BuffersInQueue
+= n
;
1696 // Invalid Source Type (can't queue on a Static Source)
1697 alSetError(AL_INVALID_OPERATION
);
1702 // Invalid Source Name
1703 alSetError(AL_INVALID_NAME
);
1706 ProcessContext(Context
);
1710 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1711 // an array of buffer IDs that are to be filled with the names of the buffers removed
1712 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1714 ALCcontext
*Context
;
1717 ALbufferlistitem
*ALBufferList
;
1718 ALboolean bBuffersProcessed
;
1723 bBuffersProcessed
= AL_TRUE
;
1725 Context
= GetContextSuspended();
1726 if(!Context
) return;
1728 if(alIsSource(source
))
1730 ALSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(source
);
1732 // Check that all 'n' buffers have been processed
1733 ALBufferList
= ALSource
->queue
;
1734 for(i
= 0; i
< n
; i
++)
1736 if(ALBufferList
!= NULL
&& ALBufferList
->bufferstate
== PROCESSED
)
1738 ALBufferList
= ALBufferList
->next
;
1742 bBuffersProcessed
= AL_FALSE
;
1747 // If all 'n' buffers have been processed, remove them from the queue
1748 if(bBuffersProcessed
)
1750 for(i
= 0; i
< n
; i
++)
1752 ALBufferList
= ALSource
->queue
;
1754 ALSource
->queue
= ALBufferList
->next
;
1755 // Record name of buffer
1756 buffers
[i
] = ALBufferList
->buffer
->buffer
;
1757 // Decrement buffer reference counter
1758 if(ALBufferList
->buffer
)
1759 ALBufferList
->buffer
->refcount
--;
1761 // Release memory for buffer list item
1763 ALSource
->BuffersInQueue
--;
1766 if(ALSource
->state
!= AL_PLAYING
)
1769 ALSource
->Buffer
= ALSource
->queue
->buffer
;
1771 ALSource
->Buffer
= NULL
;
1774 if((ALuint
)n
> ALSource
->BuffersPlayed
)
1775 ALSource
->BuffersPlayed
= 0;
1777 ALSource
->BuffersPlayed
-= n
;
1781 // Some buffers can't be unqueue because they have not been processed
1782 alSetError(AL_INVALID_VALUE
);
1787 // Invalid Source Name
1788 alSetError(AL_INVALID_NAME
);
1791 ProcessContext(Context
);
1795 static ALvoid
InitSourceParams(ALCcontext
*Context
, ALsource
*pSource
)
1797 pSource
->flInnerAngle
= 360.0f
;
1798 pSource
->flOuterAngle
= 360.0f
;
1799 pSource
->flPitch
= 1.0f
;
1800 pSource
->vPosition
[0] = 0.0f
;
1801 pSource
->vPosition
[1] = 0.0f
;
1802 pSource
->vPosition
[2] = 0.0f
;
1803 pSource
->vOrientation
[0] = 0.0f
;
1804 pSource
->vOrientation
[1] = 0.0f
;
1805 pSource
->vOrientation
[2] = 0.0f
;
1806 pSource
->vVelocity
[0] = 0.0f
;
1807 pSource
->vVelocity
[1] = 0.0f
;
1808 pSource
->vVelocity
[2] = 0.0f
;
1809 pSource
->flRefDistance
= 1.0f
;
1810 pSource
->flMaxDistance
= FLT_MAX
;
1811 pSource
->flRollOffFactor
= 1.0f
;
1812 pSource
->bLooping
= AL_FALSE
;
1813 pSource
->flGain
= 1.0f
;
1814 pSource
->flMinGain
= 0.0f
;
1815 pSource
->flMaxGain
= 1.0f
;
1816 pSource
->flOuterGain
= 0.0f
;
1817 pSource
->OuterGainHF
= 1.0f
;
1819 pSource
->DryGainHFAuto
= AL_TRUE
;
1820 pSource
->WetGainAuto
= AL_TRUE
;
1821 pSource
->WetGainHFAuto
= AL_TRUE
;
1822 pSource
->AirAbsorptionFactor
= 0.0f
;
1823 pSource
->RoomRolloffFactor
= 0.0f
;
1824 pSource
->DopplerFactor
= 1.0f
;
1826 pSource
->DistanceModel
= Context
->DistanceModel
;
1828 pSource
->state
= AL_INITIAL
;
1829 pSource
->lSourceType
= AL_UNDETERMINED
;
1831 pSource
->Buffer
= NULL
;
1838 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1839 The offset is relative to the start of the queue (not the start of the current buffer)
1841 static ALboolean
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
, ALuint updateSize
)
1843 ALbufferlistitem
*pBufferList
;
1845 ALfloat flBufferFreq
;
1847 ALint readPos
, writePos
;
1848 ALenum eOriginalFormat
;
1849 ALboolean bReturn
= AL_TRUE
;
1850 ALint lTotalBufferDataSize
;
1852 if((pSource
->state
== AL_PLAYING
|| pSource
->state
== AL_PAUSED
) && pSource
->Buffer
)
1854 pBuffer
= pSource
->Buffer
;
1855 // Get Current Buffer Size and frequency (in milliseconds)
1856 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
1857 eOriginalFormat
= pBuffer
->eOriginalFormat
;
1858 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
1860 // Get Current BytesPlayed
1861 readPos
= pSource
->position
* lChannels
* 2; // NOTE : This is the byte offset into the *current* buffer
1862 // Add byte length of any processed buffers in the queue
1863 pBufferList
= pSource
->queue
;
1864 while(pBufferList
&& pBufferList
->bufferstate
== PROCESSED
)
1866 readPos
+= pBufferList
->buffer
->size
;
1867 pBufferList
= pBufferList
->next
;
1870 if(pSource
->state
== AL_PLAYING
)
1871 writePos
= readPos
+ (updateSize
* lChannels
* 2);
1875 lTotalBufferDataSize
= 0;
1876 pBufferList
= pSource
->queue
;
1879 if (pBufferList
->buffer
)
1880 lTotalBufferDataSize
+= pBufferList
->buffer
->size
;
1881 pBufferList
= pBufferList
->next
;
1884 if (pSource
->bLooping
)
1889 readPos
%= lTotalBufferDataSize
;
1893 writePos
%= lTotalBufferDataSize
;
1897 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
1900 else if(readPos
> lTotalBufferDataSize
)
1901 readPos
= lTotalBufferDataSize
;
1904 else if(writePos
> lTotalBufferDataSize
)
1905 writePos
= lTotalBufferDataSize
;
1911 case AL_SEC_RW_OFFSETS_EXT
:
1912 pflOffset
[0] = (ALfloat
)readPos
/ (lChannels
* 2.0f
* flBufferFreq
);
1913 pflOffset
[1] = (ALfloat
)writePos
/ (lChannels
* 2.0f
* flBufferFreq
);
1915 case AL_SAMPLE_OFFSET
:
1916 case AL_SAMPLE_RW_OFFSETS_EXT
:
1917 pflOffset
[0] = (ALfloat
)(readPos
/ (lChannels
* 2));
1918 pflOffset
[1] = (ALfloat
)(writePos
/ (lChannels
* 2));
1920 case AL_BYTE_OFFSET
:
1921 case AL_BYTE_RW_OFFSETS_EXT
:
1922 // Take into account the original format of the Buffer
1923 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
1924 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
1926 // Round down to nearest ADPCM block
1927 pflOffset
[0] = (ALfloat
)((readPos
/ (65 * 2 * lChannels
)) * 36 * lChannels
);
1928 if(pSource
->state
== AL_PLAYING
)
1930 // Round up to nearest ADPCM block
1931 pflOffset
[1] = (ALfloat
)(((writePos
+ (65 * 2 * lChannels
) - 1) / (65 * 2 * lChannels
)) * 36 * lChannels
);
1934 pflOffset
[1] = pflOffset
[0];
1936 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
1938 pflOffset
[0] = (ALfloat
)(readPos
>> 2);
1939 pflOffset
[1] = (ALfloat
)(writePos
>> 2);
1941 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
1943 pflOffset
[0] = (ALfloat
)(readPos
>> 1);
1944 pflOffset
[1] = (ALfloat
)(writePos
>> 1);
1946 else if (aluBytesFromFormat(eOriginalFormat
) == 1)
1948 pflOffset
[0] = (ALfloat
)(readPos
>> 1);
1949 pflOffset
[1] = (ALfloat
)(writePos
>> 1);
1951 else if (aluBytesFromFormat(eOriginalFormat
) == 4)
1953 pflOffset
[0] = (ALfloat
)(readPos
<< 1);
1954 pflOffset
[1] = (ALfloat
)(writePos
<< 1);
1958 pflOffset
[0] = (ALfloat
)readPos
;
1959 pflOffset
[1] = (ALfloat
)writePos
;
1966 pflOffset
[0] = 0.0f
;
1967 pflOffset
[1] = 0.0f
;
1977 Apply a playback offset to the Source. This function will update the queue (to correctly
1978 mark buffers as 'pending' or 'processed' depending upon the new offset.
1980 static void ApplyOffset(ALsource
*pSource
, ALboolean bUpdateContext
)
1982 ALbufferlistitem
*pBufferList
;
1984 ALint lBufferSize
, lTotalBufferSize
;
1987 // Get true byte offset
1988 lByteOffset
= GetByteOffset(pSource
);
1990 // If this is a valid offset apply it
1991 if (lByteOffset
!= -1)
1993 // Sort out the queue (pending and processed states)
1994 pBufferList
= pSource
->queue
;
1995 lTotalBufferSize
= 0;
1996 pSource
->BuffersPlayed
= 0;
1999 pBuffer
= pBufferList
->buffer
;
2000 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
2002 if ((lTotalBufferSize
+ lBufferSize
) <= lByteOffset
)
2004 // Offset is past this buffer so increment BuffersPlayed and if the Source is NOT looping
2005 // update the state to PROCESSED
2006 pSource
->BuffersPlayed
++;
2008 if (!pSource
->bLooping
)
2009 pBufferList
->bufferstate
= PROCESSED
;
2011 else if (lTotalBufferSize
<= lByteOffset
)
2013 // Offset is within this buffer
2014 pBufferList
->bufferstate
= PENDING
;
2016 // Set Current Buffer
2017 pSource
->Buffer
= pBufferList
->buffer
;
2019 // SW Mixer Positions are in Samples
2020 pSource
->position
= (lByteOffset
- lTotalBufferSize
) /
2021 aluBytesFromFormat(pBuffer
->format
) /
2022 aluChannelsFromFormat(pBuffer
->format
);
2026 // Offset is before this buffer, so mark as pending
2027 pBufferList
->bufferstate
= PENDING
;
2030 // Increment the TotalBufferSize
2031 lTotalBufferSize
+= lBufferSize
;
2033 // Move on to next buffer in the Queue
2034 pBufferList
= pBufferList
->next
;
2040 alSetError(AL_INVALID_VALUE
);
2044 pSource
->lOffset
= 0;
2051 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2052 offset supplied by the application). This takes into account the fact that the buffer format
2053 may have been modifed by AL (e.g 8bit samples are converted to 16bit)
2055 static ALint
GetByteOffset(ALsource
*pSource
)
2057 ALbuffer
*pBuffer
= NULL
;
2058 ALbufferlistitem
*pBufferList
;
2059 ALfloat flBufferFreq
;
2061 ALint lByteOffset
= -1;
2062 ALint lTotalBufferDataSize
;
2064 // Find the first non-NULL Buffer in the Queue
2065 pBufferList
= pSource
->queue
;
2068 if (pBufferList
->buffer
)
2070 pBuffer
= pBufferList
->buffer
;
2073 pBufferList
= pBufferList
->next
;
2078 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2079 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2081 // Determine the ByteOffset (and ensure it is block aligned)
2082 switch (pSource
->lOffsetType
)
2084 case AL_BYTE_OFFSET
:
2085 // Take into consideration the original format
2086 if ((pBuffer
->eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
2087 (pBuffer
->eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
2089 // Round down to nearest ADPCM block
2090 lByteOffset
= (pSource
->lOffset
/ (36 * lChannels
)) * 36 * lChannels
;
2091 // Multiply by compression rate
2092 lByteOffset
= (ALint
)(3.6111f
* (ALfloat
)lByteOffset
);
2093 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2095 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR8
)
2097 lByteOffset
= pSource
->lOffset
* 4;
2098 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2100 else if (pBuffer
->eOriginalFormat
== AL_FORMAT_REAR16
)
2102 lByteOffset
= pSource
->lOffset
* 2;
2103 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2105 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 1)
2107 lByteOffset
= pSource
->lOffset
* 2;
2108 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2110 else if (aluBytesFromFormat(pBuffer
->eOriginalFormat
) == 4)
2112 lByteOffset
= pSource
->lOffset
/ 2;
2113 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2117 lByteOffset
= pSource
->lOffset
;
2118 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2122 case AL_SAMPLE_OFFSET
:
2123 lByteOffset
= pSource
->lOffset
* lChannels
* 2;
2127 // Note - lOffset is internally stored as Milliseconds
2128 lByteOffset
= (ALint
)(pSource
->lOffset
* lChannels
* 2.0f
* flBufferFreq
/ 1000.0f
);
2129 lByteOffset
-= (lByteOffset
% (lChannels
* 2));
2133 lTotalBufferDataSize
= 0;
2134 pBufferList
= pSource
->queue
;
2137 if (pBufferList
->buffer
)
2138 lTotalBufferDataSize
+= pBufferList
->buffer
->size
;
2139 pBufferList
= pBufferList
->next
;
2142 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2143 if (lByteOffset
>= lTotalBufferDataSize
)
2151 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2153 while(Context
->Source
)
2155 ALsource
*temp
= Context
->Source
;
2156 Context
->Source
= Context
->Source
->next
;
2158 // Release source structure
2159 ALTHUNK_REMOVEENTRY(temp
->source
);
2160 memset(temp
, 0, sizeof(ALsource
));
2163 Context
->SourceCount
= 0;