Make MAX_RESAMPLER_PADDING specify the total padding
[openal-soft.git] / alc / mixvoice.cpp
blobb701a8263272bcf6ae5607fd06c06c7fc72cc3cf
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 <algorithm>
24 #include <array>
25 #include <atomic>
26 #include <cassert>
27 #include <climits>
28 #include <cstddef>
29 #include <cstdint>
30 #include <iterator>
31 #include <memory>
32 #include <new>
33 #include <string>
34 #include <utility>
36 #include "AL/al.h"
37 #include "AL/alc.h"
39 #include "al/buffer.h"
40 #include "al/event.h"
41 #include "al/source.h"
42 #include "alcmain.h"
43 #include "albyte.h"
44 #include "alconfig.h"
45 #include "alcontext.h"
46 #include "alnumeric.h"
47 #include "aloptional.h"
48 #include "alspan.h"
49 #include "alstring.h"
50 #include "alu.h"
51 #include "cpu_caps.h"
52 #include "devformat.h"
53 #include "filters/biquad.h"
54 #include "filters/nfc.h"
55 #include "filters/splitter.h"
56 #include "hrtf.h"
57 #include "inprogext.h"
58 #include "logging.h"
59 #include "mixer/defs.h"
60 #include "opthelpers.h"
61 #include "ringbuffer.h"
62 #include "threads.h"
63 #include "vector.h"
66 static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
67 "MAX_PITCH and/or BUFFERSIZE are too large for FRACTIONBITS!");
69 /* BSinc24 requires up to 23 extra samples before the current position, and 24 after. */
70 static_assert(!(MAX_RESAMPLER_PADDING&1) && MAX_RESAMPLER_PADDING >= 48,
71 "MAX_RESAMPLER_PADDING must be a multiple of two and at least 48!");
74 Resampler ResamplerDefault{Resampler::Linear};
76 MixerFunc MixSamples = Mix_<CTag>;
77 RowMixerFunc MixRowSamples = MixRow_<CTag>;
79 namespace {
81 HrtfMixerFunc MixHrtfSamples = MixHrtf_<CTag>;
82 HrtfMixerBlendFunc MixHrtfBlendSamples = MixHrtfBlend_<CTag>;
84 inline MixerFunc SelectMixer()
86 #ifdef HAVE_NEON
87 if((CPUCapFlags&CPU_CAP_NEON))
88 return Mix_<NEONTag>;
89 #endif
90 #ifdef HAVE_SSE
91 if((CPUCapFlags&CPU_CAP_SSE))
92 return Mix_<SSETag>;
93 #endif
94 return Mix_<CTag>;
97 inline RowMixerFunc SelectRowMixer()
99 #ifdef HAVE_NEON
100 if((CPUCapFlags&CPU_CAP_NEON))
101 return MixRow_<NEONTag>;
102 #endif
103 #ifdef HAVE_SSE
104 if((CPUCapFlags&CPU_CAP_SSE))
105 return MixRow_<SSETag>;
106 #endif
107 return MixRow_<CTag>;
110 inline HrtfMixerFunc SelectHrtfMixer()
112 #ifdef HAVE_NEON
113 if((CPUCapFlags&CPU_CAP_NEON))
114 return MixHrtf_<NEONTag>;
115 #endif
116 #ifdef HAVE_SSE
117 if((CPUCapFlags&CPU_CAP_SSE))
118 return MixHrtf_<SSETag>;
119 #endif
120 return MixHrtf_<CTag>;
123 inline HrtfMixerBlendFunc SelectHrtfBlendMixer()
125 #ifdef HAVE_NEON
126 if((CPUCapFlags&CPU_CAP_NEON))
127 return MixHrtfBlend_<NEONTag>;
128 #endif
129 #ifdef HAVE_SSE
130 if((CPUCapFlags&CPU_CAP_SSE))
131 return MixHrtfBlend_<SSETag>;
132 #endif
133 return MixHrtfBlend_<CTag>;
136 } // namespace
139 void aluInitMixer()
141 if(auto resopt = ConfigValueStr(nullptr, nullptr, "resampler"))
143 struct ResamplerEntry {
144 const char name[16];
145 const Resampler resampler;
147 constexpr ResamplerEntry ResamplerList[]{
148 { "none", Resampler::Point },
149 { "point", Resampler::Point },
150 { "cubic", Resampler::Cubic },
151 { "bsinc12", Resampler::BSinc12 },
152 { "fast_bsinc12", Resampler::FastBSinc12 },
153 { "bsinc24", Resampler::BSinc24 },
154 { "fast_bsinc24", Resampler::FastBSinc24 },
157 const char *str{resopt->c_str()};
158 if(al::strcasecmp(str, "bsinc") == 0)
160 WARN("Resampler option \"%s\" is deprecated, using bsinc12\n", str);
161 str = "bsinc12";
163 else if(al::strcasecmp(str, "sinc4") == 0 || al::strcasecmp(str, "sinc8") == 0)
165 WARN("Resampler option \"%s\" is deprecated, using cubic\n", str);
166 str = "cubic";
169 auto iter = std::find_if(std::begin(ResamplerList), std::end(ResamplerList),
170 [str](const ResamplerEntry &entry) -> bool
171 { return al::strcasecmp(str, entry.name) == 0; });
172 if(iter == std::end(ResamplerList))
173 ERR("Invalid resampler: %s\n", str);
174 else
175 ResamplerDefault = iter->resampler;
178 MixHrtfBlendSamples = SelectHrtfBlendMixer();
179 MixHrtfSamples = SelectHrtfMixer();
180 MixSamples = SelectMixer();
181 MixRowSamples = SelectRowMixer();
185 namespace {
187 /* A quick'n'dirty lookup table to decode a muLaw-encoded byte sample into a
188 * signed 16-bit sample */
189 constexpr ALshort muLawDecompressionTable[256] = {
190 -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
191 -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
192 -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
193 -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
194 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
195 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
196 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
197 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
198 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
199 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
200 -876, -844, -812, -780, -748, -716, -684, -652,
201 -620, -588, -556, -524, -492, -460, -428, -396,
202 -372, -356, -340, -324, -308, -292, -276, -260,
203 -244, -228, -212, -196, -180, -164, -148, -132,
204 -120, -112, -104, -96, -88, -80, -72, -64,
205 -56, -48, -40, -32, -24, -16, -8, 0,
206 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
207 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
208 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
209 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
210 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
211 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
212 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
213 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
214 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
215 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
216 876, 844, 812, 780, 748, 716, 684, 652,
217 620, 588, 556, 524, 492, 460, 428, 396,
218 372, 356, 340, 324, 308, 292, 276, 260,
219 244, 228, 212, 196, 180, 164, 148, 132,
220 120, 112, 104, 96, 88, 80, 72, 64,
221 56, 48, 40, 32, 24, 16, 8, 0
224 /* A quick'n'dirty lookup table to decode an aLaw-encoded byte sample into a
225 * signed 16-bit sample */
226 constexpr ALshort aLawDecompressionTable[256] = {
227 -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
228 -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
229 -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
230 -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
231 -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944,
232 -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136,
233 -11008,-10496,-12032,-11520, -8960, -8448, -9984, -9472,
234 -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568,
235 -344, -328, -376, -360, -280, -264, -312, -296,
236 -472, -456, -504, -488, -408, -392, -440, -424,
237 -88, -72, -120, -104, -24, -8, -56, -40,
238 -216, -200, -248, -232, -152, -136, -184, -168,
239 -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
240 -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
241 -688, -656, -752, -720, -560, -528, -624, -592,
242 -944, -912, -1008, -976, -816, -784, -880, -848,
243 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
244 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
245 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
246 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
247 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
248 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
249 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
250 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
251 344, 328, 376, 360, 280, 264, 312, 296,
252 472, 456, 504, 488, 408, 392, 440, 424,
253 88, 72, 120, 104, 24, 8, 56, 40,
254 216, 200, 248, 232, 152, 136, 184, 168,
255 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
256 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
257 688, 656, 752, 720, 560, 528, 624, 592,
258 944, 912, 1008, 976, 816, 784, 880, 848
261 template<FmtType T>
262 struct FmtTypeTraits { };
264 template<>
265 struct FmtTypeTraits<FmtUByte> {
266 using Type = ALubyte;
267 static constexpr inline float to_float(const Type val) noexcept
268 { return val*(1.0f/128.0f) - 1.0f; }
270 template<>
271 struct FmtTypeTraits<FmtShort> {
272 using Type = ALshort;
273 static constexpr inline float to_float(const Type val) noexcept { return val*(1.0f/32768.0f); }
275 template<>
276 struct FmtTypeTraits<FmtFloat> {
277 using Type = ALfloat;
278 static constexpr inline float to_float(const Type val) noexcept { return val; }
280 template<>
281 struct FmtTypeTraits<FmtDouble> {
282 using Type = ALdouble;
283 static constexpr inline float to_float(const Type val) noexcept
284 { return static_cast<ALfloat>(val); }
286 template<>
287 struct FmtTypeTraits<FmtMulaw> {
288 using Type = ALubyte;
289 static constexpr inline float to_float(const Type val) noexcept
290 { return muLawDecompressionTable[val] * (1.0f/32768.0f); }
292 template<>
293 struct FmtTypeTraits<FmtAlaw> {
294 using Type = ALubyte;
295 static constexpr inline float to_float(const Type val) noexcept
296 { return aLawDecompressionTable[val] * (1.0f/32768.0f); }
300 void SendSourceStoppedEvent(ALCcontext *context, ALuint id)
302 RingBuffer *ring{context->mAsyncEvents.get()};
303 auto evt_vec = ring->getWriteVector();
304 if(evt_vec.first.len < 1) return;
306 AsyncEvent *evt{new (evt_vec.first.buf) AsyncEvent{EventType_SourceStateChange}};
307 evt->u.srcstate.id = id;
308 evt->u.srcstate.state = AL_STOPPED;
310 ring->writeAdvance(1);
311 context->mEventSem.post();
315 const ALfloat *DoFilters(BiquadFilter *lpfilter, BiquadFilter *hpfilter, ALfloat *dst,
316 const ALfloat *src, const size_t numsamples, int type)
318 switch(type)
320 case AF_None:
321 lpfilter->clear();
322 hpfilter->clear();
323 break;
325 case AF_LowPass:
326 lpfilter->process(dst, src, numsamples);
327 hpfilter->clear();
328 return dst;
329 case AF_HighPass:
330 lpfilter->clear();
331 hpfilter->process(dst, src, numsamples);
332 return dst;
334 case AF_BandPass:
335 lpfilter->process(dst, src, numsamples);
336 hpfilter->process(dst, dst, numsamples);
337 return dst;
339 return src;
343 template<FmtType T>
344 inline void LoadSampleArray(ALfloat *RESTRICT dst, const al::byte *src, const size_t srcstep,
345 const size_t samples) noexcept
347 using SampleType = typename FmtTypeTraits<T>::Type;
349 const SampleType *RESTRICT ssrc{reinterpret_cast<const SampleType*>(src)};
350 for(size_t i{0u};i < samples;i++)
351 dst[i] = FmtTypeTraits<T>::to_float(ssrc[i*srcstep]);
354 void LoadSamples(ALfloat *RESTRICT dst, const al::byte *src, const size_t srcstep, FmtType srctype,
355 const size_t samples) noexcept
357 #define HANDLE_FMT(T) case T: LoadSampleArray<T>(dst, src, srcstep, samples); break
358 switch(srctype)
360 HANDLE_FMT(FmtUByte);
361 HANDLE_FMT(FmtShort);
362 HANDLE_FMT(FmtFloat);
363 HANDLE_FMT(FmtDouble);
364 HANDLE_FMT(FmtMulaw);
365 HANDLE_FMT(FmtAlaw);
367 #undef HANDLE_FMT
370 ALfloat *LoadBufferStatic(ALbufferlistitem *BufferListItem, ALbufferlistitem *&BufferLoopItem,
371 const size_t NumChannels, const size_t SampleSize, const size_t chan, size_t DataPosInt,
372 al::span<ALfloat> SrcBuffer)
374 const ALbuffer *Buffer{BufferListItem->mBuffer};
375 const ALuint LoopStart{Buffer->LoopStart};
376 const ALuint LoopEnd{Buffer->LoopEnd};
377 ASSUME(LoopEnd > LoopStart);
379 /* If current pos is beyond the loop range, do not loop */
380 if(!BufferLoopItem || DataPosInt >= LoopEnd)
382 BufferLoopItem = nullptr;
384 /* Load what's left to play from the buffer */
385 const size_t DataRem{minz(SrcBuffer.size(), Buffer->SampleLen-DataPosInt)};
387 const al::byte *Data{Buffer->mData.data()};
388 Data += (DataPosInt*NumChannels + chan)*SampleSize;
390 LoadSamples(SrcBuffer.data(), Data, NumChannels, Buffer->mFmtType, DataRem);
391 SrcBuffer = SrcBuffer.subspan(DataRem);
393 else
395 /* Load what's left of this loop iteration */
396 const size_t DataRem{minz(SrcBuffer.size(), LoopEnd-DataPosInt)};
398 const al::byte *Data{Buffer->mData.data()};
399 Data += (DataPosInt*NumChannels + chan)*SampleSize;
401 LoadSamples(SrcBuffer.data(), Data, NumChannels, Buffer->mFmtType, DataRem);
402 SrcBuffer = SrcBuffer.subspan(DataRem);
404 /* Load any repeats of the loop we can to fill the buffer. */
405 const auto LoopSize = static_cast<size_t>(LoopEnd - LoopStart);
406 while(!SrcBuffer.empty())
408 const size_t DataSize{minz(SrcBuffer.size(), LoopSize)};
410 Data = Buffer->mData.data() + (LoopStart*NumChannels + chan)*SampleSize;
412 LoadSamples(SrcBuffer.data(), Data, NumChannels, Buffer->mFmtType, DataSize);
413 SrcBuffer = SrcBuffer.subspan(DataSize);
416 return SrcBuffer.begin();
419 ALfloat *LoadBufferQueue(ALbufferlistitem *BufferListItem, ALbufferlistitem *BufferLoopItem,
420 const size_t NumChannels, const size_t SampleSize, const size_t chan, size_t DataPosInt,
421 al::span<ALfloat> SrcBuffer)
423 /* Crawl the buffer queue to fill in the temp buffer */
424 while(BufferListItem && !SrcBuffer.empty())
426 ALbuffer *Buffer{BufferListItem->mBuffer};
427 if(!(Buffer && DataPosInt < Buffer->SampleLen))
429 if(Buffer) DataPosInt -= Buffer->SampleLen;
430 BufferListItem = BufferListItem->mNext.load(std::memory_order_acquire);
431 if(!BufferListItem) BufferListItem = BufferLoopItem;
432 continue;
435 const size_t DataSize{minz(SrcBuffer.size(), Buffer->SampleLen-DataPosInt)};
437 const al::byte *Data{Buffer->mData.data()};
438 Data += (DataPosInt*NumChannels + chan)*SampleSize;
440 LoadSamples(SrcBuffer.data(), Data, NumChannels, Buffer->mFmtType, DataSize);
441 SrcBuffer = SrcBuffer.subspan(DataSize);
442 if(SrcBuffer.empty()) break;
444 DataPosInt = 0;
445 BufferListItem = BufferListItem->mNext.load(std::memory_order_acquire);
446 if(!BufferListItem) BufferListItem = BufferLoopItem;
449 return SrcBuffer.begin();
453 void DoHrtfMix(ALvoice::DirectData &Direct, const float TargetGain, DirectParams &parms,
454 const float *samples, const ALuint DstBufferSize, const ALuint Counter, const ALuint OutPos,
455 const ALuint IrSize, ALCdevice *Device)
457 const ALuint OutLIdx{GetChannelIdxByName(Device->RealOut, FrontLeft)};
458 const ALuint OutRIdx{GetChannelIdxByName(Device->RealOut, FrontRight)};
459 auto &HrtfSamples = Device->HrtfSourceData;
460 auto &AccumSamples = Device->HrtfAccumData;
462 /* Copy the HRTF history and new input samples into a temp buffer. */
463 auto src_iter = std::copy(parms.Hrtf.State.History.begin(), parms.Hrtf.State.History.end(),
464 std::begin(HrtfSamples));
465 std::copy_n(samples, DstBufferSize, src_iter);
466 /* Copy the last used samples back into the history buffer for later. */
467 std::copy_n(std::begin(HrtfSamples) + DstBufferSize, parms.Hrtf.State.History.size(),
468 parms.Hrtf.State.History.begin());
470 /* Copy the current filtered values being accumulated into the temp buffer. */
471 auto accum_iter = std::copy_n(parms.Hrtf.State.Values.begin(), parms.Hrtf.State.Values.size(),
472 std::begin(AccumSamples));
473 /* Clear the accumulation buffer that will start getting filled in. */
474 std::fill_n(accum_iter, DstBufferSize, float2{});
476 /* If fading, the old gain is not silence, and this is the first mixing
477 * pass, fade between the IRs.
479 ALuint fademix{0u};
480 if(Counter && parms.Hrtf.Old.Gain > GAIN_SILENCE_THRESHOLD && OutPos == 0)
482 fademix = minu(DstBufferSize, 128);
484 float gain{TargetGain};
486 /* The new coefficients need to fade in completely since they're
487 * replacing the old ones. To keep the gain fading consistent,
488 * interpolate between the old and new target gains given how much of
489 * the fade time this mix handles.
491 if LIKELY(Counter > fademix)
493 const ALfloat a{static_cast<float>(fademix) / static_cast<float>(Counter)};
494 gain = lerp(parms.Hrtf.Old.Gain, TargetGain, a);
496 MixHrtfFilter hrtfparams;
497 hrtfparams.Coeffs = &parms.Hrtf.Target.Coeffs;
498 hrtfparams.Delay[0] = parms.Hrtf.Target.Delay[0];
499 hrtfparams.Delay[1] = parms.Hrtf.Target.Delay[1];
500 hrtfparams.Gain = 0.0f;
501 hrtfparams.GainStep = gain / static_cast<float>(fademix);
503 MixHrtfBlendSamples(Direct.Buffer[OutLIdx], Direct.Buffer[OutRIdx], HrtfSamples,
504 AccumSamples, OutPos, IrSize, &parms.Hrtf.Old, &hrtfparams, fademix);
505 /* Update the old parameters with the result. */
506 parms.Hrtf.Old = parms.Hrtf.Target;
507 if(fademix < Counter)
508 parms.Hrtf.Old.Gain = hrtfparams.Gain;
509 else
510 parms.Hrtf.Old.Gain = TargetGain;
513 if LIKELY(fademix < DstBufferSize)
515 const ALuint todo{DstBufferSize - fademix};
516 float gain{TargetGain};
518 /* Interpolate the target gain if the gain fading lasts longer than
519 * this mix.
521 if(Counter > DstBufferSize)
523 const float a{static_cast<float>(todo) / static_cast<float>(Counter-fademix)};
524 gain = lerp(parms.Hrtf.Old.Gain, TargetGain, a);
527 MixHrtfFilter hrtfparams;
528 hrtfparams.Coeffs = &parms.Hrtf.Target.Coeffs;
529 hrtfparams.Delay[0] = parms.Hrtf.Target.Delay[0];
530 hrtfparams.Delay[1] = parms.Hrtf.Target.Delay[1];
531 hrtfparams.Gain = parms.Hrtf.Old.Gain;
532 hrtfparams.GainStep = (gain - parms.Hrtf.Old.Gain) / static_cast<float>(todo);
533 MixHrtfSamples(Direct.Buffer[OutLIdx], Direct.Buffer[OutRIdx], HrtfSamples+fademix,
534 AccumSamples+fademix, OutPos+fademix, IrSize, &hrtfparams, todo);
535 /* Store the interpolated gain or the final target gain depending if
536 * the fade is done.
538 if(DstBufferSize < Counter)
539 parms.Hrtf.Old.Gain = gain;
540 else
541 parms.Hrtf.Old.Gain = TargetGain;
544 /* Copy the new in-progress accumulation values back for the next mix. */
545 std::copy_n(std::begin(AccumSamples) + DstBufferSize, parms.Hrtf.State.Values.size(),
546 parms.Hrtf.State.Values.begin());
549 void DoNfcMix(ALvoice::DirectData &Direct, const float *TargetGains, DirectParams &parms,
550 const float *samples, const ALuint DstBufferSize, const ALuint Counter, const ALuint OutPos,
551 ALCdevice *Device)
553 const size_t outcount{Device->NumChannelsPerOrder[0]};
554 MixSamples({samples, DstBufferSize}, Direct.Buffer.first(outcount),
555 parms.Gains.Current, TargetGains, Counter, OutPos);
557 const al::span<float> nfcsamples{Device->NfcSampleData, DstBufferSize};
558 size_t chanoffset{outcount};
559 using FilterProc = void (NfcFilter::*)(float*,const float*,const size_t);
560 auto apply_nfc = [&Direct,&parms,samples,TargetGains,Counter,OutPos,&chanoffset,nfcsamples](
561 const FilterProc process, const size_t chancount) -> void
563 if(chancount < 1) return;
564 (parms.NFCtrlFilter.*process)(nfcsamples.data(), samples, nfcsamples.size());
565 MixSamples(nfcsamples, Direct.Buffer.subspan(chanoffset, chancount),
566 parms.Gains.Current+chanoffset, TargetGains+chanoffset, Counter, OutPos);
567 chanoffset += chancount;
569 apply_nfc(&NfcFilter::process1, Device->NumChannelsPerOrder[1]);
570 apply_nfc(&NfcFilter::process2, Device->NumChannelsPerOrder[2]);
571 apply_nfc(&NfcFilter::process3, Device->NumChannelsPerOrder[3]);
574 } // namespace
576 void ALvoice::mix(State vstate, ALCcontext *Context, const ALuint SamplesToDo)
578 static constexpr ALfloat SilentTarget[MAX_OUTPUT_CHANNELS]{};
580 ASSUME(SamplesToDo > 0);
582 /* Get voice info */
583 const bool isstatic{(mFlags&VOICE_IS_STATIC) != 0};
584 ALuint DataPosInt{mPosition.load(std::memory_order_relaxed)};
585 ALuint DataPosFrac{mPositionFrac.load(std::memory_order_relaxed)};
586 ALbufferlistitem *BufferListItem{mCurrentBuffer.load(std::memory_order_relaxed)};
587 ALbufferlistitem *BufferLoopItem{mLoopBuffer.load(std::memory_order_relaxed)};
588 const ALuint NumChannels{mNumChannels};
589 const ALuint SampleSize{mSampleSize};
590 const ALuint increment{mStep};
591 if(increment < 1) return;
593 ASSUME(NumChannels > 0);
594 ASSUME(SampleSize > 0);
595 ASSUME(increment > 0);
597 ALCdevice *Device{Context->mDevice.get()};
598 const ALuint NumSends{Device->NumAuxSends};
599 const ALuint IrSize{Device->mHrtf ? Device->mHrtf->irSize : 0};
601 ResamplerFunc Resample{(increment == FRACTIONONE && DataPosFrac == 0) ?
602 Resample_<CopyTag,CTag> : mResampler};
604 ALuint Counter{(mFlags&VOICE_IS_FADING) ? SamplesToDo : 0};
605 if(!Counter)
607 /* No fading, just overwrite the old/current params. */
608 for(ALuint chan{0};chan < NumChannels;chan++)
610 ChannelData &chandata = mChans[chan];
612 DirectParams &parms = chandata.mDryParams;
613 if(!(mFlags&VOICE_HAS_HRTF))
614 std::copy(std::begin(parms.Gains.Target), std::end(parms.Gains.Target),
615 std::begin(parms.Gains.Current));
616 else
617 parms.Hrtf.Old = parms.Hrtf.Target;
619 for(ALuint send{0};send < NumSends;++send)
621 if(mSend[send].Buffer.empty())
622 continue;
624 SendParams &parms = chandata.mWetParams[send];
625 std::copy(std::begin(parms.Gains.Target), std::end(parms.Gains.Target),
626 std::begin(parms.Gains.Current));
630 else if((mFlags&VOICE_HAS_HRTF))
632 for(ALuint chan{0};chan < NumChannels;chan++)
634 DirectParams &parms = mChans[chan].mDryParams;
635 if(!(parms.Hrtf.Old.Gain > GAIN_SILENCE_THRESHOLD))
637 /* The old HRTF params are silent, so overwrite the old
638 * coefficients with the new, and reset the old gain to 0. The
639 * future mix will then fade from silence.
641 parms.Hrtf.Old = parms.Hrtf.Target;
642 parms.Hrtf.Old.Gain = 0.0f;
647 ALuint buffers_done{0u};
648 ALuint OutPos{0u};
649 do {
650 /* Figure out how many buffer samples will be needed */
651 ALuint DstBufferSize{SamplesToDo - OutPos};
653 /* Calculate the last written dst sample pos. */
654 uint64_t DataSize64{DstBufferSize - 1};
655 /* Calculate the last read src sample pos. */
656 DataSize64 = (DataSize64*increment + DataPosFrac) >> FRACTIONBITS;
657 /* +1 to get the src sample count, include padding. */
658 DataSize64 += 1 + MAX_RESAMPLER_PADDING;
660 auto SrcBufferSize = static_cast<ALuint>(
661 minu64(DataSize64, BUFFERSIZE + MAX_RESAMPLER_PADDING + 1));
662 if(SrcBufferSize > BUFFERSIZE + MAX_RESAMPLER_PADDING)
664 SrcBufferSize = BUFFERSIZE + MAX_RESAMPLER_PADDING;
665 /* If the source buffer got saturated, we can't fill the desired
666 * dst size. Figure out how many samples we can actually mix from
667 * this.
669 DataSize64 = SrcBufferSize - MAX_RESAMPLER_PADDING;
670 DataSize64 = ((DataSize64<<FRACTIONBITS) - DataPosFrac + increment-1) / increment;
671 DstBufferSize = static_cast<ALuint>(minu64(DataSize64, DstBufferSize));
673 /* Some mixers like having a multiple of 4, so try to give that
674 * unless this is the last update.
676 if(DstBufferSize < SamplesToDo-OutPos)
677 DstBufferSize &= ~3u;
680 ASSUME(DstBufferSize > 0);
681 for(ALuint chan{0};chan < NumChannels;chan++)
683 ChannelData &chandata = mChans[chan];
684 const al::span<ALfloat> SrcData{Device->SourceData, SrcBufferSize};
686 /* Load the previous samples into the source data first, then load
687 * what we can from the buffer queue.
689 auto srciter = std::copy_n(chandata.mPrevSamples.begin(), MAX_RESAMPLER_PADDING>>1,
690 SrcData.begin());
692 if UNLIKELY(!BufferListItem)
693 srciter = std::copy(chandata.mPrevSamples.begin()+(MAX_RESAMPLER_PADDING>>1),
694 chandata.mPrevSamples.end(), srciter);
695 else if(isstatic)
696 srciter = LoadBufferStatic(BufferListItem, BufferLoopItem, NumChannels,
697 SampleSize, chan, DataPosInt, {srciter, SrcData.end()});
698 else
699 srciter = LoadBufferQueue(BufferListItem, BufferLoopItem, NumChannels,
700 SampleSize, chan, DataPosInt, {srciter, SrcData.end()});
702 if UNLIKELY(srciter != SrcData.end())
704 /* If the source buffer wasn't filled, copy the last sample for
705 * the remaining buffer. Ideally it should have ended with
706 * silence, but if not the gain fading should help avoid clicks
707 * from sudden amplitude changes.
709 const ALfloat sample{*(srciter-1)};
710 std::fill(srciter, SrcData.end(), sample);
713 /* Store the last source samples used for next time. */
714 std::copy_n(&SrcData[(increment*DstBufferSize + DataPosFrac)>>FRACTIONBITS],
715 chandata.mPrevSamples.size(), chandata.mPrevSamples.begin());
717 /* Resample, then apply ambisonic upsampling as needed. */
718 const ALfloat *ResampledData{Resample(&mResampleState,
719 &SrcData[MAX_RESAMPLER_PADDING>>1], DataPosFrac, increment,
720 {Device->ResampledData, DstBufferSize})};
721 if((mFlags&VOICE_IS_AMBISONIC))
723 const ALfloat hfscale{chandata.mAmbiScale};
724 /* Beware the evil const_cast. It's safe since it's pointing to
725 * either SourceData or ResampledData (both non-const), but the
726 * resample method takes the source as const float* and may
727 * return it without copying to output, making it currently
728 * unavoidable.
730 chandata.mAmbiSplitter.applyHfScale(const_cast<ALfloat*>(ResampledData), hfscale,
731 DstBufferSize);
734 /* Now filter and mix to the appropriate outputs. */
735 ALfloat (&FilterBuf)[BUFFERSIZE] = Device->FilteredData;
737 DirectParams &parms = chandata.mDryParams;
738 const ALfloat *samples{DoFilters(&parms.LowPass, &parms.HighPass, FilterBuf,
739 ResampledData, DstBufferSize, mDirect.FilterType)};
741 if((mFlags&VOICE_HAS_HRTF))
743 const ALfloat TargetGain{UNLIKELY(vstate == ALvoice::Stopping) ? 0.0f :
744 parms.Hrtf.Target.Gain};
745 DoHrtfMix(mDirect, TargetGain, parms, samples, DstBufferSize, Counter, OutPos,
746 IrSize, Device);
748 else if((mFlags&VOICE_HAS_NFC))
750 const ALfloat *TargetGains{UNLIKELY(vstate == ALvoice::Stopping) ?
751 SilentTarget : parms.Gains.Target};
752 DoNfcMix(mDirect, TargetGains, parms, samples, DstBufferSize, Counter, OutPos,
753 Device);
755 else
757 const ALfloat *TargetGains{UNLIKELY(vstate == ALvoice::Stopping) ?
758 SilentTarget : parms.Gains.Target};
759 MixSamples({samples, DstBufferSize}, mDirect.Buffer, parms.Gains.Current,
760 TargetGains, Counter, OutPos);
764 for(ALuint send{0};send < NumSends;++send)
766 if(mSend[send].Buffer.empty())
767 continue;
769 SendParams &parms = chandata.mWetParams[send];
770 const ALfloat *samples{DoFilters(&parms.LowPass, &parms.HighPass, FilterBuf,
771 ResampledData, DstBufferSize, mSend[send].FilterType)};
773 const ALfloat *TargetGains{UNLIKELY(vstate==ALvoice::Stopping) ? SilentTarget :
774 parms.Gains.Target};
775 MixSamples({samples, DstBufferSize}, mSend[send].Buffer, parms.Gains.Current,
776 TargetGains, Counter, OutPos);
779 /* Update positions */
780 DataPosFrac += increment*DstBufferSize;
781 DataPosInt += DataPosFrac>>FRACTIONBITS;
782 DataPosFrac &= FRACTIONMASK;
784 OutPos += DstBufferSize;
785 Counter = maxu(DstBufferSize, Counter) - DstBufferSize;
787 if UNLIKELY(!BufferListItem)
789 /* Do nothing extra when there's no buffers. */
791 else if(isstatic)
793 if(BufferLoopItem)
795 /* Handle looping static source */
796 const ALbuffer *Buffer{BufferListItem->mBuffer};
797 const ALuint LoopStart{Buffer->LoopStart};
798 const ALuint LoopEnd{Buffer->LoopEnd};
799 if(DataPosInt >= LoopEnd)
801 assert(LoopEnd > LoopStart);
802 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
805 else
807 /* Handle non-looping static source */
808 if(DataPosInt >= BufferListItem->mSampleLen)
810 if LIKELY(vstate == ALvoice::Playing)
811 vstate = ALvoice::Stopped;
812 BufferListItem = nullptr;
813 break;
817 else while(1)
819 /* Handle streaming source */
820 if(BufferListItem->mSampleLen > DataPosInt)
821 break;
823 DataPosInt -= BufferListItem->mSampleLen;
825 ++buffers_done;
826 BufferListItem = BufferListItem->mNext.load(std::memory_order_relaxed);
827 if(!BufferListItem && !(BufferListItem=BufferLoopItem))
829 if LIKELY(vstate == ALvoice::Playing)
830 vstate = ALvoice::Stopped;
831 break;
834 } while(OutPos < SamplesToDo);
836 mFlags |= VOICE_IS_FADING;
838 /* Don't update positions and buffers if we were stopping. */
839 if UNLIKELY(vstate == ALvoice::Stopping)
841 mPlayState.store(ALvoice::Stopped, std::memory_order_release);
842 return;
845 /* Capture the source ID in case it's reset for stopping. */
846 const ALuint SourceID{mSourceID.load(std::memory_order_relaxed)};
848 /* Update voice info */
849 mPosition.store(DataPosInt, std::memory_order_relaxed);
850 mPositionFrac.store(DataPosFrac, std::memory_order_relaxed);
851 mCurrentBuffer.store(BufferListItem, std::memory_order_relaxed);
852 if(vstate == ALvoice::Stopped)
854 mLoopBuffer.store(nullptr, std::memory_order_relaxed);
855 mSourceID.store(0u, std::memory_order_relaxed);
857 std::atomic_thread_fence(std::memory_order_release);
859 /* Send any events now, after the position/buffer info was updated. */
860 const ALbitfieldSOFT enabledevt{Context->mEnabledEvts.load(std::memory_order_acquire)};
861 if(buffers_done > 0 && (enabledevt&EventType_BufferCompleted))
863 RingBuffer *ring{Context->mAsyncEvents.get()};
864 auto evt_vec = ring->getWriteVector();
865 if(evt_vec.first.len > 0)
867 AsyncEvent *evt{new (evt_vec.first.buf) AsyncEvent{EventType_BufferCompleted}};
868 evt->u.bufcomp.id = SourceID;
869 evt->u.bufcomp.count = buffers_done;
870 ring->writeAdvance(1);
871 Context->mEventSem.post();
875 if(vstate == ALvoice::Stopped)
877 /* If the voice just ended, set it to Stopping so the next render
878 * ensures any residual noise fades to 0 amplitude.
880 mPlayState.store(ALvoice::Stopping, std::memory_order_release);
881 if((enabledevt&EventType_SourceStateChange))
882 SendSourceStoppedEvent(Context, SourceID);