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 ALvoid
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
, ALfloat updateLen
);
37 static ALboolean
ApplyOffset(ALsource
*pSource
);
38 static ALint
GetByteOffset(ALsource
*pSource
);
40 DECL_VERIFIER(Source
, ALsource
, source
)
41 DECL_VERIFIER(Buffer
, ALbuffer
, buffer
)
42 DECL_VERIFIER(Filter
, ALfilter
, filter
)
43 DECL_VERIFIER(EffectSlot
, ALeffectslot
, effectslot
)
45 ALAPI ALvoid ALAPIENTRY
alGenSources(ALsizei n
,ALuint
*sources
)
51 Context
= GetContextSuspended();
56 Device
= Context
->Device
;
58 // Check that enough memory has been allocted in the 'sources' array for n Sources
59 if(!IsBadWritePtr((void*)sources
, n
* sizeof(ALuint
)))
61 // Check that the requested number of sources can be generated
62 if((Context
->SourceCount
+ n
) <= Device
->MaxNoOfSources
)
64 ALsource
**list
= &Context
->SourceList
;
66 list
= &(*list
)->next
;
68 // Add additional sources to the list (Source->next points to the location for the next Source structure)
71 *list
= calloc(1, sizeof(ALsource
));
74 alDeleteSources(i
, sources
);
75 alSetError(Context
, AL_OUT_OF_MEMORY
);
79 sources
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
80 (*list
)->source
= sources
[i
];
82 InitSourceParams(*list
);
83 Context
->SourceCount
++;
86 list
= &(*list
)->next
;
91 // Not enough resources to create the Sources
92 alSetError(Context
, AL_INVALID_VALUE
);
98 alSetError(Context
, AL_INVALID_VALUE
);
102 ProcessContext(Context
);
106 ALAPI ALvoid ALAPIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
113 ALbufferlistitem
*ALBufferList
;
114 ALboolean bSourcesValid
= AL_TRUE
;
116 Context
= GetContextSuspended();
121 Device
= Context
->Device
;
123 // Check that all Sources are valid (and can therefore be deleted)
124 for (i
= 0; i
< n
; i
++)
126 if(VerifySource(Context
->SourceList
, sources
[i
]) == NULL
)
128 alSetError(Context
, AL_INVALID_NAME
);
129 bSourcesValid
= AL_FALSE
;
136 // All Sources are valid, and can be deleted
137 for(i
= 0; i
< n
; i
++)
139 // Recheck that the Source is valid, because there could be duplicated Source names
140 if((ALSource
=VerifySource(Context
->SourceList
, sources
[i
])) != NULL
)
142 // For each buffer in the source's queue, decrement its reference counter and remove it
143 while (ALSource
->queue
!= NULL
)
145 ALBufferList
= ALSource
->queue
;
146 // Decrement buffer's reference counter
147 if(ALBufferList
->buffer
!= NULL
)
148 ALBufferList
->buffer
->refcount
--;
149 // Update queue to point to next element in list
150 ALSource
->queue
= ALBufferList
->next
;
151 // Release memory allocated for buffer list item
155 for(j
= 0;j
< MAX_SENDS
;++j
)
157 if(ALSource
->Send
[j
].Slot
)
158 ALSource
->Send
[j
].Slot
->refcount
--;
159 ALSource
->Send
[j
].Slot
= NULL
;
162 // Decrement Source count
163 Context
->SourceCount
--;
165 // Remove Source from list of Sources
166 list
= &Context
->SourceList
;
167 while(*list
&& *list
!= ALSource
)
168 list
= &(*list
)->next
;
171 *list
= (*list
)->next
;
172 ALTHUNK_REMOVEENTRY(ALSource
->source
);
174 memset(ALSource
,0,sizeof(ALsource
));
181 alSetError(Context
, AL_INVALID_VALUE
);
183 ProcessContext(Context
);
187 ALAPI ALboolean ALAPIENTRY
alIsSource(ALuint source
)
192 Context
= GetContextSuspended();
193 if(!Context
) return AL_FALSE
;
195 result
= (VerifySource(Context
->SourceList
, source
) ? AL_TRUE
: AL_FALSE
);
197 ProcessContext(Context
);
203 ALAPI ALvoid ALAPIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
205 ALCcontext
*pContext
;
208 pContext
= GetContextSuspended();
209 if(!pContext
) return;
211 if((pSource
=VerifySource(pContext
->SourceList
, source
)) != NULL
)
218 pSource
->flPitch
= flValue
;
219 if(pSource
->flPitch
< 0.001f
)
220 pSource
->flPitch
= 0.001f
;
221 pSource
->NeedsUpdate
= AL_TRUE
;
224 alSetError(pContext
, AL_INVALID_VALUE
);
227 case AL_CONE_INNER_ANGLE
:
228 if(flValue
>= 0.0f
&& flValue
<= 360.0f
)
230 pSource
->flInnerAngle
= flValue
;
231 pSource
->NeedsUpdate
= AL_TRUE
;
234 alSetError(pContext
, AL_INVALID_VALUE
);
237 case AL_CONE_OUTER_ANGLE
:
238 if(flValue
>= 0.0f
&& flValue
<= 360.0f
)
240 pSource
->flOuterAngle
= flValue
;
241 pSource
->NeedsUpdate
= AL_TRUE
;
244 alSetError(pContext
, AL_INVALID_VALUE
);
250 pSource
->flGain
= flValue
;
251 pSource
->NeedsUpdate
= AL_TRUE
;
254 alSetError(pContext
, AL_INVALID_VALUE
);
257 case AL_MAX_DISTANCE
:
260 pSource
->flMaxDistance
= flValue
;
261 pSource
->NeedsUpdate
= AL_TRUE
;
264 alSetError(pContext
, AL_INVALID_VALUE
);
267 case AL_ROLLOFF_FACTOR
:
270 pSource
->flRollOffFactor
= flValue
;
271 pSource
->NeedsUpdate
= AL_TRUE
;
274 alSetError(pContext
, AL_INVALID_VALUE
);
277 case AL_REFERENCE_DISTANCE
:
280 pSource
->flRefDistance
= flValue
;
281 pSource
->NeedsUpdate
= AL_TRUE
;
284 alSetError(pContext
, AL_INVALID_VALUE
);
288 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
290 pSource
->flMinGain
= flValue
;
291 pSource
->NeedsUpdate
= AL_TRUE
;
294 alSetError(pContext
, AL_INVALID_VALUE
);
298 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
300 pSource
->flMaxGain
= flValue
;
301 pSource
->NeedsUpdate
= AL_TRUE
;
304 alSetError(pContext
, AL_INVALID_VALUE
);
307 case AL_CONE_OUTER_GAIN
:
308 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
310 pSource
->flOuterGain
= flValue
;
311 pSource
->NeedsUpdate
= AL_TRUE
;
314 alSetError(pContext
, AL_INVALID_VALUE
);
317 case AL_CONE_OUTER_GAINHF
:
318 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
320 pSource
->OuterGainHF
= flValue
;
321 pSource
->NeedsUpdate
= AL_TRUE
;
324 alSetError(pContext
, AL_INVALID_VALUE
);
327 case AL_AIR_ABSORPTION_FACTOR
:
328 if(flValue
>= 0.0f
&& flValue
<= 10.0f
)
330 pSource
->AirAbsorptionFactor
= flValue
;
331 pSource
->NeedsUpdate
= AL_TRUE
;
334 alSetError(pContext
, AL_INVALID_VALUE
);
337 case AL_ROOM_ROLLOFF_FACTOR
:
338 if(flValue
>= 0.0f
&& flValue
<= 10.0f
)
340 pSource
->RoomRolloffFactor
= flValue
;
341 pSource
->NeedsUpdate
= AL_TRUE
;
344 alSetError(pContext
, AL_INVALID_VALUE
);
347 case AL_DOPPLER_FACTOR
:
348 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
350 pSource
->DopplerFactor
= flValue
;
351 pSource
->NeedsUpdate
= AL_TRUE
;
354 alSetError(pContext
, AL_INVALID_VALUE
);
358 case AL_SAMPLE_OFFSET
:
362 pSource
->lOffsetType
= eParam
;
364 // Store Offset (convert Seconds into Milliseconds)
365 if(eParam
== AL_SEC_OFFSET
)
366 pSource
->lOffset
= (ALint
)(flValue
* 1000.0f
);
368 pSource
->lOffset
= (ALint
)flValue
;
370 if ((pSource
->state
== AL_PLAYING
) || (pSource
->state
== AL_PAUSED
))
372 if(ApplyOffset(pSource
) == AL_FALSE
)
373 alSetError(pContext
, AL_INVALID_VALUE
);
377 alSetError(pContext
, AL_INVALID_VALUE
);
381 alSetError(pContext
, AL_INVALID_ENUM
);
387 // Invalid Source Name
388 alSetError(pContext
, AL_INVALID_NAME
);
391 ProcessContext(pContext
);
395 ALAPI ALvoid ALAPIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
397 ALCcontext
*pContext
;
400 pContext
= GetContextSuspended();
401 if(!pContext
) return;
403 if((pSource
=VerifySource(pContext
->SourceList
, source
)) != NULL
)
408 pSource
->vPosition
[0] = flValue1
;
409 pSource
->vPosition
[1] = flValue2
;
410 pSource
->vPosition
[2] = flValue3
;
411 pSource
->NeedsUpdate
= AL_TRUE
;
415 pSource
->vVelocity
[0] = flValue1
;
416 pSource
->vVelocity
[1] = flValue2
;
417 pSource
->vVelocity
[2] = flValue3
;
418 pSource
->NeedsUpdate
= AL_TRUE
;
422 pSource
->vOrientation
[0] = flValue1
;
423 pSource
->vOrientation
[1] = flValue2
;
424 pSource
->vOrientation
[2] = flValue3
;
425 pSource
->NeedsUpdate
= AL_TRUE
;
429 alSetError(pContext
, AL_INVALID_ENUM
);
434 alSetError(pContext
, AL_INVALID_NAME
);
436 ProcessContext(pContext
);
440 ALAPI ALvoid ALAPIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
442 ALCcontext
*pContext
;
444 pContext
= GetContextSuspended();
445 if(!pContext
) return;
449 if(VerifySource(pContext
->SourceList
, source
) != NULL
)
454 case AL_CONE_INNER_ANGLE
:
455 case AL_CONE_OUTER_ANGLE
:
457 case AL_MAX_DISTANCE
:
458 case AL_ROLLOFF_FACTOR
:
459 case AL_REFERENCE_DISTANCE
:
462 case AL_CONE_OUTER_GAIN
:
463 case AL_CONE_OUTER_GAINHF
:
465 case AL_SAMPLE_OFFSET
:
467 case AL_AIR_ABSORPTION_FACTOR
:
468 case AL_ROOM_ROLLOFF_FACTOR
:
469 alSourcef(source
, eParam
, pflValues
[0]);
475 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
479 alSetError(pContext
, AL_INVALID_ENUM
);
484 alSetError(pContext
, AL_INVALID_NAME
);
487 alSetError(pContext
, AL_INVALID_VALUE
);
489 ProcessContext(pContext
);
493 ALAPI ALvoid ALAPIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
495 ALCcontext
*pContext
;
497 ALbufferlistitem
*pALBufferListItem
;
499 pContext
= GetContextSuspended();
500 if(!pContext
) return;
502 if((pSource
=VerifySource(pContext
->SourceList
, source
)) != NULL
)
504 ALCdevice
*device
= pContext
->Device
;
508 case AL_MAX_DISTANCE
:
509 case AL_ROLLOFF_FACTOR
:
510 case AL_CONE_INNER_ANGLE
:
511 case AL_CONE_OUTER_ANGLE
:
512 case AL_REFERENCE_DISTANCE
:
513 alSourcef(source
, eParam
, (ALfloat
)lValue
);
516 case AL_SOURCE_RELATIVE
:
517 if(lValue
== AL_FALSE
|| lValue
== AL_TRUE
)
519 pSource
->bHeadRelative
= (ALboolean
)lValue
;
520 pSource
->NeedsUpdate
= AL_TRUE
;
523 alSetError(pContext
, AL_INVALID_VALUE
);
527 if(lValue
== AL_FALSE
|| lValue
== AL_TRUE
)
528 pSource
->bLooping
= (ALboolean
)lValue
;
530 alSetError(pContext
, AL_INVALID_VALUE
);
534 if(pSource
->state
== AL_STOPPED
|| pSource
->state
== AL_INITIAL
)
536 ALbuffer
*buffer
= NULL
;
539 (buffer
=VerifyBuffer(device
->BufferList
, lValue
)) != NULL
)
541 // Remove all elements in the queue
542 while(pSource
->queue
!= NULL
)
544 pALBufferListItem
= pSource
->queue
;
545 pSource
->queue
= pALBufferListItem
->next
;
546 // Decrement reference counter for buffer
547 if(pALBufferListItem
->buffer
)
548 pALBufferListItem
->buffer
->refcount
--;
549 // Release memory for buffer list item
550 free(pALBufferListItem
);
551 // Decrement the number of buffers in the queue
552 pSource
->BuffersInQueue
--;
555 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
558 // Source is now in STATIC mode
559 pSource
->lSourceType
= AL_STATIC
;
561 // Add the selected buffer to the queue
562 pALBufferListItem
= malloc(sizeof(ALbufferlistitem
));
563 pALBufferListItem
->buffer
= buffer
;
564 pALBufferListItem
->next
= NULL
;
566 pSource
->queue
= pALBufferListItem
;
567 pSource
->BuffersInQueue
= 1;
569 // Increment reference counter for buffer
574 // Source is now in UNDETERMINED mode
575 pSource
->lSourceType
= AL_UNDETERMINED
;
576 pSource
->BuffersPlayed
= 0;
579 // Update AL_BUFFER parameter
580 pSource
->Buffer
= buffer
;
581 pSource
->NeedsUpdate
= AL_TRUE
;
584 alSetError(pContext
, AL_INVALID_VALUE
);
587 alSetError(pContext
, AL_INVALID_OPERATION
);
590 case AL_SOURCE_STATE
:
592 alSetError(pContext
, AL_INVALID_OPERATION
);
596 case AL_SAMPLE_OFFSET
:
600 pSource
->lOffsetType
= eParam
;
602 // Store Offset (convert Seconds into Milliseconds)
603 if(eParam
== AL_SEC_OFFSET
)
604 pSource
->lOffset
= lValue
* 1000;
606 pSource
->lOffset
= lValue
;
608 if(pSource
->state
== AL_PLAYING
|| pSource
->state
== AL_PAUSED
)
610 if(ApplyOffset(pSource
) == AL_FALSE
)
611 alSetError(pContext
, AL_INVALID_VALUE
);
615 alSetError(pContext
, AL_INVALID_VALUE
);
618 case AL_DIRECT_FILTER
: {
619 ALfilter
*filter
= NULL
;
622 (filter
=VerifyFilter(pContext
->Device
->FilterList
, lValue
)) != NULL
)
626 pSource
->DirectFilter
.type
= AL_FILTER_NULL
;
627 pSource
->DirectFilter
.filter
= 0;
630 memcpy(&pSource
->DirectFilter
, filter
, sizeof(*filter
));
631 pSource
->NeedsUpdate
= AL_TRUE
;
634 alSetError(pContext
, AL_INVALID_VALUE
);
637 case AL_DIRECT_FILTER_GAINHF_AUTO
:
638 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
640 pSource
->DryGainHFAuto
= lValue
;
641 pSource
->NeedsUpdate
= AL_TRUE
;
644 alSetError(pContext
, AL_INVALID_VALUE
);
647 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
648 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
650 pSource
->WetGainAuto
= lValue
;
651 pSource
->NeedsUpdate
= AL_TRUE
;
654 alSetError(pContext
, AL_INVALID_VALUE
);
657 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
658 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
660 pSource
->WetGainHFAuto
= lValue
;
661 pSource
->NeedsUpdate
= AL_TRUE
;
664 alSetError(pContext
, AL_INVALID_VALUE
);
667 case AL_DISTANCE_MODEL
:
668 if(lValue
== AL_NONE
||
669 lValue
== AL_INVERSE_DISTANCE
||
670 lValue
== AL_INVERSE_DISTANCE_CLAMPED
||
671 lValue
== AL_LINEAR_DISTANCE
||
672 lValue
== AL_LINEAR_DISTANCE_CLAMPED
||
673 lValue
== AL_EXPONENT_DISTANCE
||
674 lValue
== AL_EXPONENT_DISTANCE_CLAMPED
)
676 pSource
->DistanceModel
= lValue
;
677 if(pContext
->SourceDistanceModel
)
678 pSource
->NeedsUpdate
= AL_TRUE
;
681 alSetError(pContext
, AL_INVALID_VALUE
);
685 alSetError(pContext
, AL_INVALID_ENUM
);
690 alSetError(pContext
, AL_INVALID_NAME
);
692 ProcessContext(pContext
);
696 ALAPI
void ALAPIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
698 ALCcontext
*pContext
;
701 pContext
= GetContextSuspended();
702 if(!pContext
) return;
704 if((pSource
=VerifySource(pContext
->SourceList
, source
)) != NULL
)
706 ALCdevice
*device
= pContext
->Device
;
713 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
716 case AL_AUXILIARY_SEND_FILTER
: {
717 ALeffectslot
*ALEffectSlot
= NULL
;
718 ALfilter
*ALFilter
= NULL
;
720 if((ALuint
)lValue2
< device
->NumAuxSends
&&
722 (ALEffectSlot
=VerifyEffectSlot(pContext
->EffectSlotList
, lValue1
)) != NULL
) &&
724 (ALFilter
=VerifyFilter(device
->FilterList
, lValue3
)) != NULL
))
726 /* Release refcount on the previous slot, and add one for
728 if(pSource
->Send
[lValue2
].Slot
)
729 pSource
->Send
[lValue2
].Slot
->refcount
--;
730 pSource
->Send
[lValue2
].Slot
= ALEffectSlot
;
731 if(pSource
->Send
[lValue2
].Slot
)
732 pSource
->Send
[lValue2
].Slot
->refcount
++;
737 pSource
->Send
[lValue2
].WetFilter
.type
= 0;
738 pSource
->Send
[lValue2
].WetFilter
.filter
= 0;
741 memcpy(&pSource
->Send
[lValue2
].WetFilter
, ALFilter
, sizeof(*ALFilter
));
742 pSource
->NeedsUpdate
= AL_TRUE
;
745 alSetError(pContext
, AL_INVALID_VALUE
);
749 alSetError(pContext
, AL_INVALID_ENUM
);
754 alSetError(pContext
, AL_INVALID_NAME
);
756 ProcessContext(pContext
);
760 ALAPI
void ALAPIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
762 ALCcontext
*pContext
;
764 pContext
= GetContextSuspended();
765 if(!pContext
) return;
769 if(VerifySource(pContext
->SourceList
, source
) != NULL
)
773 case AL_SOURCE_RELATIVE
:
774 case AL_CONE_INNER_ANGLE
:
775 case AL_CONE_OUTER_ANGLE
:
778 case AL_SOURCE_STATE
:
780 case AL_SAMPLE_OFFSET
:
782 case AL_MAX_DISTANCE
:
783 case AL_ROLLOFF_FACTOR
:
784 case AL_REFERENCE_DISTANCE
:
785 case AL_DIRECT_FILTER
:
786 case AL_DIRECT_FILTER_GAINHF_AUTO
:
787 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
788 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
789 case AL_DISTANCE_MODEL
:
790 alSourcei(source
, eParam
, plValues
[0]);
796 case AL_AUXILIARY_SEND_FILTER
:
797 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
801 alSetError(pContext
, AL_INVALID_ENUM
);
806 alSetError(pContext
, AL_INVALID_NAME
);
809 alSetError(pContext
, AL_INVALID_VALUE
);
811 ProcessContext(pContext
);
815 ALAPI ALvoid ALAPIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
817 ALCcontext
*pContext
;
822 pContext
= GetContextSuspended();
823 if(!pContext
) return;
827 if((pSource
=VerifySource(pContext
->SourceList
, source
)) != NULL
)
832 *pflValue
= pSource
->flPitch
;
836 *pflValue
= pSource
->flGain
;
840 *pflValue
= pSource
->flMinGain
;
844 *pflValue
= pSource
->flMaxGain
;
847 case AL_MAX_DISTANCE
:
848 *pflValue
= pSource
->flMaxDistance
;
851 case AL_ROLLOFF_FACTOR
:
852 *pflValue
= pSource
->flRollOffFactor
;
855 case AL_CONE_OUTER_GAIN
:
856 *pflValue
= pSource
->flOuterGain
;
859 case AL_CONE_OUTER_GAINHF
:
860 *pflValue
= pSource
->OuterGainHF
;
864 case AL_SAMPLE_OFFSET
:
866 updateLen
= (ALfloat
)pContext
->Device
->UpdateSize
/
867 pContext
->Device
->Frequency
;
868 GetSourceOffset(pSource
, eParam
, flOffset
, updateLen
);
869 *pflValue
= flOffset
[0];
872 case AL_CONE_INNER_ANGLE
:
873 *pflValue
= pSource
->flInnerAngle
;
876 case AL_CONE_OUTER_ANGLE
:
877 *pflValue
= pSource
->flOuterAngle
;
880 case AL_REFERENCE_DISTANCE
:
881 *pflValue
= pSource
->flRefDistance
;
884 case AL_AIR_ABSORPTION_FACTOR
:
885 *pflValue
= pSource
->AirAbsorptionFactor
;
888 case AL_ROOM_ROLLOFF_FACTOR
:
889 *pflValue
= pSource
->RoomRolloffFactor
;
892 case AL_DOPPLER_FACTOR
:
893 *pflValue
= pSource
->DopplerFactor
;
897 alSetError(pContext
, AL_INVALID_ENUM
);
902 alSetError(pContext
, AL_INVALID_NAME
);
905 alSetError(pContext
, AL_INVALID_VALUE
);
907 ProcessContext(pContext
);
911 ALAPI ALvoid ALAPIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
913 ALCcontext
*pContext
;
916 pContext
= GetContextSuspended();
917 if(!pContext
) return;
919 if(pflValue1
&& pflValue2
&& pflValue3
)
921 if((pSource
=VerifySource(pContext
->SourceList
, source
)) != NULL
)
926 *pflValue1
= pSource
->vPosition
[0];
927 *pflValue2
= pSource
->vPosition
[1];
928 *pflValue3
= pSource
->vPosition
[2];
932 *pflValue1
= pSource
->vVelocity
[0];
933 *pflValue2
= pSource
->vVelocity
[1];
934 *pflValue3
= pSource
->vVelocity
[2];
938 *pflValue1
= pSource
->vOrientation
[0];
939 *pflValue2
= pSource
->vOrientation
[1];
940 *pflValue3
= pSource
->vOrientation
[2];
944 alSetError(pContext
, AL_INVALID_ENUM
);
949 alSetError(pContext
, AL_INVALID_NAME
);
952 alSetError(pContext
, AL_INVALID_VALUE
);
954 ProcessContext(pContext
);
958 ALAPI ALvoid ALAPIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
960 ALCcontext
*pContext
;
965 pContext
= GetContextSuspended();
966 if(!pContext
) return;
970 if((pSource
=VerifySource(pContext
->SourceList
, source
)) != NULL
)
978 case AL_MAX_DISTANCE
:
979 case AL_ROLLOFF_FACTOR
:
980 case AL_DOPPLER_FACTOR
:
981 case AL_CONE_OUTER_GAIN
:
983 case AL_SAMPLE_OFFSET
:
985 case AL_CONE_INNER_ANGLE
:
986 case AL_CONE_OUTER_ANGLE
:
987 case AL_REFERENCE_DISTANCE
:
988 case AL_CONE_OUTER_GAINHF
:
989 case AL_AIR_ABSORPTION_FACTOR
:
990 case AL_ROOM_ROLLOFF_FACTOR
:
991 alGetSourcef(source
, eParam
, pflValues
);
994 case AL_SAMPLE_RW_OFFSETS_EXT
:
995 case AL_BYTE_RW_OFFSETS_EXT
:
996 updateLen
= (ALfloat
)pContext
->Device
->UpdateSize
/
997 pContext
->Device
->Frequency
;
998 GetSourceOffset(pSource
, eParam
, flOffset
, updateLen
);
999 pflValues
[0] = flOffset
[0];
1000 pflValues
[1] = flOffset
[1];
1004 pflValues
[0] = pSource
->vPosition
[0];
1005 pflValues
[1] = pSource
->vPosition
[1];
1006 pflValues
[2] = pSource
->vPosition
[2];
1010 pflValues
[0] = pSource
->vVelocity
[0];
1011 pflValues
[1] = pSource
->vVelocity
[1];
1012 pflValues
[2] = pSource
->vVelocity
[2];
1016 pflValues
[0] = pSource
->vOrientation
[0];
1017 pflValues
[1] = pSource
->vOrientation
[1];
1018 pflValues
[2] = pSource
->vOrientation
[2];
1022 alSetError(pContext
, AL_INVALID_ENUM
);
1027 alSetError(pContext
, AL_INVALID_NAME
);
1030 alSetError(pContext
, AL_INVALID_VALUE
);
1032 ProcessContext(pContext
);
1036 ALAPI ALvoid ALAPIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1038 ALCcontext
*pContext
;
1040 ALfloat flOffset
[2];
1043 pContext
= GetContextSuspended();
1044 if(!pContext
) return;
1048 if((pSource
=VerifySource(pContext
->SourceList
, source
)) != NULL
)
1052 case AL_MAX_DISTANCE
:
1053 *plValue
= (ALint
)pSource
->flMaxDistance
;
1056 case AL_ROLLOFF_FACTOR
:
1057 *plValue
= (ALint
)pSource
->flRollOffFactor
;
1060 case AL_REFERENCE_DISTANCE
:
1061 *plValue
= (ALint
)pSource
->flRefDistance
;
1064 case AL_SOURCE_RELATIVE
:
1065 *plValue
= pSource
->bHeadRelative
;
1068 case AL_CONE_INNER_ANGLE
:
1069 *plValue
= (ALint
)pSource
->flInnerAngle
;
1072 case AL_CONE_OUTER_ANGLE
:
1073 *plValue
= (ALint
)pSource
->flOuterAngle
;
1077 *plValue
= pSource
->bLooping
;
1081 *plValue
= (pSource
->Buffer
? pSource
->Buffer
->buffer
: 0);
1084 case AL_SOURCE_STATE
:
1085 *plValue
= pSource
->state
;
1088 case AL_BUFFERS_QUEUED
:
1089 *plValue
= pSource
->BuffersInQueue
;
1092 case AL_BUFFERS_PROCESSED
:
1093 if(pSource
->bLooping
)
1095 /* Buffers on a looping source are in a perpetual state
1096 * of PENDING, so don't report any as PROCESSED */
1100 *plValue
= pSource
->BuffersPlayed
;
1103 case AL_SOURCE_TYPE
:
1104 *plValue
= pSource
->lSourceType
;
1108 case AL_SAMPLE_OFFSET
:
1109 case AL_BYTE_OFFSET
:
1110 updateLen
= (ALfloat
)pContext
->Device
->UpdateSize
/
1111 pContext
->Device
->Frequency
;
1112 GetSourceOffset(pSource
, eParam
, flOffset
, updateLen
);
1113 *plValue
= (ALint
)flOffset
[0];
1116 case AL_DIRECT_FILTER
:
1117 *plValue
= pSource
->DirectFilter
.filter
;
1120 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1121 *plValue
= pSource
->DryGainHFAuto
;
1124 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1125 *plValue
= pSource
->WetGainAuto
;
1128 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1129 *plValue
= pSource
->WetGainHFAuto
;
1132 case AL_DOPPLER_FACTOR
:
1133 *plValue
= (ALint
)pSource
->DopplerFactor
;
1136 case AL_DISTANCE_MODEL
:
1137 *plValue
= pSource
->DistanceModel
;
1141 alSetError(pContext
, AL_INVALID_ENUM
);
1146 alSetError(pContext
, AL_INVALID_NAME
);
1149 alSetError(pContext
, AL_INVALID_VALUE
);
1151 ProcessContext(pContext
);
1155 ALAPI
void ALAPIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1157 ALCcontext
*pContext
;
1160 pContext
= GetContextSuspended();
1161 if(!pContext
) return;
1163 if(plValue1
&& plValue2
&& plValue3
)
1165 if((pSource
=VerifySource(pContext
->SourceList
, source
)) != NULL
)
1170 *plValue1
= (ALint
)pSource
->vPosition
[0];
1171 *plValue2
= (ALint
)pSource
->vPosition
[1];
1172 *plValue3
= (ALint
)pSource
->vPosition
[2];
1176 *plValue1
= (ALint
)pSource
->vVelocity
[0];
1177 *plValue2
= (ALint
)pSource
->vVelocity
[1];
1178 *plValue3
= (ALint
)pSource
->vVelocity
[2];
1182 *plValue1
= (ALint
)pSource
->vOrientation
[0];
1183 *plValue2
= (ALint
)pSource
->vOrientation
[1];
1184 *plValue3
= (ALint
)pSource
->vOrientation
[2];
1188 alSetError(pContext
, AL_INVALID_ENUM
);
1193 alSetError(pContext
, AL_INVALID_NAME
);
1196 alSetError(pContext
, AL_INVALID_VALUE
);
1198 ProcessContext(pContext
);
1202 ALAPI
void ALAPIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1204 ALCcontext
*pContext
;
1206 ALfloat flOffset
[2];
1209 pContext
= GetContextSuspended();
1210 if(!pContext
) return;
1214 if((pSource
=VerifySource(pContext
->SourceList
, source
)) != NULL
)
1218 case AL_SOURCE_RELATIVE
:
1219 case AL_CONE_INNER_ANGLE
:
1220 case AL_CONE_OUTER_ANGLE
:
1223 case AL_SOURCE_STATE
:
1224 case AL_BUFFERS_QUEUED
:
1225 case AL_BUFFERS_PROCESSED
:
1227 case AL_SAMPLE_OFFSET
:
1228 case AL_BYTE_OFFSET
:
1229 case AL_MAX_DISTANCE
:
1230 case AL_ROLLOFF_FACTOR
:
1231 case AL_DOPPLER_FACTOR
:
1232 case AL_REFERENCE_DISTANCE
:
1233 case AL_SOURCE_TYPE
:
1234 case AL_DIRECT_FILTER
:
1235 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1236 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1237 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1238 case AL_DISTANCE_MODEL
:
1239 alGetSourcei(source
, eParam
, plValues
);
1242 case AL_SAMPLE_RW_OFFSETS_EXT
:
1243 case AL_BYTE_RW_OFFSETS_EXT
:
1244 updateLen
= (ALfloat
)pContext
->Device
->UpdateSize
/
1245 pContext
->Device
->Frequency
;
1246 GetSourceOffset(pSource
, eParam
, flOffset
, updateLen
);
1247 plValues
[0] = (ALint
)flOffset
[0];
1248 plValues
[1] = (ALint
)flOffset
[1];
1252 plValues
[0] = (ALint
)pSource
->vPosition
[0];
1253 plValues
[1] = (ALint
)pSource
->vPosition
[1];
1254 plValues
[2] = (ALint
)pSource
->vPosition
[2];
1258 plValues
[0] = (ALint
)pSource
->vVelocity
[0];
1259 plValues
[1] = (ALint
)pSource
->vVelocity
[1];
1260 plValues
[2] = (ALint
)pSource
->vVelocity
[2];
1264 plValues
[0] = (ALint
)pSource
->vOrientation
[0];
1265 plValues
[1] = (ALint
)pSource
->vOrientation
[1];
1266 plValues
[2] = (ALint
)pSource
->vOrientation
[2];
1270 alSetError(pContext
, AL_INVALID_ENUM
);
1275 alSetError(pContext
, AL_INVALID_NAME
);
1278 alSetError(pContext
, AL_INVALID_VALUE
);
1280 ProcessContext(pContext
);
1284 ALAPI ALvoid ALAPIENTRY
alSourcePlay(ALuint source
)
1286 alSourcePlayv(1, &source
);
1289 ALAPI ALvoid ALAPIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*pSourceList
)
1291 ALCcontext
*pContext
;
1293 ALbufferlistitem
*ALBufferList
;
1294 ALboolean bSourcesValid
= AL_TRUE
;
1298 pContext
= GetContextSuspended();
1299 if(!pContext
) return;
1303 // Check that all the Sources are valid
1304 for(i
= 0; i
< n
; i
++)
1306 if(!VerifySource(pContext
->SourceList
, pSourceList
[i
]))
1308 alSetError(pContext
, AL_INVALID_NAME
);
1309 bSourcesValid
= AL_FALSE
;
1316 for(i
= 0; i
< n
; i
++)
1318 // Assume Source won't need to play
1321 pSource
= (ALsource
*)ALTHUNK_LOOKUPENTRY(pSourceList
[i
]);
1323 // Check that there is a queue containing at least one non-null, non zero length AL Buffer
1324 ALBufferList
= pSource
->queue
;
1327 if(ALBufferList
->buffer
!= NULL
&& ALBufferList
->buffer
->size
)
1332 ALBufferList
= ALBufferList
->next
;
1337 for(j
= 0;j
< OUTPUTCHANNELS
;j
++)
1338 pSource
->DryGains
[j
] = 0.0f
;
1339 for(j
= 0;j
< MAX_SENDS
;j
++)
1340 pSource
->WetGains
[j
] = 0.0f
;
1342 if(pSource
->state
!= AL_PAUSED
)
1344 pSource
->state
= AL_PLAYING
;
1345 pSource
->position
= 0;
1346 pSource
->position_fraction
= 0;
1347 pSource
->BuffersPlayed
= 0;
1349 pSource
->Buffer
= pSource
->queue
->buffer
;
1352 pSource
->state
= AL_PLAYING
;
1354 // Check if an Offset has been set
1355 if(pSource
->lOffset
)
1356 ApplyOffset(pSource
);
1358 if(pSource
->BuffersPlayed
== 0 && pSource
->position
== 0 &&
1359 pSource
->position_fraction
== 0)
1360 pSource
->FirstStart
= AL_TRUE
;
1362 pSource
->FirstStart
= AL_FALSE
;
1364 // If device is disconnected, go right to stopped
1365 if(!pContext
->Device
->Connected
)
1367 pSource
->state
= AL_STOPPED
;
1368 pSource
->BuffersPlayed
= pSource
->BuffersInQueue
;
1369 pSource
->position
= 0;
1370 pSource
->position_fraction
= 0;
1374 pSource
->BuffersPlayed
= pSource
->BuffersInQueue
;
1380 // sources is a NULL pointer
1381 alSetError(pContext
, AL_INVALID_VALUE
);
1384 ProcessContext(pContext
);
1387 ALAPI ALvoid ALAPIENTRY
alSourcePause(ALuint source
)
1389 alSourcePausev(1, &source
);
1392 ALAPI ALvoid ALAPIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1394 ALCcontext
*Context
;
1397 ALboolean bSourcesValid
= AL_TRUE
;
1399 Context
= GetContextSuspended();
1400 if(!Context
) return;
1404 // Check all the Sources are valid
1407 if(!VerifySource(Context
->SourceList
, sources
[i
]))
1409 alSetError(Context
, AL_INVALID_NAME
);
1410 bSourcesValid
= AL_FALSE
;
1417 for(i
= 0;i
< n
;i
++)
1419 Source
= (ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]);
1420 if(Source
->state
== AL_PLAYING
)
1421 Source
->state
= AL_PAUSED
;
1427 // sources is a NULL pointer
1428 alSetError(Context
, AL_INVALID_VALUE
);
1431 ProcessContext(Context
);
1434 ALAPI ALvoid ALAPIENTRY
alSourceStop(ALuint source
)
1436 alSourceStopv(1, &source
);
1439 ALAPI ALvoid ALAPIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1441 ALCcontext
*Context
;
1444 ALboolean bSourcesValid
= AL_TRUE
;
1446 Context
= GetContextSuspended();
1447 if(!Context
) return;
1451 // Check all the Sources are valid
1452 for(i
= 0;i
< n
;i
++)
1454 if(!VerifySource(Context
->SourceList
, sources
[i
]))
1456 alSetError(Context
, AL_INVALID_NAME
);
1457 bSourcesValid
= AL_FALSE
;
1464 for(i
= 0;i
< n
;i
++)
1466 Source
= (ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]);
1467 if(Source
->state
!= AL_INITIAL
)
1469 Source
->state
= AL_STOPPED
;
1470 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1472 Source
->lOffset
= 0;
1478 // sources is a NULL pointer
1479 alSetError(Context
, AL_INVALID_VALUE
);
1482 ProcessContext(Context
);
1485 ALAPI ALvoid ALAPIENTRY
alSourceRewind(ALuint source
)
1487 alSourceRewindv(1, &source
);
1490 ALAPI ALvoid ALAPIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1492 ALCcontext
*Context
;
1495 ALboolean bSourcesValid
= AL_TRUE
;
1497 Context
= GetContextSuspended();
1498 if(!Context
) return;
1502 // Check all the Sources are valid
1503 for(i
= 0;i
< n
;i
++)
1505 if(!VerifySource(Context
->SourceList
, sources
[i
]))
1507 alSetError(Context
, AL_INVALID_NAME
);
1508 bSourcesValid
= AL_FALSE
;
1515 for(i
= 0;i
< n
;i
++)
1517 Source
= (ALsource
*)ALTHUNK_LOOKUPENTRY(sources
[i
]);
1518 if(Source
->state
!= AL_INITIAL
)
1520 Source
->state
= AL_INITIAL
;
1521 Source
->position
= 0;
1522 Source
->position_fraction
= 0;
1523 Source
->BuffersPlayed
= 0;
1525 Source
->Buffer
= Source
->queue
->buffer
;
1527 Source
->lOffset
= 0;
1533 // sources is a NULL pointer
1534 alSetError(Context
, AL_INVALID_VALUE
);
1537 ProcessContext(Context
);
1541 ALAPI ALvoid ALAPIENTRY
alSourceQueueBuffers( ALuint source
, ALsizei n
, const ALuint
* buffers
)
1543 ALCcontext
*Context
;
1546 ALbufferlistitem
*ALBufferList
;
1547 ALbufferlistitem
*ALBufferListStart
;
1550 ALboolean bBuffersValid
= AL_TRUE
;
1551 ALboolean hadFormat
= AL_FALSE
;
1556 Context
= GetContextSuspended();
1557 if(!Context
) return;
1559 // Check that all buffers are valid or zero and that the source is valid
1561 // Check that this is a valid source
1562 if((ALSource
=VerifySource(Context
->SourceList
, source
)) != NULL
)
1564 // Check that this is not a STATIC Source
1565 if(ALSource
->lSourceType
!= AL_STATIC
)
1567 ALCdevice
*device
= Context
->Device
;
1572 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1573 ALBufferList
= ALSource
->queue
;
1576 if (ALBufferList
->buffer
)
1578 iFrequency
= ALBufferList
->buffer
->frequency
;
1579 iFormat
= ALBufferList
->buffer
->format
;
1580 hadFormat
= AL_TRUE
;
1583 ALBufferList
= ALBufferList
->next
;
1586 for(i
= 0; i
< n
; i
++)
1593 if((buffer
=VerifyBuffer(device
->BufferList
, buffers
[i
])) == NULL
)
1595 alSetError(Context
, AL_INVALID_NAME
);
1596 bBuffersValid
= AL_FALSE
;
1600 if(iFrequency
== -1 && iFormat
== -1)
1602 iFrequency
= buffer
->frequency
;
1603 iFormat
= buffer
->format
;
1605 else if(iFrequency
!= buffer
->frequency
||
1606 iFormat
!= buffer
->format
)
1608 alSetError(Context
, AL_INVALID_OPERATION
);
1609 bBuffersValid
= AL_FALSE
;
1618 // Change Source Type
1619 ALSource
->lSourceType
= AL_STREAMING
;
1621 buffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[0]);
1623 // All buffers are valid - so add them to the list
1624 ALBufferListStart
= malloc(sizeof(ALbufferlistitem
));
1625 ALBufferListStart
->buffer
= buffer
;
1626 ALBufferListStart
->next
= NULL
;
1628 // Increment reference counter for buffer
1629 if(buffer
) buffer
->refcount
++;
1631 ALBufferList
= ALBufferListStart
;
1633 for(i
= 1; i
< n
; i
++)
1635 buffer
= (ALbuffer
*)ALTHUNK_LOOKUPENTRY(buffers
[i
]);
1637 ALBufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1638 ALBufferList
->next
->buffer
= buffer
;
1639 ALBufferList
->next
->next
= NULL
;
1641 // Increment reference counter for buffer
1642 if(buffer
) buffer
->refcount
++;
1644 ALBufferList
= ALBufferList
->next
;
1647 if(ALSource
->queue
== NULL
)
1649 ALSource
->queue
= ALBufferListStart
;
1650 // Update Current Buffer
1651 ALSource
->Buffer
= ALBufferListStart
->buffer
;
1655 // Find end of queue
1656 ALBufferList
= ALSource
->queue
;
1657 while(ALBufferList
->next
!= NULL
)
1658 ALBufferList
= ALBufferList
->next
;
1660 ALBufferList
->next
= ALBufferListStart
;
1663 // Update number of buffers in queue
1664 ALSource
->BuffersInQueue
+= n
;
1665 // If no previous format, mark the source dirty now that it may
1668 ALSource
->NeedsUpdate
= AL_TRUE
;
1673 // Invalid Source Type (can't queue on a Static Source)
1674 alSetError(Context
, AL_INVALID_OPERATION
);
1679 // Invalid Source Name
1680 alSetError(Context
, AL_INVALID_NAME
);
1683 ProcessContext(Context
);
1687 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1688 // an array of buffer IDs that are to be filled with the names of the buffers removed
1689 ALAPI ALvoid ALAPIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1691 ALCcontext
*Context
;
1694 ALbufferlistitem
*ALBufferList
;
1699 Context
= GetContextSuspended();
1700 if(!Context
) return;
1702 if((ALSource
=VerifySource(Context
->SourceList
, source
)) != NULL
)
1704 // If all 'n' buffers have been processed, remove them from the queue
1705 if(!ALSource
->bLooping
&& (ALuint
)n
<= ALSource
->BuffersPlayed
)
1707 for(i
= 0; i
< n
; i
++)
1709 ALBufferList
= ALSource
->queue
;
1711 ALSource
->queue
= ALBufferList
->next
;
1712 if(ALBufferList
->buffer
)
1714 // Record name of buffer
1715 buffers
[i
] = ALBufferList
->buffer
->buffer
;
1716 // Decrement buffer reference counter
1717 ALBufferList
->buffer
->refcount
--;
1722 // Release memory for buffer list item
1724 ALSource
->BuffersInQueue
--;
1727 if(ALSource
->state
!= AL_PLAYING
)
1730 ALSource
->Buffer
= ALSource
->queue
->buffer
;
1732 ALSource
->Buffer
= NULL
;
1735 ALSource
->BuffersPlayed
-= n
;
1739 // Some buffers can't be unqueue because they have not been processed
1740 alSetError(Context
, AL_INVALID_VALUE
);
1745 // Invalid Source Name
1746 alSetError(Context
, AL_INVALID_NAME
);
1749 ProcessContext(Context
);
1753 static ALvoid
InitSourceParams(ALsource
*pSource
)
1755 pSource
->flInnerAngle
= 360.0f
;
1756 pSource
->flOuterAngle
= 360.0f
;
1757 pSource
->flPitch
= 1.0f
;
1758 pSource
->vPosition
[0] = 0.0f
;
1759 pSource
->vPosition
[1] = 0.0f
;
1760 pSource
->vPosition
[2] = 0.0f
;
1761 pSource
->vOrientation
[0] = 0.0f
;
1762 pSource
->vOrientation
[1] = 0.0f
;
1763 pSource
->vOrientation
[2] = 0.0f
;
1764 pSource
->vVelocity
[0] = 0.0f
;
1765 pSource
->vVelocity
[1] = 0.0f
;
1766 pSource
->vVelocity
[2] = 0.0f
;
1767 pSource
->flRefDistance
= 1.0f
;
1768 pSource
->flMaxDistance
= FLT_MAX
;
1769 pSource
->flRollOffFactor
= 1.0f
;
1770 pSource
->bLooping
= AL_FALSE
;
1771 pSource
->flGain
= 1.0f
;
1772 pSource
->flMinGain
= 0.0f
;
1773 pSource
->flMaxGain
= 1.0f
;
1774 pSource
->flOuterGain
= 0.0f
;
1775 pSource
->OuterGainHF
= 1.0f
;
1777 pSource
->DryGainHFAuto
= AL_TRUE
;
1778 pSource
->WetGainAuto
= AL_TRUE
;
1779 pSource
->WetGainHFAuto
= AL_TRUE
;
1780 pSource
->AirAbsorptionFactor
= 0.0f
;
1781 pSource
->RoomRolloffFactor
= 0.0f
;
1782 pSource
->DopplerFactor
= 1.0f
;
1784 pSource
->DistanceModel
= AL_INVERSE_DISTANCE_CLAMPED
;
1786 pSource
->Resampler
= DefaultResampler
;
1788 pSource
->state
= AL_INITIAL
;
1789 pSource
->lSourceType
= AL_UNDETERMINED
;
1791 pSource
->NeedsUpdate
= AL_TRUE
;
1793 pSource
->Buffer
= NULL
;
1800 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1801 The offset is relative to the start of the queue (not the start of the current buffer)
1803 static ALvoid
GetSourceOffset(ALsource
*pSource
, ALenum eName
, ALfloat
*pflOffset
, ALfloat updateLen
)
1805 ALbufferlistitem
*pBufferList
;
1807 ALfloat flBufferFreq
;
1808 ALint lChannels
, lBytes
;
1809 ALint readPos
, writePos
;
1810 ALenum eOriginalFormat
;
1811 ALint lTotalBufferDataSize
;
1814 if((pSource
->state
== AL_PLAYING
|| pSource
->state
== AL_PAUSED
) && pSource
->Buffer
)
1816 pBuffer
= pSource
->Buffer
;
1817 // Get Current Buffer Size and frequency (in milliseconds)
1818 flBufferFreq
= (ALfloat
)pBuffer
->frequency
;
1819 eOriginalFormat
= pBuffer
->eOriginalFormat
;
1820 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
1821 lBytes
= aluBytesFromFormat(pBuffer
->format
);
1823 // Get Current BytesPlayed
1824 readPos
= pSource
->position
* lChannels
* lBytes
; // NOTE : This is the byte offset into the *current* buffer
1825 // Add byte length of any processed buffers in the queue
1826 pBufferList
= pSource
->queue
;
1827 for(i
= 0;i
< pSource
->BuffersPlayed
&& pBufferList
;i
++)
1829 readPos
+= pBufferList
->buffer
->size
;
1830 pBufferList
= pBufferList
->next
;
1833 if(pSource
->state
== AL_PLAYING
)
1834 writePos
= readPos
+ ((ALuint
)(updateLen
*flBufferFreq
) * lChannels
* lBytes
);
1838 lTotalBufferDataSize
= 0;
1839 pBufferList
= pSource
->queue
;
1842 if (pBufferList
->buffer
)
1843 lTotalBufferDataSize
+= pBufferList
->buffer
->size
;
1844 pBufferList
= pBufferList
->next
;
1847 if (pSource
->bLooping
)
1852 readPos
%= lTotalBufferDataSize
;
1856 writePos
%= lTotalBufferDataSize
;
1860 // Clamp BytesPlayed to within 0 and lTotalBufferDataSize
1863 else if(readPos
> lTotalBufferDataSize
)
1864 readPos
= lTotalBufferDataSize
;
1867 else if(writePos
> lTotalBufferDataSize
)
1868 writePos
= lTotalBufferDataSize
;
1874 pflOffset
[0] = (ALfloat
)readPos
/ (lChannels
* lBytes
* flBufferFreq
);
1875 pflOffset
[1] = (ALfloat
)writePos
/ (lChannels
* lBytes
* flBufferFreq
);
1877 case AL_SAMPLE_OFFSET
:
1878 case AL_SAMPLE_RW_OFFSETS_EXT
:
1879 pflOffset
[0] = (ALfloat
)(readPos
/ (lChannels
* lBytes
));
1880 pflOffset
[1] = (ALfloat
)(writePos
/ (lChannels
* lBytes
));
1882 case AL_BYTE_OFFSET
:
1883 case AL_BYTE_RW_OFFSETS_EXT
:
1884 // Take into account the original format of the Buffer
1885 if ((eOriginalFormat
== AL_FORMAT_MONO_IMA4
) ||
1886 (eOriginalFormat
== AL_FORMAT_STEREO_IMA4
))
1888 // Round down to nearest ADPCM block
1889 pflOffset
[0] = (ALfloat
)((readPos
/ (65 * lBytes
* lChannels
)) * 36 * lChannels
);
1890 if(pSource
->state
== AL_PLAYING
)
1892 // Round up to nearest ADPCM block
1893 pflOffset
[1] = (ALfloat
)(((writePos
+ (65 * lBytes
* lChannels
) - 1) / (65 * lBytes
* lChannels
)) * 36 * lChannels
);
1896 pflOffset
[1] = pflOffset
[0];
1898 else if(eOriginalFormat
== AL_FORMAT_MONO_MULAW
||
1899 eOriginalFormat
== AL_FORMAT_STEREO_MULAW
||
1900 eOriginalFormat
== AL_FORMAT_QUAD_MULAW
||
1901 eOriginalFormat
== AL_FORMAT_51CHN_MULAW
||
1902 eOriginalFormat
== AL_FORMAT_61CHN_MULAW
||
1903 eOriginalFormat
== AL_FORMAT_71CHN_MULAW
)
1905 pflOffset
[0] = (ALfloat
)(readPos
/ lBytes
* 1);
1906 pflOffset
[1] = (ALfloat
)(writePos
/ lBytes
* 1);
1908 else if(eOriginalFormat
== AL_FORMAT_REAR_MULAW
)
1910 pflOffset
[0] = (ALfloat
)(readPos
/ 2 / lBytes
* 1);
1911 pflOffset
[1] = (ALfloat
)(writePos
/ 2 / lBytes
* 1);
1913 else if (eOriginalFormat
== AL_FORMAT_REAR8
)
1915 pflOffset
[0] = (ALfloat
)(readPos
/ 2 / lBytes
* 1);
1916 pflOffset
[1] = (ALfloat
)(writePos
/ 2 / lBytes
* 1);
1918 else if (eOriginalFormat
== AL_FORMAT_REAR16
)
1920 pflOffset
[0] = (ALfloat
)(readPos
/ 2 / lBytes
* 2);
1921 pflOffset
[1] = (ALfloat
)(writePos
/ 2 / lBytes
* 2);
1923 else if (eOriginalFormat
== AL_FORMAT_REAR32
)
1925 pflOffset
[0] = (ALfloat
)(readPos
/ 2 / lBytes
* 4);
1926 pflOffset
[1] = (ALfloat
)(writePos
/ 2 / lBytes
* 4);
1930 ALuint OrigBytes
= aluBytesFromFormat(eOriginalFormat
);
1931 pflOffset
[0] = (ALfloat
)(readPos
/ lBytes
* OrigBytes
);
1932 pflOffset
[1] = (ALfloat
)(writePos
/ lBytes
* OrigBytes
);
1939 pflOffset
[0] = 0.0f
;
1940 pflOffset
[1] = 0.0f
;
1948 Apply a playback offset to the Source. This function will update the queue (to correctly
1949 mark buffers as 'pending' or 'processed' depending upon the new offset.
1951 static ALboolean
ApplyOffset(ALsource
*pSource
)
1953 ALbufferlistitem
*pBufferList
;
1955 ALint lBufferSize
, lTotalBufferSize
;
1958 // Get true byte offset
1959 lByteOffset
= GetByteOffset(pSource
);
1961 // If the offset is invalid, don't apply it
1962 if(lByteOffset
== -1)
1965 // Sort out the queue (pending and processed states)
1966 pBufferList
= pSource
->queue
;
1967 lTotalBufferSize
= 0;
1968 pSource
->BuffersPlayed
= 0;
1972 pBuffer
= pBufferList
->buffer
;
1973 lBufferSize
= pBuffer
? pBuffer
->size
: 0;
1975 if(lTotalBufferSize
+lBufferSize
<= lByteOffset
)
1977 // Offset is past this buffer so increment BuffersPlayed
1978 pSource
->BuffersPlayed
++;
1980 else if(lTotalBufferSize
<= lByteOffset
)
1982 // Offset is within this buffer
1983 // Set Current Buffer
1984 pSource
->Buffer
= pBufferList
->buffer
;
1986 // SW Mixer Positions are in Samples
1987 pSource
->position
= (lByteOffset
- lTotalBufferSize
) /
1988 aluBytesFromFormat(pBuffer
->format
) /
1989 aluChannelsFromFormat(pBuffer
->format
);
1993 // Increment the TotalBufferSize
1994 lTotalBufferSize
+= lBufferSize
;
1996 // Move on to next buffer in the Queue
1997 pBufferList
= pBufferList
->next
;
2007 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2008 offset supplied by the application). This takes into account the fact that the buffer format
2009 may have been modifed by AL (e.g 8bit samples are converted to float)
2011 static ALint
GetByteOffset(ALsource
*pSource
)
2013 ALbuffer
*pBuffer
= NULL
;
2014 ALbufferlistitem
*pBufferList
;
2015 ALfloat flBufferFreq
;
2016 ALint lChannels
, lBytes
;
2017 ALint lByteOffset
= -1;
2018 ALint lTotalBufferDataSize
;
2019 ALenum OriginalFormat
;
2021 // Find the first non-NULL Buffer in the Queue
2022 pBufferList
= pSource
->queue
;
2025 if (pBufferList
->buffer
)
2027 pBuffer
= pBufferList
->buffer
;
2030 pBufferList
= pBufferList
->next
;
2035 flBufferFreq
= ((ALfloat
)pBuffer
->frequency
);
2036 lChannels
= aluChannelsFromFormat(pBuffer
->format
);
2037 lBytes
= aluBytesFromFormat(pBuffer
->format
);
2038 OriginalFormat
= pBuffer
->eOriginalFormat
;
2040 // Determine the ByteOffset (and ensure it is block aligned)
2041 switch (pSource
->lOffsetType
)
2043 case AL_BYTE_OFFSET
:
2044 // Take into consideration the original format
2045 if(OriginalFormat
== AL_FORMAT_MONO_IMA4
||
2046 OriginalFormat
== AL_FORMAT_STEREO_IMA4
)
2048 // Round down to nearest ADPCM block
2049 lByteOffset
= pSource
->lOffset
/ (36 * lChannels
);
2050 // Multiply by compression rate (65 samples per 36 byte block)
2051 lByteOffset
= lByteOffset
* 65 * lChannels
* lBytes
;
2053 else if(OriginalFormat
== AL_FORMAT_MONO_MULAW
||
2054 OriginalFormat
== AL_FORMAT_STEREO_MULAW
||
2055 OriginalFormat
== AL_FORMAT_QUAD_MULAW
||
2056 OriginalFormat
== AL_FORMAT_51CHN_MULAW
||
2057 OriginalFormat
== AL_FORMAT_61CHN_MULAW
||
2058 OriginalFormat
== AL_FORMAT_71CHN_MULAW
)
2060 /* muLaw has 1 byte per sample */
2061 lByteOffset
= pSource
->lOffset
/ 1 * lBytes
;
2063 else if(OriginalFormat
== AL_FORMAT_REAR_MULAW
)
2065 /* Rear is converted from 2 -> 4 channel */
2066 lByteOffset
= pSource
->lOffset
/ 1 * lBytes
* 2;
2068 else if(OriginalFormat
== AL_FORMAT_REAR8
)
2069 lByteOffset
= pSource
->lOffset
/ 1 * lBytes
* 2;
2070 else if(OriginalFormat
== AL_FORMAT_REAR16
)
2071 lByteOffset
= pSource
->lOffset
/ 2 * lBytes
* 2;
2072 else if(OriginalFormat
== AL_FORMAT_REAR32
)
2073 lByteOffset
= pSource
->lOffset
/ 4 * lBytes
* 2;
2076 ALuint OrigBytes
= aluBytesFromFormat(OriginalFormat
);
2077 lByteOffset
= pSource
->lOffset
/ OrigBytes
* lBytes
;
2079 lByteOffset
-= (lByteOffset
% (lChannels
* lBytes
));
2082 case AL_SAMPLE_OFFSET
:
2083 lByteOffset
= pSource
->lOffset
* lChannels
* lBytes
;
2087 // Note - lOffset is internally stored as Milliseconds
2088 lByteOffset
= (ALint
)(pSource
->lOffset
/ 1000.0f
* flBufferFreq
);
2089 lByteOffset
*= lChannels
* lBytes
;
2093 lTotalBufferDataSize
= 0;
2094 pBufferList
= pSource
->queue
;
2097 if (pBufferList
->buffer
)
2098 lTotalBufferDataSize
+= pBufferList
->buffer
->size
;
2099 pBufferList
= pBufferList
->next
;
2102 // Finally, if the ByteOffset is beyond the length of all the buffers in the queue, return -1
2103 if (lByteOffset
>= lTotalBufferDataSize
)
2108 pSource
->lOffset
= 0;
2114 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2118 while(Context
->SourceList
)
2120 ALsource
*temp
= Context
->SourceList
;
2121 Context
->SourceList
= temp
->next
;
2123 // For each buffer in the source's queue, decrement its reference counter and remove it
2124 while(temp
->queue
!= NULL
)
2126 ALbufferlistitem
*ALBufferList
= temp
->queue
;
2127 // Decrement buffer's reference counter
2128 if(ALBufferList
->buffer
!= NULL
)
2129 ALBufferList
->buffer
->refcount
--;
2130 // Update queue to point to next element in list
2131 temp
->queue
= ALBufferList
->next
;
2132 // Release memory allocated for buffer list item
2136 for(j
= 0;j
< MAX_SENDS
;++j
)
2138 if(temp
->Send
[j
].Slot
)
2139 temp
->Send
[j
].Slot
->refcount
--;
2142 // Release source structure
2143 ALTHUNK_REMOVEENTRY(temp
->source
);
2144 memset(temp
, 0, sizeof(ALsource
));
2147 Context
->SourceCount
= 0;