Use logging macros in the sndio backend
[openal-soft/android.git] / Alc / mixer.c
blobdf0480aabf0fdbb52d69524bd775bdbeff3f4f35
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 <math.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <assert.h>
29 #include "alMain.h"
30 #include "AL/al.h"
31 #include "AL/alc.h"
32 #include "alSource.h"
33 #include "alBuffer.h"
34 #include "alListener.h"
35 #include "alAuxEffectSlot.h"
36 #include "alu.h"
37 #include "bs2b.h"
40 static __inline ALdouble point32(const ALfloat *vals, ALint step, ALint frac)
41 { return vals[0]; (void)step; (void)frac; }
42 static __inline ALdouble lerp32(const ALfloat *vals, ALint step, ALint frac)
43 { return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)); }
44 static __inline ALdouble cubic32(const ALfloat *vals, ALint step, ALint frac)
45 { return cubic(vals[-step], vals[0], vals[step], vals[step+step],
46 frac * (1.0/FRACTIONONE)); }
48 static __inline ALdouble point16(const ALshort *vals, ALint step, ALint frac)
49 { return vals[0] * (1.0/32767.0); (void)step; (void)frac; }
50 static __inline ALdouble lerp16(const ALshort *vals, ALint step, ALint frac)
51 { return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)) * (1.0/32767.0); }
52 static __inline ALdouble cubic16(const ALshort *vals, ALint step, ALint frac)
53 { return cubic(vals[-step], vals[0], vals[step], vals[step+step],
54 frac * (1.0/FRACTIONONE)) * (1.0/32767.0); }
56 static __inline ALdouble point8(const ALbyte *vals, ALint step, ALint frac)
57 { return vals[0] * (1.0/127.0); (void)step; (void)frac; }
58 static __inline ALdouble lerp8(const ALbyte *vals, ALint step, ALint frac)
59 { return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)) * (1.0/127.0); }
60 static __inline ALdouble cubic8(const ALbyte *vals, ALint step, ALint frac)
61 { return cubic(vals[-step], vals[0], vals[step], vals[step+step],
62 frac * (1.0/FRACTIONONE)) * (1.0/127.0); }
64 #ifdef __GNUC__
65 #define LIKELY(x) __builtin_expect(!!(x), 1)
66 #define UNLIKELY(x) __builtin_expect(!!(x), 0)
67 #else
68 #define LIKELY(x) (x)
69 #define UNLIKELY(x) (x)
70 #endif
72 #define DECL_TEMPLATE(T, sampler) \
73 static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
74 const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \
75 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
76 { \
77 const ALuint NumChannels = Source->NumChannels; \
78 const T *RESTRICT data = srcdata; \
79 ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS]; \
80 ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks; \
81 ALuint pos, frac; \
82 FILTER *DryFilter; \
83 ALuint BufferIdx; \
84 ALuint increment; \
85 ALuint i, out, c; \
86 ALfloat value; \
88 increment = Source->Params.Step; \
90 DryBuffer = Device->DryBuffer; \
91 ClickRemoval = Device->ClickRemoval; \
92 PendingClicks = Device->PendingClicks; \
93 DryFilter = &Source->Params.iirFilter; \
95 pos = 0; \
96 frac = *DataPosFrac; \
98 for(i = 0;i < NumChannels;i++) \
99 { \
100 ALfloat (*RESTRICT Coeffs)[2] = Source->Params.HrtfCoeffs[i]; \
101 const ALuint *RESTRICT Delay = Source->Params.HrtfDelay[i]; \
102 ALfloat *RESTRICT History = Source->HrtfHistory[i]; \
103 ALfloat (*RESTRICT Values)[2] = Source->HrtfValues[i]; \
104 ALuint Offset = Source->HrtfOffset + OutPos; \
105 ALfloat left, right; \
107 pos = 0; \
108 frac = *DataPosFrac; \
110 if(LIKELY(OutPos == 0)) \
112 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
113 value = lpFilter2PC(DryFilter, i, value); \
115 History[Offset&SRC_HISTORY_MASK] = value; \
116 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \
117 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \
119 ClickRemoval[FRONT_LEFT] -= Values[(Offset+1)&HRIR_MASK][0] + \
120 Coeffs[0][0] * left; \
121 ClickRemoval[FRONT_RIGHT] -= Values[(Offset+1)&HRIR_MASK][1] + \
122 Coeffs[0][1] * right; \
124 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
126 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
127 value = lpFilter2P(DryFilter, i, value); \
129 History[Offset&SRC_HISTORY_MASK] = value; \
130 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \
131 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \
133 Values[Offset&HRIR_MASK][0] = 0.0f; \
134 Values[Offset&HRIR_MASK][1] = 0.0f; \
135 Offset++; \
137 for(c = 0;c < HRIR_LENGTH;c++) \
139 const ALuint off = (Offset+c)&HRIR_MASK; \
140 Values[off][0] += Coeffs[c][0] * left; \
141 Values[off][1] += Coeffs[c][1] * right; \
144 DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \
145 DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \
147 frac += increment; \
148 pos += frac>>FRACTIONBITS; \
149 frac &= FRACTIONMASK; \
150 OutPos++; \
152 if(LIKELY(OutPos == SamplesToDo)) \
154 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
155 value = lpFilter2PC(DryFilter, i, value); \
157 History[Offset&SRC_HISTORY_MASK] = value; \
158 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \
159 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \
161 PendingClicks[FRONT_LEFT] += Values[(Offset+1)&HRIR_MASK][0] + \
162 Coeffs[0][0] * left; \
163 PendingClicks[FRONT_RIGHT] += Values[(Offset+1)&HRIR_MASK][1] + \
164 Coeffs[0][1] * right; \
166 OutPos -= BufferSize; \
169 for(out = 0;out < Device->NumAuxSends;out++) \
171 ALeffectslot *Slot = Source->Params.Send[i].Slot; \
172 ALfloat WetSend; \
173 ALfloat *RESTRICT WetBuffer; \
174 ALfloat *RESTRICT WetClickRemoval; \
175 ALfloat *RESTRICT WetPendingClicks; \
176 FILTER *WetFilter; \
178 if(!Slot || Slot->effect.type == AL_EFFECT_NULL) \
179 continue; \
181 WetBuffer = Slot->WetBuffer; \
182 WetClickRemoval = Slot->ClickRemoval; \
183 WetPendingClicks = Slot->PendingClicks; \
184 WetFilter = &Source->Params.Send[out].iirFilter; \
185 WetSend = Source->Params.Send[out].WetGain; \
187 for(i = 0;i < NumChannels;i++) \
189 pos = 0; \
190 frac = *DataPosFrac; \
192 if(LIKELY(OutPos == 0)) \
194 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
195 value = lpFilter1PC(WetFilter, i, value); \
197 WetClickRemoval[0] -= value * WetSend; \
199 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
201 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
202 value = lpFilter1P(WetFilter, i, value); \
204 WetBuffer[OutPos] += value * WetSend; \
206 frac += increment; \
207 pos += frac>>FRACTIONBITS; \
208 frac &= FRACTIONMASK; \
209 OutPos++; \
211 if(LIKELY(OutPos == SamplesToDo)) \
213 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
214 value = lpFilter1PC(WetFilter, i, value); \
216 WetPendingClicks[0] += value * WetSend; \
218 OutPos -= BufferSize; \
221 *DataPosInt += pos; \
222 *DataPosFrac = frac; \
225 DECL_TEMPLATE(ALfloat, point32)
226 DECL_TEMPLATE(ALfloat, lerp32)
227 DECL_TEMPLATE(ALfloat, cubic32)
229 DECL_TEMPLATE(ALshort, point16)
230 DECL_TEMPLATE(ALshort, lerp16)
231 DECL_TEMPLATE(ALshort, cubic16)
233 DECL_TEMPLATE(ALbyte, point8)
234 DECL_TEMPLATE(ALbyte, lerp8)
235 DECL_TEMPLATE(ALbyte, cubic8)
237 #undef DECL_TEMPLATE
240 #define DECL_TEMPLATE(T, sampler) \
241 static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
242 const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \
243 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
245 const ALuint NumChannels = Source->NumChannels; \
246 const T *RESTRICT data = srcdata; \
247 ALfloat (*DryBuffer)[MAXCHANNELS]; \
248 ALfloat *ClickRemoval, *PendingClicks; \
249 ALuint pos, frac; \
250 ALfloat DrySend[MAXCHANNELS][MAXCHANNELS]; \
251 FILTER *DryFilter; \
252 ALuint BufferIdx; \
253 ALuint increment; \
254 ALuint i, out, c; \
255 ALfloat value; \
257 increment = Source->Params.Step; \
259 DryBuffer = Device->DryBuffer; \
260 ClickRemoval = Device->ClickRemoval; \
261 PendingClicks = Device->PendingClicks; \
262 DryFilter = &Source->Params.iirFilter; \
263 for(i = 0;i < NumChannels;i++) \
265 for(c = 0;c < MAXCHANNELS;c++) \
266 DrySend[i][c] = Source->Params.DryGains[i][c]; \
269 pos = 0; \
270 frac = *DataPosFrac; \
272 for(i = 0;i < NumChannels;i++) \
274 pos = 0; \
275 frac = *DataPosFrac; \
277 if(OutPos == 0) \
279 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
281 value = lpFilter2PC(DryFilter, i, value); \
282 for(c = 0;c < MAXCHANNELS;c++) \
283 ClickRemoval[c] -= value*DrySend[i][c]; \
285 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
287 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
289 value = lpFilter2P(DryFilter, i, value); \
290 for(c = 0;c < MAXCHANNELS;c++) \
291 DryBuffer[OutPos][c] += value*DrySend[i][c]; \
293 frac += increment; \
294 pos += frac>>FRACTIONBITS; \
295 frac &= FRACTIONMASK; \
296 OutPos++; \
298 if(OutPos == SamplesToDo) \
300 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
302 value = lpFilter2PC(DryFilter, i, value); \
303 for(c = 0;c < MAXCHANNELS;c++) \
304 PendingClicks[c] += value*DrySend[i][c]; \
306 OutPos -= BufferSize; \
309 for(out = 0;out < Device->NumAuxSends;out++) \
311 ALeffectslot *Slot = Source->Params.Send[i].Slot; \
312 ALfloat WetSend; \
313 ALfloat *WetBuffer; \
314 ALfloat *WetClickRemoval; \
315 ALfloat *WetPendingClicks; \
316 FILTER *WetFilter; \
318 if(!Slot || Slot->effect.type == AL_EFFECT_NULL) \
319 continue; \
321 WetBuffer = Slot->WetBuffer; \
322 WetClickRemoval = Slot->ClickRemoval; \
323 WetPendingClicks = Slot->PendingClicks; \
324 WetFilter = &Source->Params.Send[out].iirFilter; \
325 WetSend = Source->Params.Send[out].WetGain; \
327 for(i = 0;i < NumChannels;i++) \
329 pos = 0; \
330 frac = *DataPosFrac; \
332 if(OutPos == 0) \
334 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
336 value = lpFilter1PC(WetFilter, i, value); \
337 WetClickRemoval[0] -= value * WetSend; \
339 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
341 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
343 value = lpFilter1P(WetFilter, i, value); \
344 WetBuffer[OutPos] += value * WetSend; \
346 frac += increment; \
347 pos += frac>>FRACTIONBITS; \
348 frac &= FRACTIONMASK; \
349 OutPos++; \
351 if(OutPos == SamplesToDo) \
353 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
355 value = lpFilter1PC(WetFilter, i, value); \
356 WetPendingClicks[0] += value * WetSend; \
358 OutPos -= BufferSize; \
361 *DataPosInt += pos; \
362 *DataPosFrac = frac; \
365 DECL_TEMPLATE(ALfloat, point32)
366 DECL_TEMPLATE(ALfloat, lerp32)
367 DECL_TEMPLATE(ALfloat, cubic32)
369 DECL_TEMPLATE(ALshort, point16)
370 DECL_TEMPLATE(ALshort, lerp16)
371 DECL_TEMPLATE(ALshort, cubic16)
373 DECL_TEMPLATE(ALbyte, point8)
374 DECL_TEMPLATE(ALbyte, lerp8)
375 DECL_TEMPLATE(ALbyte, cubic8)
377 #undef DECL_TEMPLATE
380 #define DECL_TEMPLATE(sampler) \
381 static MixerFunc Select_##sampler(enum FmtType FmtType) \
383 switch(FmtType) \
385 case FmtByte: \
386 return Mix_ALbyte_##sampler##8; \
387 case FmtShort: \
388 return Mix_ALshort_##sampler##16; \
389 case FmtFloat: \
390 return Mix_ALfloat_##sampler##32; \
392 return NULL; \
395 DECL_TEMPLATE(point)
396 DECL_TEMPLATE(lerp)
397 DECL_TEMPLATE(cubic)
399 #undef DECL_TEMPLATE
401 MixerFunc SelectMixer(ALbuffer *Buffer, enum Resampler Resampler)
403 switch(Resampler)
405 case POINT_RESAMPLER:
406 return Select_point(Buffer->FmtType);
407 case LINEAR_RESAMPLER:
408 return Select_lerp(Buffer->FmtType);
409 case CUBIC_RESAMPLER:
410 return Select_cubic(Buffer->FmtType);
411 case RESAMPLER_MIN:
412 case RESAMPLER_MAX:
413 break;
415 return NULL;
418 #define DECL_TEMPLATE(sampler) \
419 static MixerFunc Select_Hrtf_##sampler(enum FmtType FmtType) \
421 switch(FmtType) \
423 case FmtByte: \
424 return Mix_Hrtf_ALbyte_##sampler##8; \
425 case FmtShort: \
426 return Mix_Hrtf_ALshort_##sampler##16; \
427 case FmtFloat: \
428 return Mix_Hrtf_ALfloat_##sampler##32; \
430 return NULL; \
433 DECL_TEMPLATE(point)
434 DECL_TEMPLATE(lerp)
435 DECL_TEMPLATE(cubic)
437 #undef DECL_TEMPLATE
439 MixerFunc SelectHrtfMixer(ALbuffer *Buffer, enum Resampler Resampler)
441 switch(Resampler)
443 case POINT_RESAMPLER:
444 return Select_Hrtf_point(Buffer->FmtType);
445 case LINEAR_RESAMPLER:
446 return Select_Hrtf_lerp(Buffer->FmtType);
447 case CUBIC_RESAMPLER:
448 return Select_Hrtf_cubic(Buffer->FmtType);
449 case RESAMPLER_MIN:
450 case RESAMPLER_MAX:
451 break;
453 return NULL;
457 ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
459 ALbufferlistitem *BufferListItem;
460 ALuint DataPosInt, DataPosFrac;
461 ALuint BuffersPlayed;
462 ALboolean Looping;
463 ALuint increment;
464 enum Resampler Resampler;
465 ALenum State;
466 ALuint OutPos;
467 ALuint FrameSize;
468 ALint64 DataSize64;
469 ALuint i;
471 /* Get source info */
472 State = Source->state;
473 BuffersPlayed = Source->BuffersPlayed;
474 DataPosInt = Source->position;
475 DataPosFrac = Source->position_fraction;
476 Looping = Source->bLooping;
477 increment = Source->Params.Step;
478 Resampler = Source->Resampler;
479 FrameSize = Source->NumChannels * Source->SampleSize;
481 /* Get current buffer queue item */
482 BufferListItem = Source->queue;
483 for(i = 0;i < BuffersPlayed;i++)
484 BufferListItem = BufferListItem->next;
486 OutPos = 0;
487 do {
488 const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
489 const ALuint BufferPadding = ResamplerPadding[Resampler];
490 ALubyte StackData[STACK_DATA_SIZE];
491 ALubyte *SrcData = StackData;
492 ALuint SrcDataSize = 0;
493 ALuint BufferSize;
495 /* Figure out how many buffer bytes will be needed */
496 DataSize64 = SamplesToDo-OutPos+1;
497 DataSize64 *= increment;
498 DataSize64 += DataPosFrac+FRACTIONMASK;
499 DataSize64 >>= FRACTIONBITS;
500 DataSize64 += BufferPadding+BufferPrePadding;
501 DataSize64 *= FrameSize;
503 BufferSize = min(DataSize64, STACK_DATA_SIZE);
504 BufferSize -= BufferSize%FrameSize;
506 if(Source->lSourceType == AL_STATIC)
508 const ALbuffer *ALBuffer = Source->Buffer;
509 const ALubyte *Data = ALBuffer->data;
510 ALuint DataSize;
511 ALuint pos;
513 /* If current pos is beyond the loop range, do not loop */
514 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
516 Looping = AL_FALSE;
518 if(DataPosInt >= BufferPrePadding)
519 pos = (DataPosInt-BufferPrePadding)*FrameSize;
520 else
522 DataSize = (BufferPrePadding-DataPosInt)*FrameSize;
523 DataSize = min(BufferSize, DataSize);
525 memset(&SrcData[SrcDataSize], 0, DataSize);
526 SrcDataSize += DataSize;
527 BufferSize -= DataSize;
529 pos = 0;
532 /* Copy what's left to play in the source buffer, and clear the
533 * rest of the temp buffer */
534 DataSize = ALBuffer->size - pos;
535 DataSize = min(BufferSize, DataSize);
537 memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize);
538 SrcDataSize += DataSize;
539 BufferSize -= DataSize;
541 memset(&SrcData[SrcDataSize], 0, BufferSize);
542 SrcDataSize += BufferSize;
543 BufferSize -= BufferSize;
545 else
547 ALuint LoopStart = ALBuffer->LoopStart;
548 ALuint LoopEnd = ALBuffer->LoopEnd;
550 if(DataPosInt >= LoopStart)
552 pos = DataPosInt-LoopStart;
553 while(pos < BufferPrePadding)
554 pos += LoopEnd-LoopStart;
555 pos -= BufferPrePadding;
556 pos += LoopStart;
557 pos *= FrameSize;
559 else if(DataPosInt >= BufferPrePadding)
560 pos = (DataPosInt-BufferPrePadding)*FrameSize;
561 else
563 DataSize = (BufferPrePadding-DataPosInt)*FrameSize;
564 DataSize = min(BufferSize, DataSize);
566 memset(&SrcData[SrcDataSize], 0, DataSize);
567 SrcDataSize += DataSize;
568 BufferSize -= DataSize;
570 pos = 0;
573 /* Copy what's left of this loop iteration, then copy repeats
574 * of the loop section */
575 DataSize = LoopEnd*FrameSize - pos;
576 DataSize = min(BufferSize, DataSize);
578 memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize);
579 SrcDataSize += DataSize;
580 BufferSize -= DataSize;
582 DataSize = (LoopEnd-LoopStart) * FrameSize;
583 while(BufferSize > 0)
585 DataSize = min(BufferSize, DataSize);
587 memcpy(&SrcData[SrcDataSize], &Data[LoopStart*FrameSize], DataSize);
588 SrcDataSize += DataSize;
589 BufferSize -= DataSize;
593 else
595 /* Crawl the buffer queue to fill in the temp buffer */
596 ALbufferlistitem *BufferListIter = BufferListItem;
597 ALuint pos;
599 if(DataPosInt >= BufferPrePadding)
600 pos = (DataPosInt-BufferPrePadding)*FrameSize;
601 else
603 pos = (BufferPrePadding-DataPosInt)*FrameSize;
604 while(pos > 0)
606 if(!BufferListIter->prev && !Looping)
608 ALuint DataSize = min(BufferSize, pos);
610 memset(&SrcData[SrcDataSize], 0, DataSize);
611 SrcDataSize += DataSize;
612 BufferSize -= DataSize;
614 pos = 0;
615 break;
618 if(BufferListIter->prev)
619 BufferListIter = BufferListIter->prev;
620 else
622 while(BufferListIter->next)
623 BufferListIter = BufferListIter->next;
626 if(BufferListIter->buffer)
628 if((ALuint)BufferListIter->buffer->size > pos)
630 pos = BufferListIter->buffer->size - pos;
631 break;
633 pos -= BufferListIter->buffer->size;
638 while(BufferListIter && BufferSize > 0)
640 const ALbuffer *ALBuffer;
641 if((ALBuffer=BufferListIter->buffer) != NULL)
643 const ALubyte *Data = ALBuffer->data;
644 ALuint DataSize = ALBuffer->size;
646 /* Skip the data already played */
647 if(DataSize <= pos)
648 pos -= DataSize;
649 else
651 Data += pos;
652 DataSize -= pos;
653 pos -= pos;
655 DataSize = min(BufferSize, DataSize);
656 memcpy(&SrcData[SrcDataSize], Data, DataSize);
657 SrcDataSize += DataSize;
658 BufferSize -= DataSize;
661 BufferListIter = BufferListIter->next;
662 if(!BufferListIter && Looping)
663 BufferListIter = Source->queue;
664 else if(!BufferListIter)
666 memset(&SrcData[SrcDataSize], 0, BufferSize);
667 SrcDataSize += BufferSize;
668 BufferSize -= BufferSize;
673 /* Figure out how many samples we can mix. */
674 DataSize64 = SrcDataSize / FrameSize;
675 DataSize64 -= BufferPadding+BufferPrePadding;
676 DataSize64 <<= FRACTIONBITS;
677 DataSize64 -= increment;
678 DataSize64 -= DataPosFrac;
680 BufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
681 BufferSize = min(BufferSize, (SamplesToDo-OutPos));
683 SrcData += BufferPrePadding*FrameSize;
684 Source->Params.DoMix(Source, Device, SrcData, &DataPosInt, &DataPosFrac,
685 OutPos, SamplesToDo, BufferSize);
686 OutPos += BufferSize;
688 /* Handle looping sources */
689 while(1)
691 const ALbuffer *ALBuffer;
692 ALuint DataSize = 0;
693 ALuint LoopStart = 0;
694 ALuint LoopEnd = 0;
696 if((ALBuffer=BufferListItem->buffer) != NULL)
698 DataSize = ALBuffer->size / FrameSize;
699 LoopStart = ALBuffer->LoopStart;
700 LoopEnd = ALBuffer->LoopEnd;
701 if(LoopEnd > DataPosInt)
702 break;
705 if(Looping && Source->lSourceType == AL_STATIC)
707 BufferListItem = Source->queue;
708 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
709 break;
712 if(DataSize > DataPosInt)
713 break;
715 if(BufferListItem->next)
717 BufferListItem = BufferListItem->next;
718 BuffersPlayed++;
720 else if(Looping)
722 BufferListItem = Source->queue;
723 BuffersPlayed = 0;
725 else
727 State = AL_STOPPED;
728 BufferListItem = Source->queue;
729 BuffersPlayed = Source->BuffersInQueue;
730 DataPosInt = 0;
731 DataPosFrac = 0;
732 break;
735 DataPosInt -= DataSize;
737 } while(State == AL_PLAYING && OutPos < SamplesToDo);
739 /* Update source info */
740 Source->state = State;
741 Source->BuffersPlayed = BuffersPlayed;
742 Source->position = DataPosInt;
743 Source->position_fraction = DataPosFrac;
744 Source->Buffer = BufferListItem->buffer;
745 Source->HrtfOffset += OutPos;