Use 2 chained one-pole filters for the wet path
[openal-soft/openal-hmr.git] / Alc / mixer.c
blob75ede3dc62e7dcf9f836316a35689b2de32cdd84
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(sampler) \
104 static void MixDirect_Hrtf_##sampler(ALsource *Source, ALCdevice *Device, \
105 DirectParams *params, const ALfloat *RESTRICT data, ALuint srcfrac, \
106 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
108 const ALuint NumChannels = Source->NumChannels; \
109 const ALint *RESTRICT DelayStep = params->Hrtf.DelayStep; \
110 ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS]; \
111 ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks; \
112 ALfloat (*RESTRICT CoeffStep)[2] = params->Hrtf.CoeffStep; \
113 ALuint pos, frac; \
114 FILTER *DryFilter; \
115 ALuint BufferIdx; \
116 ALuint increment; \
117 ALfloat value; \
118 ALuint i, c; \
120 increment = Source->Params.Step; \
122 DryBuffer = Device->DryBuffer; \
123 ClickRemoval = Device->ClickRemoval; \
124 PendingClicks = Device->PendingClicks; \
125 DryFilter = &params->iirFilter; \
127 for(i = 0;i < NumChannels;i++) \
129 ALfloat (*RESTRICT TargetCoeffs)[2] = params->Hrtf.Coeffs[i]; \
130 ALuint *RESTRICT TargetDelay = params->Hrtf.Delay[i]; \
131 ALfloat *RESTRICT History = Source->Hrtf.History[i]; \
132 ALfloat (*RESTRICT Values)[2] = Source->Hrtf.Values[i]; \
133 ALint Counter = maxu(Source->Hrtf.Counter, OutPos) - OutPos; \
134 ALuint Offset = Source->Hrtf.Offset + OutPos; \
135 ALfloat Coeffs[HRIR_LENGTH][2]; \
136 ALuint Delay[2]; \
137 ALfloat left, right; \
139 pos = 0; \
140 frac = srcfrac; \
142 for(c = 0;c < HRIR_LENGTH;c++) \
144 Coeffs[c][0] = TargetCoeffs[c][0] - (CoeffStep[c][0]*Counter); \
145 Coeffs[c][1] = TargetCoeffs[c][1] - (CoeffStep[c][1]*Counter); \
148 Delay[0] = TargetDelay[0] - (DelayStep[0]*Counter) + 32768; \
149 Delay[1] = TargetDelay[1] - (DelayStep[1]*Counter) + 32768; \
151 if(LIKELY(OutPos == 0)) \
153 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
154 value = lpFilter2PC(DryFilter, i, value); \
156 History[Offset&SRC_HISTORY_MASK] = value; \
157 left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \
158 right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \
160 ClickRemoval[FRONT_LEFT] -= Values[(Offset+1)&HRIR_MASK][0] + \
161 Coeffs[0][0] * left; \
162 ClickRemoval[FRONT_RIGHT] -= Values[(Offset+1)&HRIR_MASK][1] + \
163 Coeffs[0][1] * right; \
165 for(BufferIdx = 0;BufferIdx < BufferSize && Counter > 0;BufferIdx++) \
167 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
168 value = lpFilter2P(DryFilter, i, value); \
170 History[Offset&SRC_HISTORY_MASK] = value; \
171 left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \
172 right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \
174 Delay[0] += DelayStep[0]; \
175 Delay[1] += DelayStep[1]; \
177 Values[Offset&HRIR_MASK][0] = 0.0f; \
178 Values[Offset&HRIR_MASK][1] = 0.0f; \
179 Offset++; \
181 for(c = 0;c < HRIR_LENGTH;c++) \
183 const ALuint off = (Offset+c)&HRIR_MASK; \
184 Values[off][0] += Coeffs[c][0] * left; \
185 Values[off][1] += Coeffs[c][1] * right; \
186 Coeffs[c][0] += CoeffStep[c][0]; \
187 Coeffs[c][1] += CoeffStep[c][1]; \
190 DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \
191 DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \
193 frac += increment; \
194 pos += frac>>FRACTIONBITS; \
195 frac &= FRACTIONMASK; \
196 OutPos++; \
197 Counter--; \
200 Delay[0] >>= 16; \
201 Delay[1] >>= 16; \
202 for(;BufferIdx < BufferSize;BufferIdx++) \
204 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
205 value = lpFilter2P(DryFilter, i, value); \
207 History[Offset&SRC_HISTORY_MASK] = value; \
208 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \
209 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \
211 Values[Offset&HRIR_MASK][0] = 0.0f; \
212 Values[Offset&HRIR_MASK][1] = 0.0f; \
213 Offset++; \
215 ApplyCoeffs(Offset, Values, Coeffs, left, right); \
216 DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \
217 DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \
219 frac += increment; \
220 pos += frac>>FRACTIONBITS; \
221 frac &= FRACTIONMASK; \
222 OutPos++; \
224 if(LIKELY(OutPos == SamplesToDo)) \
226 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
227 value = lpFilter2PC(DryFilter, i, value); \
229 History[Offset&SRC_HISTORY_MASK] = value; \
230 left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \
231 right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \
233 PendingClicks[FRONT_LEFT] += Values[(Offset+1)&HRIR_MASK][0] + \
234 Coeffs[0][0] * left; \
235 PendingClicks[FRONT_RIGHT] += Values[(Offset+1)&HRIR_MASK][1] + \
236 Coeffs[0][1] * right; \
238 OutPos -= BufferSize; \
242 DECL_TEMPLATE(point32)
243 DECL_TEMPLATE(lerp32)
244 DECL_TEMPLATE(cubic32)
246 #undef DECL_TEMPLATE
249 #define DECL_TEMPLATE(sampler) \
250 static void MixDirect_##sampler(ALsource *Source, ALCdevice *Device, \
251 DirectParams *params, const ALfloat *RESTRICT data, ALuint srcfrac, \
252 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
254 const ALuint NumChannels = Source->NumChannels; \
255 ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS]; \
256 ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks; \
257 ALfloat DrySend[MAXCHANNELS]; \
258 FILTER *DryFilter; \
259 ALuint pos, frac; \
260 ALuint BufferIdx; \
261 ALuint increment; \
262 ALfloat value; \
263 ALuint i, c; \
265 increment = Source->Params.Step; \
267 DryBuffer = Device->DryBuffer; \
268 ClickRemoval = Device->ClickRemoval; \
269 PendingClicks = Device->PendingClicks; \
270 DryFilter = &params->iirFilter; \
272 for(i = 0;i < NumChannels;i++) \
274 for(c = 0;c < MAXCHANNELS;c++) \
275 DrySend[c] = params->Gains[i][c]; \
277 pos = 0; \
278 frac = srcfrac; \
280 if(OutPos == 0) \
282 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
284 value = lpFilter2PC(DryFilter, i, value); \
285 for(c = 0;c < MAXCHANNELS;c++) \
286 ClickRemoval[c] -= value*DrySend[c]; \
288 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
290 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
292 value = lpFilter2P(DryFilter, i, value); \
293 for(c = 0;c < MAXCHANNELS;c++) \
294 DryBuffer[OutPos][c] += value*DrySend[c]; \
296 frac += increment; \
297 pos += frac>>FRACTIONBITS; \
298 frac &= FRACTIONMASK; \
299 OutPos++; \
301 if(OutPos == SamplesToDo) \
303 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
305 value = lpFilter2PC(DryFilter, i, value); \
306 for(c = 0;c < MAXCHANNELS;c++) \
307 PendingClicks[c] += value*DrySend[c]; \
309 OutPos -= BufferSize; \
313 DECL_TEMPLATE(point32)
314 DECL_TEMPLATE(lerp32)
315 DECL_TEMPLATE(cubic32)
317 #undef DECL_TEMPLATE
319 #define DECL_TEMPLATE(sampler) \
320 static void MixSend_##sampler(ALsource *Source, ALuint sendidx, \
321 SendParams *params, const ALfloat *RESTRICT data, ALuint srcfrac, \
322 ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
324 const ALuint NumChannels = Source->NumChannels; \
325 ALeffectslot *Slot; \
326 ALfloat WetSend; \
327 ALfloat *WetBuffer; \
328 ALfloat *WetClickRemoval; \
329 ALfloat *WetPendingClicks; \
330 FILTER *WetFilter; \
331 ALuint pos, frac; \
332 ALuint BufferIdx; \
333 ALuint increment; \
334 ALfloat value; \
335 ALuint i; \
337 increment = Source->Params.Step; \
339 Slot = Source->Params.Slot[sendidx]; \
340 WetBuffer = Slot->WetBuffer; \
341 WetClickRemoval = Slot->ClickRemoval; \
342 WetPendingClicks = Slot->PendingClicks; \
343 WetFilter = &params->iirFilter; \
344 WetSend = params->Gain; \
346 for(i = 0;i < NumChannels;i++) \
348 pos = 0; \
349 frac = srcfrac; \
351 if(OutPos == 0) \
353 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
355 value = lpFilter2PC(WetFilter, i, value); \
356 WetClickRemoval[0] -= value * WetSend; \
358 for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
360 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
362 value = lpFilter2P(WetFilter, i, value); \
363 WetBuffer[OutPos] += value * WetSend; \
365 frac += increment; \
366 pos += frac>>FRACTIONBITS; \
367 frac &= FRACTIONMASK; \
368 OutPos++; \
370 if(OutPos == SamplesToDo) \
372 value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
374 value = lpFilter2PC(WetFilter, i, value); \
375 WetPendingClicks[0] += value * WetSend; \
377 OutPos -= BufferSize; \
381 DECL_TEMPLATE(point32)
382 DECL_TEMPLATE(lerp32)
383 DECL_TEMPLATE(cubic32)
385 #undef DECL_TEMPLATE
388 DryMixerFunc SelectDirectMixer(enum Resampler Resampler)
390 switch(Resampler)
392 case PointResampler:
393 return MixDirect_point32;
394 case LinearResampler:
395 return MixDirect_lerp32;
396 case CubicResampler:
397 return MixDirect_cubic32;
398 case ResamplerMax:
399 break;
401 return NULL;
404 DryMixerFunc SelectHrtfMixer(enum Resampler Resampler)
406 switch(Resampler)
408 case PointResampler:
409 return MixDirect_Hrtf_point32;
410 case LinearResampler:
411 return MixDirect_Hrtf_lerp32;
412 case CubicResampler:
413 return MixDirect_Hrtf_cubic32;
414 case ResamplerMax:
415 break;
417 return NULL;
420 WetMixerFunc SelectSendMixer(enum Resampler Resampler)
422 switch(Resampler)
424 case PointResampler:
425 return MixSend_point32;
426 case LinearResampler:
427 return MixSend_lerp32;
428 case CubicResampler:
429 return MixSend_cubic32;
430 case ResamplerMax:
431 break;
433 return NULL;
437 static __inline ALfloat Sample_ALbyte(ALbyte val)
438 { return val * (1.0f/127.0f); }
440 static __inline ALfloat Sample_ALshort(ALshort val)
441 { return val * (1.0f/32767.0f); }
443 static __inline ALfloat Sample_ALfloat(ALfloat val)
444 { return val; }
446 #define DECL_TEMPLATE(T) \
447 static void Load_##T(ALfloat *dst, const T *src, ALuint samples) \
449 ALuint i; \
450 for(i = 0;i < samples;i++) \
451 dst[i] = Sample_##T(src[i]); \
454 DECL_TEMPLATE(ALbyte)
455 DECL_TEMPLATE(ALshort)
456 DECL_TEMPLATE(ALfloat)
458 #undef DECL_TEMPLATE
460 static void LoadStack(ALfloat *dst, const ALvoid *src, enum FmtType srctype, ALuint samples)
462 switch(srctype)
464 case FmtByte:
465 Load_ALbyte(dst, src, samples);
466 break;
467 case FmtShort:
468 Load_ALshort(dst, src, samples);
469 break;
470 case FmtFloat:
471 Load_ALfloat(dst, src, samples);
472 break;
476 static void SilenceStack(ALfloat *dst, ALuint samples)
478 ALuint i;
479 for(i = 0;i < samples;i++)
480 dst[i] = 0.0f;
484 ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
486 ALbufferlistitem *BufferListItem;
487 ALuint DataPosInt, DataPosFrac;
488 ALuint BuffersPlayed;
489 ALboolean Looping;
490 ALuint increment;
491 enum Resampler Resampler;
492 ALenum State;
493 ALuint OutPos;
494 ALuint NumChannels;
495 ALuint FrameSize;
496 ALint64 DataSize64;
497 ALuint i;
499 /* Get source info */
500 State = Source->state;
501 BuffersPlayed = Source->BuffersPlayed;
502 DataPosInt = Source->position;
503 DataPosFrac = Source->position_fraction;
504 Looping = Source->Looping;
505 increment = Source->Params.Step;
506 Resampler = Source->Resampler;
507 NumChannels = Source->NumChannels;
508 FrameSize = NumChannels * Source->SampleSize;
510 /* Get current buffer queue item */
511 BufferListItem = Source->queue;
512 for(i = 0;i < BuffersPlayed;i++)
513 BufferListItem = BufferListItem->next;
515 OutPos = 0;
516 do {
517 const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
518 const ALuint BufferPadding = ResamplerPadding[Resampler];
519 ALfloat StackData[STACK_DATA_SIZE/sizeof(ALfloat)];
520 ALfloat *SrcData = StackData;
521 ALuint SrcDataSize = 0;
522 ALuint BufferSize;
524 /* Figure out how many buffer bytes will be needed */
525 DataSize64 = SamplesToDo-OutPos+1;
526 DataSize64 *= increment;
527 DataSize64 += DataPosFrac+FRACTIONMASK;
528 DataSize64 >>= FRACTIONBITS;
529 DataSize64 += BufferPadding+BufferPrePadding;
530 DataSize64 *= NumChannels;
532 BufferSize = (ALuint)mini64(DataSize64, STACK_DATA_SIZE/sizeof(ALfloat));
533 BufferSize /= NumChannels;
535 if(Source->SourceType == AL_STATIC)
537 const ALbuffer *ALBuffer = Source->queue->buffer;
538 const ALubyte *Data = ALBuffer->data;
539 ALuint DataSize;
540 ALuint pos;
542 /* If current pos is beyond the loop range, do not loop */
543 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
545 Looping = AL_FALSE;
547 if(DataPosInt >= BufferPrePadding)
548 pos = DataPosInt - BufferPrePadding;
549 else
551 DataSize = BufferPrePadding - DataPosInt;
552 DataSize = minu(BufferSize, DataSize);
554 SilenceStack(&SrcData[SrcDataSize*NumChannels],
555 DataSize*NumChannels);
556 SrcDataSize += DataSize;
557 BufferSize -= DataSize;
559 pos = 0;
562 /* Copy what's left to play in the source buffer, and clear the
563 * rest of the temp buffer */
564 DataSize = ALBuffer->SampleLen - pos;
565 DataSize = minu(BufferSize, DataSize);
567 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
568 ALBuffer->FmtType, DataSize*NumChannels);
569 SrcDataSize += DataSize;
570 BufferSize -= DataSize;
572 SilenceStack(&SrcData[SrcDataSize*NumChannels],
573 BufferSize*NumChannels);
574 SrcDataSize += BufferSize;
575 BufferSize -= BufferSize;
577 else
579 ALuint LoopStart = ALBuffer->LoopStart;
580 ALuint LoopEnd = ALBuffer->LoopEnd;
582 if(DataPosInt >= LoopStart)
584 pos = DataPosInt-LoopStart;
585 while(pos < BufferPrePadding)
586 pos += LoopEnd-LoopStart;
587 pos -= BufferPrePadding;
588 pos += LoopStart;
590 else if(DataPosInt >= BufferPrePadding)
591 pos = DataPosInt - BufferPrePadding;
592 else
594 DataSize = BufferPrePadding - DataPosInt;
595 DataSize = minu(BufferSize, DataSize);
597 SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
598 SrcDataSize += DataSize;
599 BufferSize -= DataSize;
601 pos = 0;
604 /* Copy what's left of this loop iteration, then copy repeats
605 * of the loop section */
606 DataSize = LoopEnd - pos;
607 DataSize = minu(BufferSize, DataSize);
609 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
610 ALBuffer->FmtType, DataSize*NumChannels);
611 SrcDataSize += DataSize;
612 BufferSize -= DataSize;
614 DataSize = LoopEnd-LoopStart;
615 while(BufferSize > 0)
617 DataSize = minu(BufferSize, DataSize);
619 LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[LoopStart*FrameSize],
620 ALBuffer->FmtType, DataSize*NumChannels);
621 SrcDataSize += DataSize;
622 BufferSize -= DataSize;
626 else
628 /* Crawl the buffer queue to fill in the temp buffer */
629 ALbufferlistitem *tmpiter = BufferListItem;
630 ALuint pos;
632 if(DataPosInt >= BufferPrePadding)
633 pos = DataPosInt - BufferPrePadding;
634 else
636 pos = BufferPrePadding - DataPosInt;
637 while(pos > 0)
639 if(!tmpiter->prev && !Looping)
641 ALuint DataSize = minu(BufferSize, pos);
643 SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
644 SrcDataSize += DataSize;
645 BufferSize -= DataSize;
647 pos = 0;
648 break;
651 if(tmpiter->prev)
652 tmpiter = tmpiter->prev;
653 else
655 while(tmpiter->next)
656 tmpiter = tmpiter->next;
659 if(tmpiter->buffer)
661 if((ALuint)tmpiter->buffer->SampleLen > pos)
663 pos = tmpiter->buffer->SampleLen - pos;
664 break;
666 pos -= tmpiter->buffer->SampleLen;
671 while(tmpiter && BufferSize > 0)
673 const ALbuffer *ALBuffer;
674 if((ALBuffer=tmpiter->buffer) != NULL)
676 const ALubyte *Data = ALBuffer->data;
677 ALuint DataSize = ALBuffer->SampleLen;
679 /* Skip the data already played */
680 if(DataSize <= pos)
681 pos -= DataSize;
682 else
684 Data += pos*FrameSize;
685 DataSize -= pos;
686 pos -= pos;
688 DataSize = minu(BufferSize, DataSize);
689 LoadStack(&SrcData[SrcDataSize*NumChannels], Data,
690 ALBuffer->FmtType, DataSize*NumChannels);
691 SrcDataSize += DataSize;
692 BufferSize -= DataSize;
695 tmpiter = tmpiter->next;
696 if(!tmpiter && Looping)
697 tmpiter = Source->queue;
698 else if(!tmpiter)
700 SilenceStack(&SrcData[SrcDataSize*NumChannels], BufferSize*NumChannels);
701 SrcDataSize += BufferSize;
702 BufferSize -= BufferSize;
707 /* Figure out how many samples we can mix. */
708 DataSize64 = SrcDataSize;
709 DataSize64 -= BufferPadding+BufferPrePadding;
710 DataSize64 <<= FRACTIONBITS;
711 DataSize64 -= increment;
712 DataSize64 -= DataPosFrac;
714 BufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
715 BufferSize = minu(BufferSize, (SamplesToDo-OutPos));
717 SrcData += BufferPrePadding*NumChannels;
718 Source->Params.DryMix(Source, Device, &Source->Params.Direct,
719 SrcData, DataPosFrac,
720 OutPos, SamplesToDo, BufferSize);
721 for(i = 0;i < Device->NumAuxSends;i++)
723 if(!Source->Params.Slot[i])
724 continue;
725 Source->Params.WetMix(Source, i, &Source->Params.Send[i],
726 SrcData, DataPosFrac,
727 OutPos, SamplesToDo, BufferSize);
729 for(i = 0;i < BufferSize;i++)
731 DataPosFrac += increment;
732 DataPosInt += DataPosFrac>>FRACTIONBITS;
733 DataPosFrac &= FRACTIONMASK;
734 OutPos++;
737 /* Handle looping sources */
738 while(1)
740 const ALbuffer *ALBuffer;
741 ALuint DataSize = 0;
742 ALuint LoopStart = 0;
743 ALuint LoopEnd = 0;
745 if((ALBuffer=BufferListItem->buffer) != NULL)
747 DataSize = ALBuffer->SampleLen;
748 LoopStart = ALBuffer->LoopStart;
749 LoopEnd = ALBuffer->LoopEnd;
750 if(LoopEnd > DataPosInt)
751 break;
754 if(Looping && Source->SourceType == AL_STATIC)
756 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
757 break;
760 if(DataSize > DataPosInt)
761 break;
763 if(BufferListItem->next)
765 BufferListItem = BufferListItem->next;
766 BuffersPlayed++;
768 else if(Looping)
770 BufferListItem = Source->queue;
771 BuffersPlayed = 0;
773 else
775 State = AL_STOPPED;
776 BufferListItem = Source->queue;
777 BuffersPlayed = Source->BuffersInQueue;
778 DataPosInt = 0;
779 DataPosFrac = 0;
780 break;
783 DataPosInt -= DataSize;
785 } while(State == AL_PLAYING && OutPos < SamplesToDo);
787 /* Update source info */
788 Source->state = State;
789 Source->BuffersPlayed = BuffersPlayed;
790 Source->position = DataPosInt;
791 Source->position_fraction = DataPosFrac;
792 Source->Hrtf.Offset += OutPos;
793 if(State == AL_PLAYING)
795 Source->Hrtf.Counter = maxu(Source->Hrtf.Counter, OutPos) - OutPos;
796 Source->Hrtf.Moving = AL_TRUE;
798 else
800 Source->Hrtf.Counter = 0;
801 Source->Hrtf.Moving = AL_FALSE;