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
, ALuint increment
, ALuint
*frac_arr
, ALuint
*pos_arr
, ALuint size
);
46 alignas(16) union ResamplerCoeffs ResampleCoeffs
;
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 HrtfMixerFunc MixHrtfSamples
= MixHrtf_C
;
65 static MixerFunc MixSamples
= Mix_C
;
66 static ResamplerFunc ResampleSamples
= Resample_point32_C
;
68 static inline HrtfMixerFunc
SelectHrtfMixer(void)
71 if((CPUCapFlags
&CPU_CAP_SSE
))
75 if((CPUCapFlags
&CPU_CAP_NEON
))
82 static inline MixerFunc
SelectMixer(void)
85 if((CPUCapFlags
&CPU_CAP_SSE
))
89 if((CPUCapFlags
&CPU_CAP_NEON
))
96 static inline ResamplerFunc
SelectResampler(enum Resampler resampler
)
101 return Resample_point32_C
;
102 case LinearResampler
:
104 if((CPUCapFlags
&CPU_CAP_SSE4_1
))
105 return Resample_lerp32_SSE41
;
108 if((CPUCapFlags
&CPU_CAP_SSE2
))
109 return Resample_lerp32_SSE2
;
111 return Resample_lerp32_C
;
114 if((CPUCapFlags
&CPU_CAP_SSE4_1
))
115 return Resample_fir4_32_SSE41
;
118 if((CPUCapFlags
&CPU_CAP_SSE3
))
119 return Resample_fir4_32_SSE3
;
121 return Resample_fir4_32_C
;
124 if((CPUCapFlags
&CPU_CAP_SSE4_1
))
125 return Resample_fir8_32_SSE41
;
128 if((CPUCapFlags
&CPU_CAP_SSE3
))
129 return Resample_fir8_32_SSE3
;
131 return Resample_fir8_32_C
;
134 if((CPUCapFlags
&CPU_CAP_SSE
))
135 return Resample_bsinc32_SSE
;
137 return Resample_bsinc32_C
;
140 return Resample_point32_C
;
144 /* The sinc resampler makes use of a Kaiser window to limit the needed sample
145 * points to 4 and 8, respectively.
149 #define M_PI (3.14159265358979323846)
151 static inline double Sinc(double x
)
153 if(x
== 0.0) return 1.0;
154 return sin(x
*M_PI
) / (x
*M_PI
);
157 /* The zero-order modified Bessel function of the first kind, used for the
160 * I_0(x) = sum_{k=0}^inf (1 / k!)^2 (x / 2)^(2 k)
161 * = sum_{k=0}^inf ((x / 2)^k / k!)^2
163 static double BesselI_0(double x
)
165 double term
, sum
, x2
, y
, last_sum
;
168 /* Start at k=1 since k=0 is trivial. */
174 /* Let the integration converge until the term of the sum is no longer
183 } while(sum
!= last_sum
);
187 /* Calculate a Kaiser window from the given beta value and a normalized k
190 * w(k) = { I_0(B sqrt(1 - k^2)) / I_0(B), -1 <= k <= 1
193 * Where k can be calculated as:
195 * k = i / l, where -l <= i <= l.
199 * k = 2 i / M - 1, where 0 <= i <= M.
201 static inline double Kaiser(double b
, double k
)
203 if(k
<= -1.0 || k
>= 1.0) return 0.0;
204 return BesselI_0(b
* sqrt(1.0 - (k
*k
))) / BesselI_0(b
);
207 static inline double CalcKaiserBeta(double rejection
)
210 return 0.1102 * (rejection
- 8.7);
211 if(rejection
>= 21.0)
212 return (0.5842 * pow(rejection
- 21.0, 0.4)) +
213 (0.07886 * (rejection
- 21.0));
217 static float SincKaiser(double r
, double x
)
219 /* Limit rippling to -60dB. */
220 return (float)(Kaiser(CalcKaiserBeta(60.0), x
/ r
) * Sinc(x
));
224 void aluInitMixer(void)
226 enum Resampler resampler
= ResamplerDefault
;
230 if(ConfigValueStr(NULL
, NULL
, "resampler", &str
))
232 if(strcasecmp(str
, "point") == 0 || strcasecmp(str
, "none") == 0)
233 resampler
= PointResampler
;
234 else if(strcasecmp(str
, "linear") == 0)
235 resampler
= LinearResampler
;
236 else if(strcasecmp(str
, "sinc4") == 0)
237 resampler
= FIR4Resampler
;
238 else if(strcasecmp(str
, "sinc8") == 0)
239 resampler
= FIR8Resampler
;
240 else if(strcasecmp(str
, "bsinc") == 0)
241 resampler
= BSincResampler
;
242 else if(strcasecmp(str
, "cubic") == 0)
244 WARN("Resampler option \"cubic\" is deprecated, using sinc4\n");
245 resampler
= FIR4Resampler
;
250 long n
= strtol(str
, &end
, 0);
251 if(*end
== '\0' && (n
== PointResampler
|| n
== LinearResampler
|| n
== FIR4Resampler
))
254 WARN("Invalid resampler: %s\n", str
);
258 if(resampler
== FIR8Resampler
)
259 for(i
= 0;i
< FRACTIONONE
;i
++)
261 ALdouble mu
= (ALdouble
)i
/ FRACTIONONE
;
262 ResampleCoeffs
.FIR8
[i
][0] = SincKaiser(4.0, mu
- -3.0);
263 ResampleCoeffs
.FIR8
[i
][1] = SincKaiser(4.0, mu
- -2.0);
264 ResampleCoeffs
.FIR8
[i
][2] = SincKaiser(4.0, mu
- -1.0);
265 ResampleCoeffs
.FIR8
[i
][3] = SincKaiser(4.0, mu
- 0.0);
266 ResampleCoeffs
.FIR8
[i
][4] = SincKaiser(4.0, mu
- 1.0);
267 ResampleCoeffs
.FIR8
[i
][5] = SincKaiser(4.0, mu
- 2.0);
268 ResampleCoeffs
.FIR8
[i
][6] = SincKaiser(4.0, mu
- 3.0);
269 ResampleCoeffs
.FIR8
[i
][7] = SincKaiser(4.0, mu
- 4.0);
271 else if(resampler
== FIR4Resampler
)
272 for(i
= 0;i
< FRACTIONONE
;i
++)
274 ALdouble mu
= (ALdouble
)i
/ FRACTIONONE
;
275 ResampleCoeffs
.FIR4
[i
][0] = SincKaiser(2.0, mu
- -1.0);
276 ResampleCoeffs
.FIR4
[i
][1] = SincKaiser(2.0, mu
- 0.0);
277 ResampleCoeffs
.FIR4
[i
][2] = SincKaiser(2.0, mu
- 1.0);
278 ResampleCoeffs
.FIR4
[i
][3] = SincKaiser(2.0, mu
- 2.0);
281 MixHrtfSamples
= SelectHrtfMixer();
282 MixSamples
= SelectMixer();
283 ResampleSamples
= SelectResampler(resampler
);
287 static inline ALfloat
Sample_ALbyte(ALbyte val
)
288 { return val
* (1.0f
/127.0f
); }
290 static inline ALfloat
Sample_ALshort(ALshort val
)
291 { return val
* (1.0f
/32767.0f
); }
293 static inline ALfloat
Sample_ALfloat(ALfloat val
)
296 #define DECL_TEMPLATE(T) \
297 static inline void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\
300 for(i = 0;i < samples;i++) \
301 dst[i] = Sample_##T(src[i*srcstep]); \
304 DECL_TEMPLATE(ALbyte
)
305 DECL_TEMPLATE(ALshort
)
306 DECL_TEMPLATE(ALfloat
)
310 static void LoadSamples(ALfloat
*dst
, const ALvoid
*src
, ALuint srcstep
, enum FmtType srctype
, ALuint samples
)
315 Load_ALbyte(dst
, src
, srcstep
, samples
);
318 Load_ALshort(dst
, src
, srcstep
, samples
);
321 Load_ALfloat(dst
, src
, srcstep
, samples
);
326 static inline void SilenceSamples(ALfloat
*dst
, ALuint samples
)
329 for(i
= 0;i
< samples
;i
++)
334 static const ALfloat
*DoFilters(ALfilterState
*lpfilter
, ALfilterState
*hpfilter
,
335 ALfloat
*restrict dst
, const ALfloat
*restrict src
,
336 ALuint numsamples
, enum ActiveFilters type
)
342 ALfilterState_processPassthru(lpfilter
, src
, numsamples
);
343 ALfilterState_processPassthru(hpfilter
, src
, numsamples
);
347 ALfilterState_process(lpfilter
, dst
, src
, numsamples
);
348 ALfilterState_processPassthru(hpfilter
, dst
, numsamples
);
351 ALfilterState_processPassthru(lpfilter
, src
, numsamples
);
352 ALfilterState_process(hpfilter
, dst
, src
, numsamples
);
356 for(i
= 0;i
< numsamples
;)
359 ALuint todo
= minu(256, numsamples
-i
);
361 ALfilterState_process(lpfilter
, temp
, src
+i
, todo
);
362 ALfilterState_process(hpfilter
, dst
+i
, temp
, todo
);
371 ALvoid
MixSource(ALvoice
*voice
, ALsource
*Source
, ALCdevice
*Device
, ALuint SamplesToDo
)
373 ResamplerFunc Resample
;
374 ALbufferlistitem
*BufferListItem
;
375 ALuint DataPosInt
, DataPosFrac
;
386 /* Get source info */
387 State
= Source
->state
;
388 BufferListItem
= ATOMIC_LOAD(&Source
->current_buffer
);
389 DataPosInt
= Source
->position
;
390 DataPosFrac
= Source
->position_fraction
;
391 Looping
= Source
->Looping
;
392 NumChannels
= Source
->NumChannels
;
393 SampleSize
= Source
->SampleSize
;
394 increment
= voice
->Step
;
396 IrSize
= (Device
->Hrtf
? GetHrtfIrSize(Device
->Hrtf
) : 0);
398 Resample
= ((increment
== FRACTIONONE
&& DataPosFrac
== 0) ?
399 Resample_copy32_C
: ResampleSamples
);
403 ALuint SrcBufferSize
, DstBufferSize
;
414 Counter
= SamplesToDo
- OutPos
;
415 Delta
= 1.0f
/ (ALfloat
)Counter
;
418 /* Figure out how many buffer samples will be needed */
419 DataSize64
= SamplesToDo
-OutPos
;
420 DataSize64
*= increment
;
421 DataSize64
+= DataPosFrac
+FRACTIONMASK
;
422 DataSize64
>>= FRACTIONBITS
;
423 DataSize64
+= MAX_POST_SAMPLES
+MAX_PRE_SAMPLES
;
425 SrcBufferSize
= (ALuint
)mini64(DataSize64
, BUFFERSIZE
);
427 /* Figure out how many samples we can actually mix from this. */
428 DataSize64
= SrcBufferSize
;
429 DataSize64
-= MAX_POST_SAMPLES
+MAX_PRE_SAMPLES
;
430 DataSize64
<<= FRACTIONBITS
;
431 DataSize64
-= DataPosFrac
;
433 DstBufferSize
= (ALuint
)((DataSize64
+(increment
-1)) / increment
);
434 DstBufferSize
= minu(DstBufferSize
, (SamplesToDo
-OutPos
));
436 /* Some mixers like having a multiple of 4, so try to give that unless
437 * this is the last update. */
438 if(OutPos
+DstBufferSize
< SamplesToDo
)
441 for(chan
= 0;chan
< NumChannels
;chan
++)
443 const ALfloat
*ResampledData
;
444 ALfloat
*SrcData
= Device
->SourceData
;
447 /* Load the previous samples into the source data first. */
448 memcpy(SrcData
, voice
->PrevSamples
[chan
], MAX_PRE_SAMPLES
*sizeof(ALfloat
));
449 SrcDataSize
= MAX_PRE_SAMPLES
;
451 if(Source
->SourceType
== AL_STATIC
)
453 const ALbuffer
*ALBuffer
= BufferListItem
->buffer
;
454 const ALubyte
*Data
= ALBuffer
->data
;
458 /* Offset buffer data to current channel */
459 Data
+= chan
*SampleSize
;
461 /* If current pos is beyond the loop range, do not loop */
462 if(Looping
== AL_FALSE
|| DataPosInt
>= (ALuint
)ALBuffer
->LoopEnd
)
466 /* Load what's left to play from the source buffer, and
467 * clear the rest of the temp buffer */
469 DataSize
= minu(SrcBufferSize
- SrcDataSize
, ALBuffer
->SampleLen
- pos
);
471 LoadSamples(&SrcData
[SrcDataSize
], &Data
[pos
* NumChannels
*SampleSize
],
472 NumChannels
, ALBuffer
->FmtType
, DataSize
);
473 SrcDataSize
+= DataSize
;
475 SilenceSamples(&SrcData
[SrcDataSize
], SrcBufferSize
- SrcDataSize
);
476 SrcDataSize
+= SrcBufferSize
- SrcDataSize
;
480 ALuint LoopStart
= ALBuffer
->LoopStart
;
481 ALuint LoopEnd
= ALBuffer
->LoopEnd
;
483 /* Load what's left of this loop iteration, then load
484 * repeats of the loop section */
486 DataSize
= LoopEnd
- pos
;
487 DataSize
= minu(SrcBufferSize
- SrcDataSize
, DataSize
);
489 LoadSamples(&SrcData
[SrcDataSize
], &Data
[pos
* NumChannels
*SampleSize
],
490 NumChannels
, ALBuffer
->FmtType
, DataSize
);
491 SrcDataSize
+= DataSize
;
493 DataSize
= LoopEnd
-LoopStart
;
494 while(SrcBufferSize
> SrcDataSize
)
496 DataSize
= minu(SrcBufferSize
- SrcDataSize
, DataSize
);
498 LoadSamples(&SrcData
[SrcDataSize
], &Data
[LoopStart
* NumChannels
*SampleSize
],
499 NumChannels
, ALBuffer
->FmtType
, DataSize
);
500 SrcDataSize
+= DataSize
;
506 /* Crawl the buffer queue to fill in the temp buffer */
507 ALbufferlistitem
*tmpiter
= BufferListItem
;
508 ALuint pos
= DataPosInt
;
510 while(tmpiter
&& SrcBufferSize
> SrcDataSize
)
512 const ALbuffer
*ALBuffer
;
513 if((ALBuffer
=tmpiter
->buffer
) != NULL
)
515 const ALubyte
*Data
= ALBuffer
->data
;
516 ALuint DataSize
= ALBuffer
->SampleLen
;
518 /* Skip the data already played */
523 Data
+= (pos
*NumChannels
+ chan
)*SampleSize
;
527 DataSize
= minu(SrcBufferSize
- SrcDataSize
, DataSize
);
528 LoadSamples(&SrcData
[SrcDataSize
], Data
, NumChannels
,
529 ALBuffer
->FmtType
, DataSize
);
530 SrcDataSize
+= DataSize
;
533 tmpiter
= tmpiter
->next
;
534 if(!tmpiter
&& Looping
)
535 tmpiter
= ATOMIC_LOAD(&Source
->queue
);
538 SilenceSamples(&SrcData
[SrcDataSize
], SrcBufferSize
- SrcDataSize
);
539 SrcDataSize
+= SrcBufferSize
- SrcDataSize
;
544 /* Store the last source samples used for next time. */
545 memcpy(voice
->PrevSamples
[chan
],
546 &SrcData
[(increment
*DstBufferSize
+ DataPosFrac
)>>FRACTIONBITS
],
547 MAX_PRE_SAMPLES
*sizeof(ALfloat
)
550 /* Now resample, then filter and mix to the appropriate outputs. */
551 ResampledData
= Resample(&voice
->SincState
,
552 &SrcData
[MAX_PRE_SAMPLES
], DataPosFrac
, increment
,
553 Device
->ResampledData
, DstBufferSize
556 DirectParams
*parms
= &voice
->Direct
;
557 const ALfloat
*samples
;
560 &parms
->Filters
[chan
].LowPass
, &parms
->Filters
[chan
].HighPass
,
561 Device
->FilteredData
, ResampledData
, DstBufferSize
,
562 parms
->Filters
[chan
].ActiveType
566 ALfloat
*restrict currents
= parms
->Gains
[chan
].Current
;
567 const ALfloat
*targets
= parms
->Gains
[chan
].Target
;
568 MixGains gains
[MAX_OUTPUT_CHANNELS
];
572 for(j
= 0;j
< parms
->OutChannels
;j
++)
574 gains
[j
].Target
= targets
[j
];
575 gains
[j
].Current
= gains
[j
].Target
;
576 gains
[j
].Step
= 0.0f
;
581 for(j
= 0;j
< parms
->OutChannels
;j
++)
584 gains
[j
].Target
= targets
[j
];
585 gains
[j
].Current
= currents
[j
];
586 diff
= gains
[j
].Target
- gains
[j
].Current
;
587 if(fabsf(diff
) >= GAIN_SILENCE_THRESHOLD
)
588 gains
[j
].Step
= diff
* Delta
;
591 gains
[j
].Current
= gains
[j
].Target
;
592 gains
[j
].Step
= 0.0f
;
597 MixSamples(samples
, parms
->OutChannels
, parms
->OutBuffer
, gains
,
598 Counter
, OutPos
, DstBufferSize
);
600 for(j
= 0;j
< parms
->OutChannels
;j
++)
601 currents
[j
] = gains
[j
].Current
;
605 MixHrtfParams hrtfparams
;
608 parms
->Hrtf
[chan
].Current
= parms
->Hrtf
[chan
].Target
;
609 for(j
= 0;j
< HRIR_LENGTH
;j
++)
611 hrtfparams
.Steps
.Coeffs
[j
][0] = 0.0f
;
612 hrtfparams
.Steps
.Coeffs
[j
][1] = 0.0f
;
614 hrtfparams
.Steps
.Delay
[0] = 0;
615 hrtfparams
.Steps
.Delay
[1] = 0;
621 for(j
= 0;j
< IrSize
;j
++)
623 coeffdiff
= parms
->Hrtf
[chan
].Target
.Coeffs
[j
][0] - parms
->Hrtf
[chan
].Current
.Coeffs
[j
][0];
624 hrtfparams
.Steps
.Coeffs
[j
][0] = coeffdiff
* Delta
;
625 coeffdiff
= parms
->Hrtf
[chan
].Target
.Coeffs
[j
][1] - parms
->Hrtf
[chan
].Current
.Coeffs
[j
][1];
626 hrtfparams
.Steps
.Coeffs
[j
][1] = coeffdiff
* Delta
;
628 delaydiff
= (ALint
)(parms
->Hrtf
[chan
].Target
.Delay
[0] - parms
->Hrtf
[chan
].Current
.Delay
[0]);
629 hrtfparams
.Steps
.Delay
[0] = fastf2i((ALfloat
)delaydiff
* Delta
);
630 delaydiff
= (ALint
)(parms
->Hrtf
[chan
].Target
.Delay
[1] - parms
->Hrtf
[chan
].Current
.Delay
[1]);
631 hrtfparams
.Steps
.Delay
[1] = fastf2i((ALfloat
)delaydiff
* Delta
);
633 hrtfparams
.Target
= &parms
->Hrtf
[chan
].Target
;
634 hrtfparams
.Current
= &parms
->Hrtf
[chan
].Current
;
636 MixHrtfSamples(parms
->OutBuffer
, samples
, Counter
, voice
->Offset
,
637 OutPos
, IrSize
, &hrtfparams
, &parms
->Hrtf
[chan
].State
,
642 for(j
= 0;j
< Device
->NumAuxSends
;j
++)
644 SendParams
*parms
= &voice
->Send
[j
];
645 ALfloat
*restrict currents
= parms
->Gains
[chan
].Current
;
646 const ALfloat
*targets
= parms
->Gains
[chan
].Target
;
647 MixGains gains
[MAX_OUTPUT_CHANNELS
];
648 const ALfloat
*samples
;
650 if(!parms
->OutBuffer
)
654 &parms
->Filters
[chan
].LowPass
, &parms
->Filters
[chan
].HighPass
,
655 Device
->FilteredData
, ResampledData
, DstBufferSize
,
656 parms
->Filters
[chan
].ActiveType
661 for(j
= 0;j
< parms
->OutChannels
;j
++)
663 gains
[j
].Target
= targets
[j
];
664 gains
[j
].Current
= gains
[j
].Target
;
665 gains
[j
].Step
= 0.0f
;
670 for(j
= 0;j
< parms
->OutChannels
;j
++)
673 gains
[j
].Target
= targets
[j
];
674 gains
[j
].Current
= currents
[j
];
675 diff
= gains
[j
].Target
- gains
[j
].Current
;
676 if(fabsf(diff
) >= GAIN_SILENCE_THRESHOLD
)
677 gains
[j
].Step
= diff
* Delta
;
680 gains
[j
].Current
= gains
[j
].Target
;
681 gains
[j
].Step
= 0.0f
;
686 MixSamples(samples
, parms
->OutChannels
, parms
->OutBuffer
, gains
,
687 Counter
, OutPos
, DstBufferSize
);
689 for(j
= 0;j
< parms
->OutChannels
;j
++)
690 currents
[j
] = gains
[j
].Current
;
693 /* Update positions */
694 DataPosFrac
+= increment
*DstBufferSize
;
695 DataPosInt
+= DataPosFrac
>>FRACTIONBITS
;
696 DataPosFrac
&= FRACTIONMASK
;
698 OutPos
+= DstBufferSize
;
699 voice
->Offset
+= DstBufferSize
;
701 /* Handle looping sources */
704 const ALbuffer
*ALBuffer
;
706 ALuint LoopStart
= 0;
709 if((ALBuffer
=BufferListItem
->buffer
) != NULL
)
711 DataSize
= ALBuffer
->SampleLen
;
712 LoopStart
= ALBuffer
->LoopStart
;
713 LoopEnd
= ALBuffer
->LoopEnd
;
714 if(LoopEnd
> DataPosInt
)
718 if(Looping
&& Source
->SourceType
== AL_STATIC
)
720 assert(LoopEnd
> LoopStart
);
721 DataPosInt
= ((DataPosInt
-LoopStart
)%(LoopEnd
-LoopStart
)) + LoopStart
;
725 if(DataSize
> DataPosInt
)
728 if(!(BufferListItem
=BufferListItem
->next
))
731 BufferListItem
= ATOMIC_LOAD(&Source
->queue
);
735 BufferListItem
= NULL
;
742 DataPosInt
-= DataSize
;
744 } while(State
== AL_PLAYING
&& OutPos
< SamplesToDo
);
746 voice
->Moving
= AL_TRUE
;
748 /* Update source info */
749 Source
->state
= State
;
750 ATOMIC_STORE(&Source
->current_buffer
, BufferListItem
);
751 Source
->position
= DataPosInt
;
752 Source
->position_fraction
= DataPosFrac
;