Removed duplicate file in Android.mk file list.
[openal-soft/android.git] / Alc / mixer.c
blob8b3c754e3068c1b51fa1af32308dc6bbfd1f0609
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 ALfloat point32(const ALfloat *vals, ALint step, ALint frac)
41 { return vals[0]; (void)step; (void)frac; }
42 static __inline ALfloat lerp32(const ALfloat *vals, ALint step, ALint frac)
43 { return lerp(vals[0], vals[step], frac * (1.0f/FRACTIONONE)); }
44 static __inline ALfloat cubic32(const ALfloat *vals, ALint step, ALint frac)
45 { return cubic(vals[-step], vals[0], vals[step], vals[step+step],
46 frac * (1.0f/FRACTIONONE)); }
48 #ifdef __GNUC__
49 #define LIKELY(x) __builtin_expect(!!(x), 1)
50 #define UNLIKELY(x) __builtin_expect(!!(x), 0)
51 #else
52 #define LIKELY(x) (x)
53 #define UNLIKELY(x) (x)
54 #endif
56 #if defined(__ARM_NEON__) && defined(HAVE_ARM_NEON_H)
57 #include <arm_neon.h>
59 static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
60 ALfloat (*RESTRICT Coeffs)[2],
61 ALfloat left, ALfloat right)
63 ALuint c;
64 float32x4_t leftright4;
66 float32x2_t leftright2 = vdup_n_f32(0.0);
67 leftright2 = vset_lane_f32(left, leftright2, 0);
68 leftright2 = vset_lane_f32(right, leftright2, 1);
69 leftright4 = vcombine_f32(leftright2, leftright2);
71 for(c = 0;c < HRIR_LENGTH;c += 2)
73 const ALuint o0 = (Offset+c)&HRIR_MASK;
74 const ALuint o1 = (o0+1)&HRIR_MASK;
75 float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[o0][0]),
76 vld1_f32((float32_t*)&Values[o1][0]));
77 float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]);
79 vals = vmlaq_f32(vals, coefs, leftright4);
81 vst1_f32((float32_t*)&Values[o0][0], vget_low_f32(vals));
82 vst1_f32((float32_t*)&Values[o1][0], vget_high_f32(vals));
86 #else
88 static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
89 ALfloat (*RESTRICT Coeffs)[2],
90 ALfloat left, ALfloat right)
92 ALuint c;
93 for(c = 0;c < HRIR_LENGTH;c++)
95 const ALuint off = (Offset+c)&HRIR_MASK;
96 Values[off][0] += Coeffs[c][0] * left;
97 Values[off][1] += Coeffs[c][1] * right;
101 #endif
103 #define DECL_TEMPLATE(T, sampler) \
104 static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
105 const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \
106 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
108 const ALuint NumChannels = Source->NumChannels; \
109 const T *RESTRICT data = srcdata; \
110 const ALint *RESTRICT DelayStep = Source->Params.HrtfDelayStep; \
111 ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS]; \
112 ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks; \
113 ALfloat (*RESTRICT CoeffStep)[2] = Source->Params.HrtfCoeffStep; \
114 ALuint pos, frac; \
115 FILTER *DryFilter; \
116 ALuint BufferIdx; \
117 ALuint increment; \
118 ALuint i, out, c; \
119 ALfloat value; \
121 increment = Source->Params.Step; \
123 DryBuffer = Device->DryBuffer; \
124 ClickRemoval = Device->ClickRemoval; \
125 PendingClicks = Device->PendingClicks; \
126 DryFilter = &Source->Params.iirFilter; \
128 pos = 0; \
129 frac = *DataPosFrac; \
131 for(i = 0;i < NumChannels;i++) \
133 ALfloat (*RESTRICT TargetCoeffs)[2] = Source->Params.HrtfCoeffs[i]; \
134 ALuint *RESTRICT TargetDelay = Source->Params.HrtfDelay[i]; \
135 ALfloat *RESTRICT History = Source->HrtfHistory[i]; \
136 ALfloat (*RESTRICT Values)[2] = Source->HrtfValues[i]; \
137 ALint Counter = maxu(Source->HrtfCounter, OutPos) - OutPos; \
138 ALuint Offset = Source->HrtfOffset + OutPos; \
139 ALfloat Coeffs[HRIR_LENGTH][2]; \
140 ALuint Delay[2]; \
141 ALfloat left, right; \
143 pos = 0; \
144 frac = *DataPosFrac; \
146 for(c = 0;c < HRIR_LENGTH;c++) \
148 Coeffs[c][0] = TargetCoeffs[c][0] - (CoeffStep[c][0]*Counter); \
149 Coeffs[c][1] = TargetCoeffs[c][1] - (CoeffStep[c][1]*Counter); \
152 Delay[0] = TargetDelay[0] - (DelayStep[0]*Counter) + 32768; \
153 Delay[1] = TargetDelay[1] - (DelayStep[1]*Counter) + 32768; \
155 if(LIKELY(OutPos == 0)) \
157 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
158 value = lpFilter2PC(DryFilter, i, value); \
160 History[Offset&SRC_HISTORY_MASK] = value; \
161 left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \
162 right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \
164 ClickRemoval[FRONT_LEFT] -= Values[(Offset+1)&HRIR_MASK][0] + \
165 Coeffs[0][0] * left; \
166 ClickRemoval[FRONT_RIGHT] -= Values[(Offset+1)&HRIR_MASK][1] + \
167 Coeffs[0][1] * right; \
169 for(BufferIdx = 0;BufferIdx < BufferSize && Counter > 0;BufferIdx++) \
171 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
172 value = lpFilter2P(DryFilter, i, value); \
174 History[Offset&SRC_HISTORY_MASK] = value; \
175 left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \
176 right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \
178 Delay[0] += DelayStep[0]; \
179 Delay[1] += DelayStep[1]; \
181 Values[Offset&HRIR_MASK][0] = 0.0f; \
182 Values[Offset&HRIR_MASK][1] = 0.0f; \
183 Offset++; \
185 for(c = 0;c < HRIR_LENGTH;c++) \
187 const ALuint off = (Offset+c)&HRIR_MASK; \
188 Values[off][0] += Coeffs[c][0] * left; \
189 Values[off][1] += Coeffs[c][1] * right; \
190 Coeffs[c][0] += CoeffStep[c][0]; \
191 Coeffs[c][1] += CoeffStep[c][1]; \
194 DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \
195 DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \
197 frac += increment; \
198 pos += frac>>FRACTIONBITS; \
199 frac &= FRACTIONMASK; \
200 OutPos++; \
201 Counter--; \
204 Delay[0] >>= 16; \
205 Delay[1] >>= 16; \
206 for(;BufferIdx < BufferSize;BufferIdx++) \
208 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
209 value = lpFilter2P(DryFilter, i, value); \
211 History[Offset&SRC_HISTORY_MASK] = value; \
212 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \
213 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \
215 Values[Offset&HRIR_MASK][0] = 0.0f; \
216 Values[Offset&HRIR_MASK][1] = 0.0f; \
217 Offset++; \
219 ApplyCoeffs(Offset, Values, Coeffs, left, right); \
220 DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \
221 DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \
223 frac += increment; \
224 pos += frac>>FRACTIONBITS; \
225 frac &= FRACTIONMASK; \
226 OutPos++; \
228 if(LIKELY(OutPos == SamplesToDo)) \
230 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
231 value = lpFilter2PC(DryFilter, i, value); \
233 History[Offset&SRC_HISTORY_MASK] = value; \
234 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \
235 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \
237 PendingClicks[FRONT_LEFT] += Values[(Offset+1)&HRIR_MASK][0] + \
238 Coeffs[0][0] * left; \
239 PendingClicks[FRONT_RIGHT] += Values[(Offset+1)&HRIR_MASK][1] + \
240 Coeffs[0][1] * right; \
242 OutPos -= BufferSize; \
245 for(out = 0;out < Device->NumAuxSends;out++) \
247 ALeffectslot *Slot = Source->Params.Send[out].Slot; \
248 ALfloat WetSend; \
249 ALfloat *RESTRICT WetBuffer; \
250 ALfloat *RESTRICT WetClickRemoval; \
251 ALfloat *RESTRICT WetPendingClicks; \
252 FILTER *WetFilter; \
254 if(Slot == NULL) \
255 continue; \
257 WetBuffer = Slot->WetBuffer; \
258 WetClickRemoval = Slot->ClickRemoval; \
259 WetPendingClicks = Slot->PendingClicks; \
260 WetFilter = &Source->Params.Send[out].iirFilter; \
261 WetSend = Source->Params.Send[out].WetGain; \
263 for(i = 0;i < NumChannels;i++) \
265 pos = 0; \
266 frac = *DataPosFrac; \
268 if(LIKELY(OutPos == 0)) \
270 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
271 value = lpFilter1PC(WetFilter, i, value); \
273 WetClickRemoval[0] -= value * WetSend; \
275 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
277 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
278 value = lpFilter1P(WetFilter, i, value); \
280 WetBuffer[OutPos] += value * WetSend; \
282 frac += increment; \
283 pos += frac>>FRACTIONBITS; \
284 frac &= FRACTIONMASK; \
285 OutPos++; \
287 if(LIKELY(OutPos == SamplesToDo)) \
289 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
290 value = lpFilter1PC(WetFilter, i, value); \
292 WetPendingClicks[0] += value * WetSend; \
294 OutPos -= BufferSize; \
297 *DataPosInt += pos; \
298 *DataPosFrac = frac; \
301 DECL_TEMPLATE(ALfloat, point32)
302 DECL_TEMPLATE(ALfloat, lerp32)
303 DECL_TEMPLATE(ALfloat, cubic32)
305 #undef DECL_TEMPLATE
308 #define DECL_TEMPLATE(T, sampler) \
309 static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
310 const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \
311 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
313 const ALuint NumChannels = Source->NumChannels; \
314 const T *RESTRICT data = srcdata; \
315 ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS]; \
316 ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks; \
317 ALfloat DrySend[MAXCHANNELS]; \
318 FILTER *DryFilter; \
319 ALuint pos, frac; \
320 ALuint BufferIdx; \
321 ALuint increment; \
322 ALuint i, out, c; \
323 ALfloat value; \
325 increment = Source->Params.Step; \
327 DryBuffer = Device->DryBuffer; \
328 ClickRemoval = Device->ClickRemoval; \
329 PendingClicks = Device->PendingClicks; \
330 DryFilter = &Source->Params.iirFilter; \
332 pos = 0; \
333 frac = *DataPosFrac; \
335 for(i = 0;i < NumChannels;i++) \
337 for(c = 0;c < MAXCHANNELS;c++) \
338 DrySend[c] = Source->Params.DryGains[i][c]; \
340 pos = 0; \
341 frac = *DataPosFrac; \
343 if(OutPos == 0) \
345 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
347 value = lpFilter2PC(DryFilter, i, value); \
348 for(c = 0;c < MAXCHANNELS;c++) \
349 ClickRemoval[c] -= value*DrySend[c]; \
351 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
353 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
355 value = lpFilter2P(DryFilter, i, value); \
356 for(c = 0;c < MAXCHANNELS;c++) \
357 DryBuffer[OutPos][c] += value*DrySend[c]; \
359 frac += increment; \
360 pos += frac>>FRACTIONBITS; \
361 frac &= FRACTIONMASK; \
362 OutPos++; \
364 if(OutPos == SamplesToDo) \
366 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
368 value = lpFilter2PC(DryFilter, i, value); \
369 for(c = 0;c < MAXCHANNELS;c++) \
370 PendingClicks[c] += value*DrySend[c]; \
372 OutPos -= BufferSize; \
375 for(out = 0;out < Device->NumAuxSends;out++) \
377 ALeffectslot *Slot = Source->Params.Send[out].Slot; \
378 ALfloat WetSend; \
379 ALfloat *WetBuffer; \
380 ALfloat *WetClickRemoval; \
381 ALfloat *WetPendingClicks; \
382 FILTER *WetFilter; \
384 if(Slot == NULL) \
385 continue; \
387 WetBuffer = Slot->WetBuffer; \
388 WetClickRemoval = Slot->ClickRemoval; \
389 WetPendingClicks = Slot->PendingClicks; \
390 WetFilter = &Source->Params.Send[out].iirFilter; \
391 WetSend = Source->Params.Send[out].WetGain; \
393 for(i = 0;i < NumChannels;i++) \
395 pos = 0; \
396 frac = *DataPosFrac; \
398 if(OutPos == 0) \
400 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
402 value = lpFilter1PC(WetFilter, i, value); \
403 WetClickRemoval[0] -= value * WetSend; \
405 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
407 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
409 value = lpFilter1P(WetFilter, i, value); \
410 WetBuffer[OutPos] += value * WetSend; \
412 frac += increment; \
413 pos += frac>>FRACTIONBITS; \
414 frac &= FRACTIONMASK; \
415 OutPos++; \
417 if(OutPos == SamplesToDo) \
419 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
421 value = lpFilter1PC(WetFilter, i, value); \
422 WetPendingClicks[0] += value * WetSend; \
424 OutPos -= BufferSize; \
427 *DataPosInt += pos; \
428 *DataPosFrac = frac; \
431 DECL_TEMPLATE(ALfloat, point32)
432 DECL_TEMPLATE(ALfloat, lerp32)
433 DECL_TEMPLATE(ALfloat, cubic32)
435 #undef DECL_TEMPLATE
438 MixerFunc SelectMixer(enum Resampler Resampler)
440 switch(Resampler)
442 case POINT_RESAMPLER:
443 return Mix_ALfloat_point32;
444 case LINEAR_RESAMPLER:
445 return Mix_ALfloat_lerp32;
446 case CUBIC_RESAMPLER:
447 return Mix_ALfloat_cubic32;
448 case RESAMPLER_MIN:
449 case RESAMPLER_MAX:
450 break;
452 return NULL;
455 MixerFunc SelectHrtfMixer(enum Resampler Resampler)
457 switch(Resampler)
459 case POINT_RESAMPLER:
460 return Mix_Hrtf_ALfloat_point32;
461 case LINEAR_RESAMPLER:
462 return Mix_Hrtf_ALfloat_lerp32;
463 case CUBIC_RESAMPLER:
464 return Mix_Hrtf_ALfloat_cubic32;
465 case RESAMPLER_MIN:
466 case RESAMPLER_MAX:
467 break;
469 return NULL;
473 static __inline ALfloat Sample_ALbyte(ALbyte val)
474 { return val * (1.0f/127.0f); }
476 static __inline ALfloat Sample_ALshort(ALshort val)
477 { return val * (1.0f/32767.0f); }
479 static __inline ALfloat Sample_ALfloat(ALfloat val)
480 { return val; }
482 #define DECL_TEMPLATE(T) \
483 static void Load_##T(ALfloat *dst, const T *src, ALuint samples) \
485 ALuint i; \
486 for(i = 0;i < samples;i++) \
487 dst[i] = Sample_##T(src[i]); \
490 DECL_TEMPLATE(ALbyte)
491 DECL_TEMPLATE(ALshort)
492 DECL_TEMPLATE(ALfloat)
494 #undef DECL_TEMPLATE
496 static void LoadStack(ALfloat *dst, const ALvoid *src, enum FmtType srctype, ALuint samples)
498 switch(srctype)
500 case FmtByte:
501 Load_ALbyte(dst, src, samples);
502 break;
503 case FmtShort:
504 Load_ALshort(dst, src, samples);
505 break;
506 case FmtFloat:
507 Load_ALfloat(dst, src, samples);
508 break;
512 static void SilenceStack(ALfloat *dst, ALuint samples)
514 ALuint i;
515 for(i = 0;i < samples;i++)
516 dst[i] = 0.0f;
520 ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
522 ALbufferlistitem *BufferListItem;
523 ALuint DataPosInt, DataPosFrac;
524 ALuint BuffersPlayed;
525 ALboolean Looping;
526 ALuint increment;
527 enum Resampler Resampler;
528 ALenum State;
529 ALuint OutPos;
530 ALuint NumChannels;
531 ALuint FrameSize;
532 ALint64 DataSize64;
533 ALuint i;
535 /* Get source info */
536 State = Source->state;
537 BuffersPlayed = Source->BuffersPlayed;
538 DataPosInt = Source->position;
539 DataPosFrac = Source->position_fraction;
540 Looping = Source->bLooping;
541 increment = Source->Params.Step;
542 Resampler = Source->Resampler;
543 NumChannels = Source->NumChannels;
544 FrameSize = NumChannels * Source->SampleSize;
546 /* Get current buffer queue item */
547 BufferListItem = Source->queue;
548 for(i = 0;i < BuffersPlayed;i++)
549 BufferListItem = BufferListItem->next;
551 OutPos = 0;
552 do {
553 const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
554 const ALuint BufferPadding = ResamplerPadding[Resampler];
555 ALfloat StackData[STACK_DATA_SIZE/sizeof(ALfloat)];
556 ALfloat *SrcData = StackData;
557 ALuint SrcDataSize = 0;
558 ALuint BufferSize;
560 /* Figure out how many buffer bytes will be needed */
561 DataSize64 = SamplesToDo-OutPos+1;
562 DataSize64 *= increment;
563 DataSize64 += DataPosFrac+FRACTIONMASK;
564 DataSize64 >>= FRACTIONBITS;
565 DataSize64 += BufferPadding+BufferPrePadding;
566 DataSize64 *= NumChannels;
568 BufferSize = (ALuint)mini64(DataSize64, STACK_DATA_SIZE/sizeof(ALfloat));
569 BufferSize /= NumChannels;
571 if(Source->lSourceType == AL_STATIC)
573 const ALbuffer *ALBuffer = Source->queue->buffer;
574 const ALubyte *Data = ALBuffer->data;
575 ALuint DataSize;
576 ALuint pos;
578 /* If current pos is beyond the loop range, do not loop */
579 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
581 Looping = AL_FALSE;
583 if(DataPosInt >= BufferPrePadding)
584 pos = DataPosInt - BufferPrePadding;
585 else
587 DataSize = BufferPrePadding - DataPosInt;
588 DataSize = minu(BufferSize, DataSize);
590 SilenceStack(&SrcData[SrcDataSize*NumChannels],
591 DataSize*NumChannels);
592 SrcDataSize += DataSize;
593 BufferSize -= DataSize;
595 pos = 0;
598 /* Copy what's left to play in the source buffer, and clear the
599 * rest of the temp buffer */
600 DataSize = ALBuffer->SampleLen - pos;
601 DataSize = minu(BufferSize, DataSize);
603 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
604 ALBuffer->FmtType, DataSize*NumChannels);
605 SrcDataSize += DataSize;
606 BufferSize -= DataSize;
608 SilenceStack(&SrcData[SrcDataSize*NumChannels],
609 BufferSize*NumChannels);
610 SrcDataSize += BufferSize;
611 BufferSize -= BufferSize;
613 else
615 ALuint LoopStart = ALBuffer->LoopStart;
616 ALuint LoopEnd = ALBuffer->LoopEnd;
618 if(DataPosInt >= LoopStart)
620 pos = DataPosInt-LoopStart;
621 while(pos < BufferPrePadding)
622 pos += LoopEnd-LoopStart;
623 pos -= BufferPrePadding;
624 pos += LoopStart;
626 else if(DataPosInt >= BufferPrePadding)
627 pos = DataPosInt - BufferPrePadding;
628 else
630 DataSize = BufferPrePadding - DataPosInt;
631 DataSize = minu(BufferSize, DataSize);
633 SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
634 SrcDataSize += DataSize;
635 BufferSize -= DataSize;
637 pos = 0;
640 /* Copy what's left of this loop iteration, then copy repeats
641 * of the loop section */
642 DataSize = LoopEnd - pos;
643 DataSize = minu(BufferSize, DataSize);
645 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
646 ALBuffer->FmtType, DataSize*NumChannels);
647 SrcDataSize += DataSize;
648 BufferSize -= DataSize;
650 DataSize = LoopEnd-LoopStart;
651 while(BufferSize > 0)
653 DataSize = minu(BufferSize, DataSize);
655 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[LoopStart*FrameSize],
656 ALBuffer->FmtType, DataSize*NumChannels);
657 SrcDataSize += DataSize;
658 BufferSize -= DataSize;
662 else
664 /* Crawl the buffer queue to fill in the temp buffer */
665 ALbufferlistitem *tmpiter = BufferListItem;
666 ALuint pos;
668 if(DataPosInt >= BufferPrePadding)
669 pos = DataPosInt - BufferPrePadding;
670 else
672 pos = BufferPrePadding - DataPosInt;
673 while(pos > 0)
675 if(!tmpiter->prev && !Looping)
677 ALuint DataSize = minu(BufferSize, pos);
679 SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
680 SrcDataSize += DataSize;
681 BufferSize -= DataSize;
683 pos = 0;
684 break;
687 if(tmpiter->prev)
688 tmpiter = tmpiter->prev;
689 else
691 while(tmpiter->next)
692 tmpiter = tmpiter->next;
695 if(tmpiter->buffer)
697 if((ALuint)tmpiter->buffer->SampleLen > pos)
699 pos = tmpiter->buffer->SampleLen - pos;
700 break;
702 pos -= tmpiter->buffer->SampleLen;
707 while(tmpiter && BufferSize > 0)
709 const ALbuffer *ALBuffer;
710 if((ALBuffer=tmpiter->buffer) != NULL)
712 const ALubyte *Data = ALBuffer->data;
713 ALuint DataSize = ALBuffer->SampleLen;
715 /* Skip the data already played */
716 if(DataSize <= pos)
717 pos -= DataSize;
718 else
720 Data += pos*FrameSize;
721 DataSize -= pos;
722 pos -= pos;
724 DataSize = minu(BufferSize, DataSize);
725 LoadStack(&SrcData[SrcDataSize*NumChannels], Data,
726 ALBuffer->FmtType, DataSize*NumChannels);
727 SrcDataSize += DataSize;
728 BufferSize -= DataSize;
731 tmpiter = tmpiter->next;
732 if(!tmpiter && Looping)
733 tmpiter = Source->queue;
734 else if(!tmpiter)
736 SilenceStack(&SrcData[SrcDataSize*NumChannels], BufferSize*NumChannels);
737 SrcDataSize += BufferSize;
738 BufferSize -= BufferSize;
743 /* Figure out how many samples we can mix. */
744 DataSize64 = SrcDataSize;
745 DataSize64 -= BufferPadding+BufferPrePadding;
746 DataSize64 <<= FRACTIONBITS;
747 DataSize64 -= increment;
748 DataSize64 -= DataPosFrac;
750 BufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
751 BufferSize = minu(BufferSize, (SamplesToDo-OutPos));
753 SrcData += BufferPrePadding*NumChannels;
754 Source->Params.DoMix(Source, Device, SrcData, &DataPosInt, &DataPosFrac,
755 OutPos, SamplesToDo, BufferSize);
756 OutPos += BufferSize;
758 /* Handle looping sources */
759 while(1)
761 const ALbuffer *ALBuffer;
762 ALuint DataSize = 0;
763 ALuint LoopStart = 0;
764 ALuint LoopEnd = 0;
766 if((ALBuffer=BufferListItem->buffer) != NULL)
768 DataSize = ALBuffer->SampleLen;
769 LoopStart = ALBuffer->LoopStart;
770 LoopEnd = ALBuffer->LoopEnd;
771 if(LoopEnd > DataPosInt)
772 break;
775 if(Looping && Source->lSourceType == AL_STATIC)
777 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
778 break;
781 if(DataSize > DataPosInt)
782 break;
784 if(BufferListItem->next)
786 BufferListItem = BufferListItem->next;
787 BuffersPlayed++;
789 else if(Looping)
791 BufferListItem = Source->queue;
792 BuffersPlayed = 0;
794 else
796 State = AL_STOPPED;
797 BufferListItem = Source->queue;
798 BuffersPlayed = Source->BuffersInQueue;
799 DataPosInt = 0;
800 DataPosFrac = 0;
801 break;
804 DataPosInt -= DataSize;
806 } while(State == AL_PLAYING && OutPos < SamplesToDo);
808 /* Update source info */
809 Source->state = State;
810 Source->BuffersPlayed = BuffersPlayed;
811 Source->position = DataPosInt;
812 Source->position_fraction = DataPosFrac;
813 Source->HrtfOffset += OutPos;
814 if(State == AL_PLAYING)
816 Source->HrtfCounter = maxu(Source->HrtfCounter, OutPos) - OutPos;
817 Source->HrtfMoving = AL_TRUE;
819 else
821 Source->HrtfCounter = 0;
822 Source->HrtfMoving = AL_FALSE;