Make some pointer-to-array parameters const
[openal-soft.git] / Alc / mixer.c
blob864e2395420ee201ca20c6e2e799c8ea8c548250
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.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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"
38 #include "mixer_defs.h"
41 static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
42 "MAX_PITCH and/or BUFFERSIZE are too large for FRACTIONBITS!");
44 extern inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr, ALuint size);
46 alignas(16) union ResamplerCoeffs ResampleCoeffs;
49 enum Resampler {
50 PointResampler,
51 LinearResampler,
52 FIR4Resampler,
53 FIR8Resampler,
54 BSincResampler,
56 ResamplerDefault = LinearResampler
59 /* FIR8 requires 3 extra samples before the current position, and 4 after. */
60 static_assert(MAX_PRE_SAMPLES >= 3, "MAX_PRE_SAMPLES must be at least 3!");
61 static_assert(MAX_POST_SAMPLES >= 4, "MAX_POST_SAMPLES must be at least 4!");
64 static MixerFunc MixSamples = Mix_C;
65 static HrtfMixerFunc MixHrtfSamples = MixHrtf_C;
66 static ResamplerFunc ResampleSamples = Resample_point32_C;
68 MixerFunc SelectMixer(void)
70 #ifdef HAVE_SSE
71 if((CPUCapFlags&CPU_CAP_SSE))
72 return Mix_SSE;
73 #endif
74 #ifdef HAVE_NEON
75 if((CPUCapFlags&CPU_CAP_NEON))
76 return Mix_Neon;
77 #endif
79 return Mix_C;
82 RowMixerFunc SelectRowMixer(void)
84 #ifdef HAVE_SSE
85 if((CPUCapFlags&CPU_CAP_SSE))
86 return MixRow_SSE;
87 #endif
88 #ifdef HAVE_NEON
89 if((CPUCapFlags&CPU_CAP_NEON))
90 return MixRow_Neon;
91 #endif
92 return MixRow_C;
95 static inline HrtfMixerFunc SelectHrtfMixer(void)
97 #ifdef HAVE_SSE
98 if((CPUCapFlags&CPU_CAP_SSE))
99 return MixHrtf_SSE;
100 #endif
101 #ifdef HAVE_NEON
102 if((CPUCapFlags&CPU_CAP_NEON))
103 return MixHrtf_Neon;
104 #endif
106 return MixHrtf_C;
109 static inline ResamplerFunc SelectResampler(enum Resampler resampler)
111 switch(resampler)
113 case PointResampler:
114 return Resample_point32_C;
115 case LinearResampler:
116 #ifdef HAVE_SSE4_1
117 if((CPUCapFlags&CPU_CAP_SSE4_1))
118 return Resample_lerp32_SSE41;
119 #endif
120 #ifdef HAVE_SSE2
121 if((CPUCapFlags&CPU_CAP_SSE2))
122 return Resample_lerp32_SSE2;
123 #endif
124 return Resample_lerp32_C;
125 case FIR4Resampler:
126 #ifdef HAVE_SSE4_1
127 if((CPUCapFlags&CPU_CAP_SSE4_1))
128 return Resample_fir4_32_SSE41;
129 #endif
130 #ifdef HAVE_SSE3
131 if((CPUCapFlags&CPU_CAP_SSE3))
132 return Resample_fir4_32_SSE3;
133 #endif
134 return Resample_fir4_32_C;
135 case FIR8Resampler:
136 #ifdef HAVE_SSE4_1
137 if((CPUCapFlags&CPU_CAP_SSE4_1))
138 return Resample_fir8_32_SSE41;
139 #endif
140 #ifdef HAVE_SSE3
141 if((CPUCapFlags&CPU_CAP_SSE3))
142 return Resample_fir8_32_SSE3;
143 #endif
144 return Resample_fir8_32_C;
145 case BSincResampler:
146 #ifdef HAVE_SSE
147 if((CPUCapFlags&CPU_CAP_SSE))
148 return Resample_bsinc32_SSE;
149 #endif
150 return Resample_bsinc32_C;
153 return Resample_point32_C;
157 /* The sinc resampler makes use of a Kaiser window to limit the needed sample
158 * points to 4 and 8, respectively.
161 #ifndef M_PI
162 #define M_PI (3.14159265358979323846)
163 #endif
164 static inline double Sinc(double x)
166 if(x == 0.0) return 1.0;
167 return sin(x*M_PI) / (x*M_PI);
170 /* The zero-order modified Bessel function of the first kind, used for the
171 * Kaiser window.
173 * I_0(x) = sum_{k=0}^inf (1 / k!)^2 (x / 2)^(2 k)
174 * = sum_{k=0}^inf ((x / 2)^k / k!)^2
176 static double BesselI_0(double x)
178 double term, sum, x2, y, last_sum;
179 int k;
181 /* Start at k=1 since k=0 is trivial. */
182 term = 1.0;
183 sum = 1.0;
184 x2 = x / 2.0;
185 k = 1;
187 /* Let the integration converge until the term of the sum is no longer
188 * significant.
190 do {
191 y = x2 / k;
192 k ++;
193 last_sum = sum;
194 term *= y * y;
195 sum += term;
196 } while(sum != last_sum);
197 return sum;
200 /* Calculate a Kaiser window from the given beta value and a normalized k
201 * [-1, 1].
203 * w(k) = { I_0(B sqrt(1 - k^2)) / I_0(B), -1 <= k <= 1
204 * { 0, elsewhere.
206 * Where k can be calculated as:
208 * k = i / l, where -l <= i <= l.
210 * or:
212 * k = 2 i / M - 1, where 0 <= i <= M.
214 static inline double Kaiser(double b, double k)
216 if(k <= -1.0 || k >= 1.0) return 0.0;
217 return BesselI_0(b * sqrt(1.0 - (k*k))) / BesselI_0(b);
220 static inline double CalcKaiserBeta(double rejection)
222 if(rejection > 50.0)
223 return 0.1102 * (rejection - 8.7);
224 if(rejection >= 21.0)
225 return (0.5842 * pow(rejection - 21.0, 0.4)) +
226 (0.07886 * (rejection - 21.0));
227 return 0.0;
230 static float SincKaiser(double r, double x)
232 /* Limit rippling to -60dB. */
233 return (float)(Kaiser(CalcKaiserBeta(60.0), x / r) * Sinc(x));
237 void aluInitMixer(void)
239 enum Resampler resampler = ResamplerDefault;
240 const char *str;
241 ALuint i;
243 if(ConfigValueStr(NULL, NULL, "resampler", &str))
245 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
246 resampler = PointResampler;
247 else if(strcasecmp(str, "linear") == 0)
248 resampler = LinearResampler;
249 else if(strcasecmp(str, "sinc4") == 0)
250 resampler = FIR4Resampler;
251 else if(strcasecmp(str, "sinc8") == 0)
252 resampler = FIR8Resampler;
253 else if(strcasecmp(str, "bsinc") == 0)
254 resampler = BSincResampler;
255 else if(strcasecmp(str, "cubic") == 0)
257 WARN("Resampler option \"cubic\" is deprecated, using sinc4\n");
258 resampler = FIR4Resampler;
260 else
262 char *end;
263 long n = strtol(str, &end, 0);
264 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == FIR4Resampler))
265 resampler = n;
266 else
267 WARN("Invalid resampler: %s\n", str);
271 if(resampler == FIR8Resampler)
272 for(i = 0;i < FRACTIONONE;i++)
274 ALdouble mu = (ALdouble)i / FRACTIONONE;
275 ResampleCoeffs.FIR8[i][0] = SincKaiser(4.0, mu - -3.0);
276 ResampleCoeffs.FIR8[i][1] = SincKaiser(4.0, mu - -2.0);
277 ResampleCoeffs.FIR8[i][2] = SincKaiser(4.0, mu - -1.0);
278 ResampleCoeffs.FIR8[i][3] = SincKaiser(4.0, mu - 0.0);
279 ResampleCoeffs.FIR8[i][4] = SincKaiser(4.0, mu - 1.0);
280 ResampleCoeffs.FIR8[i][5] = SincKaiser(4.0, mu - 2.0);
281 ResampleCoeffs.FIR8[i][6] = SincKaiser(4.0, mu - 3.0);
282 ResampleCoeffs.FIR8[i][7] = SincKaiser(4.0, mu - 4.0);
284 else if(resampler == FIR4Resampler)
285 for(i = 0;i < FRACTIONONE;i++)
287 ALdouble mu = (ALdouble)i / FRACTIONONE;
288 ResampleCoeffs.FIR4[i][0] = SincKaiser(2.0, mu - -1.0);
289 ResampleCoeffs.FIR4[i][1] = SincKaiser(2.0, mu - 0.0);
290 ResampleCoeffs.FIR4[i][2] = SincKaiser(2.0, mu - 1.0);
291 ResampleCoeffs.FIR4[i][3] = SincKaiser(2.0, mu - 2.0);
294 MixHrtfSamples = SelectHrtfMixer();
295 MixSamples = SelectMixer();
296 ResampleSamples = SelectResampler(resampler);
300 static inline ALfloat Sample_ALbyte(ALbyte val)
301 { return val * (1.0f/127.0f); }
303 static inline ALfloat Sample_ALshort(ALshort val)
304 { return val * (1.0f/32767.0f); }
306 static inline ALfloat Sample_ALfloat(ALfloat val)
307 { return val; }
309 #define DECL_TEMPLATE(T) \
310 static inline void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\
312 ALuint i; \
313 for(i = 0;i < samples;i++) \
314 dst[i] = Sample_##T(src[i*srcstep]); \
317 DECL_TEMPLATE(ALbyte)
318 DECL_TEMPLATE(ALshort)
319 DECL_TEMPLATE(ALfloat)
321 #undef DECL_TEMPLATE
323 static void LoadSamples(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples)
325 switch(srctype)
327 case FmtByte:
328 Load_ALbyte(dst, src, srcstep, samples);
329 break;
330 case FmtShort:
331 Load_ALshort(dst, src, srcstep, samples);
332 break;
333 case FmtFloat:
334 Load_ALfloat(dst, src, srcstep, samples);
335 break;
339 static inline void SilenceSamples(ALfloat *dst, ALuint samples)
341 ALuint i;
342 for(i = 0;i < samples;i++)
343 dst[i] = 0.0f;
347 static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter,
348 ALfloat *restrict dst, const ALfloat *restrict src,
349 ALuint numsamples, enum ActiveFilters type)
351 ALuint i;
352 switch(type)
354 case AF_None:
355 ALfilterState_processPassthru(lpfilter, src, numsamples);
356 ALfilterState_processPassthru(hpfilter, src, numsamples);
357 break;
359 case AF_LowPass:
360 ALfilterState_process(lpfilter, dst, src, numsamples);
361 ALfilterState_processPassthru(hpfilter, dst, numsamples);
362 return dst;
363 case AF_HighPass:
364 ALfilterState_processPassthru(lpfilter, src, numsamples);
365 ALfilterState_process(hpfilter, dst, src, numsamples);
366 return dst;
368 case AF_BandPass:
369 for(i = 0;i < numsamples;)
371 ALfloat temp[256];
372 ALuint todo = minu(256, numsamples-i);
374 ALfilterState_process(lpfilter, temp, src+i, todo);
375 ALfilterState_process(hpfilter, dst+i, temp, todo);
376 i += todo;
378 return dst;
380 return src;
384 ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
386 ResamplerFunc Resample;
387 ALbufferlistitem *BufferListItem;
388 ALuint DataPosInt, DataPosFrac;
389 ALboolean Looping;
390 ALuint increment;
391 ALenum State;
392 ALuint OutPos;
393 ALuint NumChannels;
394 ALuint SampleSize;
395 ALint64 DataSize64;
396 ALuint IrSize;
397 ALuint chan, send, j;
399 /* Get source info */
400 State = AL_PLAYING; /* Only called while playing. */
401 BufferListItem = ATOMIC_LOAD(&Source->current_buffer);
402 DataPosInt = ATOMIC_LOAD(&Source->position, almemory_order_relaxed);
403 DataPosFrac = ATOMIC_LOAD(&Source->position_fraction, almemory_order_relaxed);
404 Looping = ATOMIC_LOAD(&Source->looping, almemory_order_relaxed);
405 NumChannels = Source->NumChannels;
406 SampleSize = Source->SampleSize;
407 increment = voice->Step;
409 IrSize = (Device->Hrtf.Handle ? Device->Hrtf.Handle->irSize : 0);
411 Resample = ((increment == FRACTIONONE && DataPosFrac == 0) ?
412 Resample_copy32_C : ResampleSamples);
414 OutPos = 0;
415 do {
416 ALuint SrcBufferSize, DstBufferSize;
417 ALuint Counter;
418 ALfloat Delta;
420 if(!voice->Moving)
422 Counter = 0;
423 Delta = 0.0f;
425 else
427 Counter = SamplesToDo - OutPos;
428 Delta = 1.0f / (ALfloat)Counter;
431 /* Figure out how many buffer samples will be needed */
432 DataSize64 = SamplesToDo-OutPos;
433 DataSize64 *= increment;
434 DataSize64 += DataPosFrac+FRACTIONMASK;
435 DataSize64 >>= FRACTIONBITS;
436 DataSize64 += MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
438 SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
440 /* Figure out how many samples we can actually mix from this. */
441 DataSize64 = SrcBufferSize;
442 DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
443 DataSize64 <<= FRACTIONBITS;
444 DataSize64 -= DataPosFrac;
446 DstBufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
447 DstBufferSize = minu(DstBufferSize, (SamplesToDo-OutPos));
449 /* Some mixers like having a multiple of 4, so try to give that unless
450 * this is the last update. */
451 if(OutPos+DstBufferSize < SamplesToDo)
452 DstBufferSize &= ~3;
454 for(chan = 0;chan < NumChannels;chan++)
456 const ALfloat *ResampledData;
457 ALfloat *SrcData = Device->SourceData;
458 ALuint SrcDataSize;
460 /* Load the previous samples into the source data first. */
461 memcpy(SrcData, voice->PrevSamples[chan], MAX_PRE_SAMPLES*sizeof(ALfloat));
462 SrcDataSize = MAX_PRE_SAMPLES;
464 if(Source->SourceType == AL_STATIC)
466 const ALbuffer *ALBuffer = BufferListItem->buffer;
467 const ALubyte *Data = ALBuffer->data;
468 ALuint DataSize;
469 ALuint pos;
471 /* Offset buffer data to current channel */
472 Data += chan*SampleSize;
474 /* If current pos is beyond the loop range, do not loop */
475 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
477 Looping = AL_FALSE;
479 /* Load what's left to play from the source buffer, and
480 * clear the rest of the temp buffer */
481 pos = DataPosInt;
482 DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos);
484 LoadSamples(&SrcData[SrcDataSize], &Data[pos * NumChannels*SampleSize],
485 NumChannels, ALBuffer->FmtType, DataSize);
486 SrcDataSize += DataSize;
488 SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
489 SrcDataSize += SrcBufferSize - SrcDataSize;
491 else
493 ALuint LoopStart = ALBuffer->LoopStart;
494 ALuint LoopEnd = ALBuffer->LoopEnd;
496 /* Load what's left of this loop iteration, then load
497 * repeats of the loop section */
498 pos = DataPosInt;
499 DataSize = LoopEnd - pos;
500 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
502 LoadSamples(&SrcData[SrcDataSize], &Data[pos * NumChannels*SampleSize],
503 NumChannels, ALBuffer->FmtType, DataSize);
504 SrcDataSize += DataSize;
506 DataSize = LoopEnd-LoopStart;
507 while(SrcBufferSize > SrcDataSize)
509 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
511 LoadSamples(&SrcData[SrcDataSize], &Data[LoopStart * NumChannels*SampleSize],
512 NumChannels, ALBuffer->FmtType, DataSize);
513 SrcDataSize += DataSize;
517 else
519 /* Crawl the buffer queue to fill in the temp buffer */
520 ALbufferlistitem *tmpiter = BufferListItem;
521 ALuint pos = DataPosInt;
523 while(tmpiter && SrcBufferSize > SrcDataSize)
525 const ALbuffer *ALBuffer;
526 if((ALBuffer=tmpiter->buffer) != NULL)
528 const ALubyte *Data = ALBuffer->data;
529 ALuint DataSize = ALBuffer->SampleLen;
531 /* Skip the data already played */
532 if(DataSize <= pos)
533 pos -= DataSize;
534 else
536 Data += (pos*NumChannels + chan)*SampleSize;
537 DataSize -= pos;
538 pos -= pos;
540 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
541 LoadSamples(&SrcData[SrcDataSize], Data, NumChannels,
542 ALBuffer->FmtType, DataSize);
543 SrcDataSize += DataSize;
546 tmpiter = tmpiter->next;
547 if(!tmpiter && Looping)
548 tmpiter = ATOMIC_LOAD(&Source->queue);
549 else if(!tmpiter)
551 SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
552 SrcDataSize += SrcBufferSize - SrcDataSize;
557 /* Store the last source samples used for next time. */
558 memcpy(voice->PrevSamples[chan],
559 &SrcData[(increment*DstBufferSize + DataPosFrac)>>FRACTIONBITS],
560 MAX_PRE_SAMPLES*sizeof(ALfloat)
563 /* Now resample, then filter and mix to the appropriate outputs. */
564 ResampledData = Resample(&voice->SincState,
565 &SrcData[MAX_PRE_SAMPLES], DataPosFrac, increment,
566 Device->ResampledData, DstBufferSize
569 DirectParams *parms = &voice->Chan[chan].Direct;
570 const ALfloat *samples;
572 samples = DoFilters(
573 &parms->LowPass, &parms->HighPass, Device->FilteredData,
574 ResampledData, DstBufferSize, parms->FilterType
576 if(!voice->IsHrtf)
578 ALfloat *restrict currents = parms->Gains.Current;
579 const ALfloat *targets = parms->Gains.Target;
580 MixGains gains[MAX_OUTPUT_CHANNELS];
582 if(!Counter)
584 for(j = 0;j < voice->DirectOut.Channels;j++)
586 gains[j].Target = targets[j];
587 gains[j].Current = gains[j].Target;
588 gains[j].Step = 0.0f;
591 else
593 for(j = 0;j < voice->DirectOut.Channels;j++)
595 ALfloat diff;
596 gains[j].Target = targets[j];
597 gains[j].Current = currents[j];
598 diff = gains[j].Target - gains[j].Current;
599 if(fabsf(diff) >= GAIN_SILENCE_THRESHOLD)
600 gains[j].Step = diff * Delta;
601 else
603 gains[j].Current = gains[j].Target;
604 gains[j].Step = 0.0f;
609 MixSamples(samples, voice->DirectOut.Channels, voice->DirectOut.Buffer,
610 gains, Counter, OutPos, DstBufferSize);
612 for(j = 0;j < voice->DirectOut.Channels;j++)
613 currents[j] = gains[j].Current;
615 else
617 MixHrtfParams hrtfparams;
618 int lidx, ridx;
620 if(!Counter)
622 parms->Hrtf.Current = parms->Hrtf.Target;
623 for(j = 0;j < HRIR_LENGTH;j++)
625 hrtfparams.Steps.Coeffs[j][0] = 0.0f;
626 hrtfparams.Steps.Coeffs[j][1] = 0.0f;
628 hrtfparams.Steps.Delay[0] = 0;
629 hrtfparams.Steps.Delay[1] = 0;
631 else
633 ALfloat coeffdiff;
634 ALint delaydiff;
635 for(j = 0;j < IrSize;j++)
637 coeffdiff = parms->Hrtf.Target.Coeffs[j][0] - parms->Hrtf.Current.Coeffs[j][0];
638 hrtfparams.Steps.Coeffs[j][0] = coeffdiff * Delta;
639 coeffdiff = parms->Hrtf.Target.Coeffs[j][1] - parms->Hrtf.Current.Coeffs[j][1];
640 hrtfparams.Steps.Coeffs[j][1] = coeffdiff * Delta;
642 delaydiff = (ALint)(parms->Hrtf.Target.Delay[0] - parms->Hrtf.Current.Delay[0]);
643 hrtfparams.Steps.Delay[0] = fastf2i((ALfloat)delaydiff * Delta);
644 delaydiff = (ALint)(parms->Hrtf.Target.Delay[1] - parms->Hrtf.Current.Delay[1]);
645 hrtfparams.Steps.Delay[1] = fastf2i((ALfloat)delaydiff * Delta);
647 hrtfparams.Target = &parms->Hrtf.Target;
648 hrtfparams.Current = &parms->Hrtf.Current;
650 lidx = GetChannelIdxByName(Device->RealOut, FrontLeft);
651 ridx = GetChannelIdxByName(Device->RealOut, FrontRight);
652 assert(lidx != -1 && ridx != -1);
654 MixHrtfSamples(voice->DirectOut.Buffer, lidx, ridx, samples, Counter,
655 voice->Offset, OutPos, IrSize, &hrtfparams,
656 &parms->Hrtf.State, DstBufferSize);
660 for(send = 0;send < Device->NumAuxSends;send++)
662 SendParams *parms = &voice->Chan[chan].Send[send];
663 ALfloat *restrict currents = parms->Gains.Current;
664 const ALfloat *targets = parms->Gains.Target;
665 MixGains gains[MAX_OUTPUT_CHANNELS];
666 const ALfloat *samples;
668 if(!voice->SendOut[send].Buffer)
669 continue;
671 samples = DoFilters(
672 &parms->LowPass, &parms->HighPass, Device->FilteredData,
673 ResampledData, DstBufferSize, parms->FilterType
676 if(!Counter)
678 for(j = 0;j < voice->SendOut[send].Channels;j++)
680 gains[j].Target = targets[j];
681 gains[j].Current = gains[j].Target;
682 gains[j].Step = 0.0f;
685 else
687 for(j = 0;j < voice->SendOut[send].Channels;j++)
689 ALfloat diff;
690 gains[j].Target = targets[j];
691 gains[j].Current = currents[j];
692 diff = gains[j].Target - gains[j].Current;
693 if(fabsf(diff) >= GAIN_SILENCE_THRESHOLD)
694 gains[j].Step = diff * Delta;
695 else
697 gains[j].Current = gains[j].Target;
698 gains[j].Step = 0.0f;
703 MixSamples(samples,
704 voice->SendOut[send].Channels, voice->SendOut[send].Buffer,
705 gains, Counter, OutPos, DstBufferSize
708 for(j = 0;j < voice->SendOut[send].Channels;j++)
709 currents[j] = gains[j].Current;
712 /* Update positions */
713 DataPosFrac += increment*DstBufferSize;
714 DataPosInt += DataPosFrac>>FRACTIONBITS;
715 DataPosFrac &= FRACTIONMASK;
717 OutPos += DstBufferSize;
718 voice->Offset += DstBufferSize;
720 /* Handle looping sources */
721 while(1)
723 const ALbuffer *ALBuffer;
724 ALuint DataSize = 0;
725 ALuint LoopStart = 0;
726 ALuint LoopEnd = 0;
728 if((ALBuffer=BufferListItem->buffer) != NULL)
730 DataSize = ALBuffer->SampleLen;
731 LoopStart = ALBuffer->LoopStart;
732 LoopEnd = ALBuffer->LoopEnd;
733 if(LoopEnd > DataPosInt)
734 break;
737 if(Looping && Source->SourceType == AL_STATIC)
739 assert(LoopEnd > LoopStart);
740 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
741 break;
744 if(DataSize > DataPosInt)
745 break;
747 if(!(BufferListItem=BufferListItem->next))
749 if(Looping)
750 BufferListItem = ATOMIC_LOAD(&Source->queue);
751 else
753 State = AL_STOPPED;
754 BufferListItem = NULL;
755 DataPosInt = 0;
756 DataPosFrac = 0;
757 break;
761 DataPosInt -= DataSize;
763 } while(State == AL_PLAYING && OutPos < SamplesToDo);
765 voice->Moving = AL_TRUE;
767 /* Update source info */
768 Source->state = State;
769 ATOMIC_STORE(&Source->current_buffer, BufferListItem, almemory_order_relaxed);
770 ATOMIC_STORE(&Source->position, DataPosInt, almemory_order_relaxed);
771 ATOMIC_STORE(&Source->position_fraction, DataPosFrac);