bd2e6f657cb71d2ba1947c3d8fdb0c78c0b46f38
[openal-soft.git] / OpenAL32 / alSource.c
blobbd2e6f657cb71d2ba1947c3d8fdb0c78c0b46f38
1 /**
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
21 #include "config.h"
23 #include <stdlib.h>
24 #include <math.h>
25 #include <float.h>
27 #include "AL/al.h"
28 #include "AL/alc.h"
29 #include "alMain.h"
30 #include "alError.h"
31 #include "alSource.h"
32 #include "alBuffer.h"
33 #include "alThunk.h"
34 #include "alAuxEffectSlot.h"
37 enum Resampler DefaultResampler = LinearResampler;
38 const ALsizei ResamplerPadding[ResamplerMax] = {
39 0, /* Point */
40 1, /* Linear */
41 2, /* Cubic */
43 const ALsizei ResamplerPrePadding[ResamplerMax] = {
44 0, /* Point */
45 0, /* Linear */
46 1, /* Cubic */
50 static ALvoid InitSourceParams(ALsource *Source);
51 static ALint64 GetSourceOffset(const ALsource *Source);
52 static ALdouble GetSourceSecOffset(const ALsource *Source);
53 static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offsets, ALdouble updateLen);
54 static ALint GetSampleOffset(ALsource *Source);
56 typedef enum SrcFloatProp {
57 sfPitch = AL_PITCH,
58 sfGain = AL_GAIN,
59 sfMinGain = AL_MIN_GAIN,
60 sfMaxGain = AL_MAX_GAIN,
61 sfMaxDistance = AL_MAX_DISTANCE,
62 sfRolloffFactor = AL_ROLLOFF_FACTOR,
63 sfDopplerFactor = AL_DOPPLER_FACTOR,
64 sfConeOuterGain = AL_CONE_OUTER_GAIN,
65 sfSecOffset = AL_SEC_OFFSET,
66 sfSampleOffset = AL_SAMPLE_OFFSET,
67 sfByteOffset = AL_BYTE_OFFSET,
68 sfConeInnerAngle = AL_CONE_INNER_ANGLE,
69 sfConeOuterAngle = AL_CONE_OUTER_ANGLE,
70 sfRefDistance = AL_REFERENCE_DISTANCE,
72 sfPosition = AL_POSITION,
73 sfVelocity = AL_VELOCITY,
74 sfDirection = AL_DIRECTION,
76 sfSourceRelative = AL_SOURCE_RELATIVE,
77 sfLooping = AL_LOOPING,
78 sfBuffer = AL_BUFFER,
79 sfSourceState = AL_SOURCE_STATE,
80 sfBuffersQueued = AL_BUFFERS_QUEUED,
81 sfBuffersProcessed = AL_BUFFERS_PROCESSED,
82 sfSourceType = AL_SOURCE_TYPE,
84 /* ALC_EXT_EFX */
85 sfConeOuterGainHF = AL_CONE_OUTER_GAINHF,
86 sfAirAbsorptionFactor = AL_AIR_ABSORPTION_FACTOR,
87 sfRoomRolloffFactor = AL_ROOM_ROLLOFF_FACTOR,
88 sfDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO,
89 sfAuxSendFilterGainAuto = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO,
90 sfAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO,
92 /* AL_SOFT_direct_channels */
93 sfDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT,
95 /* AL_EXT_source_distance_model */
96 sfDistanceModel = AL_DISTANCE_MODEL,
98 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
99 sfSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT,
100 sfByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT,
102 /* AL_SOFT_source_latency */
103 sfSecOffsetLatencySOFT = AL_SEC_OFFSET_LATENCY_SOFT,
104 } SrcFloatProp;
106 typedef enum SrcIntProp {
107 siMaxDistance = AL_MAX_DISTANCE,
108 siRolloffFactor = AL_ROLLOFF_FACTOR,
109 siRefDistance = AL_REFERENCE_DISTANCE,
110 siSourceRelative = AL_SOURCE_RELATIVE,
111 siConeInnerAngle = AL_CONE_INNER_ANGLE,
112 siConeOuterAngle = AL_CONE_OUTER_ANGLE,
113 siLooping = AL_LOOPING,
114 siBuffer = AL_BUFFER,
115 siSourceState = AL_SOURCE_STATE,
116 siBuffersQueued = AL_BUFFERS_QUEUED,
117 siBuffersProcessed = AL_BUFFERS_PROCESSED,
118 siSourceType = AL_SOURCE_TYPE,
119 siSecOffset = AL_SEC_OFFSET,
120 siSampleOffset = AL_SAMPLE_OFFSET,
121 siByteOffset = AL_BYTE_OFFSET,
122 siDopplerFactor = AL_DOPPLER_FACTOR,
123 siPosition = AL_POSITION,
124 siVelocity = AL_VELOCITY,
125 siDirection = AL_DIRECTION,
127 /* ALC_EXT_EFX */
128 siDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO,
129 siAuxSendFilterGainAutio = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO,
130 siAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO,
131 siDirectFilter = AL_DIRECT_FILTER,
132 siAuxSendFilter = AL_AUXILIARY_SEND_FILTER,
134 /* AL_SOFT_direct_channels */
135 siDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT,
137 /* AL_EXT_source_distance_model */
138 siDistanceModel = AL_DISTANCE_MODEL,
140 /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
141 siSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT,
142 siByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT,
144 /* AL_SOFT_source_latency */
145 siSampleOffsetLatencySOFT = AL_SAMPLE_OFFSET_LATENCY_SOFT,
146 } SrcIntProp;
148 static ALenum SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values);
149 static ALenum SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint *values);
150 static ALenum SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint64SOFT *values);
152 static ALenum GetSourcedv(const ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values);
153 static ALenum GetSourceiv(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values);
154 static ALenum GetSourcei64v(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values);
156 static ALint FloatValsByProp(ALenum prop)
158 if(prop != (ALenum)((SrcFloatProp)prop))
159 return 0;
160 switch((SrcFloatProp)prop)
162 case sfPitch:
163 case sfGain:
164 case sfMinGain:
165 case sfMaxGain:
166 case sfMaxDistance:
167 case sfRolloffFactor:
168 case sfDopplerFactor:
169 case sfConeOuterGain:
170 case sfSecOffset:
171 case sfSampleOffset:
172 case sfByteOffset:
173 case sfConeInnerAngle:
174 case sfConeOuterAngle:
175 case sfRefDistance:
176 case sfConeOuterGainHF:
177 case sfAirAbsorptionFactor:
178 case sfRoomRolloffFactor:
179 case sfDirectFilterGainHFAuto:
180 case sfAuxSendFilterGainAuto:
181 case sfAuxSendFilterGainHFAuto:
182 case sfDirectChannelsSOFT:
183 case sfDistanceModel:
184 case sfSourceRelative:
185 case sfLooping:
186 case sfBuffer:
187 case sfSourceState:
188 case sfBuffersQueued:
189 case sfBuffersProcessed:
190 case sfSourceType:
191 return 1;
193 case sfSampleRWOffsetsSOFT:
194 case sfByteRWOffsetsSOFT:
195 return 2;
197 case sfPosition:
198 case sfVelocity:
199 case sfDirection:
200 return 3;
202 case sfSecOffsetLatencySOFT:
203 break; /* Double only */
205 return 0;
207 static ALint DoubleValsByProp(ALenum prop)
209 if(prop != (ALenum)((SrcFloatProp)prop))
210 return 0;
211 switch((SrcFloatProp)prop)
213 case sfPitch:
214 case sfGain:
215 case sfMinGain:
216 case sfMaxGain:
217 case sfMaxDistance:
218 case sfRolloffFactor:
219 case sfDopplerFactor:
220 case sfConeOuterGain:
221 case sfSecOffset:
222 case sfSampleOffset:
223 case sfByteOffset:
224 case sfConeInnerAngle:
225 case sfConeOuterAngle:
226 case sfRefDistance:
227 case sfConeOuterGainHF:
228 case sfAirAbsorptionFactor:
229 case sfRoomRolloffFactor:
230 case sfDirectFilterGainHFAuto:
231 case sfAuxSendFilterGainAuto:
232 case sfAuxSendFilterGainHFAuto:
233 case sfDirectChannelsSOFT:
234 case sfDistanceModel:
235 case sfSourceRelative:
236 case sfLooping:
237 case sfBuffer:
238 case sfSourceState:
239 case sfBuffersQueued:
240 case sfBuffersProcessed:
241 case sfSourceType:
242 return 1;
244 case sfSampleRWOffsetsSOFT:
245 case sfByteRWOffsetsSOFT:
246 case sfSecOffsetLatencySOFT:
247 return 2;
249 case sfPosition:
250 case sfVelocity:
251 case sfDirection:
252 return 3;
254 return 0;
257 static ALint IntValsByProp(ALenum prop)
259 if(prop != (ALenum)((SrcIntProp)prop))
260 return 0;
261 switch((SrcIntProp)prop)
263 case siMaxDistance:
264 case siRolloffFactor:
265 case siRefDistance:
266 case siSourceRelative:
267 case siConeInnerAngle:
268 case siConeOuterAngle:
269 case siLooping:
270 case siBuffer:
271 case siSourceState:
272 case siBuffersQueued:
273 case siBuffersProcessed:
274 case siSourceType:
275 case siSecOffset:
276 case siSampleOffset:
277 case siByteOffset:
278 case siDopplerFactor:
279 case siDirectFilterGainHFAuto:
280 case siAuxSendFilterGainAutio:
281 case siAuxSendFilterGainHFAuto:
282 case siDirectFilter:
283 case siDirectChannelsSOFT:
284 case siDistanceModel:
285 return 1;
287 case siSampleRWOffsetsSOFT:
288 case siByteRWOffsetsSOFT:
289 return 2;
291 case siPosition:
292 case siVelocity:
293 case siDirection:
294 case siAuxSendFilter:
295 return 3;
297 case siSampleOffsetLatencySOFT:
298 break; /* i64 only */
300 return 0;
302 static ALint Int64ValsByProp(ALenum prop)
304 if(prop != (ALenum)((SrcIntProp)prop))
305 return 0;
306 switch((SrcIntProp)prop)
308 case siMaxDistance:
309 case siRolloffFactor:
310 case siRefDistance:
311 case siSourceRelative:
312 case siConeInnerAngle:
313 case siConeOuterAngle:
314 case siLooping:
315 case siBuffer:
316 case siSourceState:
317 case siBuffersQueued:
318 case siBuffersProcessed:
319 case siSourceType:
320 case siSecOffset:
321 case siSampleOffset:
322 case siByteOffset:
323 case siDopplerFactor:
324 case siDirectFilterGainHFAuto:
325 case siAuxSendFilterGainAutio:
326 case siAuxSendFilterGainHFAuto:
327 case siDirectFilter:
328 case siDirectChannelsSOFT:
329 case siDistanceModel:
330 return 1;
332 case siSampleRWOffsetsSOFT:
333 case siByteRWOffsetsSOFT:
334 case siSampleOffsetLatencySOFT:
335 return 2;
337 case siPosition:
338 case siVelocity:
339 case siDirection:
340 case siAuxSendFilter:
341 return 3;
343 return 0;
347 #define RETERR(x) do { \
348 alSetError(Context, (x)); \
349 return (x); \
350 } while(0)
352 #define CHECKVAL(x) do { \
353 if(!(x)) \
354 RETERR(AL_INVALID_VALUE); \
355 } while(0)
357 static ALenum SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values)
359 ALint ival;
361 switch(prop)
363 case AL_PITCH:
364 CHECKVAL(*values >= 0.0f);
366 Source->Pitch = *values;
367 Source->NeedsUpdate = AL_TRUE;
368 return AL_NO_ERROR;
370 case AL_CONE_INNER_ANGLE:
371 CHECKVAL(*values >= 0.0f && *values <= 360.0f);
373 Source->InnerAngle = *values;
374 Source->NeedsUpdate = AL_TRUE;
375 return AL_NO_ERROR;
377 case AL_CONE_OUTER_ANGLE:
378 CHECKVAL(*values >= 0.0f && *values <= 360.0f);
380 Source->OuterAngle = *values;
381 Source->NeedsUpdate = AL_TRUE;
382 return AL_NO_ERROR;
384 case AL_GAIN:
385 CHECKVAL(*values >= 0.0f);
387 Source->Gain = *values;
388 Source->NeedsUpdate = AL_TRUE;
389 return AL_NO_ERROR;
391 case AL_MAX_DISTANCE:
392 CHECKVAL(*values >= 0.0f);
394 Source->MaxDistance = *values;
395 Source->NeedsUpdate = AL_TRUE;
396 return AL_NO_ERROR;
398 case AL_ROLLOFF_FACTOR:
399 CHECKVAL(*values >= 0.0f);
401 Source->RollOffFactor = *values;
402 Source->NeedsUpdate = AL_TRUE;
403 return AL_NO_ERROR;
405 case AL_REFERENCE_DISTANCE:
406 CHECKVAL(*values >= 0.0f);
408 Source->RefDistance = *values;
409 Source->NeedsUpdate = AL_TRUE;
410 return AL_NO_ERROR;
412 case AL_MIN_GAIN:
413 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
415 Source->MinGain = *values;
416 Source->NeedsUpdate = AL_TRUE;
417 return AL_NO_ERROR;
419 case AL_MAX_GAIN:
420 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
422 Source->MaxGain = *values;
423 Source->NeedsUpdate = AL_TRUE;
424 return AL_NO_ERROR;
426 case AL_CONE_OUTER_GAIN:
427 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
429 Source->OuterGain = *values;
430 Source->NeedsUpdate = AL_TRUE;
431 return AL_NO_ERROR;
433 case AL_CONE_OUTER_GAINHF:
434 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
436 Source->OuterGainHF = *values;
437 Source->NeedsUpdate = AL_TRUE;
438 return AL_NO_ERROR;
440 case AL_AIR_ABSORPTION_FACTOR:
441 CHECKVAL(*values >= 0.0f && *values <= 10.0f);
443 Source->AirAbsorptionFactor = *values;
444 Source->NeedsUpdate = AL_TRUE;
445 return AL_NO_ERROR;
447 case AL_ROOM_ROLLOFF_FACTOR:
448 CHECKVAL(*values >= 0.0f && *values <= 10.0f);
450 Source->RoomRolloffFactor = *values;
451 Source->NeedsUpdate = AL_TRUE;
452 return AL_NO_ERROR;
454 case AL_DOPPLER_FACTOR:
455 CHECKVAL(*values >= 0.0f && *values <= 1.0f);
457 Source->DopplerFactor = *values;
458 Source->NeedsUpdate = AL_TRUE;
459 return AL_NO_ERROR;
461 case AL_SEC_OFFSET:
462 case AL_SAMPLE_OFFSET:
463 case AL_BYTE_OFFSET:
464 CHECKVAL(*values >= 0.0f);
466 LockContext(Context);
467 Source->OffsetType = prop;
468 Source->Offset = *values;
470 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
471 !Context->DeferUpdates)
473 if(ApplyOffset(Source) == AL_FALSE)
475 UnlockContext(Context);
476 RETERR(AL_INVALID_VALUE);
479 UnlockContext(Context);
480 return AL_NO_ERROR;
483 case AL_SEC_OFFSET_LATENCY_SOFT:
484 /* Query only */
485 RETERR(AL_INVALID_OPERATION);
488 case AL_POSITION:
489 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
491 LockContext(Context);
492 Source->Position[0] = values[0];
493 Source->Position[1] = values[1];
494 Source->Position[2] = values[2];
495 UnlockContext(Context);
496 Source->NeedsUpdate = AL_TRUE;
497 return AL_NO_ERROR;
499 case AL_VELOCITY:
500 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
502 LockContext(Context);
503 Source->Velocity[0] = values[0];
504 Source->Velocity[1] = values[1];
505 Source->Velocity[2] = values[2];
506 UnlockContext(Context);
507 Source->NeedsUpdate = AL_TRUE;
508 return AL_NO_ERROR;
510 case AL_DIRECTION:
511 CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
513 LockContext(Context);
514 Source->Orientation[0] = values[0];
515 Source->Orientation[1] = values[1];
516 Source->Orientation[2] = values[2];
517 UnlockContext(Context);
518 Source->NeedsUpdate = AL_TRUE;
519 return AL_NO_ERROR;
522 case sfSampleRWOffsetsSOFT:
523 case sfByteRWOffsetsSOFT:
524 RETERR(AL_INVALID_OPERATION);
527 case sfSourceRelative:
528 case sfLooping:
529 case sfSourceState:
530 case sfSourceType:
531 case sfDistanceModel:
532 case sfDirectFilterGainHFAuto:
533 case sfAuxSendFilterGainAuto:
534 case sfAuxSendFilterGainHFAuto:
535 case sfDirectChannelsSOFT:
536 ival = (ALint)values[0];
537 return SetSourceiv(Source, Context, prop, &ival);
539 case sfBuffer:
540 case sfBuffersQueued:
541 case sfBuffersProcessed:
542 ival = (ALint)((ALuint)values[0]);
543 return SetSourceiv(Source, Context, prop, &ival);
546 ERR("Unexpected property: 0x%04x\n", prop);
547 RETERR(AL_INVALID_ENUM);
550 static ALenum SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint *values)
552 ALCdevice *device = Context->Device;
553 ALbuffer *buffer = NULL;
554 ALfilter *filter = NULL;
555 ALeffectslot *slot = NULL;
556 ALbufferlistitem *oldlist;
557 ALfloat fvals[3];
559 switch(prop)
561 case AL_SOURCE_RELATIVE:
562 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
564 Source->HeadRelative = (ALboolean)*values;
565 Source->NeedsUpdate = AL_TRUE;
566 return AL_NO_ERROR;
568 case AL_LOOPING:
569 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
571 Source->Looping = (ALboolean)*values;
572 return AL_NO_ERROR;
574 case AL_BUFFER:
575 CHECKVAL(*values == 0 || (buffer=LookupBuffer(device, *values)) != NULL);
577 LockContext(Context);
578 if(!(Source->state == AL_STOPPED || Source->state == AL_INITIAL))
580 UnlockContext(Context);
581 RETERR(AL_INVALID_OPERATION);
584 Source->BuffersInQueue = 0;
585 Source->BuffersPlayed = 0;
587 if(buffer != NULL)
589 ALbufferlistitem *BufferListItem;
591 /* Source is now Static */
592 Source->SourceType = AL_STATIC;
594 /* Add the selected buffer to a one-item queue */
595 BufferListItem = malloc(sizeof(ALbufferlistitem));
596 BufferListItem->buffer = buffer;
597 BufferListItem->next = NULL;
598 BufferListItem->prev = NULL;
599 IncrementRef(&buffer->ref);
601 oldlist = ExchangePtr((XchgPtr*)&Source->queue, BufferListItem);
602 Source->BuffersInQueue = 1;
604 ReadLock(&buffer->lock);
605 Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
606 Source->SampleSize = BytesFromFmt(buffer->FmtType);
607 ReadUnlock(&buffer->lock);
608 if(buffer->FmtChannels == FmtMono)
609 Source->Update = CalcSourceParams;
610 else
611 Source->Update = CalcNonAttnSourceParams;
612 Source->NeedsUpdate = AL_TRUE;
614 else
616 /* Source is now Undetermined */
617 Source->SourceType = AL_UNDETERMINED;
618 oldlist = ExchangePtr((XchgPtr*)&Source->queue, NULL);
621 /* Delete all elements in the previous queue */
622 while(oldlist != NULL)
624 ALbufferlistitem *temp = oldlist;
625 oldlist = temp->next;
627 if(temp->buffer)
628 DecrementRef(&temp->buffer->ref);
629 free(temp);
631 UnlockContext(Context);
632 return AL_NO_ERROR;
634 case siSourceState:
635 case siSourceType:
636 case siBuffersQueued:
637 case siBuffersProcessed:
638 /* Query only */
639 RETERR(AL_INVALID_OPERATION);
641 case AL_SEC_OFFSET:
642 case AL_SAMPLE_OFFSET:
643 case AL_BYTE_OFFSET:
644 CHECKVAL(*values >= 0);
646 LockContext(Context);
647 Source->OffsetType = prop;
648 Source->Offset = *values;
650 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
651 !Context->DeferUpdates)
653 if(ApplyOffset(Source) == AL_FALSE)
655 UnlockContext(Context);
656 RETERR(AL_INVALID_VALUE);
659 UnlockContext(Context);
660 return AL_NO_ERROR;
663 case siSampleRWOffsetsSOFT:
664 case siByteRWOffsetsSOFT:
665 case siSampleOffsetLatencySOFT:
666 /* Query only */
667 RETERR(AL_INVALID_OPERATION);
670 case AL_DIRECT_FILTER:
671 CHECKVAL(*values == 0 || (filter=LookupFilter(device, *values)) != NULL);
673 LockContext(Context);
674 if(!filter)
676 Source->DirectGain = 1.0f;
677 Source->DirectGainHF = 1.0f;
679 else
681 Source->DirectGain = filter->Gain;
682 Source->DirectGainHF = filter->GainHF;
684 UnlockContext(Context);
685 Source->NeedsUpdate = AL_TRUE;
686 return AL_NO_ERROR;
688 case AL_DIRECT_FILTER_GAINHF_AUTO:
689 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
691 Source->DryGainHFAuto = *values;
692 Source->NeedsUpdate = AL_TRUE;
693 return AL_NO_ERROR;
695 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
696 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
698 Source->WetGainAuto = *values;
699 Source->NeedsUpdate = AL_TRUE;
700 return AL_NO_ERROR;
702 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
703 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
705 Source->WetGainHFAuto = *values;
706 Source->NeedsUpdate = AL_TRUE;
707 return AL_NO_ERROR;
709 case AL_DIRECT_CHANNELS_SOFT:
710 CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
712 Source->DirectChannels = *values;
713 Source->NeedsUpdate = AL_TRUE;
714 return AL_NO_ERROR;
716 case AL_DISTANCE_MODEL:
717 CHECKVAL(*values == AL_NONE ||
718 *values == AL_INVERSE_DISTANCE ||
719 *values == AL_INVERSE_DISTANCE_CLAMPED ||
720 *values == AL_LINEAR_DISTANCE ||
721 *values == AL_LINEAR_DISTANCE_CLAMPED ||
722 *values == AL_EXPONENT_DISTANCE ||
723 *values == AL_EXPONENT_DISTANCE_CLAMPED);
725 Source->DistanceModel = *values;
726 if(Context->SourceDistanceModel)
727 Source->NeedsUpdate = AL_TRUE;
728 return AL_NO_ERROR;
731 case AL_AUXILIARY_SEND_FILTER:
732 LockContext(Context);
733 if(!((ALuint)values[1] < device->NumAuxSends &&
734 (values[0] == 0 || (slot=LookupEffectSlot(Context, values[0])) != NULL) &&
735 (values[2] == 0 || (filter=LookupFilter(device, values[2])) != NULL)))
737 UnlockContext(Context);
738 RETERR(AL_INVALID_VALUE);
741 /* Add refcount on the new slot, and release the previous slot */
742 if(slot) IncrementRef(&slot->ref);
743 slot = ExchangePtr((XchgPtr*)&Source->Send[values[1]].Slot, slot);
744 if(slot) DecrementRef(&slot->ref);
746 if(!filter)
748 /* Disable filter */
749 Source->Send[values[1]].Gain = 1.0f;
750 Source->Send[values[1]].GainHF = 1.0f;
752 else
754 Source->Send[values[1]].Gain = filter->Gain;
755 Source->Send[values[1]].GainHF = filter->GainHF;
757 Source->NeedsUpdate = AL_TRUE;
758 UnlockContext(Context);
759 return AL_NO_ERROR;
762 case AL_MAX_DISTANCE:
763 case AL_ROLLOFF_FACTOR:
764 case AL_CONE_INNER_ANGLE:
765 case AL_CONE_OUTER_ANGLE:
766 case AL_REFERENCE_DISTANCE:
767 case siDopplerFactor:
768 fvals[0] = (ALfloat)*values;
769 return SetSourcefv(Source, Context, (int)prop, fvals);
771 case AL_POSITION:
772 case AL_VELOCITY:
773 case AL_DIRECTION:
774 fvals[0] = (ALfloat)values[0];
775 fvals[1] = (ALfloat)values[1];
776 fvals[2] = (ALfloat)values[2];
777 return SetSourcefv(Source, Context, (int)prop, fvals);
780 ERR("Unexpected property: 0x%04x\n", prop);
781 RETERR(AL_INVALID_ENUM);
784 static ALenum SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint64SOFT *values)
786 ALfloat fvals[3];
787 ALint ivals[3];
789 switch(prop)
791 case siSampleRWOffsetsSOFT:
792 case siByteRWOffsetsSOFT:
793 case siSampleOffsetLatencySOFT:
794 /* Query only */
795 RETERR(AL_INVALID_OPERATION);
798 /* 1x int */
799 case AL_SOURCE_RELATIVE:
800 case AL_LOOPING:
801 case AL_SOURCE_STATE:
802 case AL_BYTE_OFFSET:
803 case AL_SAMPLE_OFFSET:
804 case siSourceType:
805 case siBuffersQueued:
806 case siBuffersProcessed:
807 case AL_DIRECT_FILTER_GAINHF_AUTO:
808 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
809 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
810 case AL_DIRECT_CHANNELS_SOFT:
811 case AL_DISTANCE_MODEL:
812 CHECKVAL(*values <= INT_MAX && *values >= INT_MIN);
814 ivals[0] = (ALint)*values;
815 return SetSourceiv(Source, Context, (int)prop, ivals);
817 /* 1x uint */
818 case AL_BUFFER:
819 case AL_DIRECT_FILTER:
820 CHECKVAL(*values <= UINT_MAX && *values >= 0);
822 ivals[0] = (ALuint)*values;
823 return SetSourceiv(Source, Context, (int)prop, ivals);
825 /* 3x uint */
826 case AL_AUXILIARY_SEND_FILTER:
827 CHECKVAL(values[0] <= UINT_MAX && values[0] >= 0 &&
828 values[1] <= UINT_MAX && values[1] >= 0 &&
829 values[2] <= UINT_MAX && values[2] >= 0);
831 ivals[0] = (ALuint)values[0];
832 ivals[1] = (ALuint)values[1];
833 ivals[2] = (ALuint)values[2];
834 return SetSourceiv(Source, Context, (int)prop, ivals);
836 /* 1x float */
837 case AL_MAX_DISTANCE:
838 case AL_ROLLOFF_FACTOR:
839 case AL_CONE_INNER_ANGLE:
840 case AL_CONE_OUTER_ANGLE:
841 case AL_REFERENCE_DISTANCE:
842 case AL_SEC_OFFSET:
843 case siDopplerFactor:
844 fvals[0] = (ALfloat)*values;
845 return SetSourcefv(Source, Context, (int)prop, fvals);
847 /* 3x float */
848 case AL_POSITION:
849 case AL_VELOCITY:
850 case AL_DIRECTION:
851 fvals[0] = (ALfloat)values[0];
852 fvals[1] = (ALfloat)values[1];
853 fvals[2] = (ALfloat)values[2];
854 return SetSourcefv(Source, Context, (int)prop, fvals);
857 ERR("Unexpected property: 0x%04x\n", prop);
858 RETERR(AL_INVALID_ENUM);
861 #undef CHECKVAL
864 static ALenum GetSourcedv(const ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values)
866 ALdouble offsets[2];
867 ALdouble updateLen;
868 ALint ivals[3];
869 ALenum err;
871 switch(prop)
873 case AL_GAIN:
874 *values = Source->Gain;
875 return AL_NO_ERROR;
877 case AL_PITCH:
878 *values = Source->Pitch;
879 return AL_NO_ERROR;
881 case AL_MAX_DISTANCE:
882 *values = Source->MaxDistance;
883 return AL_NO_ERROR;
885 case AL_ROLLOFF_FACTOR:
886 *values = Source->RollOffFactor;
887 return AL_NO_ERROR;
889 case AL_REFERENCE_DISTANCE:
890 *values = Source->RefDistance;
891 return AL_NO_ERROR;
893 case AL_CONE_INNER_ANGLE:
894 *values = Source->InnerAngle;
895 return AL_NO_ERROR;
897 case AL_CONE_OUTER_ANGLE:
898 *values = Source->OuterAngle;
899 return AL_NO_ERROR;
901 case AL_MIN_GAIN:
902 *values = Source->MinGain;
903 return AL_NO_ERROR;
905 case AL_MAX_GAIN:
906 *values = Source->MaxGain;
907 return AL_NO_ERROR;
909 case AL_CONE_OUTER_GAIN:
910 *values = Source->OuterGain;
911 return AL_NO_ERROR;
913 case AL_SEC_OFFSET:
914 case AL_SAMPLE_OFFSET:
915 case AL_BYTE_OFFSET:
916 LockContext(Context);
917 updateLen = (ALdouble)Context->Device->UpdateSize /
918 Context->Device->Frequency;
919 GetSourceOffsets(Source, prop, offsets, updateLen);
920 UnlockContext(Context);
921 *values = offsets[0];
922 return AL_NO_ERROR;
924 case AL_CONE_OUTER_GAINHF:
925 *values = Source->OuterGainHF;
926 return AL_NO_ERROR;
928 case AL_AIR_ABSORPTION_FACTOR:
929 *values = Source->AirAbsorptionFactor;
930 return AL_NO_ERROR;
932 case AL_ROOM_ROLLOFF_FACTOR:
933 *values = Source->RoomRolloffFactor;
934 return AL_NO_ERROR;
936 case AL_DOPPLER_FACTOR:
937 *values = Source->DopplerFactor;
938 return AL_NO_ERROR;
940 case AL_SAMPLE_RW_OFFSETS_SOFT:
941 case AL_BYTE_RW_OFFSETS_SOFT:
942 LockContext(Context);
943 updateLen = (ALdouble)Context->Device->UpdateSize /
944 Context->Device->Frequency;
945 GetSourceOffsets(Source, prop, values, updateLen);
946 UnlockContext(Context);
947 return AL_NO_ERROR;
949 case AL_SEC_OFFSET_LATENCY_SOFT:
950 LockContext(Context);
951 values[0] = GetSourceSecOffset(Source);
952 values[1] = (ALdouble)ALCdevice_GetLatency(Context->Device) /
953 1000000000.0;
954 UnlockContext(Context);
955 return AL_NO_ERROR;
957 case AL_POSITION:
958 LockContext(Context);
959 values[0] = Source->Position[0];
960 values[1] = Source->Position[1];
961 values[2] = Source->Position[2];
962 UnlockContext(Context);
963 return AL_NO_ERROR;
965 case AL_VELOCITY:
966 LockContext(Context);
967 values[0] = Source->Velocity[0];
968 values[1] = Source->Velocity[1];
969 values[2] = Source->Velocity[2];
970 UnlockContext(Context);
971 return AL_NO_ERROR;
973 case AL_DIRECTION:
974 LockContext(Context);
975 values[0] = Source->Orientation[0];
976 values[1] = Source->Orientation[1];
977 values[2] = Source->Orientation[2];
978 UnlockContext(Context);
979 return AL_NO_ERROR;
981 case AL_SOURCE_RELATIVE:
982 case AL_LOOPING:
983 case AL_BUFFER:
984 case AL_SOURCE_STATE:
985 case AL_BUFFERS_QUEUED:
986 case AL_BUFFERS_PROCESSED:
987 case AL_SOURCE_TYPE:
988 case AL_DIRECT_FILTER_GAINHF_AUTO:
989 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
990 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
991 case AL_DIRECT_CHANNELS_SOFT:
992 case AL_DISTANCE_MODEL:
993 if((err=GetSourceiv(Source, Context, (int)prop, ivals)) == AL_NO_ERROR)
994 *values = (ALdouble)ivals[0];
995 return err;
998 ERR("Unexpected property: 0x%04x\n", prop);
999 RETERR(AL_INVALID_ENUM);
1002 static ALenum GetSourceiv(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values)
1004 ALbufferlistitem *BufferList;
1005 ALdouble dvals[3];
1006 ALenum err;
1008 switch(prop)
1010 case AL_SOURCE_RELATIVE:
1011 *values = Source->HeadRelative;
1012 return AL_NO_ERROR;
1014 case AL_LOOPING:
1015 *values = Source->Looping;
1016 return AL_NO_ERROR;
1018 case AL_BUFFER:
1019 LockContext(Context);
1020 BufferList = Source->queue;
1021 if(Source->SourceType != AL_STATIC)
1023 ALuint i = Source->BuffersPlayed;
1024 while(i > 0)
1026 BufferList = BufferList->next;
1027 i--;
1030 *values = ((BufferList && BufferList->buffer) ?
1031 BufferList->buffer->id : 0);
1032 UnlockContext(Context);
1033 return AL_NO_ERROR;
1035 case AL_SOURCE_STATE:
1036 *values = Source->state;
1037 return AL_NO_ERROR;
1039 case AL_BUFFERS_QUEUED:
1040 *values = Source->BuffersInQueue;
1041 return AL_NO_ERROR;
1043 case AL_BUFFERS_PROCESSED:
1044 LockContext(Context);
1045 if(Source->Looping || Source->SourceType != AL_STREAMING)
1047 /* Buffers on a looping source are in a perpetual state of
1048 * PENDING, so don't report any as PROCESSED */
1049 *values = 0;
1051 else
1052 *values = Source->BuffersPlayed;
1053 UnlockContext(Context);
1054 return AL_NO_ERROR;
1056 case AL_SOURCE_TYPE:
1057 *values = Source->SourceType;
1058 return AL_NO_ERROR;
1060 case AL_DIRECT_FILTER_GAINHF_AUTO:
1061 *values = Source->DryGainHFAuto;
1062 return AL_NO_ERROR;
1064 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1065 *values = Source->WetGainAuto;
1066 return AL_NO_ERROR;
1068 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1069 *values = Source->WetGainHFAuto;
1070 return AL_NO_ERROR;
1072 case AL_DIRECT_CHANNELS_SOFT:
1073 *values = Source->DirectChannels;
1074 return AL_NO_ERROR;
1076 case AL_DISTANCE_MODEL:
1077 *values = Source->DistanceModel;
1078 return AL_NO_ERROR;
1080 case AL_MAX_DISTANCE:
1081 case AL_ROLLOFF_FACTOR:
1082 case AL_REFERENCE_DISTANCE:
1083 case AL_CONE_INNER_ANGLE:
1084 case AL_CONE_OUTER_ANGLE:
1085 case AL_SEC_OFFSET:
1086 case AL_SAMPLE_OFFSET:
1087 case AL_BYTE_OFFSET:
1088 case AL_DOPPLER_FACTOR:
1089 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
1090 *values = (ALint)dvals[0];
1091 return err;
1093 case AL_SAMPLE_RW_OFFSETS_SOFT:
1094 case AL_BYTE_RW_OFFSETS_SOFT:
1095 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
1097 values[0] = (ALint)dvals[0];
1098 values[1] = (ALint)dvals[1];
1100 return err;
1102 case AL_POSITION:
1103 case AL_VELOCITY:
1104 case AL_DIRECTION:
1105 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
1107 values[0] = (ALint)dvals[0];
1108 values[1] = (ALint)dvals[1];
1109 values[2] = (ALint)dvals[2];
1111 return err;
1113 case siSampleOffsetLatencySOFT:
1114 /* i64 only */
1115 break;
1117 case siDirectFilter:
1118 case siAuxSendFilter:
1119 /* ??? */
1120 break;
1123 ERR("Unexpected property: 0x%04x\n", prop);
1124 RETERR(AL_INVALID_ENUM);
1127 static ALenum GetSourcei64v(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values)
1129 ALdouble dvals[3];
1130 ALint ivals[3];
1131 ALenum err;
1133 switch(prop)
1135 case AL_SAMPLE_OFFSET_LATENCY_SOFT:
1136 LockContext(Context);
1137 values[0] = GetSourceOffset(Source);
1138 values[1] = ALCdevice_GetLatency(Context->Device);
1139 UnlockContext(Context);
1140 return AL_NO_ERROR;
1142 case AL_MAX_DISTANCE:
1143 case AL_ROLLOFF_FACTOR:
1144 case AL_REFERENCE_DISTANCE:
1145 case AL_CONE_INNER_ANGLE:
1146 case AL_CONE_OUTER_ANGLE:
1147 case AL_SEC_OFFSET:
1148 case AL_SAMPLE_OFFSET:
1149 case AL_BYTE_OFFSET:
1150 case AL_DOPPLER_FACTOR:
1151 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
1152 *values = (ALint64)dvals[0];
1153 return err;
1155 case AL_SAMPLE_RW_OFFSETS_SOFT:
1156 case AL_BYTE_RW_OFFSETS_SOFT:
1157 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
1159 values[0] = (ALint64)dvals[0];
1160 values[1] = (ALint64)dvals[1];
1162 return err;
1164 case AL_POSITION:
1165 case AL_VELOCITY:
1166 case AL_DIRECTION:
1167 if((err=GetSourcedv(Source, Context, (int)prop, dvals)) == AL_NO_ERROR)
1169 values[0] = (ALint64)dvals[0];
1170 values[1] = (ALint64)dvals[1];
1171 values[2] = (ALint64)dvals[2];
1173 return err;
1175 case AL_SOURCE_RELATIVE:
1176 case AL_LOOPING:
1177 case AL_BUFFER:
1178 case AL_SOURCE_STATE:
1179 case AL_BUFFERS_QUEUED:
1180 case AL_BUFFERS_PROCESSED:
1181 case AL_SOURCE_TYPE:
1182 case AL_DIRECT_FILTER_GAINHF_AUTO:
1183 case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
1184 case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
1185 case AL_DIRECT_CHANNELS_SOFT:
1186 case AL_DISTANCE_MODEL:
1187 case siDirectFilter:
1188 case siAuxSendFilter:
1189 if((err=GetSourceiv(Source, Context, (int)prop, ivals)) == AL_NO_ERROR)
1190 *values = ivals[0];
1191 return err;
1194 ERR("Unexpected property: 0x%04x\n", prop);
1195 RETERR(AL_INVALID_ENUM);
1198 #undef RETERR
1201 AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
1203 ALCcontext *Context;
1204 ALsizei cur = 0;
1206 Context = GetContextRef();
1207 if(!Context) return;
1209 al_try
1211 ALenum err;
1213 CHECK_VALUE(Context, n >= 0);
1214 for(cur = 0;cur < n;cur++)
1216 ALsource *source = al_calloc(16, sizeof(ALsource));
1217 if(!source)
1218 al_throwerr(Context, AL_OUT_OF_MEMORY);
1219 InitSourceParams(source);
1221 err = NewThunkEntry(&source->id);
1222 if(err == AL_NO_ERROR)
1223 err = InsertUIntMapEntry(&Context->SourceMap, source->id, source);
1224 if(err != AL_NO_ERROR)
1226 FreeThunkEntry(source->id);
1227 memset(source, 0, sizeof(ALsource));
1228 al_free(source);
1230 al_throwerr(Context, err);
1233 sources[cur] = source->id;
1236 al_catchany()
1238 if(cur > 0)
1239 alDeleteSources(cur, sources);
1241 al_endtry;
1243 ALCcontext_DecRef(Context);
1247 AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
1249 ALCcontext *Context;
1251 Context = GetContextRef();
1252 if(!Context) return;
1254 al_try
1256 ALbufferlistitem *BufferList;
1257 ALsource *Source;
1258 ALsizei i, j;
1260 CHECK_VALUE(Context, n >= 0);
1262 /* Check that all Sources are valid */
1263 for(i = 0;i < n;i++)
1265 if(LookupSource(Context, sources[i]) == NULL)
1266 al_throwerr(Context, AL_INVALID_NAME);
1269 for(i = 0;i < n;i++)
1271 ALsource **srclist, **srclistend;
1273 if((Source=RemoveSource(Context, sources[i])) == NULL)
1274 continue;
1275 FreeThunkEntry(Source->id);
1277 LockContext(Context);
1278 srclist = Context->ActiveSources;
1279 srclistend = srclist + Context->ActiveSourceCount;
1280 while(srclist != srclistend)
1282 if(*srclist == Source)
1284 Context->ActiveSourceCount--;
1285 *srclist = *(--srclistend);
1286 break;
1288 srclist++;
1290 UnlockContext(Context);
1292 while(Source->queue != NULL)
1294 BufferList = Source->queue;
1295 Source->queue = BufferList->next;
1297 if(BufferList->buffer != NULL)
1298 DecrementRef(&BufferList->buffer->ref);
1299 free(BufferList);
1302 for(j = 0;j < MAX_SENDS;++j)
1304 if(Source->Send[j].Slot)
1305 DecrementRef(&Source->Send[j].Slot->ref);
1306 Source->Send[j].Slot = NULL;
1309 memset(Source, 0, sizeof(*Source));
1310 al_free(Source);
1313 al_endtry;
1315 ALCcontext_DecRef(Context);
1319 AL_API ALboolean AL_APIENTRY alIsSource(ALuint source)
1321 ALCcontext *Context;
1322 ALboolean result;
1324 Context = GetContextRef();
1325 if(!Context) return AL_FALSE;
1327 result = (LookupSource(Context, source) ? AL_TRUE : AL_FALSE);
1329 ALCcontext_DecRef(Context);
1331 return result;
1335 AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value)
1337 ALCcontext *Context;
1338 ALsource *Source;
1340 Context = GetContextRef();
1341 if(!Context) return;
1343 if((Source=LookupSource(Context, source)) == NULL)
1344 alSetError(Context, AL_INVALID_NAME);
1345 else if(!(FloatValsByProp(param) == 1))
1346 alSetError(Context, AL_INVALID_ENUM);
1347 else
1348 SetSourcefv(Source, Context, param, &value);
1350 ALCcontext_DecRef(Context);
1353 AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
1355 ALCcontext *Context;
1356 ALsource *Source;
1358 Context = GetContextRef();
1359 if(!Context) return;
1361 if((Source=LookupSource(Context, source)) == NULL)
1362 alSetError(Context, AL_INVALID_NAME);
1363 else if(!(FloatValsByProp(param) == 3))
1364 alSetError(Context, AL_INVALID_ENUM);
1365 else
1367 ALfloat fvals[3] = { value1, value2, value3 };
1368 SetSourcefv(Source, Context, param, fvals);
1371 ALCcontext_DecRef(Context);
1374 AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values)
1376 ALCcontext *Context;
1377 ALsource *Source;
1379 Context = GetContextRef();
1380 if(!Context) return;
1382 if((Source=LookupSource(Context, source)) == NULL)
1383 alSetError(Context, AL_INVALID_NAME);
1384 else if(!values)
1385 alSetError(Context, AL_INVALID_VALUE);
1386 else if(!(FloatValsByProp(param) > 0))
1387 alSetError(Context, AL_INVALID_ENUM);
1388 else
1389 SetSourcefv(Source, Context, param, values);
1391 ALCcontext_DecRef(Context);
1395 AL_API ALvoid AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value)
1397 ALCcontext *Context;
1398 ALsource *Source;
1400 Context = GetContextRef();
1401 if(!Context) return;
1403 if((Source=LookupSource(Context, source)) == NULL)
1404 alSetError(Context, AL_INVALID_NAME);
1405 else if(!(DoubleValsByProp(param) == 1))
1406 alSetError(Context, AL_INVALID_ENUM);
1407 else
1409 ALfloat fval = (ALfloat)value;
1410 SetSourcefv(Source, Context, param, &fval);
1413 ALCcontext_DecRef(Context);
1416 AL_API ALvoid AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3)
1418 ALCcontext *Context;
1419 ALsource *Source;
1421 Context = GetContextRef();
1422 if(!Context) return;
1424 if((Source=LookupSource(Context, source)) == NULL)
1425 alSetError(Context, AL_INVALID_NAME);
1426 else if(!(DoubleValsByProp(param) == 3))
1427 alSetError(Context, AL_INVALID_ENUM);
1428 else
1430 ALfloat fvals[3] = { (ALfloat)value1, (ALfloat)value2, (ALfloat)value3 };
1431 SetSourcefv(Source, Context, param, fvals);
1434 ALCcontext_DecRef(Context);
1437 AL_API ALvoid AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values)
1439 ALCcontext *Context;
1440 ALsource *Source;
1441 ALint count;
1443 Context = GetContextRef();
1444 if(!Context) return;
1446 if((Source=LookupSource(Context, source)) == NULL)
1447 alSetError(Context, AL_INVALID_NAME);
1448 else if(!values)
1449 alSetError(Context, AL_INVALID_VALUE);
1450 else if(!((count=DoubleValsByProp(param)) > 0 && count <= 3))
1451 alSetError(Context, AL_INVALID_ENUM);
1452 else
1454 ALfloat fvals[3];
1455 ALint i;
1457 for(i = 0;i < count;i++)
1458 fvals[i] = (ALfloat)values[i];
1459 SetSourcefv(Source, Context, param, fvals);
1462 ALCcontext_DecRef(Context);
1466 AL_API ALvoid AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value)
1468 ALCcontext *Context;
1469 ALsource *Source;
1471 Context = GetContextRef();
1472 if(!Context) return;
1474 if((Source=LookupSource(Context, source)) == NULL)
1475 alSetError(Context, AL_INVALID_NAME);
1476 else if(!(IntValsByProp(param) == 1))
1477 alSetError(Context, AL_INVALID_ENUM);
1478 else
1479 SetSourceiv(Source, Context, param, &value);
1481 ALCcontext_DecRef(Context);
1484 AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3)
1486 ALCcontext *Context;
1487 ALsource *Source;
1489 Context = GetContextRef();
1490 if(!Context) return;
1492 if((Source=LookupSource(Context, source)) == NULL)
1493 alSetError(Context, AL_INVALID_NAME);
1494 else if(!(IntValsByProp(param) == 3))
1495 alSetError(Context, AL_INVALID_ENUM);
1496 else
1498 ALint ivals[3] = { value1, value2, value3 };
1499 SetSourceiv(Source, Context, param, ivals);
1502 ALCcontext_DecRef(Context);
1505 AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values)
1507 ALCcontext *Context;
1508 ALsource *Source;
1510 Context = GetContextRef();
1511 if(!Context) return;
1513 if((Source=LookupSource(Context, source)) == NULL)
1514 alSetError(Context, AL_INVALID_NAME);
1515 else if(!values)
1516 alSetError(Context, AL_INVALID_VALUE);
1517 else if(!(IntValsByProp(param) > 0))
1518 alSetError(Context, AL_INVALID_ENUM);
1519 else
1520 SetSourceiv(Source, Context, param, values);
1522 ALCcontext_DecRef(Context);
1526 AL_API ALvoid AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value)
1528 ALCcontext *Context;
1529 ALsource *Source;
1531 Context = GetContextRef();
1532 if(!Context) return;
1534 if((Source=LookupSource(Context, source)) == NULL)
1535 alSetError(Context, AL_INVALID_NAME);
1536 else if(!(Int64ValsByProp(param) == 1))
1537 alSetError(Context, AL_INVALID_ENUM);
1538 else
1539 SetSourcei64v(Source, Context, param, &value);
1541 ALCcontext_DecRef(Context);
1544 AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3)
1546 ALCcontext *Context;
1547 ALsource *Source;
1549 Context = GetContextRef();
1550 if(!Context) return;
1552 if((Source=LookupSource(Context, source)) == NULL)
1553 alSetError(Context, AL_INVALID_NAME);
1554 else if(!(Int64ValsByProp(param) == 3))
1555 alSetError(Context, AL_INVALID_ENUM);
1556 else
1558 ALint64SOFT i64vals[3] = { value1, value2, value3 };
1559 SetSourcei64v(Source, Context, param, i64vals);
1562 ALCcontext_DecRef(Context);
1565 AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values)
1567 ALCcontext *Context;
1568 ALsource *Source;
1570 Context = GetContextRef();
1571 if(!Context) return;
1573 if((Source=LookupSource(Context, source)) == NULL)
1574 alSetError(Context, AL_INVALID_NAME);
1575 else if(!values)
1576 alSetError(Context, AL_INVALID_VALUE);
1577 else if(!(Int64ValsByProp(param) > 0))
1578 alSetError(Context, AL_INVALID_ENUM);
1579 else
1580 SetSourcei64v(Source, Context, param, values);
1582 ALCcontext_DecRef(Context);
1586 AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value)
1588 ALCcontext *Context;
1589 ALsource *Source;
1591 Context = GetContextRef();
1592 if(!Context) return;
1594 if((Source=LookupSource(Context, source)) == NULL)
1595 alSetError(Context, AL_INVALID_NAME);
1596 else if(!value)
1597 alSetError(Context, AL_INVALID_VALUE);
1598 else if(!(FloatValsByProp(param) == 1))
1599 alSetError(Context, AL_INVALID_ENUM);
1600 else
1602 ALdouble dval;
1603 if(GetSourcedv(Source, Context, param, &dval) == AL_NO_ERROR)
1604 *value = (ALfloat)dval;
1607 ALCcontext_DecRef(Context);
1611 AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
1613 ALCcontext *Context;
1614 ALsource *Source;
1616 Context = GetContextRef();
1617 if(!Context) return;
1619 if((Source=LookupSource(Context, source)) == NULL)
1620 alSetError(Context, AL_INVALID_NAME);
1621 else if(!(value1 && value2 && value3))
1622 alSetError(Context, AL_INVALID_VALUE);
1623 else if(!(FloatValsByProp(param) == 3))
1624 alSetError(Context, AL_INVALID_ENUM);
1625 else
1627 ALdouble dvals[3];
1628 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1630 *value1 = (ALfloat)dvals[0];
1631 *value2 = (ALfloat)dvals[1];
1632 *value3 = (ALfloat)dvals[2];
1636 ALCcontext_DecRef(Context);
1640 AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values)
1642 ALCcontext *Context;
1643 ALsource *Source;
1644 ALint count;
1646 Context = GetContextRef();
1647 if(!Context) return;
1649 if((Source=LookupSource(Context, source)) == NULL)
1650 alSetError(Context, AL_INVALID_NAME);
1651 else if(!values)
1652 alSetError(Context, AL_INVALID_VALUE);
1653 else if(!((count=FloatValsByProp(param)) > 0 && count <= 3))
1654 alSetError(Context, AL_INVALID_ENUM);
1655 else
1657 ALdouble dvals[3];
1658 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1660 ALint i;
1661 for(i = 0;i < count;i++)
1662 values[i] = (ALfloat)dvals[i];
1666 ALCcontext_DecRef(Context);
1670 AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value)
1672 ALCcontext *Context;
1673 ALsource *Source;
1675 Context = GetContextRef();
1676 if(!Context) return;
1678 if((Source=LookupSource(Context, source)) == NULL)
1679 alSetError(Context, AL_INVALID_NAME);
1680 else if(!value)
1681 alSetError(Context, AL_INVALID_VALUE);
1682 else if(!(DoubleValsByProp(param) == 1))
1683 alSetError(Context, AL_INVALID_ENUM);
1684 else
1685 GetSourcedv(Source, Context, param, value);
1687 ALCcontext_DecRef(Context);
1690 AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3)
1692 ALCcontext *Context;
1693 ALsource *Source;
1695 Context = GetContextRef();
1696 if(!Context) return;
1698 if((Source=LookupSource(Context, source)) == NULL)
1699 alSetError(Context, AL_INVALID_NAME);
1700 else if(!(value1 && value2 && value3))
1701 alSetError(Context, AL_INVALID_VALUE);
1702 else if(!(DoubleValsByProp(param) == 3))
1703 alSetError(Context, AL_INVALID_ENUM);
1704 else
1706 ALdouble dvals[3];
1707 if(GetSourcedv(Source, Context, param, dvals) == AL_NO_ERROR)
1709 *value1 = dvals[0];
1710 *value2 = dvals[1];
1711 *value3 = dvals[2];
1715 ALCcontext_DecRef(Context);
1718 AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values)
1720 ALCcontext *Context;
1721 ALsource *Source;
1723 Context = GetContextRef();
1724 if(!Context) return;
1726 if((Source=LookupSource(Context, source)) == NULL)
1727 alSetError(Context, AL_INVALID_NAME);
1728 else if(!values)
1729 alSetError(Context, AL_INVALID_VALUE);
1730 else if(!(DoubleValsByProp(param) > 0))
1731 alSetError(Context, AL_INVALID_ENUM);
1732 else
1733 GetSourcedv(Source, Context, param, values);
1735 ALCcontext_DecRef(Context);
1739 AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value)
1741 ALCcontext *Context;
1742 ALsource *Source;
1744 Context = GetContextRef();
1745 if(!Context) return;
1747 if((Source=LookupSource(Context, source)) == NULL)
1748 alSetError(Context, AL_INVALID_NAME);
1749 else if(!value)
1750 alSetError(Context, AL_INVALID_VALUE);
1751 else if(!(IntValsByProp(param) == 1))
1752 alSetError(Context, AL_INVALID_ENUM);
1753 else
1754 GetSourceiv(Source, Context, param, value);
1756 ALCcontext_DecRef(Context);
1760 AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3)
1762 ALCcontext *Context;
1763 ALsource *Source;
1765 Context = GetContextRef();
1766 if(!Context) return;
1768 if((Source=LookupSource(Context, source)) == NULL)
1769 alSetError(Context, AL_INVALID_NAME);
1770 else if(!(value1 && value2 && value3))
1771 alSetError(Context, AL_INVALID_VALUE);
1772 else if(!(IntValsByProp(param) == 3))
1773 alSetError(Context, AL_INVALID_ENUM);
1774 else
1776 ALint ivals[3];
1777 if(GetSourceiv(Source, Context, param, ivals) == AL_NO_ERROR)
1779 *value1 = ivals[0];
1780 *value2 = ivals[1];
1781 *value3 = ivals[2];
1785 ALCcontext_DecRef(Context);
1789 AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values)
1791 ALCcontext *Context;
1792 ALsource *Source;
1794 Context = GetContextRef();
1795 if(!Context) return;
1797 if((Source=LookupSource(Context, source)) == NULL)
1798 alSetError(Context, AL_INVALID_NAME);
1799 else if(!values)
1800 alSetError(Context, AL_INVALID_VALUE);
1801 else if(!(IntValsByProp(param) > 0))
1802 alSetError(Context, AL_INVALID_ENUM);
1803 else
1804 GetSourceiv(Source, Context, param, values);
1806 ALCcontext_DecRef(Context);
1810 AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value)
1812 ALCcontext *Context;
1813 ALsource *Source;
1815 Context = GetContextRef();
1816 if(!Context) return;
1818 if((Source=LookupSource(Context, source)) == NULL)
1819 alSetError(Context, AL_INVALID_NAME);
1820 else if(!value)
1821 alSetError(Context, AL_INVALID_VALUE);
1822 else if(!(Int64ValsByProp(param) == 1))
1823 alSetError(Context, AL_INVALID_ENUM);
1824 else
1825 GetSourcei64v(Source, Context, param, value);
1827 ALCcontext_DecRef(Context);
1830 AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3)
1832 ALCcontext *Context;
1833 ALsource *Source;
1835 Context = GetContextRef();
1836 if(!Context) return;
1838 if((Source=LookupSource(Context, source)) == NULL)
1839 alSetError(Context, AL_INVALID_NAME);
1840 else if(!(value1 && value2 && value3))
1841 alSetError(Context, AL_INVALID_VALUE);
1842 else if(!(Int64ValsByProp(param) == 3))
1843 alSetError(Context, AL_INVALID_ENUM);
1844 else
1846 ALint64 i64vals[3];
1847 if(GetSourcei64v(Source, Context, param, i64vals) == AL_NO_ERROR)
1849 *value1 = i64vals[0];
1850 *value2 = i64vals[1];
1851 *value3 = i64vals[2];
1855 ALCcontext_DecRef(Context);
1858 AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values)
1860 ALCcontext *Context;
1861 ALsource *Source;
1863 Context = GetContextRef();
1864 if(!Context) return;
1866 if((Source=LookupSource(Context, source)) == NULL)
1867 alSetError(Context, AL_INVALID_NAME);
1868 else if(!values)
1869 alSetError(Context, AL_INVALID_VALUE);
1870 else if(!(Int64ValsByProp(param) > 0))
1871 alSetError(Context, AL_INVALID_ENUM);
1872 else
1873 GetSourcei64v(Source, Context, param, values);
1875 ALCcontext_DecRef(Context);
1879 AL_API ALvoid AL_APIENTRY alSourcePlay(ALuint source)
1881 alSourcePlayv(1, &source);
1883 AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
1885 ALCcontext *Context;
1886 ALsource *Source;
1887 ALsizei i;
1889 Context = GetContextRef();
1890 if(!Context) return;
1892 al_try
1894 CHECK_VALUE(Context, n >= 0);
1895 for(i = 0;i < n;i++)
1897 if(!LookupSource(Context, sources[i]))
1898 al_throwerr(Context, AL_INVALID_NAME);
1901 LockContext(Context);
1902 while(Context->MaxActiveSources-Context->ActiveSourceCount < n)
1904 void *temp = NULL;
1905 ALsizei newcount;
1907 newcount = Context->MaxActiveSources << 1;
1908 if(newcount > 0)
1909 temp = realloc(Context->ActiveSources,
1910 sizeof(*Context->ActiveSources) * newcount);
1911 if(!temp)
1913 UnlockContext(Context);
1914 al_throwerr(Context, AL_OUT_OF_MEMORY);
1917 Context->ActiveSources = temp;
1918 Context->MaxActiveSources = newcount;
1921 for(i = 0;i < n;i++)
1923 Source = LookupSource(Context, sources[i]);
1924 if(Context->DeferUpdates) Source->new_state = AL_PLAYING;
1925 else SetSourceState(Source, Context, AL_PLAYING);
1927 UnlockContext(Context);
1929 al_endtry;
1931 ALCcontext_DecRef(Context);
1934 AL_API ALvoid AL_APIENTRY alSourcePause(ALuint source)
1936 alSourcePausev(1, &source);
1938 AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
1940 ALCcontext *Context;
1941 ALsource *Source;
1942 ALsizei i;
1944 Context = GetContextRef();
1945 if(!Context) return;
1947 al_try
1949 CHECK_VALUE(Context, n >= 0);
1950 for(i = 0;i < n;i++)
1952 if(!LookupSource(Context, sources[i]))
1953 al_throwerr(Context, AL_INVALID_NAME);
1956 LockContext(Context);
1957 for(i = 0;i < n;i++)
1959 Source = LookupSource(Context, sources[i]);
1960 if(Context->DeferUpdates) Source->new_state = AL_PAUSED;
1961 else SetSourceState(Source, Context, AL_PAUSED);
1963 UnlockContext(Context);
1965 al_endtry;
1967 ALCcontext_DecRef(Context);
1970 AL_API ALvoid AL_APIENTRY alSourceStop(ALuint source)
1972 alSourceStopv(1, &source);
1974 AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
1976 ALCcontext *Context;
1977 ALsource *Source;
1978 ALsizei i;
1980 Context = GetContextRef();
1981 if(!Context) return;
1983 al_try
1985 CHECK_VALUE(Context, n >= 0);
1986 for(i = 0;i < n;i++)
1988 if(!LookupSource(Context, sources[i]))
1989 al_throwerr(Context, AL_INVALID_NAME);
1992 LockContext(Context);
1993 for(i = 0;i < n;i++)
1995 Source = LookupSource(Context, sources[i]);
1996 Source->new_state = AL_NONE;
1997 SetSourceState(Source, Context, AL_STOPPED);
1999 UnlockContext(Context);
2001 al_endtry;
2003 ALCcontext_DecRef(Context);
2006 AL_API ALvoid AL_APIENTRY alSourceRewind(ALuint source)
2008 alSourceRewindv(1, &source);
2010 AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
2012 ALCcontext *Context;
2013 ALsource *Source;
2014 ALsizei i;
2016 Context = GetContextRef();
2017 if(!Context) return;
2019 al_try
2021 CHECK_VALUE(Context, n >= 0);
2022 for(i = 0;i < n;i++)
2024 if(!LookupSource(Context, sources[i]))
2025 al_throwerr(Context, AL_INVALID_NAME);
2028 LockContext(Context);
2029 for(i = 0;i < n;i++)
2031 Source = LookupSource(Context, sources[i]);
2032 Source->new_state = AL_NONE;
2033 SetSourceState(Source, Context, AL_INITIAL);
2035 UnlockContext(Context);
2037 al_endtry;
2039 ALCcontext_DecRef(Context);
2043 AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers)
2045 ALCcontext *Context;
2046 ALsource *Source;
2047 ALsizei i;
2048 ALbufferlistitem *BufferListStart = NULL;
2049 ALbufferlistitem *BufferList;
2050 ALbuffer *BufferFmt;
2052 if(nb == 0)
2053 return;
2055 Context = GetContextRef();
2056 if(!Context) return;
2058 al_try
2060 ALCdevice *device = Context->Device;
2062 CHECK_VALUE(Context, nb >= 0);
2064 if((Source=LookupSource(Context, source)) == NULL)
2065 al_throwerr(Context, AL_INVALID_NAME);
2067 LockContext(Context);
2068 if(Source->SourceType == AL_STATIC)
2070 UnlockContext(Context);
2071 /* Can't queue on a Static Source */
2072 al_throwerr(Context, AL_INVALID_OPERATION);
2075 BufferFmt = NULL;
2077 /* Check for a valid Buffer, for its frequency and format */
2078 BufferList = Source->queue;
2079 while(BufferList)
2081 if(BufferList->buffer)
2083 BufferFmt = BufferList->buffer;
2084 break;
2086 BufferList = BufferList->next;
2089 for(i = 0;i < nb;i++)
2091 ALbuffer *buffer = NULL;
2092 if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
2094 UnlockContext(Context);
2095 al_throwerr(Context, AL_INVALID_NAME);
2098 if(!BufferListStart)
2100 BufferListStart = malloc(sizeof(ALbufferlistitem));
2101 BufferListStart->buffer = buffer;
2102 BufferListStart->next = NULL;
2103 BufferListStart->prev = NULL;
2104 BufferList = BufferListStart;
2106 else
2108 BufferList->next = malloc(sizeof(ALbufferlistitem));
2109 BufferList->next->buffer = buffer;
2110 BufferList->next->next = NULL;
2111 BufferList->next->prev = BufferList;
2112 BufferList = BufferList->next;
2114 if(!buffer) continue;
2115 IncrementRef(&buffer->ref);
2117 ReadLock(&buffer->lock);
2118 if(BufferFmt == NULL)
2120 BufferFmt = buffer;
2122 Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
2123 Source->SampleSize = BytesFromFmt(buffer->FmtType);
2124 if(buffer->FmtChannels == FmtMono)
2125 Source->Update = CalcSourceParams;
2126 else
2127 Source->Update = CalcNonAttnSourceParams;
2129 Source->NeedsUpdate = AL_TRUE;
2131 else if(BufferFmt->Frequency != buffer->Frequency ||
2132 BufferFmt->OriginalChannels != buffer->OriginalChannels ||
2133 BufferFmt->OriginalType != buffer->OriginalType)
2135 ReadUnlock(&buffer->lock);
2136 UnlockContext(Context);
2137 al_throwerr(Context, AL_INVALID_OPERATION);
2139 ReadUnlock(&buffer->lock);
2142 /* Source is now streaming */
2143 Source->SourceType = AL_STREAMING;
2145 if(Source->queue == NULL)
2146 Source->queue = BufferListStart;
2147 else
2149 /* Append to the end of the queue */
2150 BufferList = Source->queue;
2151 while(BufferList->next != NULL)
2152 BufferList = BufferList->next;
2154 BufferListStart->prev = BufferList;
2155 BufferList->next = BufferListStart;
2158 Source->BuffersInQueue += nb;
2160 UnlockContext(Context);
2162 al_catchany()
2164 while(BufferListStart)
2166 BufferList = BufferListStart;
2167 BufferListStart = BufferList->next;
2169 if(BufferList->buffer)
2170 DecrementRef(&BufferList->buffer->ref);
2171 free(BufferList);
2174 al_endtry;
2176 ALCcontext_DecRef(Context);
2179 AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers)
2181 ALCcontext *Context;
2182 ALsource *Source;
2183 ALsizei i;
2184 ALbufferlistitem *BufferList;
2186 if(nb == 0)
2187 return;
2189 Context = GetContextRef();
2190 if(!Context) return;
2192 al_try
2194 CHECK_VALUE(Context, nb >= 0);
2196 if((Source=LookupSource(Context, source)) == NULL)
2197 al_throwerr(Context, AL_INVALID_NAME);
2199 LockContext(Context);
2200 if(Source->Looping || Source->SourceType != AL_STREAMING ||
2201 (ALuint)nb > Source->BuffersPlayed)
2203 UnlockContext(Context);
2204 /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
2205 al_throwerr(Context, AL_INVALID_VALUE);
2208 for(i = 0;i < nb;i++)
2210 BufferList = Source->queue;
2211 Source->queue = BufferList->next;
2212 Source->BuffersInQueue--;
2213 Source->BuffersPlayed--;
2215 if(BufferList->buffer)
2217 buffers[i] = BufferList->buffer->id;
2218 DecrementRef(&BufferList->buffer->ref);
2220 else
2221 buffers[i] = 0;
2223 free(BufferList);
2225 if(Source->queue)
2226 Source->queue->prev = NULL;
2227 UnlockContext(Context);
2229 al_endtry;
2231 ALCcontext_DecRef(Context);
2235 static ALvoid InitSourceParams(ALsource *Source)
2237 ALuint i;
2239 Source->InnerAngle = 360.0f;
2240 Source->OuterAngle = 360.0f;
2241 Source->Pitch = 1.0f;
2242 Source->Position[0] = 0.0f;
2243 Source->Position[1] = 0.0f;
2244 Source->Position[2] = 0.0f;
2245 Source->Orientation[0] = 0.0f;
2246 Source->Orientation[1] = 0.0f;
2247 Source->Orientation[2] = 0.0f;
2248 Source->Velocity[0] = 0.0f;
2249 Source->Velocity[1] = 0.0f;
2250 Source->Velocity[2] = 0.0f;
2251 Source->RefDistance = 1.0f;
2252 Source->MaxDistance = FLT_MAX;
2253 Source->RollOffFactor = 1.0f;
2254 Source->Looping = AL_FALSE;
2255 Source->Gain = 1.0f;
2256 Source->MinGain = 0.0f;
2257 Source->MaxGain = 1.0f;
2258 Source->OuterGain = 0.0f;
2259 Source->OuterGainHF = 1.0f;
2261 Source->DryGainHFAuto = AL_TRUE;
2262 Source->WetGainAuto = AL_TRUE;
2263 Source->WetGainHFAuto = AL_TRUE;
2264 Source->AirAbsorptionFactor = 0.0f;
2265 Source->RoomRolloffFactor = 0.0f;
2266 Source->DopplerFactor = 1.0f;
2267 Source->DirectChannels = AL_FALSE;
2269 Source->DistanceModel = DefaultDistanceModel;
2271 Source->Resampler = DefaultResampler;
2273 Source->state = AL_INITIAL;
2274 Source->new_state = AL_NONE;
2275 Source->SourceType = AL_UNDETERMINED;
2276 Source->Offset = -1.0;
2278 Source->DirectGain = 1.0f;
2279 Source->DirectGainHF = 1.0f;
2280 for(i = 0;i < MAX_SENDS;i++)
2282 Source->Send[i].Gain = 1.0f;
2283 Source->Send[i].GainHF = 1.0f;
2286 Source->NeedsUpdate = AL_TRUE;
2288 Source->Hrtf.Moving = AL_FALSE;
2289 Source->Hrtf.Counter = 0;
2293 /* SetSourceState
2295 * Sets the source's new play state given its current state.
2297 ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
2299 if(state == AL_PLAYING)
2301 ALbufferlistitem *BufferList;
2302 ALsizei j, k;
2304 /* Check that there is a queue containing at least one valid, non zero
2305 * length Buffer. */
2306 BufferList = Source->queue;
2307 while(BufferList)
2309 if(BufferList->buffer != NULL && BufferList->buffer->SampleLen)
2310 break;
2311 BufferList = BufferList->next;
2314 if(Source->state != AL_PLAYING)
2316 for(j = 0;j < MaxChannels;j++)
2318 for(k = 0;k < SRC_HISTORY_LENGTH;k++)
2319 Source->Hrtf.History[j][k] = 0.0f;
2320 for(k = 0;k < HRIR_LENGTH;k++)
2322 Source->Hrtf.Values[j][k][0] = 0.0f;
2323 Source->Hrtf.Values[j][k][1] = 0.0f;
2328 if(Source->state != AL_PAUSED)
2330 Source->state = AL_PLAYING;
2331 Source->position = 0;
2332 Source->position_fraction = 0;
2333 Source->BuffersPlayed = 0;
2335 else
2336 Source->state = AL_PLAYING;
2338 // Check if an Offset has been set
2339 if(Source->Offset >= 0.0)
2340 ApplyOffset(Source);
2342 /* If there's nothing to play, or device is disconnected, go right to
2343 * stopped */
2344 if(!BufferList || !Context->Device->Connected)
2346 SetSourceState(Source, Context, AL_STOPPED);
2347 return;
2350 for(j = 0;j < Context->ActiveSourceCount;j++)
2352 if(Context->ActiveSources[j] == Source)
2353 break;
2355 if(j == Context->ActiveSourceCount)
2356 Context->ActiveSources[Context->ActiveSourceCount++] = Source;
2358 else if(state == AL_PAUSED)
2360 if(Source->state == AL_PLAYING)
2362 Source->state = AL_PAUSED;
2363 Source->Hrtf.Moving = AL_FALSE;
2364 Source->Hrtf.Counter = 0;
2367 else if(state == AL_STOPPED)
2369 if(Source->state != AL_INITIAL)
2371 Source->state = AL_STOPPED;
2372 Source->BuffersPlayed = Source->BuffersInQueue;
2373 Source->Hrtf.Moving = AL_FALSE;
2374 Source->Hrtf.Counter = 0;
2376 Source->Offset = -1.0;
2378 else if(state == AL_INITIAL)
2380 if(Source->state != AL_INITIAL)
2382 Source->state = AL_INITIAL;
2383 Source->position = 0;
2384 Source->position_fraction = 0;
2385 Source->BuffersPlayed = 0;
2386 Source->Hrtf.Moving = AL_FALSE;
2387 Source->Hrtf.Counter = 0;
2389 Source->Offset = -1.0;
2393 /* GetSourceOffset
2395 * Gets the current read offset for the given Source, in 32.32 fixed-point
2396 * samples. The offset is relative to the start of the queue (not the start of
2397 * the current buffer).
2399 static ALint64 GetSourceOffset(const ALsource *Source)
2401 const ALbufferlistitem *BufferList;
2402 ALuint64 readPos;
2403 ALuint i;
2405 if(Source->state != AL_PLAYING && Source->state != AL_PAUSED)
2406 return 0;
2408 /* NOTE: This is the offset into the *current* buffer, so add the length of
2409 * any played buffers */
2410 readPos = (ALuint64)Source->position << 32;
2411 readPos |= (ALuint64)Source->position_fraction << (32-FRACTIONBITS);
2412 BufferList = Source->queue;
2413 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2415 if(BufferList->buffer)
2416 readPos += (ALuint64)BufferList->buffer->SampleLen << 32;
2417 BufferList = BufferList->next;
2420 return (ALint64)minu64(readPos, MAKEU64(0x7fffffff,0xffffffff));
2423 /* GetSourceSecOffset
2425 * Gets the current read offset for the given Source, in seconds. The offset is
2426 * relative to the start of the queue (not the start of the current buffer).
2428 static ALdouble GetSourceSecOffset(const ALsource *Source)
2430 const ALbufferlistitem *BufferList;
2431 const ALbuffer *Buffer = NULL;
2432 ALuint64 readPos;
2433 ALuint i;
2435 BufferList = Source->queue;
2436 while(BufferList)
2438 if(BufferList->buffer)
2440 Buffer = BufferList->buffer;
2441 break;
2443 BufferList = BufferList->next;
2446 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2447 return 0.0;
2449 /* NOTE: This is the offset into the *current* buffer, so add the length of
2450 * any played buffers */
2451 readPos = (ALuint64)Source->position << FRACTIONBITS;
2452 readPos |= (ALuint64)Source->position_fraction;
2453 BufferList = Source->queue;
2454 for(i = 0;i < Source->BuffersPlayed && BufferList;i++)
2456 if(BufferList->buffer)
2457 readPos += (ALuint64)BufferList->buffer->SampleLen << FRACTIONBITS;
2458 BufferList = BufferList->next;
2461 return (ALdouble)readPos / (ALdouble)FRACTIONONE / (ALdouble)Buffer->Frequency;
2464 /* GetSourceOffsets
2466 * Gets the current read and write offsets for the given Source, in the
2467 * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
2468 * the start of the queue (not the start of the current buffer).
2470 static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen)
2472 const ALbufferlistitem *BufferList;
2473 const ALbuffer *Buffer = NULL;
2474 ALuint readPos, writePos;
2475 ALuint totalBufferLen;
2476 ALuint i;
2478 // Find the first valid Buffer in the Queue
2479 BufferList = Source->queue;
2480 while(BufferList)
2482 if(BufferList->buffer)
2484 Buffer = BufferList->buffer;
2485 break;
2487 BufferList = BufferList->next;
2490 if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer)
2492 offset[0] = 0.0;
2493 offset[1] = 0.0;
2494 return;
2497 if(updateLen > 0.0 && updateLen < 0.015)
2498 updateLen = 0.015;
2500 /* NOTE: This is the offset into the *current* buffer, so add the length of
2501 * any played buffers */
2502 readPos = Source->position;
2503 totalBufferLen = 0;
2504 BufferList = Source->queue;
2505 for(i = 0;BufferList;i++)
2507 if(BufferList->buffer)
2509 if(i < Source->BuffersPlayed)
2510 readPos += BufferList->buffer->SampleLen;
2511 totalBufferLen += BufferList->buffer->SampleLen;
2513 BufferList = BufferList->next;
2515 if(Source->state == AL_PLAYING)
2516 writePos = readPos + (ALuint)(updateLen*Buffer->Frequency);
2517 else
2518 writePos = readPos;
2520 if(Source->Looping)
2522 readPos %= totalBufferLen;
2523 writePos %= totalBufferLen;
2525 else
2527 /* Wrap positions back to 0 */
2528 if(readPos >= totalBufferLen)
2529 readPos = 0;
2530 if(writePos >= totalBufferLen)
2531 writePos = 0;
2534 switch(name)
2536 case AL_SEC_OFFSET:
2537 offset[0] = (ALdouble)readPos / Buffer->Frequency;
2538 offset[1] = (ALdouble)writePos / Buffer->Frequency;
2539 break;
2541 case AL_SAMPLE_OFFSET:
2542 case AL_SAMPLE_RW_OFFSETS_SOFT:
2543 offset[0] = (ALdouble)readPos;
2544 offset[1] = (ALdouble)writePos;
2545 break;
2547 case AL_BYTE_OFFSET:
2548 case AL_BYTE_RW_OFFSETS_SOFT:
2549 if(Buffer->OriginalType == UserFmtIMA4)
2551 ALuint BlockSize = 36 * ChannelsFromFmt(Buffer->FmtChannels);
2552 ALuint FrameBlockSize = 65;
2554 /* Round down to nearest ADPCM block */
2555 offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize);
2556 if(Source->state != AL_PLAYING)
2557 offset[1] = offset[0];
2558 else
2560 /* Round up to nearest ADPCM block */
2561 offset[1] = (ALdouble)((writePos+FrameBlockSize-1) /
2562 FrameBlockSize * BlockSize);
2565 else
2567 ALuint FrameSize = FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2568 offset[0] = (ALdouble)(readPos * FrameSize);
2569 offset[1] = (ALdouble)(writePos * FrameSize);
2571 break;
2576 /* ApplyOffset
2578 * Apply the stored playback offset to the Source. This function will update
2579 * the number of buffers "played" given the stored offset.
2581 ALboolean ApplyOffset(ALsource *Source)
2583 const ALbufferlistitem *BufferList;
2584 const ALbuffer *Buffer;
2585 ALint bufferLen, totalBufferLen;
2586 ALint buffersPlayed;
2587 ALint offset;
2589 /* Get sample frame offset */
2590 offset = GetSampleOffset(Source);
2591 if(offset == -1)
2592 return AL_FALSE;
2594 buffersPlayed = 0;
2595 totalBufferLen = 0;
2597 BufferList = Source->queue;
2598 while(BufferList)
2600 Buffer = BufferList->buffer;
2601 bufferLen = Buffer ? Buffer->SampleLen : 0;
2603 if(bufferLen <= offset-totalBufferLen)
2605 /* Offset is past this buffer so increment to the next buffer */
2606 buffersPlayed++;
2608 else if(totalBufferLen <= offset)
2610 /* Offset is in this buffer */
2611 Source->BuffersPlayed = buffersPlayed;
2613 Source->position = offset - totalBufferLen;
2614 Source->position_fraction = 0;
2615 return AL_TRUE;
2618 totalBufferLen += bufferLen;
2620 BufferList = BufferList->next;
2623 /* Offset is out of range of the queue */
2624 return AL_FALSE;
2628 /* GetSampleOffset
2630 * Returns the sample offset into the Source's queue (from the Sample, Byte or
2631 * Second offset supplied by the application). This takes into account the fact
2632 * that the buffer format may have been modifed since.
2634 static ALint GetSampleOffset(ALsource *Source)
2636 const ALbuffer *Buffer = NULL;
2637 const ALbufferlistitem *BufferList;
2638 ALint Offset = -1;
2640 /* Find the first valid Buffer in the Queue */
2641 BufferList = Source->queue;
2642 while(BufferList)
2644 if(BufferList->buffer)
2646 Buffer = BufferList->buffer;
2647 break;
2649 BufferList = BufferList->next;
2652 if(!Buffer)
2654 Source->Offset = -1.0;
2655 return -1;
2658 switch(Source->OffsetType)
2660 case AL_BYTE_OFFSET:
2661 /* Determine the ByteOffset (and ensure it is block aligned) */
2662 Offset = (ALint)Source->Offset;
2663 if(Buffer->OriginalType == UserFmtIMA4)
2665 Offset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels);
2666 Offset *= 65;
2668 else
2669 Offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
2670 break;
2672 case AL_SAMPLE_OFFSET:
2673 Offset = (ALint)Source->Offset;
2674 break;
2676 case AL_SEC_OFFSET:
2677 Offset = (ALint)(Source->Offset * Buffer->Frequency);
2678 break;
2680 Source->Offset = -1.0;
2682 return Offset;
2686 /* ReleaseALSources
2688 * Destroys all sources in the source map.
2690 ALvoid ReleaseALSources(ALCcontext *Context)
2692 ALsizei pos;
2693 ALuint j;
2694 for(pos = 0;pos < Context->SourceMap.size;pos++)
2696 ALsource *temp = Context->SourceMap.array[pos].value;
2697 Context->SourceMap.array[pos].value = NULL;
2699 while(temp->queue != NULL)
2701 ALbufferlistitem *BufferList = temp->queue;
2702 temp->queue = BufferList->next;
2704 if(BufferList->buffer != NULL)
2705 DecrementRef(&BufferList->buffer->ref);
2706 free(BufferList);
2709 for(j = 0;j < MAX_SENDS;++j)
2711 if(temp->Send[j].Slot)
2712 DecrementRef(&temp->Send[j].Slot->ref);
2713 temp->Send[j].Slot = NULL;
2716 FreeThunkEntry(temp->id);
2717 memset(temp, 0, sizeof(*temp));
2718 al_free(temp);