Rename LOWPASSFREQCUTOFF to LOWPASSFREQREF
[openal-soft/android.git] / Alc / mixer.c
blobd6c0714bf74e2ad06298efa5046cb55d8a535044
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 static __inline ALfloat point16(const ALshort *vals, ALint step, ALint frac)
49 { return vals[0] * (1.0f/32767.0f); (void)step; (void)frac; }
50 static __inline ALfloat lerp16(const ALshort *vals, ALint step, ALint frac)
51 { return lerp(vals[0], vals[step], frac * (1.0f/FRACTIONONE)) * (1.0f/32767.0f); }
52 static __inline ALfloat cubic16(const ALshort *vals, ALint step, ALint frac)
53 { return cubic(vals[-step], vals[0], vals[step], vals[step+step],
54 frac * (1.0f/FRACTIONONE)) * (1.0f/32767.0f); }
56 static __inline ALfloat point8(const ALbyte *vals, ALint step, ALint frac)
57 { return vals[0] * (1.0f/127.0f); (void)step; (void)frac; }
58 static __inline ALfloat lerp8(const ALbyte *vals, ALint step, ALint frac)
59 { return lerp(vals[0], vals[step], frac * (1.0f/FRACTIONONE)) * (1.0f/127.0f); }
60 static __inline ALfloat cubic8(const ALbyte *vals, ALint step, ALint frac)
61 { return cubic(vals[-step], vals[0], vals[step], vals[step+step],
62 frac * (1.0f/FRACTIONONE)) * (1.0f/127.0f); }
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 #if defined(__ARM_NEON__) && defined(HAVE_ARM_NEON_H)
73 #include <arm_neon.h>
75 static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
76 ALfloat (*RESTRICT Coeffs)[2],
77 ALfloat left, ALfloat right)
79 ALuint c;
80 float32x4_t leftright4;
82 float32x2_t leftright2 = vdup_n_f32(0.0);
83 leftright2 = vset_lane_f32(left, leftright2, 0);
84 leftright2 = vset_lane_f32(right, leftright2, 1);
85 leftright4 = vcombine_f32(leftright2, leftright2);
87 for(c = 0;c < HRIR_LENGTH;c += 2)
89 const ALuint o0 = (Offset+c)&HRIR_MASK;
90 const ALuint o1 = (o0+1)&HRIR_MASK;
91 float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[o0][0]),
92 vld1_f32((float32_t*)&Values[o1][0]));
93 float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]);
95 vals = vmlaq_f32(vals, coefs, leftright4);
97 vst1_f32((float32_t*)&Values[o0][0], vget_low_f32(vals));
98 vst1_f32((float32_t*)&Values[o1][0], vget_high_f32(vals));
102 #else
104 static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
105 ALfloat (*RESTRICT Coeffs)[2],
106 ALfloat left, ALfloat right)
108 ALuint c;
109 for(c = 0;c < HRIR_LENGTH;c++)
111 const ALuint off = (Offset+c)&HRIR_MASK;
112 Values[off][0] += Coeffs[c][0] * left;
113 Values[off][1] += Coeffs[c][1] * right;
117 #endif
119 #define DECL_TEMPLATE(T, sampler) \
120 static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
121 const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \
122 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
124 const ALuint NumChannels = Source->NumChannels; \
125 const T *RESTRICT data = srcdata; \
126 const ALint *RESTRICT DelayStep = Source->Params.HrtfDelayStep; \
127 ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS]; \
128 ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks; \
129 ALfloat (*RESTRICT CoeffStep)[2] = Source->Params.HrtfCoeffStep; \
130 ALuint pos, frac; \
131 FILTER *DryFilter; \
132 ALuint BufferIdx; \
133 ALuint increment; \
134 ALuint i, out, c; \
135 ALfloat value; \
137 increment = Source->Params.Step; \
139 DryBuffer = Device->DryBuffer; \
140 ClickRemoval = Device->ClickRemoval; \
141 PendingClicks = Device->PendingClicks; \
142 DryFilter = &Source->Params.iirFilter; \
144 pos = 0; \
145 frac = *DataPosFrac; \
147 for(i = 0;i < NumChannels;i++) \
149 ALfloat (*RESTRICT TargetCoeffs)[2] = Source->Params.HrtfCoeffs[i]; \
150 ALuint *RESTRICT TargetDelay = Source->Params.HrtfDelay[i]; \
151 ALfloat *RESTRICT History = Source->HrtfHistory[i]; \
152 ALfloat (*RESTRICT Values)[2] = Source->HrtfValues[i]; \
153 ALint Counter = maxu(Source->HrtfCounter, OutPos) - OutPos; \
154 ALuint Offset = Source->HrtfOffset + OutPos; \
155 ALfloat Coeffs[HRIR_LENGTH][2]; \
156 ALuint Delay[2]; \
157 ALfloat left, right; \
159 pos = 0; \
160 frac = *DataPosFrac; \
162 for(c = 0;c < HRIR_LENGTH;c++) \
164 Coeffs[c][0] = TargetCoeffs[c][0] - (CoeffStep[c][0]*Counter); \
165 Coeffs[c][1] = TargetCoeffs[c][1] - (CoeffStep[c][1]*Counter); \
168 Delay[0] = TargetDelay[0] - (DelayStep[0]*Counter) + 32768; \
169 Delay[1] = TargetDelay[1] - (DelayStep[1]*Counter) + 32768; \
171 if(LIKELY(OutPos == 0)) \
173 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
174 value = lpFilter2PC(DryFilter, i, value); \
176 History[Offset&SRC_HISTORY_MASK] = value; \
177 left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \
178 right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \
180 ClickRemoval[FRONT_LEFT] -= Values[(Offset+1)&HRIR_MASK][0] + \
181 Coeffs[0][0] * left; \
182 ClickRemoval[FRONT_RIGHT] -= Values[(Offset+1)&HRIR_MASK][1] + \
183 Coeffs[0][1] * right; \
185 for(BufferIdx = 0;BufferIdx < BufferSize && Counter > 0;BufferIdx++) \
187 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
188 value = lpFilter2P(DryFilter, i, value); \
190 History[Offset&SRC_HISTORY_MASK] = value; \
191 left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \
192 right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \
194 Delay[0] += DelayStep[0]; \
195 Delay[1] += DelayStep[1]; \
197 Values[Offset&HRIR_MASK][0] = 0.0f; \
198 Values[Offset&HRIR_MASK][1] = 0.0f; \
199 Offset++; \
201 for(c = 0;c < HRIR_LENGTH;c++) \
203 const ALuint off = (Offset+c)&HRIR_MASK; \
204 Values[off][0] += Coeffs[c][0] * left; \
205 Values[off][1] += Coeffs[c][1] * right; \
206 Coeffs[c][0] += CoeffStep[c][0]; \
207 Coeffs[c][1] += CoeffStep[c][1]; \
210 DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \
211 DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \
213 frac += increment; \
214 pos += frac>>FRACTIONBITS; \
215 frac &= FRACTIONMASK; \
216 OutPos++; \
217 Counter--; \
220 Delay[0] >>= 16; \
221 Delay[1] >>= 16; \
222 for(;BufferIdx < BufferSize;BufferIdx++) \
224 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
225 value = lpFilter2P(DryFilter, i, value); \
227 History[Offset&SRC_HISTORY_MASK] = value; \
228 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \
229 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \
231 Values[Offset&HRIR_MASK][0] = 0.0f; \
232 Values[Offset&HRIR_MASK][1] = 0.0f; \
233 Offset++; \
235 ApplyCoeffs(Offset, Values, Coeffs, left, right); \
236 DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \
237 DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \
239 frac += increment; \
240 pos += frac>>FRACTIONBITS; \
241 frac &= FRACTIONMASK; \
242 OutPos++; \
244 if(LIKELY(OutPos == SamplesToDo)) \
246 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
247 value = lpFilter2PC(DryFilter, i, value); \
249 History[Offset&SRC_HISTORY_MASK] = value; \
250 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \
251 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \
253 PendingClicks[FRONT_LEFT] += Values[(Offset+1)&HRIR_MASK][0] + \
254 Coeffs[0][0] * left; \
255 PendingClicks[FRONT_RIGHT] += Values[(Offset+1)&HRIR_MASK][1] + \
256 Coeffs[0][1] * right; \
258 OutPos -= BufferSize; \
261 for(out = 0;out < Device->NumAuxSends;out++) \
263 ALeffectslot *Slot = Source->Params.Send[out].Slot; \
264 ALfloat WetSend; \
265 ALfloat *RESTRICT WetBuffer; \
266 ALfloat *RESTRICT WetClickRemoval; \
267 ALfloat *RESTRICT WetPendingClicks; \
268 FILTER *WetFilter; \
270 if(!Slot || Slot->effect.type == AL_EFFECT_NULL) \
271 continue; \
273 WetBuffer = Slot->WetBuffer; \
274 WetClickRemoval = Slot->ClickRemoval; \
275 WetPendingClicks = Slot->PendingClicks; \
276 WetFilter = &Source->Params.Send[out].iirFilter; \
277 WetSend = Source->Params.Send[out].WetGain; \
279 for(i = 0;i < NumChannels;i++) \
281 pos = 0; \
282 frac = *DataPosFrac; \
284 if(LIKELY(OutPos == 0)) \
286 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
287 value = lpFilter1PC(WetFilter, i, value); \
289 WetClickRemoval[0] -= value * WetSend; \
291 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
293 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
294 value = lpFilter1P(WetFilter, i, value); \
296 WetBuffer[OutPos] += value * WetSend; \
298 frac += increment; \
299 pos += frac>>FRACTIONBITS; \
300 frac &= FRACTIONMASK; \
301 OutPos++; \
303 if(LIKELY(OutPos == SamplesToDo)) \
305 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
306 value = lpFilter1PC(WetFilter, i, value); \
308 WetPendingClicks[0] += value * WetSend; \
310 OutPos -= BufferSize; \
313 *DataPosInt += pos; \
314 *DataPosFrac = frac; \
317 DECL_TEMPLATE(ALfloat, point32)
318 DECL_TEMPLATE(ALfloat, lerp32)
319 DECL_TEMPLATE(ALfloat, cubic32)
321 DECL_TEMPLATE(ALshort, point16)
322 DECL_TEMPLATE(ALshort, lerp16)
323 DECL_TEMPLATE(ALshort, cubic16)
325 DECL_TEMPLATE(ALbyte, point8)
326 DECL_TEMPLATE(ALbyte, lerp8)
327 DECL_TEMPLATE(ALbyte, cubic8)
329 #undef DECL_TEMPLATE
332 #define DECL_TEMPLATE(T, sampler) \
333 static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
334 const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \
335 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
337 const ALuint NumChannels = Source->NumChannels; \
338 const T *RESTRICT data = srcdata; \
339 ALfloat (*DryBuffer)[MAXCHANNELS]; \
340 ALfloat *ClickRemoval, *PendingClicks; \
341 ALfloat DrySend[MAXCHANNELS]; \
342 FILTER *DryFilter; \
343 ALuint pos, frac; \
344 ALuint BufferIdx; \
345 ALuint increment; \
346 ALuint i, out, c; \
347 ALfloat value; \
349 increment = Source->Params.Step; \
351 DryBuffer = Device->DryBuffer; \
352 ClickRemoval = Device->ClickRemoval; \
353 PendingClicks = Device->PendingClicks; \
354 DryFilter = &Source->Params.iirFilter; \
356 pos = 0; \
357 frac = *DataPosFrac; \
359 for(i = 0;i < NumChannels;i++) \
361 for(c = 0;c < MAXCHANNELS;c++) \
362 DrySend[c] = Source->Params.DryGains[i][c]; \
364 pos = 0; \
365 frac = *DataPosFrac; \
367 if(OutPos == 0) \
369 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
371 value = lpFilter2PC(DryFilter, i, value); \
372 for(c = 0;c < MAXCHANNELS;c++) \
373 ClickRemoval[c] -= value*DrySend[c]; \
375 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
377 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
379 value = lpFilter2P(DryFilter, i, value); \
380 for(c = 0;c < MAXCHANNELS;c++) \
381 DryBuffer[OutPos][c] += value*DrySend[c]; \
383 frac += increment; \
384 pos += frac>>FRACTIONBITS; \
385 frac &= FRACTIONMASK; \
386 OutPos++; \
388 if(OutPos == SamplesToDo) \
390 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
392 value = lpFilter2PC(DryFilter, i, value); \
393 for(c = 0;c < MAXCHANNELS;c++) \
394 PendingClicks[c] += value*DrySend[c]; \
396 OutPos -= BufferSize; \
399 for(out = 0;out < Device->NumAuxSends;out++) \
401 ALeffectslot *Slot = Source->Params.Send[out].Slot; \
402 ALfloat WetSend; \
403 ALfloat *WetBuffer; \
404 ALfloat *WetClickRemoval; \
405 ALfloat *WetPendingClicks; \
406 FILTER *WetFilter; \
408 if(!Slot || Slot->effect.type == AL_EFFECT_NULL) \
409 continue; \
411 WetBuffer = Slot->WetBuffer; \
412 WetClickRemoval = Slot->ClickRemoval; \
413 WetPendingClicks = Slot->PendingClicks; \
414 WetFilter = &Source->Params.Send[out].iirFilter; \
415 WetSend = Source->Params.Send[out].WetGain; \
417 for(i = 0;i < NumChannels;i++) \
419 pos = 0; \
420 frac = *DataPosFrac; \
422 if(OutPos == 0) \
424 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
426 value = lpFilter1PC(WetFilter, i, value); \
427 WetClickRemoval[0] -= value * WetSend; \
429 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
431 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
433 value = lpFilter1P(WetFilter, i, value); \
434 WetBuffer[OutPos] += value * WetSend; \
436 frac += increment; \
437 pos += frac>>FRACTIONBITS; \
438 frac &= FRACTIONMASK; \
439 OutPos++; \
441 if(OutPos == SamplesToDo) \
443 value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
445 value = lpFilter1PC(WetFilter, i, value); \
446 WetPendingClicks[0] += value * WetSend; \
448 OutPos -= BufferSize; \
451 *DataPosInt += pos; \
452 *DataPosFrac = frac; \
455 DECL_TEMPLATE(ALfloat, point32)
456 DECL_TEMPLATE(ALfloat, lerp32)
457 DECL_TEMPLATE(ALfloat, cubic32)
459 DECL_TEMPLATE(ALshort, point16)
460 DECL_TEMPLATE(ALshort, lerp16)
461 DECL_TEMPLATE(ALshort, cubic16)
463 DECL_TEMPLATE(ALbyte, point8)
464 DECL_TEMPLATE(ALbyte, lerp8)
465 DECL_TEMPLATE(ALbyte, cubic8)
467 #undef DECL_TEMPLATE
470 #define DECL_TEMPLATE(sampler) \
471 static MixerFunc Select_##sampler(enum FmtType FmtType) \
473 switch(FmtType) \
475 case FmtByte: \
476 return Mix_ALbyte_##sampler##8; \
477 case FmtShort: \
478 return Mix_ALshort_##sampler##16; \
479 case FmtFloat: \
480 return Mix_ALfloat_##sampler##32; \
482 return NULL; \
485 DECL_TEMPLATE(point)
486 DECL_TEMPLATE(lerp)
487 DECL_TEMPLATE(cubic)
489 #undef DECL_TEMPLATE
491 MixerFunc SelectMixer(ALbuffer *Buffer, enum Resampler Resampler)
493 switch(Resampler)
495 case POINT_RESAMPLER:
496 return Select_point(Buffer->FmtType);
497 case LINEAR_RESAMPLER:
498 return Select_lerp(Buffer->FmtType);
499 case CUBIC_RESAMPLER:
500 return Select_cubic(Buffer->FmtType);
501 case RESAMPLER_MIN:
502 case RESAMPLER_MAX:
503 break;
505 return NULL;
508 #define DECL_TEMPLATE(sampler) \
509 static MixerFunc Select_Hrtf_##sampler(enum FmtType FmtType) \
511 switch(FmtType) \
513 case FmtByte: \
514 return Mix_Hrtf_ALbyte_##sampler##8; \
515 case FmtShort: \
516 return Mix_Hrtf_ALshort_##sampler##16; \
517 case FmtFloat: \
518 return Mix_Hrtf_ALfloat_##sampler##32; \
520 return NULL; \
523 DECL_TEMPLATE(point)
524 DECL_TEMPLATE(lerp)
525 DECL_TEMPLATE(cubic)
527 #undef DECL_TEMPLATE
529 MixerFunc SelectHrtfMixer(ALbuffer *Buffer, enum Resampler Resampler)
531 switch(Resampler)
533 case POINT_RESAMPLER:
534 return Select_Hrtf_point(Buffer->FmtType);
535 case LINEAR_RESAMPLER:
536 return Select_Hrtf_lerp(Buffer->FmtType);
537 case CUBIC_RESAMPLER:
538 return Select_Hrtf_cubic(Buffer->FmtType);
539 case RESAMPLER_MIN:
540 case RESAMPLER_MAX:
541 break;
543 return NULL;
547 ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
549 ALbufferlistitem *BufferListItem;
550 ALuint DataPosInt, DataPosFrac;
551 ALuint BuffersPlayed;
552 ALboolean Looping;
553 ALuint increment;
554 enum Resampler Resampler;
555 ALenum State;
556 ALuint OutPos;
557 ALuint FrameSize;
558 ALint64 DataSize64;
559 ALuint i;
561 /* Get source info */
562 State = Source->state;
563 BuffersPlayed = Source->BuffersPlayed;
564 DataPosInt = Source->position;
565 DataPosFrac = Source->position_fraction;
566 Looping = Source->bLooping;
567 increment = Source->Params.Step;
568 Resampler = Source->Resampler;
569 FrameSize = Source->NumChannels * Source->SampleSize;
571 /* Get current buffer queue item */
572 BufferListItem = Source->queue;
573 for(i = 0;i < BuffersPlayed;i++)
574 BufferListItem = BufferListItem->next;
576 OutPos = 0;
577 do {
578 const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
579 const ALuint BufferPadding = ResamplerPadding[Resampler];
580 ALubyte StackData[STACK_DATA_SIZE];
581 ALubyte *SrcData = StackData;
582 ALuint SrcDataSize = 0;
583 ALuint BufferSize;
585 /* Figure out how many buffer bytes will be needed */
586 DataSize64 = SamplesToDo-OutPos+1;
587 DataSize64 *= increment;
588 DataSize64 += DataPosFrac+FRACTIONMASK;
589 DataSize64 >>= FRACTIONBITS;
590 DataSize64 += BufferPadding+BufferPrePadding;
591 DataSize64 *= FrameSize;
593 BufferSize = (ALuint)((DataSize64 > STACK_DATA_SIZE) ?
594 STACK_DATA_SIZE : DataSize64);
595 BufferSize -= BufferSize%FrameSize;
597 if(Source->lSourceType == AL_STATIC)
599 const ALbuffer *ALBuffer = Source->queue->buffer;
600 const ALubyte *Data = ALBuffer->data;
601 ALuint DataSize;
602 ALuint pos;
604 /* If current pos is beyond the loop range, do not loop */
605 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
607 Looping = AL_FALSE;
609 if(DataPosInt >= BufferPrePadding)
610 pos = (DataPosInt-BufferPrePadding)*FrameSize;
611 else
613 DataSize = (BufferPrePadding-DataPosInt)*FrameSize;
614 DataSize = minu(BufferSize, DataSize);
616 memset(&SrcData[SrcDataSize], 0, DataSize);
617 SrcDataSize += DataSize;
618 BufferSize -= DataSize;
620 pos = 0;
623 /* Copy what's left to play in the source buffer, and clear the
624 * rest of the temp buffer */
625 DataSize = ALBuffer->size - pos;
626 DataSize = minu(BufferSize, DataSize);
628 memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize);
629 SrcDataSize += DataSize;
630 BufferSize -= DataSize;
632 memset(&SrcData[SrcDataSize], 0, BufferSize);
633 SrcDataSize += BufferSize;
634 BufferSize -= BufferSize;
636 else
638 ALuint LoopStart = ALBuffer->LoopStart;
639 ALuint LoopEnd = ALBuffer->LoopEnd;
641 if(DataPosInt >= LoopStart)
643 pos = DataPosInt-LoopStart;
644 while(pos < BufferPrePadding)
645 pos += LoopEnd-LoopStart;
646 pos -= BufferPrePadding;
647 pos += LoopStart;
648 pos *= FrameSize;
650 else if(DataPosInt >= BufferPrePadding)
651 pos = (DataPosInt-BufferPrePadding)*FrameSize;
652 else
654 DataSize = (BufferPrePadding-DataPosInt)*FrameSize;
655 DataSize = minu(BufferSize, DataSize);
657 memset(&SrcData[SrcDataSize], 0, DataSize);
658 SrcDataSize += DataSize;
659 BufferSize -= DataSize;
661 pos = 0;
664 /* Copy what's left of this loop iteration, then copy repeats
665 * of the loop section */
666 DataSize = LoopEnd*FrameSize - pos;
667 DataSize = minu(BufferSize, DataSize);
669 memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize);
670 SrcDataSize += DataSize;
671 BufferSize -= DataSize;
673 DataSize = (LoopEnd-LoopStart) * FrameSize;
674 while(BufferSize > 0)
676 DataSize = minu(BufferSize, DataSize);
678 memcpy(&SrcData[SrcDataSize], &Data[LoopStart*FrameSize], DataSize);
679 SrcDataSize += DataSize;
680 BufferSize -= DataSize;
684 else
686 /* Crawl the buffer queue to fill in the temp buffer */
687 ALbufferlistitem *BufferListIter = BufferListItem;
688 ALuint pos;
690 if(DataPosInt >= BufferPrePadding)
691 pos = (DataPosInt-BufferPrePadding)*FrameSize;
692 else
694 pos = (BufferPrePadding-DataPosInt)*FrameSize;
695 while(pos > 0)
697 if(!BufferListIter->prev && !Looping)
699 ALuint DataSize = minu(BufferSize, pos);
701 memset(&SrcData[SrcDataSize], 0, DataSize);
702 SrcDataSize += DataSize;
703 BufferSize -= DataSize;
705 pos = 0;
706 break;
709 if(BufferListIter->prev)
710 BufferListIter = BufferListIter->prev;
711 else
713 while(BufferListIter->next)
714 BufferListIter = BufferListIter->next;
717 if(BufferListIter->buffer)
719 if((ALuint)BufferListIter->buffer->size > pos)
721 pos = BufferListIter->buffer->size - pos;
722 break;
724 pos -= BufferListIter->buffer->size;
729 while(BufferListIter && BufferSize > 0)
731 const ALbuffer *ALBuffer;
732 if((ALBuffer=BufferListIter->buffer) != NULL)
734 const ALubyte *Data = ALBuffer->data;
735 ALuint DataSize = ALBuffer->size;
737 /* Skip the data already played */
738 if(DataSize <= pos)
739 pos -= DataSize;
740 else
742 Data += pos;
743 DataSize -= pos;
744 pos -= pos;
746 DataSize = minu(BufferSize, DataSize);
747 memcpy(&SrcData[SrcDataSize], Data, DataSize);
748 SrcDataSize += DataSize;
749 BufferSize -= DataSize;
752 BufferListIter = BufferListIter->next;
753 if(!BufferListIter && Looping)
754 BufferListIter = Source->queue;
755 else if(!BufferListIter)
757 memset(&SrcData[SrcDataSize], 0, BufferSize);
758 SrcDataSize += BufferSize;
759 BufferSize -= BufferSize;
764 /* Figure out how many samples we can mix. */
765 DataSize64 = SrcDataSize / FrameSize;
766 DataSize64 -= BufferPadding+BufferPrePadding;
767 DataSize64 <<= FRACTIONBITS;
768 DataSize64 -= increment;
769 DataSize64 -= DataPosFrac;
771 BufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
772 BufferSize = minu(BufferSize, (SamplesToDo-OutPos));
774 SrcData += BufferPrePadding*FrameSize;
775 Source->Params.DoMix(Source, Device, SrcData, &DataPosInt, &DataPosFrac,
776 OutPos, SamplesToDo, BufferSize);
777 OutPos += BufferSize;
779 /* Handle looping sources */
780 while(1)
782 const ALbuffer *ALBuffer;
783 ALuint DataSize = 0;
784 ALuint LoopStart = 0;
785 ALuint LoopEnd = 0;
787 if((ALBuffer=BufferListItem->buffer) != NULL)
789 DataSize = ALBuffer->size / FrameSize;
790 LoopStart = ALBuffer->LoopStart;
791 LoopEnd = ALBuffer->LoopEnd;
792 if(LoopEnd > DataPosInt)
793 break;
796 if(Looping && Source->lSourceType == AL_STATIC)
798 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
799 break;
802 if(DataSize > DataPosInt)
803 break;
805 if(BufferListItem->next)
807 BufferListItem = BufferListItem->next;
808 BuffersPlayed++;
810 else if(Looping)
812 BufferListItem = Source->queue;
813 BuffersPlayed = 0;
815 else
817 State = AL_STOPPED;
818 BufferListItem = Source->queue;
819 BuffersPlayed = Source->BuffersInQueue;
820 DataPosInt = 0;
821 DataPosFrac = 0;
822 break;
825 DataPosInt -= DataSize;
827 } while(State == AL_PLAYING && OutPos < SamplesToDo);
829 /* Update source info */
830 Source->state = State;
831 Source->BuffersPlayed = BuffersPlayed;
832 Source->position = DataPosInt;
833 Source->position_fraction = DataPosFrac;
834 Source->HrtfOffset += OutPos;
835 if(State == AL_PLAYING)
837 Source->HrtfCounter = maxu(Source->HrtfCounter, OutPos) - OutPos;
838 Source->HrtfMoving = AL_TRUE;
840 else
842 Source->HrtfCounter = 0;
843 Source->HrtfMoving = AL_FALSE;