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"
36 enum Resampler DefaultResampler
= RESAMPLER_DEFAULT
;
37 const ALsizei ResamplerPadding
[RESAMPLER_MAX
] = {
42 const ALsizei ResamplerPrePadding
[RESAMPLER_MAX
] = {
49 static ALvoid
InitSourceParams(ALsource
*Source
);
50 static ALvoid
GetSourceOffset(ALsource
*Source
, ALenum eName
, ALdouble
*Offsets
, ALdouble updateLen
);
51 static ALint
GetByteOffset(ALsource
*Source
);
53 #define LookupSource(m, k) ((ALsource*)LookupUIntMapKey(&(m), (k)))
54 #define RemoveSource(m, k) ((ALsource*)PopUIntMapValue(&(m), (k)))
55 #define LookupBuffer(m, k) ((ALbuffer*)LookupUIntMapKey(&(m), (k)))
56 #define LookupFilter(m, k) ((ALfilter*)LookupUIntMapKey(&(m), (k)))
57 #define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k)))
59 AL_API ALvoid AL_APIENTRY
alGenSources(ALsizei n
,ALuint
*sources
)
64 Context
= GetContextRef();
67 Device
= Context
->Device
;
68 if(n
< 0 || IsBadWritePtr((void*)sources
, n
* sizeof(ALuint
)))
69 alSetError(Context
, AL_INVALID_VALUE
);
75 // Add additional sources to the list
79 ALsource
*source
= calloc(1, sizeof(ALsource
));
82 alSetError(Context
, AL_OUT_OF_MEMORY
);
83 alDeleteSources(i
, sources
);
86 InitSourceParams(source
);
88 err
= NewThunkEntry(&source
->source
);
89 if(err
== AL_NO_ERROR
)
90 err
= InsertUIntMapEntry(&Context
->SourceMap
, source
->source
, source
);
91 if(err
!= AL_NO_ERROR
)
93 FreeThunkEntry(source
->source
);
94 memset(source
, 0, sizeof(ALsource
));
97 alSetError(Context
, err
);
98 alDeleteSources(i
, sources
);
102 sources
[i
++] = source
->source
;
106 ALCcontext_DecRef(Context
);
110 AL_API ALvoid AL_APIENTRY
alDeleteSources(ALsizei n
, const ALuint
*sources
)
115 ALbufferlistitem
*BufferList
;
117 Context
= GetContextRef();
121 alSetError(Context
, AL_INVALID_VALUE
);
124 // Check that all Sources are valid (and can therefore be deleted)
127 if(LookupSource(Context
->SourceMap
, sources
[i
]) == NULL
)
129 alSetError(Context
, AL_INVALID_NAME
);
135 // All Sources are valid, and can be deleted
138 ALsource
**srclist
, **srclistend
;
140 // Remove Source from list of Sources
141 if((Source
=RemoveSource(Context
->SourceMap
, sources
[i
])) == NULL
)
144 FreeThunkEntry(Source
->source
);
146 LockContext(Context
);
147 srclist
= Context
->ActiveSources
;
148 srclistend
= srclist
+ Context
->ActiveSourceCount
;
149 while(srclist
!= srclistend
)
151 if(*srclist
== Source
)
153 Context
->ActiveSourceCount
--;
154 *srclist
= *(--srclistend
);
159 UnlockContext(Context
);
161 // For each buffer in the source's queue...
162 while(Source
->queue
!= NULL
)
164 BufferList
= Source
->queue
;
165 Source
->queue
= BufferList
->next
;
167 if(BufferList
->buffer
!= NULL
)
168 DecrementRef(&BufferList
->buffer
->ref
);
172 for(j
= 0;j
< MAX_SENDS
;++j
)
174 if(Source
->Send
[j
].Slot
)
175 DecrementRef(&Source
->Send
[j
].Slot
->ref
);
176 Source
->Send
[j
].Slot
= NULL
;
179 memset(Source
,0,sizeof(ALsource
));
184 ALCcontext_DecRef(Context
);
188 AL_API ALboolean AL_APIENTRY
alIsSource(ALuint source
)
193 Context
= GetContextRef();
194 if(!Context
) return AL_FALSE
;
196 result
= (LookupSource(Context
->SourceMap
, source
) ? AL_TRUE
: AL_FALSE
);
198 ALCcontext_DecRef(Context
);
204 AL_API ALvoid AL_APIENTRY
alSourcef(ALuint source
, ALenum eParam
, ALfloat flValue
)
206 ALCcontext
*pContext
;
209 pContext
= GetContextRef();
210 if(!pContext
) return;
212 if((Source
=LookupSource(pContext
->SourceMap
, source
)) != NULL
)
219 Source
->flPitch
= flValue
;
220 Source
->NeedsUpdate
= AL_TRUE
;
223 alSetError(pContext
, AL_INVALID_VALUE
);
226 case AL_CONE_INNER_ANGLE
:
227 if(flValue
>= 0.0f
&& flValue
<= 360.0f
)
229 Source
->flInnerAngle
= flValue
;
230 Source
->NeedsUpdate
= AL_TRUE
;
233 alSetError(pContext
, AL_INVALID_VALUE
);
236 case AL_CONE_OUTER_ANGLE
:
237 if(flValue
>= 0.0f
&& flValue
<= 360.0f
)
239 Source
->flOuterAngle
= flValue
;
240 Source
->NeedsUpdate
= AL_TRUE
;
243 alSetError(pContext
, AL_INVALID_VALUE
);
249 Source
->flGain
= flValue
;
250 Source
->NeedsUpdate
= AL_TRUE
;
253 alSetError(pContext
, AL_INVALID_VALUE
);
256 case AL_MAX_DISTANCE
:
259 Source
->flMaxDistance
= flValue
;
260 Source
->NeedsUpdate
= AL_TRUE
;
263 alSetError(pContext
, AL_INVALID_VALUE
);
266 case AL_ROLLOFF_FACTOR
:
269 Source
->flRollOffFactor
= flValue
;
270 Source
->NeedsUpdate
= AL_TRUE
;
273 alSetError(pContext
, AL_INVALID_VALUE
);
276 case AL_REFERENCE_DISTANCE
:
279 Source
->flRefDistance
= flValue
;
280 Source
->NeedsUpdate
= AL_TRUE
;
283 alSetError(pContext
, AL_INVALID_VALUE
);
287 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
289 Source
->flMinGain
= flValue
;
290 Source
->NeedsUpdate
= AL_TRUE
;
293 alSetError(pContext
, AL_INVALID_VALUE
);
297 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
299 Source
->flMaxGain
= flValue
;
300 Source
->NeedsUpdate
= AL_TRUE
;
303 alSetError(pContext
, AL_INVALID_VALUE
);
306 case AL_CONE_OUTER_GAIN
:
307 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
309 Source
->flOuterGain
= flValue
;
310 Source
->NeedsUpdate
= AL_TRUE
;
313 alSetError(pContext
, AL_INVALID_VALUE
);
316 case AL_CONE_OUTER_GAINHF
:
317 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
319 Source
->OuterGainHF
= flValue
;
320 Source
->NeedsUpdate
= AL_TRUE
;
323 alSetError(pContext
, AL_INVALID_VALUE
);
326 case AL_AIR_ABSORPTION_FACTOR
:
327 if(flValue
>= 0.0f
&& flValue
<= 10.0f
)
329 Source
->AirAbsorptionFactor
= flValue
;
330 Source
->NeedsUpdate
= AL_TRUE
;
333 alSetError(pContext
, AL_INVALID_VALUE
);
336 case AL_ROOM_ROLLOFF_FACTOR
:
337 if(flValue
>= 0.0f
&& flValue
<= 10.0f
)
339 Source
->RoomRolloffFactor
= flValue
;
340 Source
->NeedsUpdate
= AL_TRUE
;
343 alSetError(pContext
, AL_INVALID_VALUE
);
346 case AL_DOPPLER_FACTOR
:
347 if(flValue
>= 0.0f
&& flValue
<= 1.0f
)
349 Source
->DopplerFactor
= flValue
;
350 Source
->NeedsUpdate
= AL_TRUE
;
353 alSetError(pContext
, AL_INVALID_VALUE
);
357 case AL_SAMPLE_OFFSET
:
361 LockContext(pContext
);
362 Source
->lOffsetType
= eParam
;
364 // Store Offset (convert Seconds into Milliseconds)
365 if(eParam
== AL_SEC_OFFSET
)
366 Source
->lOffset
= (ALint
)(flValue
* 1000.0f
);
368 Source
->lOffset
= (ALint
)flValue
;
370 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
371 !pContext
->DeferUpdates
)
373 if(ApplyOffset(Source
) == AL_FALSE
)
374 alSetError(pContext
, AL_INVALID_VALUE
);
376 UnlockContext(pContext
);
379 alSetError(pContext
, AL_INVALID_VALUE
);
383 alSetError(pContext
, AL_INVALID_ENUM
);
389 // Invalid Source Name
390 alSetError(pContext
, AL_INVALID_NAME
);
393 ALCcontext_DecRef(pContext
);
397 AL_API ALvoid AL_APIENTRY
alSource3f(ALuint source
, ALenum eParam
, ALfloat flValue1
,ALfloat flValue2
,ALfloat flValue3
)
399 ALCcontext
*pContext
;
402 pContext
= GetContextRef();
403 if(!pContext
) return;
405 if((Source
=LookupSource(pContext
->SourceMap
, source
)) != NULL
)
410 if(isfinite(flValue1
) && isfinite(flValue2
) && isfinite(flValue3
))
412 LockContext(pContext
);
413 Source
->vPosition
[0] = flValue1
;
414 Source
->vPosition
[1] = flValue2
;
415 Source
->vPosition
[2] = flValue3
;
416 UnlockContext(pContext
);
417 Source
->NeedsUpdate
= AL_TRUE
;
420 alSetError(pContext
, AL_INVALID_VALUE
);
424 if(isfinite(flValue1
) && isfinite(flValue2
) && isfinite(flValue3
))
426 LockContext(pContext
);
427 Source
->vVelocity
[0] = flValue1
;
428 Source
->vVelocity
[1] = flValue2
;
429 Source
->vVelocity
[2] = flValue3
;
430 UnlockContext(pContext
);
431 Source
->NeedsUpdate
= AL_TRUE
;
434 alSetError(pContext
, AL_INVALID_VALUE
);
438 if(isfinite(flValue1
) && isfinite(flValue2
) && isfinite(flValue3
))
440 LockContext(pContext
);
441 Source
->vOrientation
[0] = flValue1
;
442 Source
->vOrientation
[1] = flValue2
;
443 Source
->vOrientation
[2] = flValue3
;
444 UnlockContext(pContext
);
445 Source
->NeedsUpdate
= AL_TRUE
;
448 alSetError(pContext
, AL_INVALID_VALUE
);
452 alSetError(pContext
, AL_INVALID_ENUM
);
457 alSetError(pContext
, AL_INVALID_NAME
);
459 ALCcontext_DecRef(pContext
);
463 AL_API ALvoid AL_APIENTRY
alSourcefv(ALuint source
, ALenum eParam
, const ALfloat
*pflValues
)
465 ALCcontext
*pContext
;
472 case AL_CONE_INNER_ANGLE
:
473 case AL_CONE_OUTER_ANGLE
:
475 case AL_MAX_DISTANCE
:
476 case AL_ROLLOFF_FACTOR
:
477 case AL_REFERENCE_DISTANCE
:
480 case AL_CONE_OUTER_GAIN
:
481 case AL_CONE_OUTER_GAINHF
:
483 case AL_SAMPLE_OFFSET
:
485 case AL_AIR_ABSORPTION_FACTOR
:
486 case AL_ROOM_ROLLOFF_FACTOR
:
487 alSourcef(source
, eParam
, pflValues
[0]);
493 alSource3f(source
, eParam
, pflValues
[0], pflValues
[1], pflValues
[2]);
498 pContext
= GetContextRef();
499 if(!pContext
) return;
503 if(LookupSource(pContext
->SourceMap
, source
) != NULL
)
508 alSetError(pContext
, AL_INVALID_ENUM
);
513 alSetError(pContext
, AL_INVALID_NAME
);
516 alSetError(pContext
, AL_INVALID_VALUE
);
518 ALCcontext_DecRef(pContext
);
522 AL_API ALvoid AL_APIENTRY
alSourcei(ALuint source
,ALenum eParam
,ALint lValue
)
524 ALCcontext
*pContext
;
526 ALbufferlistitem
*BufferListItem
;
530 case AL_MAX_DISTANCE
:
531 case AL_ROLLOFF_FACTOR
:
532 case AL_CONE_INNER_ANGLE
:
533 case AL_CONE_OUTER_ANGLE
:
534 case AL_REFERENCE_DISTANCE
:
535 alSourcef(source
, eParam
, (ALfloat
)lValue
);
539 pContext
= GetContextRef();
540 if(!pContext
) return;
542 if((Source
=LookupSource(pContext
->SourceMap
, source
)) != NULL
)
544 ALCdevice
*device
= pContext
->Device
;
548 case AL_SOURCE_RELATIVE
:
549 if(lValue
== AL_FALSE
|| lValue
== AL_TRUE
)
551 Source
->bHeadRelative
= (ALboolean
)lValue
;
552 Source
->NeedsUpdate
= AL_TRUE
;
555 alSetError(pContext
, AL_INVALID_VALUE
);
559 if(lValue
== AL_FALSE
|| lValue
== AL_TRUE
)
560 Source
->bLooping
= (ALboolean
)lValue
;
562 alSetError(pContext
, AL_INVALID_VALUE
);
566 LockContext(pContext
);
567 if(Source
->state
== AL_STOPPED
|| Source
->state
== AL_INITIAL
)
569 ALbufferlistitem
*oldlist
;
570 ALbuffer
*buffer
= NULL
;
573 (buffer
=LookupBuffer(device
->BufferMap
, lValue
)) != NULL
)
575 Source
->BuffersInQueue
= 0;
576 Source
->BuffersPlayed
= 0;
578 // Add the buffer to the queue (as long as it is NOT the NULL buffer)
581 // Source is now in STATIC mode
582 Source
->lSourceType
= AL_STATIC
;
584 // Add the selected buffer to the queue
585 BufferListItem
= malloc(sizeof(ALbufferlistitem
));
586 BufferListItem
->buffer
= buffer
;
587 BufferListItem
->next
= NULL
;
588 BufferListItem
->prev
= NULL
;
589 // Increment reference counter for buffer
590 IncrementRef(&buffer
->ref
);
592 oldlist
= ExchangePtr((void**)&Source
->queue
, BufferListItem
);
593 Source
->BuffersInQueue
= 1;
595 ReadLock(&buffer
->lock
);
596 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
597 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
598 ReadUnlock(&buffer
->lock
);
599 if(buffer
->FmtChannels
== FmtMono
)
600 Source
->Update
= CalcSourceParams
;
602 Source
->Update
= CalcNonAttnSourceParams
;
603 Source
->NeedsUpdate
= AL_TRUE
;
607 // Source is now in UNDETERMINED mode
608 Source
->lSourceType
= AL_UNDETERMINED
;
609 oldlist
= ExchangePtr((void**)&Source
->queue
, NULL
);
612 // Delete all previous elements in the queue
613 while(oldlist
!= NULL
)
615 BufferListItem
= oldlist
;
616 oldlist
= BufferListItem
->next
;
618 if(BufferListItem
->buffer
)
619 DecrementRef(&BufferListItem
->buffer
->ref
);
620 free(BufferListItem
);
624 alSetError(pContext
, AL_INVALID_VALUE
);
627 alSetError(pContext
, AL_INVALID_OPERATION
);
628 UnlockContext(pContext
);
631 case AL_SOURCE_STATE
:
633 alSetError(pContext
, AL_INVALID_OPERATION
);
637 case AL_SAMPLE_OFFSET
:
641 LockContext(pContext
);
642 Source
->lOffsetType
= eParam
;
644 // Store Offset (convert Seconds into Milliseconds)
645 if(eParam
== AL_SEC_OFFSET
)
646 Source
->lOffset
= lValue
* 1000;
648 Source
->lOffset
= lValue
;
650 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
651 !pContext
->DeferUpdates
)
653 if(ApplyOffset(Source
) == AL_FALSE
)
654 alSetError(pContext
, AL_INVALID_VALUE
);
656 UnlockContext(pContext
);
659 alSetError(pContext
, AL_INVALID_VALUE
);
662 case AL_DIRECT_FILTER
: {
663 ALfilter
*filter
= NULL
;
666 (filter
=LookupFilter(pContext
->Device
->FilterMap
, lValue
)) != NULL
)
668 LockContext(pContext
);
671 Source
->DirectGain
= 1.0f
;
672 Source
->DirectGainHF
= 1.0f
;
676 Source
->DirectGain
= filter
->Gain
;
677 Source
->DirectGainHF
= filter
->GainHF
;
679 UnlockContext(pContext
);
680 Source
->NeedsUpdate
= AL_TRUE
;
683 alSetError(pContext
, AL_INVALID_VALUE
);
686 case AL_DIRECT_FILTER_GAINHF_AUTO
:
687 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
689 Source
->DryGainHFAuto
= lValue
;
690 Source
->NeedsUpdate
= AL_TRUE
;
693 alSetError(pContext
, AL_INVALID_VALUE
);
696 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
697 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
699 Source
->WetGainAuto
= lValue
;
700 Source
->NeedsUpdate
= AL_TRUE
;
703 alSetError(pContext
, AL_INVALID_VALUE
);
706 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
707 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
709 Source
->WetGainHFAuto
= lValue
;
710 Source
->NeedsUpdate
= AL_TRUE
;
713 alSetError(pContext
, AL_INVALID_VALUE
);
716 case AL_VIRTUAL_CHANNELS_SOFT
:
717 if(lValue
== AL_TRUE
|| lValue
== AL_FALSE
)
719 Source
->VirtualChannels
= lValue
;
720 Source
->NeedsUpdate
= AL_TRUE
;
723 alSetError(pContext
, AL_INVALID_VALUE
);
726 case AL_DISTANCE_MODEL
:
727 if(lValue
== AL_NONE
||
728 lValue
== AL_INVERSE_DISTANCE
||
729 lValue
== AL_INVERSE_DISTANCE_CLAMPED
||
730 lValue
== AL_LINEAR_DISTANCE
||
731 lValue
== AL_LINEAR_DISTANCE_CLAMPED
||
732 lValue
== AL_EXPONENT_DISTANCE
||
733 lValue
== AL_EXPONENT_DISTANCE_CLAMPED
)
735 Source
->DistanceModel
= lValue
;
736 if(pContext
->SourceDistanceModel
)
737 Source
->NeedsUpdate
= AL_TRUE
;
740 alSetError(pContext
, AL_INVALID_VALUE
);
744 alSetError(pContext
, AL_INVALID_ENUM
);
749 alSetError(pContext
, AL_INVALID_NAME
);
751 ALCcontext_DecRef(pContext
);
755 AL_API
void AL_APIENTRY
alSource3i(ALuint source
, ALenum eParam
, ALint lValue1
, ALint lValue2
, ALint lValue3
)
757 ALCcontext
*pContext
;
765 alSource3f(source
, eParam
, (ALfloat
)lValue1
, (ALfloat
)lValue2
, (ALfloat
)lValue3
);
769 pContext
= GetContextRef();
770 if(!pContext
) return;
772 if((Source
=LookupSource(pContext
->SourceMap
, source
)) != NULL
)
774 ALCdevice
*device
= pContext
->Device
;
778 case AL_AUXILIARY_SEND_FILTER
: {
779 ALeffectslot
*ALEffectSlot
= NULL
;
780 ALfilter
*ALFilter
= NULL
;
782 LockContext(pContext
);
783 if((ALuint
)lValue2
< device
->NumAuxSends
&&
785 (ALEffectSlot
=LookupEffectSlot(pContext
->EffectSlotMap
, lValue1
)) != NULL
) &&
787 (ALFilter
=LookupFilter(device
->FilterMap
, lValue3
)) != NULL
))
789 /* Release refcount on the previous slot, and add one for
791 if(ALEffectSlot
) IncrementRef(&ALEffectSlot
->ref
);
792 ALEffectSlot
= ExchangePtr((void**)&Source
->Send
[lValue2
].Slot
, ALEffectSlot
);
793 if(ALEffectSlot
) DecrementRef(&ALEffectSlot
->ref
);
798 Source
->Send
[lValue2
].WetGain
= 1.0f
;
799 Source
->Send
[lValue2
].WetGainHF
= 1.0f
;
803 Source
->Send
[lValue2
].WetGain
= ALFilter
->Gain
;
804 Source
->Send
[lValue2
].WetGainHF
= ALFilter
->GainHF
;
806 Source
->NeedsUpdate
= AL_TRUE
;
809 alSetError(pContext
, AL_INVALID_VALUE
);
810 UnlockContext(pContext
);
814 alSetError(pContext
, AL_INVALID_ENUM
);
819 alSetError(pContext
, AL_INVALID_NAME
);
821 ALCcontext_DecRef(pContext
);
825 AL_API
void AL_APIENTRY
alSourceiv(ALuint source
, ALenum eParam
, const ALint
* plValues
)
827 ALCcontext
*pContext
;
833 case AL_SOURCE_RELATIVE
:
834 case AL_CONE_INNER_ANGLE
:
835 case AL_CONE_OUTER_ANGLE
:
838 case AL_SOURCE_STATE
:
840 case AL_SAMPLE_OFFSET
:
842 case AL_MAX_DISTANCE
:
843 case AL_ROLLOFF_FACTOR
:
844 case AL_REFERENCE_DISTANCE
:
845 case AL_DIRECT_FILTER
:
846 case AL_DIRECT_FILTER_GAINHF_AUTO
:
847 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
848 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
849 case AL_DISTANCE_MODEL
:
850 case AL_VIRTUAL_CHANNELS_SOFT
:
851 alSourcei(source
, eParam
, plValues
[0]);
857 case AL_AUXILIARY_SEND_FILTER
:
858 alSource3i(source
, eParam
, plValues
[0], plValues
[1], plValues
[2]);
863 pContext
= GetContextRef();
864 if(!pContext
) return;
868 if(LookupSource(pContext
->SourceMap
, source
) != NULL
)
873 alSetError(pContext
, AL_INVALID_ENUM
);
878 alSetError(pContext
, AL_INVALID_NAME
);
881 alSetError(pContext
, AL_INVALID_VALUE
);
883 ALCcontext_DecRef(pContext
);
887 AL_API ALvoid AL_APIENTRY
alGetSourcef(ALuint source
, ALenum eParam
, ALfloat
*pflValue
)
889 ALCcontext
*pContext
;
894 pContext
= GetContextRef();
895 if(!pContext
) return;
899 if((Source
=LookupSource(pContext
->SourceMap
, source
)) != NULL
)
904 *pflValue
= Source
->flPitch
;
908 *pflValue
= Source
->flGain
;
912 *pflValue
= Source
->flMinGain
;
916 *pflValue
= Source
->flMaxGain
;
919 case AL_MAX_DISTANCE
:
920 *pflValue
= Source
->flMaxDistance
;
923 case AL_ROLLOFF_FACTOR
:
924 *pflValue
= Source
->flRollOffFactor
;
927 case AL_CONE_OUTER_GAIN
:
928 *pflValue
= Source
->flOuterGain
;
931 case AL_CONE_OUTER_GAINHF
:
932 *pflValue
= Source
->OuterGainHF
;
936 case AL_SAMPLE_OFFSET
:
938 LockContext(pContext
);
939 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
940 pContext
->Device
->Frequency
;
941 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
942 UnlockContext(pContext
);
943 *pflValue
= (ALfloat
)Offsets
[0];
946 case AL_CONE_INNER_ANGLE
:
947 *pflValue
= Source
->flInnerAngle
;
950 case AL_CONE_OUTER_ANGLE
:
951 *pflValue
= Source
->flOuterAngle
;
954 case AL_REFERENCE_DISTANCE
:
955 *pflValue
= Source
->flRefDistance
;
958 case AL_AIR_ABSORPTION_FACTOR
:
959 *pflValue
= Source
->AirAbsorptionFactor
;
962 case AL_ROOM_ROLLOFF_FACTOR
:
963 *pflValue
= Source
->RoomRolloffFactor
;
966 case AL_DOPPLER_FACTOR
:
967 *pflValue
= Source
->DopplerFactor
;
971 alSetError(pContext
, AL_INVALID_ENUM
);
976 alSetError(pContext
, AL_INVALID_NAME
);
979 alSetError(pContext
, AL_INVALID_VALUE
);
981 ALCcontext_DecRef(pContext
);
985 AL_API ALvoid AL_APIENTRY
alGetSource3f(ALuint source
, ALenum eParam
, ALfloat
* pflValue1
, ALfloat
* pflValue2
, ALfloat
* pflValue3
)
987 ALCcontext
*pContext
;
990 pContext
= GetContextRef();
991 if(!pContext
) return;
993 if(pflValue1
&& pflValue2
&& pflValue3
)
995 if((Source
=LookupSource(pContext
->SourceMap
, source
)) != NULL
)
1000 LockContext(pContext
);
1001 *pflValue1
= Source
->vPosition
[0];
1002 *pflValue2
= Source
->vPosition
[1];
1003 *pflValue3
= Source
->vPosition
[2];
1004 UnlockContext(pContext
);
1008 LockContext(pContext
);
1009 *pflValue1
= Source
->vVelocity
[0];
1010 *pflValue2
= Source
->vVelocity
[1];
1011 *pflValue3
= Source
->vVelocity
[2];
1012 UnlockContext(pContext
);
1016 LockContext(pContext
);
1017 *pflValue1
= Source
->vOrientation
[0];
1018 *pflValue2
= Source
->vOrientation
[1];
1019 *pflValue3
= Source
->vOrientation
[2];
1020 UnlockContext(pContext
);
1024 alSetError(pContext
, AL_INVALID_ENUM
);
1029 alSetError(pContext
, AL_INVALID_NAME
);
1032 alSetError(pContext
, AL_INVALID_VALUE
);
1034 ALCcontext_DecRef(pContext
);
1038 AL_API ALvoid AL_APIENTRY
alGetSourcefv(ALuint source
, ALenum eParam
, ALfloat
*pflValues
)
1040 ALCcontext
*pContext
;
1042 ALdouble Offsets
[2];
1051 case AL_MAX_DISTANCE
:
1052 case AL_ROLLOFF_FACTOR
:
1053 case AL_DOPPLER_FACTOR
:
1054 case AL_CONE_OUTER_GAIN
:
1056 case AL_SAMPLE_OFFSET
:
1057 case AL_BYTE_OFFSET
:
1058 case AL_CONE_INNER_ANGLE
:
1059 case AL_CONE_OUTER_ANGLE
:
1060 case AL_REFERENCE_DISTANCE
:
1061 case AL_CONE_OUTER_GAINHF
:
1062 case AL_AIR_ABSORPTION_FACTOR
:
1063 case AL_ROOM_ROLLOFF_FACTOR
:
1064 alGetSourcef(source
, eParam
, pflValues
);
1070 alGetSource3f(source
, eParam
, pflValues
+0, pflValues
+1, pflValues
+2);
1074 pContext
= GetContextRef();
1075 if(!pContext
) return;
1079 if((Source
=LookupSource(pContext
->SourceMap
, source
)) != NULL
)
1083 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1084 case AL_BYTE_RW_OFFSETS_SOFT
:
1085 LockContext(pContext
);
1086 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
1087 pContext
->Device
->Frequency
;
1088 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
1089 UnlockContext(pContext
);
1090 pflValues
[0] = (ALfloat
)Offsets
[0];
1091 pflValues
[1] = (ALfloat
)Offsets
[1];
1095 alSetError(pContext
, AL_INVALID_ENUM
);
1100 alSetError(pContext
, AL_INVALID_NAME
);
1103 alSetError(pContext
, AL_INVALID_VALUE
);
1105 ALCcontext_DecRef(pContext
);
1109 AL_API ALvoid AL_APIENTRY
alGetSourcei(ALuint source
, ALenum eParam
, ALint
*plValue
)
1111 ALbufferlistitem
*BufferList
;
1112 ALCcontext
*pContext
;
1114 ALdouble Offsets
[2];
1117 pContext
= GetContextRef();
1118 if(!pContext
) return;
1122 if((Source
=LookupSource(pContext
->SourceMap
, source
)) != NULL
)
1126 case AL_MAX_DISTANCE
:
1127 *plValue
= (ALint
)Source
->flMaxDistance
;
1130 case AL_ROLLOFF_FACTOR
:
1131 *plValue
= (ALint
)Source
->flRollOffFactor
;
1134 case AL_REFERENCE_DISTANCE
:
1135 *plValue
= (ALint
)Source
->flRefDistance
;
1138 case AL_SOURCE_RELATIVE
:
1139 *plValue
= Source
->bHeadRelative
;
1142 case AL_CONE_INNER_ANGLE
:
1143 *plValue
= (ALint
)Source
->flInnerAngle
;
1146 case AL_CONE_OUTER_ANGLE
:
1147 *plValue
= (ALint
)Source
->flOuterAngle
;
1151 *plValue
= Source
->bLooping
;
1155 LockContext(pContext
);
1156 BufferList
= Source
->queue
;
1157 if(Source
->lSourceType
!= AL_STATIC
)
1159 ALuint i
= Source
->BuffersPlayed
;
1162 BufferList
= BufferList
->next
;
1166 *plValue
= ((BufferList
&& BufferList
->buffer
) ?
1167 BufferList
->buffer
->buffer
: 0);
1168 UnlockContext(pContext
);
1171 case AL_SOURCE_STATE
:
1172 *plValue
= Source
->state
;
1175 case AL_BUFFERS_QUEUED
:
1176 *plValue
= Source
->BuffersInQueue
;
1179 case AL_BUFFERS_PROCESSED
:
1180 LockContext(pContext
);
1181 if(Source
->bLooping
|| Source
->lSourceType
!= AL_STREAMING
)
1183 /* Buffers on a looping source are in a perpetual state
1184 * of PENDING, so don't report any as PROCESSED */
1188 *plValue
= Source
->BuffersPlayed
;
1189 UnlockContext(pContext
);
1192 case AL_SOURCE_TYPE
:
1193 *plValue
= Source
->lSourceType
;
1197 case AL_SAMPLE_OFFSET
:
1198 case AL_BYTE_OFFSET
:
1199 LockContext(pContext
);
1200 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
1201 pContext
->Device
->Frequency
;
1202 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
1203 UnlockContext(pContext
);
1204 *plValue
= (ALint
)Offsets
[0];
1207 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1208 *plValue
= Source
->DryGainHFAuto
;
1211 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1212 *plValue
= Source
->WetGainAuto
;
1215 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1216 *plValue
= Source
->WetGainHFAuto
;
1219 case AL_DOPPLER_FACTOR
:
1220 *plValue
= (ALint
)Source
->DopplerFactor
;
1223 case AL_VIRTUAL_CHANNELS_SOFT
:
1224 *plValue
= Source
->VirtualChannels
;
1227 case AL_DISTANCE_MODEL
:
1228 *plValue
= Source
->DistanceModel
;
1232 alSetError(pContext
, AL_INVALID_ENUM
);
1237 alSetError(pContext
, AL_INVALID_NAME
);
1240 alSetError(pContext
, AL_INVALID_VALUE
);
1242 ALCcontext_DecRef(pContext
);
1246 AL_API
void AL_APIENTRY
alGetSource3i(ALuint source
, ALenum eParam
, ALint
* plValue1
, ALint
* plValue2
, ALint
* plValue3
)
1248 ALCcontext
*pContext
;
1251 pContext
= GetContextRef();
1252 if(!pContext
) return;
1254 if(plValue1
&& plValue2
&& plValue3
)
1256 if((Source
=LookupSource(pContext
->SourceMap
, source
)) != NULL
)
1261 LockContext(pContext
);
1262 *plValue1
= (ALint
)Source
->vPosition
[0];
1263 *plValue2
= (ALint
)Source
->vPosition
[1];
1264 *plValue3
= (ALint
)Source
->vPosition
[2];
1265 UnlockContext(pContext
);
1269 LockContext(pContext
);
1270 *plValue1
= (ALint
)Source
->vVelocity
[0];
1271 *plValue2
= (ALint
)Source
->vVelocity
[1];
1272 *plValue3
= (ALint
)Source
->vVelocity
[2];
1273 UnlockContext(pContext
);
1277 LockContext(pContext
);
1278 *plValue1
= (ALint
)Source
->vOrientation
[0];
1279 *plValue2
= (ALint
)Source
->vOrientation
[1];
1280 *plValue3
= (ALint
)Source
->vOrientation
[2];
1281 UnlockContext(pContext
);
1285 alSetError(pContext
, AL_INVALID_ENUM
);
1290 alSetError(pContext
, AL_INVALID_NAME
);
1293 alSetError(pContext
, AL_INVALID_VALUE
);
1295 ALCcontext_DecRef(pContext
);
1299 AL_API
void AL_APIENTRY
alGetSourceiv(ALuint source
, ALenum eParam
, ALint
* plValues
)
1301 ALCcontext
*pContext
;
1303 ALdouble Offsets
[2];
1308 case AL_SOURCE_RELATIVE
:
1309 case AL_CONE_INNER_ANGLE
:
1310 case AL_CONE_OUTER_ANGLE
:
1313 case AL_SOURCE_STATE
:
1314 case AL_BUFFERS_QUEUED
:
1315 case AL_BUFFERS_PROCESSED
:
1317 case AL_SAMPLE_OFFSET
:
1318 case AL_BYTE_OFFSET
:
1319 case AL_MAX_DISTANCE
:
1320 case AL_ROLLOFF_FACTOR
:
1321 case AL_DOPPLER_FACTOR
:
1322 case AL_REFERENCE_DISTANCE
:
1323 case AL_SOURCE_TYPE
:
1324 case AL_DIRECT_FILTER
:
1325 case AL_DIRECT_FILTER_GAINHF_AUTO
:
1326 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
:
1327 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
:
1328 case AL_DISTANCE_MODEL
:
1329 case AL_VIRTUAL_CHANNELS_SOFT
:
1330 alGetSourcei(source
, eParam
, plValues
);
1336 alGetSource3i(source
, eParam
, plValues
+0, plValues
+1, plValues
+2);
1340 pContext
= GetContextRef();
1341 if(!pContext
) return;
1345 if((Source
=LookupSource(pContext
->SourceMap
, source
)) != NULL
)
1349 case AL_SAMPLE_RW_OFFSETS_SOFT
:
1350 case AL_BYTE_RW_OFFSETS_SOFT
:
1351 LockContext(pContext
);
1352 updateLen
= (ALdouble
)pContext
->Device
->UpdateSize
/
1353 pContext
->Device
->Frequency
;
1354 GetSourceOffset(Source
, eParam
, Offsets
, updateLen
);
1355 UnlockContext(pContext
);
1356 plValues
[0] = (ALint
)Offsets
[0];
1357 plValues
[1] = (ALint
)Offsets
[1];
1361 alSetError(pContext
, AL_INVALID_ENUM
);
1366 alSetError(pContext
, AL_INVALID_NAME
);
1369 alSetError(pContext
, AL_INVALID_VALUE
);
1371 ALCcontext_DecRef(pContext
);
1375 AL_API ALvoid AL_APIENTRY
alSourcePlay(ALuint source
)
1377 alSourcePlayv(1, &source
);
1380 AL_API ALvoid AL_APIENTRY
alSourcePlayv(ALsizei n
, const ALuint
*sources
)
1382 ALCcontext
*Context
;
1386 Context
= GetContextRef();
1387 if(!Context
) return;
1391 alSetError(Context
, AL_INVALID_VALUE
);
1394 if(n
> 0 && !sources
)
1396 alSetError(Context
, AL_INVALID_VALUE
);
1400 // Check that all the Sources are valid
1401 for(i
= 0;i
< n
;i
++)
1403 if(!LookupSource(Context
->SourceMap
, sources
[i
]))
1405 alSetError(Context
, AL_INVALID_NAME
);
1410 LockContext(Context
);
1411 while(Context
->MaxActiveSources
-Context
->ActiveSourceCount
< n
)
1416 newcount
= Context
->MaxActiveSources
<< 1;
1418 temp
= realloc(Context
->ActiveSources
,
1419 sizeof(*Context
->ActiveSources
) * newcount
);
1422 UnlockContext(Context
);
1423 alSetError(Context
, AL_OUT_OF_MEMORY
);
1427 Context
->ActiveSources
= temp
;
1428 Context
->MaxActiveSources
= newcount
;
1431 for(i
= 0;i
< n
;i
++)
1433 Source
= LookupSource(Context
->SourceMap
, sources
[i
]);
1434 if(Context
->DeferUpdates
) Source
->new_state
= AL_PLAYING
;
1435 else SetSourceState(Source
, Context
, AL_PLAYING
);
1437 UnlockContext(Context
);
1440 ALCcontext_DecRef(Context
);
1443 AL_API ALvoid AL_APIENTRY
alSourcePause(ALuint source
)
1445 alSourcePausev(1, &source
);
1448 AL_API ALvoid AL_APIENTRY
alSourcePausev(ALsizei n
, const ALuint
*sources
)
1450 ALCcontext
*Context
;
1454 Context
= GetContextRef();
1455 if(!Context
) return;
1459 alSetError(Context
, AL_INVALID_VALUE
);
1462 if(n
> 0 && !sources
)
1464 alSetError(Context
, AL_INVALID_VALUE
);
1468 // Check all the Sources are valid
1469 for(i
= 0;i
< n
;i
++)
1471 if(!LookupSource(Context
->SourceMap
, sources
[i
]))
1473 alSetError(Context
, AL_INVALID_NAME
);
1478 LockContext(Context
);
1479 for(i
= 0;i
< n
;i
++)
1481 Source
= LookupSource(Context
->SourceMap
, sources
[i
]);
1482 if(Context
->DeferUpdates
) Source
->new_state
= AL_PAUSED
;
1483 else SetSourceState(Source
, Context
, AL_PAUSED
);
1485 UnlockContext(Context
);
1488 ALCcontext_DecRef(Context
);
1491 AL_API ALvoid AL_APIENTRY
alSourceStop(ALuint source
)
1493 alSourceStopv(1, &source
);
1496 AL_API ALvoid AL_APIENTRY
alSourceStopv(ALsizei n
, const ALuint
*sources
)
1498 ALCcontext
*Context
;
1502 Context
= GetContextRef();
1503 if(!Context
) return;
1507 alSetError(Context
, AL_INVALID_VALUE
);
1510 if(n
> 0 && !sources
)
1512 alSetError(Context
, AL_INVALID_VALUE
);
1516 // Check all the Sources are valid
1517 for(i
= 0;i
< n
;i
++)
1519 if(!LookupSource(Context
->SourceMap
, sources
[i
]))
1521 alSetError(Context
, AL_INVALID_NAME
);
1526 LockContext(Context
);
1527 for(i
= 0;i
< n
;i
++)
1529 Source
= LookupSource(Context
->SourceMap
, sources
[i
]);
1530 Source
->new_state
= AL_NONE
;
1531 SetSourceState(Source
, Context
, AL_STOPPED
);
1533 UnlockContext(Context
);
1536 ALCcontext_DecRef(Context
);
1539 AL_API ALvoid AL_APIENTRY
alSourceRewind(ALuint source
)
1541 alSourceRewindv(1, &source
);
1544 AL_API ALvoid AL_APIENTRY
alSourceRewindv(ALsizei n
, const ALuint
*sources
)
1546 ALCcontext
*Context
;
1550 Context
= GetContextRef();
1551 if(!Context
) return;
1555 alSetError(Context
, AL_INVALID_VALUE
);
1558 if(n
> 0 && !sources
)
1560 alSetError(Context
, AL_INVALID_VALUE
);
1564 // Check all the Sources are valid
1565 for(i
= 0;i
< n
;i
++)
1567 if(!LookupSource(Context
->SourceMap
, sources
[i
]))
1569 alSetError(Context
, AL_INVALID_NAME
);
1574 LockContext(Context
);
1575 for(i
= 0;i
< n
;i
++)
1577 Source
= LookupSource(Context
->SourceMap
, sources
[i
]);
1578 Source
->new_state
= AL_NONE
;
1579 SetSourceState(Source
, Context
, AL_INITIAL
);
1581 UnlockContext(Context
);
1584 ALCcontext_DecRef(Context
);
1588 AL_API ALvoid AL_APIENTRY
alSourceQueueBuffers(ALuint source
, ALsizei n
, const ALuint
*buffers
)
1590 ALCcontext
*Context
;
1594 ALbufferlistitem
*BufferListStart
= NULL
;
1595 ALbufferlistitem
*BufferList
;
1596 ALbuffer
*BufferFmt
;
1601 Context
= GetContextRef();
1602 if(!Context
) return;
1606 alSetError(Context
, AL_INVALID_VALUE
);
1610 // Check that all buffers are valid or zero and that the source is valid
1612 // Check that this is a valid source
1613 if((Source
=LookupSource(Context
->SourceMap
, source
)) == NULL
)
1615 alSetError(Context
, AL_INVALID_NAME
);
1619 LockContext(Context
);
1620 // Check that this is not a STATIC Source
1621 if(Source
->lSourceType
== AL_STATIC
)
1623 UnlockContext(Context
);
1624 // Invalid Source Type (can't queue on a Static Source)
1625 alSetError(Context
, AL_INVALID_OPERATION
);
1629 device
= Context
->Device
;
1633 // Check existing Queue (if any) for a valid Buffers and get its frequency and format
1634 BufferList
= Source
->queue
;
1637 if(BufferList
->buffer
)
1639 BufferFmt
= BufferList
->buffer
;
1642 BufferList
= BufferList
->next
;
1645 for(i
= 0;i
< n
;i
++)
1647 ALbuffer
*buffer
= NULL
;
1648 if(buffers
[i
] && (buffer
=LookupBuffer(device
->BufferMap
, buffers
[i
])) == NULL
)
1650 UnlockContext(Context
);
1651 alSetError(Context
, AL_INVALID_NAME
);
1655 if(!BufferListStart
)
1657 BufferListStart
= malloc(sizeof(ALbufferlistitem
));
1658 BufferListStart
->buffer
= buffer
;
1659 BufferListStart
->next
= NULL
;
1660 BufferListStart
->prev
= NULL
;
1661 BufferList
= BufferListStart
;
1665 BufferList
->next
= malloc(sizeof(ALbufferlistitem
));
1666 BufferList
->next
->buffer
= buffer
;
1667 BufferList
->next
->next
= NULL
;
1668 BufferList
->next
->prev
= BufferList
;
1669 BufferList
= BufferList
->next
;
1671 if(!buffer
) continue;
1673 // Increment reference counter for buffer
1674 IncrementRef(&buffer
->ref
);
1675 ReadLock(&buffer
->lock
);
1676 if(BufferFmt
== NULL
)
1680 Source
->NumChannels
= ChannelsFromFmt(buffer
->FmtChannels
);
1681 Source
->SampleSize
= BytesFromFmt(buffer
->FmtType
);
1682 if(buffer
->FmtChannels
== FmtMono
)
1683 Source
->Update
= CalcSourceParams
;
1685 Source
->Update
= CalcNonAttnSourceParams
;
1687 Source
->NeedsUpdate
= AL_TRUE
;
1689 else if(BufferFmt
->Frequency
!= buffer
->Frequency
||
1690 BufferFmt
->OriginalChannels
!= buffer
->OriginalChannels
||
1691 BufferFmt
->OriginalType
!= buffer
->OriginalType
)
1693 ReadUnlock(&buffer
->lock
);
1694 UnlockContext(Context
);
1695 alSetError(Context
, AL_INVALID_OPERATION
);
1698 ReadUnlock(&buffer
->lock
);
1701 // Change Source Type
1702 Source
->lSourceType
= AL_STREAMING
;
1704 if(Source
->queue
== NULL
)
1705 Source
->queue
= BufferListStart
;
1708 // Find end of queue
1709 BufferList
= Source
->queue
;
1710 while(BufferList
->next
!= NULL
)
1711 BufferList
= BufferList
->next
;
1713 BufferListStart
->prev
= BufferList
;
1714 BufferList
->next
= BufferListStart
;
1717 // Update number of buffers in queue
1718 Source
->BuffersInQueue
+= n
;
1720 UnlockContext(Context
);
1721 ALCcontext_DecRef(Context
);
1725 while(BufferListStart
)
1727 BufferList
= BufferListStart
;
1728 BufferListStart
= BufferList
->next
;
1730 if(BufferList
->buffer
)
1731 DecrementRef(&BufferList
->buffer
->ref
);
1734 ALCcontext_DecRef(Context
);
1738 // Implementation assumes that n is the number of buffers to be removed from the queue and buffers is
1739 // an array of buffer IDs that are to be filled with the names of the buffers removed
1740 AL_API ALvoid AL_APIENTRY
alSourceUnqueueBuffers( ALuint source
, ALsizei n
, ALuint
* buffers
)
1742 ALCcontext
*Context
;
1745 ALbufferlistitem
*BufferList
;
1750 Context
= GetContextRef();
1751 if(!Context
) return;
1755 alSetError(Context
, AL_INVALID_VALUE
);
1759 if((Source
=LookupSource(Context
->SourceMap
, source
)) == NULL
)
1761 alSetError(Context
, AL_INVALID_NAME
);
1765 LockContext(Context
);
1766 if(Source
->bLooping
|| Source
->lSourceType
!= AL_STREAMING
||
1767 (ALuint
)n
> Source
->BuffersPlayed
)
1769 UnlockContext(Context
);
1770 // Some buffers can't be unqueue because they have not been processed
1771 alSetError(Context
, AL_INVALID_VALUE
);
1775 for(i
= 0;i
< n
;i
++)
1777 BufferList
= Source
->queue
;
1778 Source
->queue
= BufferList
->next
;
1779 Source
->BuffersInQueue
--;
1780 Source
->BuffersPlayed
--;
1782 if(BufferList
->buffer
)
1784 // Record name of buffer
1785 buffers
[i
] = BufferList
->buffer
->buffer
;
1786 // Decrement buffer reference counter
1787 DecrementRef(&BufferList
->buffer
->ref
);
1792 // Release memory for buffer list item
1796 Source
->queue
->prev
= NULL
;
1797 UnlockContext(Context
);
1800 ALCcontext_DecRef(Context
);
1804 static ALvoid
InitSourceParams(ALsource
*Source
)
1808 Source
->flInnerAngle
= 360.0f
;
1809 Source
->flOuterAngle
= 360.0f
;
1810 Source
->flPitch
= 1.0f
;
1811 Source
->vPosition
[0] = 0.0f
;
1812 Source
->vPosition
[1] = 0.0f
;
1813 Source
->vPosition
[2] = 0.0f
;
1814 Source
->vOrientation
[0] = 0.0f
;
1815 Source
->vOrientation
[1] = 0.0f
;
1816 Source
->vOrientation
[2] = 0.0f
;
1817 Source
->vVelocity
[0] = 0.0f
;
1818 Source
->vVelocity
[1] = 0.0f
;
1819 Source
->vVelocity
[2] = 0.0f
;
1820 Source
->flRefDistance
= 1.0f
;
1821 Source
->flMaxDistance
= FLT_MAX
;
1822 Source
->flRollOffFactor
= 1.0f
;
1823 Source
->bLooping
= AL_FALSE
;
1824 Source
->flGain
= 1.0f
;
1825 Source
->flMinGain
= 0.0f
;
1826 Source
->flMaxGain
= 1.0f
;
1827 Source
->flOuterGain
= 0.0f
;
1828 Source
->OuterGainHF
= 1.0f
;
1830 Source
->DryGainHFAuto
= AL_TRUE
;
1831 Source
->WetGainAuto
= AL_TRUE
;
1832 Source
->WetGainHFAuto
= AL_TRUE
;
1833 Source
->AirAbsorptionFactor
= 0.0f
;
1834 Source
->RoomRolloffFactor
= 0.0f
;
1835 Source
->DopplerFactor
= 1.0f
;
1836 Source
->VirtualChannels
= AL_TRUE
;
1838 Source
->DistanceModel
= AL_INVERSE_DISTANCE_CLAMPED
;
1840 Source
->Resampler
= DefaultResampler
;
1842 Source
->state
= AL_INITIAL
;
1843 Source
->new_state
= AL_NONE
;
1844 Source
->lSourceType
= AL_UNDETERMINED
;
1845 Source
->lOffset
= -1;
1847 Source
->DirectGain
= 1.0f
;
1848 Source
->DirectGainHF
= 1.0f
;
1849 for(i
= 0;i
< MAX_SENDS
;i
++)
1851 Source
->Send
[i
].WetGain
= 1.0f
;
1852 Source
->Send
[i
].WetGainHF
= 1.0f
;
1855 Source
->NeedsUpdate
= AL_TRUE
;
1857 Source
->HrtfMoving
= AL_FALSE
;
1858 Source
->HrtfCounter
= 0;
1865 * Sets the source's new play state given its current state
1867 ALvoid
SetSourceState(ALsource
*Source
, ALCcontext
*Context
, ALenum state
)
1869 if(state
== AL_PLAYING
)
1871 ALbufferlistitem
*BufferList
;
1874 /* Check that there is a queue containing at least one non-null, non zero length AL Buffer */
1875 BufferList
= Source
->queue
;
1878 if(BufferList
->buffer
!= NULL
&& BufferList
->buffer
->size
)
1880 BufferList
= BufferList
->next
;
1883 /* If there's nothing to play, or device is disconnected, go right to
1885 if(!BufferList
|| !Context
->Device
->Connected
)
1887 SetSourceState(Source
, Context
, AL_STOPPED
);
1891 if(Source
->state
!= AL_PLAYING
)
1893 for(j
= 0;j
< MAXCHANNELS
;j
++)
1895 for(k
= 0;k
< SRC_HISTORY_LENGTH
;k
++)
1896 Source
->HrtfHistory
[j
][k
] = 0.0f
;
1897 for(k
= 0;k
< HRIR_LENGTH
;k
++)
1899 Source
->HrtfValues
[j
][k
][0] = 0.0f
;
1900 Source
->HrtfValues
[j
][k
][1] = 0.0f
;
1905 if(Source
->state
!= AL_PAUSED
)
1907 Source
->state
= AL_PLAYING
;
1908 Source
->position
= 0;
1909 Source
->position_fraction
= 0;
1910 Source
->BuffersPlayed
= 0;
1913 Source
->state
= AL_PLAYING
;
1915 // Check if an Offset has been set
1916 if(Source
->lOffset
!= -1)
1917 ApplyOffset(Source
);
1919 for(j
= 0;j
< Context
->ActiveSourceCount
;j
++)
1921 if(Context
->ActiveSources
[j
] == Source
)
1924 if(j
== Context
->ActiveSourceCount
)
1925 Context
->ActiveSources
[Context
->ActiveSourceCount
++] = Source
;
1927 else if(state
== AL_PAUSED
)
1929 if(Source
->state
== AL_PLAYING
)
1931 Source
->state
= AL_PAUSED
;
1932 Source
->HrtfMoving
= AL_FALSE
;
1933 Source
->HrtfCounter
= 0;
1936 else if(state
== AL_STOPPED
)
1938 if(Source
->state
!= AL_INITIAL
)
1940 Source
->state
= AL_STOPPED
;
1941 Source
->BuffersPlayed
= Source
->BuffersInQueue
;
1942 Source
->HrtfMoving
= AL_FALSE
;
1943 Source
->HrtfCounter
= 0;
1945 Source
->lOffset
= -1;
1947 else if(state
== AL_INITIAL
)
1949 if(Source
->state
!= AL_INITIAL
)
1951 Source
->state
= AL_INITIAL
;
1952 Source
->position
= 0;
1953 Source
->position_fraction
= 0;
1954 Source
->BuffersPlayed
= 0;
1955 Source
->HrtfMoving
= AL_FALSE
;
1956 Source
->HrtfCounter
= 0;
1958 Source
->lOffset
= -1;
1965 Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds)
1966 The offset is relative to the start of the queue (not the start of the current buffer)
1968 static ALvoid
GetSourceOffset(ALsource
*Source
, ALenum name
, ALdouble
*offset
, ALdouble updateLen
)
1970 const ALbufferlistitem
*BufferList
;
1971 const ALbuffer
*Buffer
= NULL
;
1972 enum UserFmtType OriginalType
;
1974 ALint Channels
, Bytes
;
1975 ALuint readPos
, writePos
;
1976 ALuint TotalBufferDataSize
;
1979 // Find the first non-NULL Buffer in the Queue
1980 BufferList
= Source
->queue
;
1983 if(BufferList
->buffer
)
1985 Buffer
= BufferList
->buffer
;
1988 BufferList
= BufferList
->next
;
1991 if((Source
->state
!= AL_PLAYING
&& Source
->state
!= AL_PAUSED
) || !Buffer
)
1998 // Get Current Buffer Size and frequency (in milliseconds)
1999 BufferFreq
= Buffer
->Frequency
;
2000 OriginalType
= Buffer
->OriginalType
;
2001 Channels
= ChannelsFromFmt(Buffer
->FmtChannels
);
2002 Bytes
= BytesFromFmt(Buffer
->FmtType
);
2004 // Get Current BytesPlayed (NOTE : This is the byte offset into the *current* buffer)
2005 readPos
= Source
->position
* Channels
* Bytes
;
2006 // Add byte length of any processed buffers in the queue
2007 TotalBufferDataSize
= 0;
2008 BufferList
= Source
->queue
;
2009 for(i
= 0;BufferList
;i
++)
2011 if(BufferList
->buffer
)
2013 if(i
< Source
->BuffersPlayed
)
2014 readPos
+= BufferList
->buffer
->size
;
2015 TotalBufferDataSize
+= BufferList
->buffer
->size
;
2017 BufferList
= BufferList
->next
;
2019 if(Source
->state
== AL_PLAYING
)
2020 writePos
= readPos
+ ((ALuint
)(updateLen
*BufferFreq
) * Channels
* Bytes
);
2024 if(Source
->bLooping
)
2026 readPos
%= TotalBufferDataSize
;
2027 writePos
%= TotalBufferDataSize
;
2031 // Wrap positions back to 0
2032 if(readPos
>= TotalBufferDataSize
)
2034 if(writePos
>= TotalBufferDataSize
)
2041 offset
[0] = (ALdouble
)readPos
/ (Channels
* Bytes
* BufferFreq
);
2042 offset
[1] = (ALdouble
)writePos
/ (Channels
* Bytes
* BufferFreq
);
2044 case AL_SAMPLE_OFFSET
:
2045 case AL_SAMPLE_RW_OFFSETS_SOFT
:
2046 offset
[0] = (ALdouble
)(readPos
/ (Channels
* Bytes
));
2047 offset
[1] = (ALdouble
)(writePos
/ (Channels
* Bytes
));
2049 case AL_BYTE_OFFSET
:
2050 case AL_BYTE_RW_OFFSETS_SOFT
:
2051 // Take into account the original format of the Buffer
2052 if(OriginalType
== UserFmtIMA4
)
2054 ALuint FrameBlockSize
= 65 * Bytes
* Channels
;
2055 ALuint BlockSize
= 36 * Channels
;
2057 // Round down to nearest ADPCM block
2058 offset
[0] = (ALdouble
)(readPos
/ FrameBlockSize
* BlockSize
);
2059 if(Source
->state
!= AL_PLAYING
)
2060 offset
[1] = offset
[0];
2063 // Round up to nearest ADPCM block
2064 offset
[1] = (ALdouble
)((writePos
+FrameBlockSize
-1) /
2065 FrameBlockSize
* BlockSize
);
2070 ALuint OrigBytes
= BytesFromUserFmt(OriginalType
);
2071 offset
[0] = (ALdouble
)(readPos
/ Bytes
* OrigBytes
);
2072 offset
[1] = (ALdouble
)(writePos
/ Bytes
* OrigBytes
);
2082 Apply a playback offset to the Source. This function will update the queue (to correctly
2083 mark buffers as 'pending' or 'processed' depending upon the new offset.
2085 ALboolean
ApplyOffset(ALsource
*Source
)
2087 const ALbufferlistitem
*BufferList
;
2088 const ALbuffer
*Buffer
;
2089 ALint lBufferSize
, lTotalBufferSize
;
2090 ALint BuffersPlayed
;
2093 // Get true byte offset
2094 lByteOffset
= GetByteOffset(Source
);
2096 // If the offset is invalid, don't apply it
2097 if(lByteOffset
== -1)
2100 // Sort out the queue (pending and processed states)
2101 BufferList
= Source
->queue
;
2102 lTotalBufferSize
= 0;
2107 Buffer
= BufferList
->buffer
;
2108 lBufferSize
= Buffer
? Buffer
->size
: 0;
2110 if(lBufferSize
<= lByteOffset
-lTotalBufferSize
)
2112 // Offset is past this buffer so increment BuffersPlayed
2115 else if(lTotalBufferSize
<= lByteOffset
)
2117 // Offset is within this buffer
2118 Source
->BuffersPlayed
= BuffersPlayed
;
2120 // SW Mixer Positions are in Samples
2121 Source
->position
= (lByteOffset
- lTotalBufferSize
) /
2122 FrameSizeFromFmt(Buffer
->FmtChannels
, Buffer
->FmtType
);
2126 // Increment the TotalBufferSize
2127 lTotalBufferSize
+= lBufferSize
;
2129 // Move on to next buffer in the Queue
2130 BufferList
= BufferList
->next
;
2132 // Offset is out of range of the buffer queue
2140 Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
2141 offset supplied by the application). This takes into account the fact that the buffer format
2142 may have been modifed by AL (e.g 8bit samples are converted to float)
2144 static ALint
GetByteOffset(ALsource
*Source
)
2146 const ALbuffer
*Buffer
= NULL
;
2147 const ALbufferlistitem
*BufferList
;
2148 ALint ByteOffset
= -1;
2150 // Find the first non-NULL Buffer in the Queue
2151 BufferList
= Source
->queue
;
2154 if(BufferList
->buffer
)
2156 Buffer
= BufferList
->buffer
;
2159 BufferList
= BufferList
->next
;
2164 Source
->lOffset
= -1;
2168 // Determine the ByteOffset (and ensure it is block aligned)
2169 switch(Source
->lOffsetType
)
2171 case AL_BYTE_OFFSET
:
2172 // Take into consideration the original format
2173 ByteOffset
= Source
->lOffset
;
2174 if(Buffer
->OriginalType
== UserFmtIMA4
)
2176 // Round down to nearest ADPCM block
2177 ByteOffset
/= 36 * ChannelsFromUserFmt(Buffer
->OriginalChannels
);
2178 // Multiply by compression rate (65 sample frames per block)
2182 ByteOffset
/= FrameSizeFromUserFmt(Buffer
->OriginalChannels
, Buffer
->OriginalType
);
2183 ByteOffset
*= FrameSizeFromFmt(Buffer
->FmtChannels
, Buffer
->FmtType
);
2186 case AL_SAMPLE_OFFSET
:
2187 ByteOffset
= Source
->lOffset
* FrameSizeFromFmt(Buffer
->FmtChannels
, Buffer
->FmtType
);
2191 // Note - lOffset is internally stored as Milliseconds
2192 ByteOffset
= (ALint
)(Source
->lOffset
/ 1000.0 * Buffer
->Frequency
);
2193 ByteOffset
*= FrameSizeFromFmt(Buffer
->FmtChannels
, Buffer
->FmtType
);
2197 Source
->lOffset
= -1;
2203 ALvoid
ReleaseALSources(ALCcontext
*Context
)
2207 for(pos
= 0;pos
< Context
->SourceMap
.size
;pos
++)
2209 ALsource
*temp
= Context
->SourceMap
.array
[pos
].value
;
2210 Context
->SourceMap
.array
[pos
].value
= NULL
;
2212 // For each buffer in the source's queue, decrement its reference counter and remove it
2213 while(temp
->queue
!= NULL
)
2215 ALbufferlistitem
*BufferList
= temp
->queue
;
2216 temp
->queue
= BufferList
->next
;
2218 if(BufferList
->buffer
!= NULL
)
2219 DecrementRef(&BufferList
->buffer
->ref
);
2223 for(j
= 0;j
< MAX_SENDS
;++j
)
2225 if(temp
->Send
[j
].Slot
)
2226 DecrementRef(&temp
->Send
[j
].Slot
->ref
);
2227 temp
->Send
[j
].Slot
= NULL
;
2230 // Release source structure
2231 FreeThunkEntry(temp
->source
);
2232 memset(temp
, 0, sizeof(ALsource
));