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
34 #include "alListener.h"
35 #include "alAuxEffectSlot.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];
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)
70 if((CPUCapFlags
&CPU_CAP_SSE
))
74 if((CPUCapFlags
&CPU_CAP_NEON
))
81 RowMixerFunc
SelectRowMixer(void)
84 if((CPUCapFlags
&CPU_CAP_SSE
))
88 if((CPUCapFlags
&CPU_CAP_NEON
))
94 static inline HrtfMixerFunc
SelectHrtfMixer(void)
97 if((CPUCapFlags
&CPU_CAP_SSE
))
101 if((CPUCapFlags
&CPU_CAP_NEON
))
108 static inline ResamplerFunc
SelectResampler(enum Resampler resampler
)
113 return Resample_point32_C
;
114 case LinearResampler
:
116 if((CPUCapFlags
&CPU_CAP_NEON
))
117 return Resample_lerp32_Neon
;
120 if((CPUCapFlags
&CPU_CAP_SSE4_1
))
121 return Resample_lerp32_SSE41
;
124 if((CPUCapFlags
&CPU_CAP_SSE2
))
125 return Resample_lerp32_SSE2
;
127 return Resample_lerp32_C
;
130 if((CPUCapFlags
&CPU_CAP_NEON
))
131 return Resample_fir4_32_Neon
;
134 if((CPUCapFlags
&CPU_CAP_SSE4_1
))
135 return Resample_fir4_32_SSE41
;
138 if((CPUCapFlags
&CPU_CAP_SSE3
))
139 return Resample_fir4_32_SSE3
;
141 return Resample_fir4_32_C
;
144 if((CPUCapFlags
&CPU_CAP_NEON
))
145 return Resample_bsinc32_Neon
;
148 if((CPUCapFlags
&CPU_CAP_SSE
))
149 return Resample_bsinc32_SSE
;
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.
163 #define M_PI (3.14159265358979323846)
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
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
;
182 /* Start at k=1 since k=0 is trivial. */
188 /* Let the integration converge until the term of the sum is no longer
197 } while(sum
!= last_sum
);
201 /* Calculate a Kaiser window from the given beta value and a normalized k
204 * w(k) = { I_0(B sqrt(1 - k^2)) / I_0(B), -1 <= k <= 1
207 * Where k can be calculated as:
209 * k = i / l, where -l <= i <= l.
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
)
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));
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
;
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
;
262 long n
= strtol(str
, &end
, 0);
263 if(*end
== '\0' && (n
== PointResampler
|| n
== LinearResampler
|| n
== FIR4Resampler
))
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
)
294 #define DECL_TEMPLATE(T) \
295 static inline void Load_##T(ALfloat *dst, const T *src, ALint srcstep, ALsizei samples)\
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
)
308 static void LoadSamples(ALfloat
*dst
, const ALvoid
*src
, ALint srcstep
, enum FmtType srctype
, ALsizei samples
)
313 Load_ALbyte(dst
, src
, srcstep
, samples
);
316 Load_ALshort(dst
, src
, srcstep
, samples
);
319 Load_ALfloat(dst
, src
, srcstep
, samples
);
324 static inline void SilenceSamples(ALfloat
*dst
, ALsizei samples
)
327 for(i
= 0;i
< samples
;i
++)
332 static const ALfloat
*DoFilters(ALfilterState
*lpfilter
, ALfilterState
*hpfilter
,
333 ALfloat
*restrict dst
, const ALfloat
*restrict src
,
334 ALsizei numsamples
, enum ActiveFilters type
)
340 ALfilterState_processPassthru(lpfilter
, src
, numsamples
);
341 ALfilterState_processPassthru(hpfilter
, src
, numsamples
);
345 ALfilterState_process(lpfilter
, dst
, src
, numsamples
);
346 ALfilterState_processPassthru(hpfilter
, dst
, numsamples
);
349 ALfilterState_processPassthru(lpfilter
, src
, numsamples
);
350 ALfilterState_process(hpfilter
, dst
, src
, numsamples
);
354 for(i
= 0;i
< numsamples
;)
357 ALsizei todo
= mini(256, numsamples
-i
);
359 ALfilterState_process(lpfilter
, temp
, src
+i
, todo
);
360 ALfilterState_process(hpfilter
, dst
+i
, temp
, todo
);
369 void MixSource(ALvoice
*voice
, ALsource
*Source
, ALCdevice
*Device
, ALsizei SamplesToDo
)
371 ResamplerFunc Resample
;
372 ALbufferlistitem
*BufferListItem
;
373 ALuint DataPosInt
, DataPosFrac
;
386 /* Get source info */
387 State
= AL_PLAYING
; /* Only called while playing. */
388 BufferListItem
= ATOMIC_LOAD(&Source
->current_buffer
, almemory_order_acquire
);
389 DataPosInt
= ATOMIC_LOAD(&Source
->position
, almemory_order_relaxed
);
390 DataPosFrac
= ATOMIC_LOAD(&Source
->position_fraction
, almemory_order_relaxed
);
391 Looping
= ATOMIC_LOAD(&Source
->looping
, almemory_order_relaxed
);
392 NumChannels
= Source
->NumChannels
;
393 SampleSize
= Source
->SampleSize
;
394 increment
= voice
->Step
;
396 IrSize
= (Device
->Hrtf
.Handle
? Device
->Hrtf
.Handle
->irSize
: 0);
398 Resample
= ((increment
== FRACTIONONE
&& DataPosFrac
== 0) ?
399 Resample_copy32_C
: ResampleSamples
);
401 Counter
= voice
->Moving
? SamplesToDo
: 0;
404 ALsizei SrcBufferSize
, DstBufferSize
;
406 /* Figure out how many buffer samples will be needed */
407 DataSize64
= SamplesToDo
-OutPos
;
408 DataSize64
*= increment
;
409 DataSize64
+= DataPosFrac
+FRACTIONMASK
;
410 DataSize64
>>= FRACTIONBITS
;
411 DataSize64
+= MAX_POST_SAMPLES
+MAX_PRE_SAMPLES
;
413 SrcBufferSize
= (ALsizei
)mini64(DataSize64
, BUFFERSIZE
);
415 /* Figure out how many samples we can actually mix from this. */
416 DataSize64
= SrcBufferSize
;
417 DataSize64
-= MAX_POST_SAMPLES
+MAX_PRE_SAMPLES
;
418 DataSize64
<<= FRACTIONBITS
;
419 DataSize64
-= DataPosFrac
;
421 DstBufferSize
= (ALsizei
)((DataSize64
+(increment
-1)) / increment
);
422 DstBufferSize
= mini(DstBufferSize
, (SamplesToDo
-OutPos
));
424 /* Some mixers like having a multiple of 4, so try to give that unless
425 * this is the last update. */
426 if(OutPos
+DstBufferSize
< SamplesToDo
)
429 for(chan
= 0;chan
< NumChannels
;chan
++)
431 const ALfloat
*ResampledData
;
432 ALfloat
*SrcData
= Device
->SourceData
;
435 /* Load the previous samples into the source data first. */
436 memcpy(SrcData
, voice
->PrevSamples
[chan
], MAX_PRE_SAMPLES
*sizeof(ALfloat
));
437 SrcDataSize
= MAX_PRE_SAMPLES
;
439 if(Source
->SourceType
== AL_STATIC
)
441 const ALbuffer
*ALBuffer
= BufferListItem
->buffer
;
442 const ALubyte
*Data
= ALBuffer
->data
;
445 /* Offset buffer data to current channel */
446 Data
+= chan
*SampleSize
;
448 /* If current pos is beyond the loop range, do not loop */
449 if(Looping
== AL_FALSE
|| DataPosInt
>= (ALuint
)ALBuffer
->LoopEnd
)
453 /* Load what's left to play from the source buffer, and
454 * clear the rest of the temp buffer */
455 DataSize
= minu(SrcBufferSize
- SrcDataSize
,
456 ALBuffer
->SampleLen
- DataPosInt
);
458 LoadSamples(&SrcData
[SrcDataSize
], &Data
[DataPosInt
* NumChannels
*SampleSize
],
459 NumChannels
, ALBuffer
->FmtType
, DataSize
);
460 SrcDataSize
+= DataSize
;
462 SilenceSamples(&SrcData
[SrcDataSize
], SrcBufferSize
- SrcDataSize
);
463 SrcDataSize
+= SrcBufferSize
- SrcDataSize
;
467 ALsizei LoopStart
= ALBuffer
->LoopStart
;
468 ALsizei LoopEnd
= ALBuffer
->LoopEnd
;
470 /* Load what's left of this loop iteration, then load
471 * repeats of the loop section */
472 DataSize
= minu(SrcBufferSize
- SrcDataSize
, LoopEnd
- DataPosInt
);
474 LoadSamples(&SrcData
[SrcDataSize
], &Data
[DataPosInt
* NumChannels
*SampleSize
],
475 NumChannels
, ALBuffer
->FmtType
, DataSize
);
476 SrcDataSize
+= DataSize
;
478 DataSize
= LoopEnd
-LoopStart
;
479 while(SrcBufferSize
> SrcDataSize
)
481 DataSize
= mini(SrcBufferSize
- SrcDataSize
, DataSize
);
483 LoadSamples(&SrcData
[SrcDataSize
], &Data
[LoopStart
* NumChannels
*SampleSize
],
484 NumChannels
, ALBuffer
->FmtType
, DataSize
);
485 SrcDataSize
+= DataSize
;
491 /* Crawl the buffer queue to fill in the temp buffer */
492 ALbufferlistitem
*tmpiter
= BufferListItem
;
493 ALuint pos
= DataPosInt
;
495 while(tmpiter
&& SrcBufferSize
> SrcDataSize
)
497 const ALbuffer
*ALBuffer
;
498 if((ALBuffer
=tmpiter
->buffer
) != NULL
)
500 const ALubyte
*Data
= ALBuffer
->data
;
501 ALuint DataSize
= ALBuffer
->SampleLen
;
503 /* Skip the data already played */
508 Data
+= (pos
*NumChannels
+ chan
)*SampleSize
;
512 DataSize
= minu(SrcBufferSize
- SrcDataSize
, DataSize
);
513 LoadSamples(&SrcData
[SrcDataSize
], Data
, NumChannels
,
514 ALBuffer
->FmtType
, DataSize
);
515 SrcDataSize
+= DataSize
;
518 tmpiter
= tmpiter
->next
;
519 if(!tmpiter
&& Looping
)
520 tmpiter
= ATOMIC_LOAD(&Source
->queue
, almemory_order_acquire
);
523 SilenceSamples(&SrcData
[SrcDataSize
], SrcBufferSize
- SrcDataSize
);
524 SrcDataSize
+= SrcBufferSize
- SrcDataSize
;
529 /* Store the last source samples used for next time. */
530 memcpy(voice
->PrevSamples
[chan
],
531 &SrcData
[(increment
*DstBufferSize
+ DataPosFrac
)>>FRACTIONBITS
],
532 MAX_PRE_SAMPLES
*sizeof(ALfloat
)
535 /* Now resample, then filter and mix to the appropriate outputs. */
536 ResampledData
= Resample(&voice
->ResampleState
,
537 &SrcData
[MAX_PRE_SAMPLES
], DataPosFrac
, increment
,
538 Device
->ResampledData
, DstBufferSize
541 DirectParams
*parms
= &voice
->Direct
.Params
[chan
];
542 const ALfloat
*samples
;
545 &parms
->LowPass
, &parms
->HighPass
, Device
->FilteredData
,
546 ResampledData
, DstBufferSize
, parms
->FilterType
551 memcpy(parms
->Gains
.Current
, parms
->Gains
.Target
,
552 sizeof(parms
->Gains
.Current
));
553 MixSamples(samples
, voice
->Direct
.Channels
, voice
->Direct
.Buffer
,
554 parms
->Gains
.Current
, parms
->Gains
.Target
, Counter
, OutPos
,
560 MixHrtfParams hrtfparams
;
565 parms
->Hrtf
.Current
= parms
->Hrtf
.Target
;
566 for(j
= 0;j
< HRIR_LENGTH
;j
++)
568 hrtfparams
.Steps
.Coeffs
[j
][0] = 0.0f
;
569 hrtfparams
.Steps
.Coeffs
[j
][1] = 0.0f
;
571 hrtfparams
.Steps
.Delay
[0] = 0;
572 hrtfparams
.Steps
.Delay
[1] = 0;
576 ALfloat delta
= 1.0f
/ (ALfloat
)Counter
;
579 for(j
= 0;j
< IrSize
;j
++)
581 coeffdiff
= parms
->Hrtf
.Target
.Coeffs
[j
][0] - parms
->Hrtf
.Current
.Coeffs
[j
][0];
582 hrtfparams
.Steps
.Coeffs
[j
][0] = coeffdiff
* delta
;
583 coeffdiff
= parms
->Hrtf
.Target
.Coeffs
[j
][1] - parms
->Hrtf
.Current
.Coeffs
[j
][1];
584 hrtfparams
.Steps
.Coeffs
[j
][1] = coeffdiff
* delta
;
586 delaydiff
= parms
->Hrtf
.Target
.Delay
[0] - parms
->Hrtf
.Current
.Delay
[0];
587 hrtfparams
.Steps
.Delay
[0] = fastf2i((ALfloat
)delaydiff
* delta
);
588 delaydiff
= parms
->Hrtf
.Target
.Delay
[1] - parms
->Hrtf
.Current
.Delay
[1];
589 hrtfparams
.Steps
.Delay
[1] = fastf2i((ALfloat
)delaydiff
* delta
);
591 hrtfparams
.Target
= &parms
->Hrtf
.Target
;
592 hrtfparams
.Current
= &parms
->Hrtf
.Current
;
594 lidx
= GetChannelIdxByName(Device
->RealOut
, FrontLeft
);
595 ridx
= GetChannelIdxByName(Device
->RealOut
, FrontRight
);
596 assert(lidx
!= -1 && ridx
!= -1);
599 voice
->Direct
.Buffer
[lidx
], voice
->Direct
.Buffer
[ridx
],
600 samples
, Counter
, voice
->Offset
, OutPos
, IrSize
, &hrtfparams
,
601 &parms
->Hrtf
.State
, DstBufferSize
606 for(send
= 0;send
< Device
->NumAuxSends
;send
++)
608 SendParams
*parms
= &voice
->Send
[send
].Params
[chan
];
609 const ALfloat
*samples
;
611 if(!voice
->Send
[send
].Buffer
)
615 &parms
->LowPass
, &parms
->HighPass
, Device
->FilteredData
,
616 ResampledData
, DstBufferSize
, parms
->FilterType
620 memcpy(parms
->Gains
.Current
, parms
->Gains
.Target
,
621 sizeof(parms
->Gains
.Current
));
622 MixSamples(samples
, voice
->Send
[send
].Channels
, voice
->Send
[send
].Buffer
,
623 parms
->Gains
.Current
, parms
->Gains
.Target
, Counter
, OutPos
, DstBufferSize
627 /* Update positions */
628 DataPosFrac
+= increment
*DstBufferSize
;
629 DataPosInt
+= DataPosFrac
>>FRACTIONBITS
;
630 DataPosFrac
&= FRACTIONMASK
;
632 OutPos
+= DstBufferSize
;
633 voice
->Offset
+= DstBufferSize
;
634 Counter
= maxi(DstBufferSize
, Counter
) - DstBufferSize
;
636 /* Handle looping sources */
639 const ALbuffer
*ALBuffer
;
640 ALsizei DataSize
= 0;
641 ALsizei LoopStart
= 0;
644 if((ALBuffer
=BufferListItem
->buffer
) != NULL
)
646 DataSize
= ALBuffer
->SampleLen
;
647 LoopStart
= ALBuffer
->LoopStart
;
648 LoopEnd
= ALBuffer
->LoopEnd
;
649 if((ALuint
)LoopEnd
> DataPosInt
)
653 if(Looping
&& Source
->SourceType
== AL_STATIC
)
655 assert(LoopEnd
> LoopStart
);
656 DataPosInt
= ((DataPosInt
-LoopStart
)%(LoopEnd
-LoopStart
)) + LoopStart
;
660 if((ALuint
)DataSize
> DataPosInt
)
663 if(!(BufferListItem
=BufferListItem
->next
))
666 BufferListItem
= ATOMIC_LOAD(&Source
->queue
, almemory_order_acquire
);
670 BufferListItem
= NULL
;
677 DataPosInt
-= DataSize
;
679 } while(State
== AL_PLAYING
&& OutPos
< SamplesToDo
);
681 voice
->Moving
= AL_TRUE
;
683 /* Update source info */
684 ATOMIC_STORE(&Source
->state
, State
, almemory_order_relaxed
);
685 ATOMIC_STORE(&Source
->current_buffer
, BufferListItem
, almemory_order_relaxed
);
686 ATOMIC_STORE(&Source
->position
, DataPosInt
, almemory_order_relaxed
);
687 ATOMIC_STORE(&Source
->position_fraction
, DataPosFrac
, almemory_order_release
);