Use proper bools for boolean states
[openal-soft.git] / Alc / mixer.c
blobb9eb4a99508fde842647f9fc834f45a02ffef7a4
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, ALint increment, ALuint *restrict frac_arr, ALint *restrict pos_arr, ALsizei size);
46 alignas(16) ALfloat ResampleCoeffs_FIR4[FRACTIONONE][4];
49 enum Resampler {
50 PointResampler,
51 LinearResampler,
52 FIR4Resampler,
53 BSincResampler,
55 ResamplerDefault = LinearResampler
58 /* BSinc requires up to 11 extra samples before the current position, and 12 after. */
59 static_assert(MAX_PRE_SAMPLES >= 11, "MAX_PRE_SAMPLES must be at least 11!");
60 static_assert(MAX_POST_SAMPLES >= 12, "MAX_POST_SAMPLES must be at least 12!");
63 static MixerFunc MixSamples = Mix_C;
64 static HrtfMixerFunc MixHrtfSamples = MixHrtf_C;
65 static ResamplerFunc ResampleSamples = Resample_point32_C;
67 MixerFunc SelectMixer(void)
69 #ifdef HAVE_SSE
70 if((CPUCapFlags&CPU_CAP_SSE))
71 return Mix_SSE;
72 #endif
73 #ifdef HAVE_NEON
74 if((CPUCapFlags&CPU_CAP_NEON))
75 return Mix_Neon;
76 #endif
78 return Mix_C;
81 RowMixerFunc SelectRowMixer(void)
83 #ifdef HAVE_SSE
84 if((CPUCapFlags&CPU_CAP_SSE))
85 return MixRow_SSE;
86 #endif
87 #ifdef HAVE_NEON
88 if((CPUCapFlags&CPU_CAP_NEON))
89 return MixRow_Neon;
90 #endif
91 return MixRow_C;
94 static inline HrtfMixerFunc SelectHrtfMixer(void)
96 #ifdef HAVE_NEON
97 if((CPUCapFlags&CPU_CAP_NEON))
98 return MixHrtf_Neon;
99 #endif
100 #ifdef HAVE_SSE
101 if((CPUCapFlags&CPU_CAP_SSE))
102 return MixHrtf_SSE;
103 #endif
105 return MixHrtf_C;
108 static inline ResamplerFunc SelectResampler(enum Resampler resampler)
110 switch(resampler)
112 case PointResampler:
113 return Resample_point32_C;
114 case LinearResampler:
115 #ifdef HAVE_NEON
116 if((CPUCapFlags&CPU_CAP_NEON))
117 return Resample_lerp32_Neon;
118 #endif
119 #ifdef HAVE_SSE4_1
120 if((CPUCapFlags&CPU_CAP_SSE4_1))
121 return Resample_lerp32_SSE41;
122 #endif
123 #ifdef HAVE_SSE2
124 if((CPUCapFlags&CPU_CAP_SSE2))
125 return Resample_lerp32_SSE2;
126 #endif
127 return Resample_lerp32_C;
128 case FIR4Resampler:
129 #ifdef HAVE_NEON
130 if((CPUCapFlags&CPU_CAP_NEON))
131 return Resample_fir4_32_Neon;
132 #endif
133 #ifdef HAVE_SSE4_1
134 if((CPUCapFlags&CPU_CAP_SSE4_1))
135 return Resample_fir4_32_SSE41;
136 #endif
137 #ifdef HAVE_SSE3
138 if((CPUCapFlags&CPU_CAP_SSE3))
139 return Resample_fir4_32_SSE3;
140 #endif
141 return Resample_fir4_32_C;
142 case BSincResampler:
143 #ifdef HAVE_NEON
144 if((CPUCapFlags&CPU_CAP_NEON))
145 return Resample_bsinc32_Neon;
146 #endif
147 #ifdef HAVE_SSE
148 if((CPUCapFlags&CPU_CAP_SSE))
149 return Resample_bsinc32_SSE;
150 #endif
151 return Resample_bsinc32_C;
154 return Resample_point32_C;
158 /* The sinc resampler makes use of a Kaiser window to limit the needed sample
159 * points to 4 and 8, respectively.
162 #ifndef M_PI
163 #define M_PI (3.14159265358979323846)
164 #endif
165 static inline double Sinc(double x)
167 if(x == 0.0) return 1.0;
168 return sin(x*M_PI) / (x*M_PI);
171 /* The zero-order modified Bessel function of the first kind, used for the
172 * Kaiser window.
174 * I_0(x) = sum_{k=0}^inf (1 / k!)^2 (x / 2)^(2 k)
175 * = sum_{k=0}^inf ((x / 2)^k / k!)^2
177 static double BesselI_0(double x)
179 double term, sum, x2, y, last_sum;
180 int k;
182 /* Start at k=1 since k=0 is trivial. */
183 term = 1.0;
184 sum = 1.0;
185 x2 = x / 2.0;
186 k = 1;
188 /* Let the integration converge until the term of the sum is no longer
189 * significant.
191 do {
192 y = x2 / k;
193 k ++;
194 last_sum = sum;
195 term *= y * y;
196 sum += term;
197 } while(sum != last_sum);
198 return sum;
201 /* Calculate a Kaiser window from the given beta value and a normalized k
202 * [-1, 1].
204 * w(k) = { I_0(B sqrt(1 - k^2)) / I_0(B), -1 <= k <= 1
205 * { 0, elsewhere.
207 * Where k can be calculated as:
209 * k = i / l, where -l <= i <= l.
211 * or:
213 * k = 2 i / M - 1, where 0 <= i <= M.
215 static inline double Kaiser(double b, double k)
217 if(k <= -1.0 || k >= 1.0) return 0.0;
218 return BesselI_0(b * sqrt(1.0 - (k*k))) / BesselI_0(b);
221 static inline double CalcKaiserBeta(double rejection)
223 if(rejection > 50.0)
224 return 0.1102 * (rejection - 8.7);
225 if(rejection >= 21.0)
226 return (0.5842 * pow(rejection - 21.0, 0.4)) +
227 (0.07886 * (rejection - 21.0));
228 return 0.0;
231 static float SincKaiser(double r, double x)
233 /* Limit rippling to -60dB. */
234 return (float)(Kaiser(CalcKaiserBeta(60.0), x / r) * Sinc(x));
238 void aluInitMixer(void)
240 enum Resampler resampler = ResamplerDefault;
241 const char *str;
242 ALuint i;
244 if(ConfigValueStr(NULL, NULL, "resampler", &str))
246 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
247 resampler = PointResampler;
248 else if(strcasecmp(str, "linear") == 0)
249 resampler = LinearResampler;
250 else if(strcasecmp(str, "sinc4") == 0)
251 resampler = FIR4Resampler;
252 else if(strcasecmp(str, "bsinc") == 0)
253 resampler = BSincResampler;
254 else if(strcasecmp(str, "cubic") == 0 || strcasecmp(str, "sinc8") == 0)
256 WARN("Resampler option \"%s\" is deprecated, using sinc4\n", str);
257 resampler = FIR4Resampler;
259 else
261 char *end;
262 long n = strtol(str, &end, 0);
263 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == FIR4Resampler))
264 resampler = n;
265 else
266 WARN("Invalid resampler: %s\n", str);
270 for(i = 0;i < FRACTIONONE;i++)
272 ALdouble mu = (ALdouble)i / FRACTIONONE;
273 ResampleCoeffs_FIR4[i][0] = SincKaiser(2.0, mu - -1.0);
274 ResampleCoeffs_FIR4[i][1] = SincKaiser(2.0, mu - 0.0);
275 ResampleCoeffs_FIR4[i][2] = SincKaiser(2.0, mu - 1.0);
276 ResampleCoeffs_FIR4[i][3] = SincKaiser(2.0, mu - 2.0);
279 MixHrtfSamples = SelectHrtfMixer();
280 MixSamples = SelectMixer();
281 ResampleSamples = SelectResampler(resampler);
285 static inline ALfloat Sample_ALbyte(ALbyte val)
286 { return val * (1.0f/127.0f); }
288 static inline ALfloat Sample_ALshort(ALshort val)
289 { return val * (1.0f/32767.0f); }
291 static inline ALfloat Sample_ALfloat(ALfloat val)
292 { return val; }
294 #define DECL_TEMPLATE(T) \
295 static inline void Load_##T(ALfloat *dst, const T *src, ALint srcstep, ALsizei samples)\
297 ALsizei i; \
298 for(i = 0;i < samples;i++) \
299 dst[i] = Sample_##T(src[i*srcstep]); \
302 DECL_TEMPLATE(ALbyte)
303 DECL_TEMPLATE(ALshort)
304 DECL_TEMPLATE(ALfloat)
306 #undef DECL_TEMPLATE
308 static void LoadSamples(ALfloat *dst, const ALvoid *src, ALint srcstep, enum FmtType srctype, ALsizei samples)
310 switch(srctype)
312 case FmtByte:
313 Load_ALbyte(dst, src, srcstep, samples);
314 break;
315 case FmtShort:
316 Load_ALshort(dst, src, srcstep, samples);
317 break;
318 case FmtFloat:
319 Load_ALfloat(dst, src, srcstep, samples);
320 break;
324 static inline void SilenceSamples(ALfloat *dst, ALsizei samples)
326 ALsizei i;
327 for(i = 0;i < samples;i++)
328 dst[i] = 0.0f;
332 static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter,
333 ALfloat *restrict dst, const ALfloat *restrict src,
334 ALsizei numsamples, enum ActiveFilters type)
336 ALsizei i;
337 switch(type)
339 case AF_None:
340 ALfilterState_processPassthru(lpfilter, src, numsamples);
341 ALfilterState_processPassthru(hpfilter, src, numsamples);
342 break;
344 case AF_LowPass:
345 ALfilterState_process(lpfilter, dst, src, numsamples);
346 ALfilterState_processPassthru(hpfilter, dst, numsamples);
347 return dst;
348 case AF_HighPass:
349 ALfilterState_processPassthru(lpfilter, src, numsamples);
350 ALfilterState_process(hpfilter, dst, src, numsamples);
351 return dst;
353 case AF_BandPass:
354 for(i = 0;i < numsamples;)
356 ALfloat temp[256];
357 ALsizei todo = mini(256, numsamples-i);
359 ALfilterState_process(lpfilter, temp, src+i, todo);
360 ALfilterState_process(hpfilter, dst+i, temp, todo);
361 i += todo;
363 return dst;
365 return src;
369 ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei SamplesToDo)
371 ResamplerFunc Resample;
372 ALbufferlistitem *BufferListItem;
373 ALuint DataPosInt, DataPosFrac;
374 bool isplaying = true;
375 bool islooping;
376 ALint increment;
377 ALsizei OutPos;
378 ALsizei NumChannels;
379 ALsizei SampleSize;
380 ALint64 DataSize64;
381 ALsizei Counter;
382 ALsizei IrSize;
383 ALsizei chan;
384 ALsizei send;
386 /* Get source info */
387 DataPosInt = ATOMIC_LOAD(&voice->position, almemory_order_acquire);
388 DataPosFrac = ATOMIC_LOAD(&voice->position_fraction, almemory_order_relaxed);
389 BufferListItem = ATOMIC_LOAD(&voice->current_buffer, almemory_order_relaxed);
390 islooping = ATOMIC_LOAD(&Source->looping, almemory_order_relaxed);
391 NumChannels = voice->NumChannels;
392 SampleSize = voice->SampleSize;
393 increment = voice->Step;
395 IrSize = (Device->HrtfHandle ? Device->HrtfHandle->irSize : 0);
397 Resample = ((increment == FRACTIONONE && DataPosFrac == 0) ?
398 Resample_copy32_C : ResampleSamples);
400 Counter = (voice->Flags&VOICE_IS_MOVING) ? SamplesToDo : 0;
401 OutPos = 0;
402 do {
403 ALsizei SrcBufferSize, DstBufferSize;
405 /* Figure out how many buffer samples will be needed */
406 DataSize64 = SamplesToDo-OutPos;
407 DataSize64 *= increment;
408 DataSize64 += DataPosFrac+FRACTIONMASK;
409 DataSize64 >>= FRACTIONBITS;
410 DataSize64 += MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
412 SrcBufferSize = (ALsizei)mini64(DataSize64, BUFFERSIZE);
414 /* Figure out how many samples we can actually mix from this. */
415 DataSize64 = SrcBufferSize;
416 DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
417 DataSize64 <<= FRACTIONBITS;
418 DataSize64 -= DataPosFrac;
420 DstBufferSize = (ALsizei)((DataSize64+(increment-1)) / increment);
421 DstBufferSize = mini(DstBufferSize, (SamplesToDo-OutPos));
423 /* Some mixers like having a multiple of 4, so try to give that unless
424 * this is the last update. */
425 if(OutPos+DstBufferSize < SamplesToDo)
426 DstBufferSize &= ~3;
428 for(chan = 0;chan < NumChannels;chan++)
430 const ALfloat *ResampledData;
431 ALfloat *SrcData = Device->SourceData;
432 ALsizei SrcDataSize;
434 /* Load the previous samples into the source data first. */
435 memcpy(SrcData, voice->PrevSamples[chan], MAX_PRE_SAMPLES*sizeof(ALfloat));
436 SrcDataSize = MAX_PRE_SAMPLES;
438 if(Source->SourceType == AL_STATIC)
440 const ALbuffer *ALBuffer = BufferListItem->buffer;
441 const ALubyte *Data = ALBuffer->data;
442 ALsizei DataSize;
444 /* Offset buffer data to current channel */
445 Data += chan*SampleSize;
447 /* If current pos is beyond the loop range, do not loop */
448 if(!islooping || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
450 islooping = false;
452 /* Load what's left to play from the source buffer, and
453 * clear the rest of the temp buffer */
454 DataSize = minu(SrcBufferSize - SrcDataSize,
455 ALBuffer->SampleLen - DataPosInt);
457 LoadSamples(&SrcData[SrcDataSize], &Data[DataPosInt * NumChannels*SampleSize],
458 NumChannels, ALBuffer->FmtType, DataSize);
459 SrcDataSize += DataSize;
461 SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
462 SrcDataSize += SrcBufferSize - SrcDataSize;
464 else
466 ALsizei LoopStart = ALBuffer->LoopStart;
467 ALsizei LoopEnd = ALBuffer->LoopEnd;
469 /* Load what's left of this loop iteration, then load
470 * repeats of the loop section */
471 DataSize = minu(SrcBufferSize - SrcDataSize, LoopEnd - DataPosInt);
473 LoadSamples(&SrcData[SrcDataSize], &Data[DataPosInt * NumChannels*SampleSize],
474 NumChannels, ALBuffer->FmtType, DataSize);
475 SrcDataSize += DataSize;
477 DataSize = LoopEnd-LoopStart;
478 while(SrcBufferSize > SrcDataSize)
480 DataSize = mini(SrcBufferSize - SrcDataSize, DataSize);
482 LoadSamples(&SrcData[SrcDataSize], &Data[LoopStart * NumChannels*SampleSize],
483 NumChannels, ALBuffer->FmtType, DataSize);
484 SrcDataSize += DataSize;
488 else
490 /* Crawl the buffer queue to fill in the temp buffer */
491 ALbufferlistitem *tmpiter = BufferListItem;
492 ALuint pos = DataPosInt;
494 while(tmpiter && SrcBufferSize > SrcDataSize)
496 const ALbuffer *ALBuffer;
497 if((ALBuffer=tmpiter->buffer) != NULL)
499 const ALubyte *Data = ALBuffer->data;
500 ALuint DataSize = ALBuffer->SampleLen;
502 /* Skip the data already played */
503 if(DataSize <= pos)
504 pos -= DataSize;
505 else
507 Data += (pos*NumChannels + chan)*SampleSize;
508 DataSize -= pos;
509 pos -= pos;
511 DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
512 LoadSamples(&SrcData[SrcDataSize], Data, NumChannels,
513 ALBuffer->FmtType, DataSize);
514 SrcDataSize += DataSize;
517 tmpiter = tmpiter->next;
518 if(!tmpiter && islooping)
519 tmpiter = ATOMIC_LOAD(&Source->queue, almemory_order_acquire);
520 else if(!tmpiter)
522 SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
523 SrcDataSize += SrcBufferSize - SrcDataSize;
528 /* Store the last source samples used for next time. */
529 memcpy(voice->PrevSamples[chan],
530 &SrcData[(increment*DstBufferSize + DataPosFrac)>>FRACTIONBITS],
531 MAX_PRE_SAMPLES*sizeof(ALfloat)
534 /* Now resample, then filter and mix to the appropriate outputs. */
535 ResampledData = Resample(&voice->ResampleState,
536 &SrcData[MAX_PRE_SAMPLES], DataPosFrac, increment,
537 Device->ResampledData, DstBufferSize
540 DirectParams *parms = &voice->Direct.Params[chan];
541 const ALfloat *samples;
543 samples = DoFilters(
544 &parms->LowPass, &parms->HighPass, Device->FilteredData,
545 ResampledData, DstBufferSize, parms->FilterType
547 if(!(voice->Flags&VOICE_IS_HRTF))
549 if(!Counter)
550 memcpy(parms->Gains.Current, parms->Gains.Target,
551 sizeof(parms->Gains.Current));
552 if(!(voice->Flags&VOICE_HAS_NFC))
553 MixSamples(samples, voice->Direct.Channels, voice->Direct.Buffer,
554 parms->Gains.Current, parms->Gains.Target, Counter, OutPos,
555 DstBufferSize
557 else
559 ALfloat *nfcsamples = Device->NFCtrlData;
560 ALsizei chanoffset = 0;
561 MixSamples(samples,
562 voice->Direct.ChannelsPerOrder[0], voice->Direct.Buffer,
563 parms->Gains.Current, parms->Gains.Target, Counter, OutPos,
564 DstBufferSize
566 chanoffset += voice->Direct.ChannelsPerOrder[0];
567 if(voice->Direct.ChannelsPerOrder[1] > 0)
569 NfcFilterUpdate1(&parms->NFCtrlFilter[0], nfcsamples, samples,
570 DstBufferSize);
571 MixSamples(nfcsamples,
572 voice->Direct.ChannelsPerOrder[1], voice->Direct.Buffer+chanoffset,
573 parms->Gains.Current+chanoffset, parms->Gains.Target+chanoffset,
574 Counter, OutPos, DstBufferSize
576 chanoffset += voice->Direct.ChannelsPerOrder[1];
578 if(voice->Direct.ChannelsPerOrder[2] > 0)
580 NfcFilterUpdate2(&parms->NFCtrlFilter[1], nfcsamples, samples,
581 DstBufferSize);
582 MixSamples(nfcsamples,
583 voice->Direct.ChannelsPerOrder[2], voice->Direct.Buffer+chanoffset,
584 parms->Gains.Current+chanoffset, parms->Gains.Target+chanoffset,
585 Counter, OutPos, DstBufferSize
587 chanoffset += voice->Direct.ChannelsPerOrder[2];
589 if(voice->Direct.ChannelsPerOrder[3] > 0)
591 NfcFilterUpdate3(&parms->NFCtrlFilter[2], nfcsamples, samples,
592 DstBufferSize);
593 MixSamples(nfcsamples,
594 voice->Direct.ChannelsPerOrder[3], voice->Direct.Buffer+chanoffset,
595 parms->Gains.Current+chanoffset, parms->Gains.Target+chanoffset,
596 Counter, OutPos, DstBufferSize
598 chanoffset += voice->Direct.ChannelsPerOrder[3];
602 else
604 MixHrtfParams hrtfparams;
605 int lidx, ridx;
607 lidx = GetChannelIdxByName(Device->RealOut, FrontLeft);
608 ridx = GetChannelIdxByName(Device->RealOut, FrontRight);
609 assert(lidx != -1 && ridx != -1);
611 if(!Counter)
613 parms->Hrtf.Old = parms->Hrtf.Target;
614 hrtfparams.Coeffs = SAFE_CONST(ALfloat2*,parms->Hrtf.Target.Coeffs);
615 hrtfparams.Delay[0] = parms->Hrtf.Target.Delay[0];
616 hrtfparams.Delay[1] = parms->Hrtf.Target.Delay[1];
617 hrtfparams.Gain = parms->Hrtf.Target.Gain;
618 hrtfparams.GainStep = 0.0f;
619 MixHrtfSamples(
620 voice->Direct.Buffer[lidx], voice->Direct.Buffer[ridx],
621 samples, voice->Offset, OutPos, IrSize, &hrtfparams,
622 &parms->Hrtf.State, DstBufferSize
625 else
627 HrtfState backupstate = parms->Hrtf.State;
628 ALfloat gain;
630 /* The old coefficients need to fade to silence
631 * completely since they'll be replaced after the mix.
632 * So it needs to fade out over DstBufferSize instead
633 * of Counter.
635 hrtfparams.Coeffs = SAFE_CONST(ALfloat2*,parms->Hrtf.Old.Coeffs);
636 hrtfparams.Delay[0] = parms->Hrtf.Old.Delay[0];
637 hrtfparams.Delay[1] = parms->Hrtf.Old.Delay[1];
638 hrtfparams.Gain = parms->Hrtf.Old.Gain;
639 hrtfparams.GainStep = -hrtfparams.Gain /
640 (ALfloat)DstBufferSize;
641 MixHrtfSamples(
642 voice->Direct.Buffer[lidx], voice->Direct.Buffer[ridx],
643 samples, voice->Offset, OutPos, IrSize, &hrtfparams,
644 &backupstate, DstBufferSize
647 /* The new coefficients need to fade in completely
648 * since they're replacing the old ones. To keep the
649 * source gain fading consistent, interpolate between
650 * the old and new target gain given how much of the
651 * fade time this mix handles.
653 gain = lerp(parms->Hrtf.Old.Gain, parms->Hrtf.Target.Gain,
654 minf(1.0f, (ALfloat)Counter/DstBufferSize));
655 hrtfparams.Coeffs = SAFE_CONST(ALfloat2*,parms->Hrtf.Target.Coeffs);
656 hrtfparams.Delay[0] = parms->Hrtf.Target.Delay[0];
657 hrtfparams.Delay[1] = parms->Hrtf.Target.Delay[1];
658 hrtfparams.Gain = 0.0f;
659 hrtfparams.GainStep = gain / (ALfloat)DstBufferSize;
660 MixHrtfSamples(
661 voice->Direct.Buffer[lidx], voice->Direct.Buffer[ridx],
662 samples, voice->Offset, OutPos, IrSize, &hrtfparams,
663 &parms->Hrtf.State, DstBufferSize
665 /* Update the old parameters with the result. */
666 parms->Hrtf.Old = parms->Hrtf.Target;
667 if(Counter > DstBufferSize)
668 parms->Hrtf.Old.Gain = hrtfparams.Gain;
673 for(send = 0;send < Device->NumAuxSends;send++)
675 SendParams *parms = &voice->Send[send].Params[chan];
676 const ALfloat *samples;
678 if(!voice->Send[send].Buffer)
679 continue;
681 samples = DoFilters(
682 &parms->LowPass, &parms->HighPass, Device->FilteredData,
683 ResampledData, DstBufferSize, parms->FilterType
686 if(!Counter)
687 memcpy(parms->Gains.Current, parms->Gains.Target,
688 sizeof(parms->Gains.Current));
689 MixSamples(samples, voice->Send[send].Channels, voice->Send[send].Buffer,
690 parms->Gains.Current, parms->Gains.Target, Counter, OutPos, DstBufferSize
694 /* Update positions */
695 DataPosFrac += increment*DstBufferSize;
696 DataPosInt += DataPosFrac>>FRACTIONBITS;
697 DataPosFrac &= FRACTIONMASK;
699 OutPos += DstBufferSize;
700 voice->Offset += DstBufferSize;
701 Counter = maxi(DstBufferSize, Counter) - DstBufferSize;
703 /* Handle looping sources */
704 while(1)
706 const ALbuffer *ALBuffer;
707 ALsizei DataSize = 0;
708 ALsizei LoopStart = 0;
709 ALsizei LoopEnd = 0;
711 if((ALBuffer=BufferListItem->buffer) != NULL)
713 DataSize = ALBuffer->SampleLen;
714 LoopStart = ALBuffer->LoopStart;
715 LoopEnd = ALBuffer->LoopEnd;
716 if((ALuint)LoopEnd > DataPosInt)
717 break;
720 if(islooping && Source->SourceType == AL_STATIC)
722 assert(LoopEnd > LoopStart);
723 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
724 break;
727 if((ALuint)DataSize > DataPosInt)
728 break;
730 if(!(BufferListItem=BufferListItem->next))
732 if(islooping)
733 BufferListItem = ATOMIC_LOAD(&Source->queue, almemory_order_acquire);
734 else
736 isplaying = false;
737 BufferListItem = NULL;
738 DataPosInt = 0;
739 DataPosFrac = 0;
740 break;
744 DataPosInt -= DataSize;
746 } while(isplaying && OutPos < SamplesToDo);
748 voice->Flags |= VOICE_IS_MOVING;
750 /* Update source info */
751 ATOMIC_STORE(&voice->position, DataPosInt, almemory_order_relaxed);
752 ATOMIC_STORE(&voice->position_fraction, DataPosFrac, almemory_order_relaxed);
753 ATOMIC_STORE(&voice->current_buffer, BufferListItem, almemory_order_release);
754 return isplaying;