Pass IrSize to the HRTF mixers as unsigned
[openal-soft.git] / alc / mixvoice.cpp
blob7bdeea5e12deeb6c4beadcbc2b5ca367c73aee91
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 <cstring>
31 #include <iterator>
32 #include <memory>
33 #include <new>
34 #include <numeric>
35 #include <string>
36 #include <utility>
38 #include "AL/al.h"
39 #include "AL/alc.h"
41 #include "al/buffer.h"
42 #include "al/event.h"
43 #include "al/source.h"
44 #include "alcmain.h"
45 #include "albyte.h"
46 #include "alconfig.h"
47 #include "alcontext.h"
48 #include "alnumeric.h"
49 #include "aloptional.h"
50 #include "alspan.h"
51 #include "alu.h"
52 #include "cpu_caps.h"
53 #include "devformat.h"
54 #include "filters/biquad.h"
55 #include "filters/nfc.h"
56 #include "filters/splitter.h"
57 #include "hrtf.h"
58 #include "inprogext.h"
59 #include "logging.h"
60 #include "mixer/defs.h"
61 #include "opthelpers.h"
62 #include "ringbuffer.h"
63 #include "threads.h"
64 #include "vector.h"
67 static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
68 "MAX_PITCH and/or BUFFERSIZE are too large for FRACTIONBITS!");
70 /* BSinc24 requires up to 23 extra samples before the current position, and 24 after. */
71 static_assert(MAX_RESAMPLE_PADDING >= 24, "MAX_RESAMPLE_PADDING must be at least 24!");
74 Resampler ResamplerDefault = LinearResampler;
76 MixerFunc MixSamples = Mix_<CTag>;
77 RowMixerFunc MixRowSamples = MixRow_<CTag>;
78 static HrtfMixerFunc MixHrtfSamples = MixHrtf_<CTag>;
79 static HrtfMixerBlendFunc MixHrtfBlendSamples = MixHrtfBlend_<CTag>;
81 static MixerFunc SelectMixer()
83 #ifdef HAVE_NEON
84 if((CPUCapFlags&CPU_CAP_NEON))
85 return Mix_<NEONTag>;
86 #endif
87 #ifdef HAVE_SSE
88 if((CPUCapFlags&CPU_CAP_SSE))
89 return Mix_<SSETag>;
90 #endif
91 return Mix_<CTag>;
94 static RowMixerFunc SelectRowMixer()
96 #ifdef HAVE_NEON
97 if((CPUCapFlags&CPU_CAP_NEON))
98 return MixRow_<NEONTag>;
99 #endif
100 #ifdef HAVE_SSE
101 if((CPUCapFlags&CPU_CAP_SSE))
102 return MixRow_<SSETag>;
103 #endif
104 return MixRow_<CTag>;
107 static inline HrtfMixerFunc SelectHrtfMixer()
109 #ifdef HAVE_NEON
110 if((CPUCapFlags&CPU_CAP_NEON))
111 return MixHrtf_<NEONTag>;
112 #endif
113 #ifdef HAVE_SSE
114 if((CPUCapFlags&CPU_CAP_SSE))
115 return MixHrtf_<SSETag>;
116 #endif
117 return MixHrtf_<CTag>;
120 static inline HrtfMixerBlendFunc SelectHrtfBlendMixer()
122 #ifdef HAVE_NEON
123 if((CPUCapFlags&CPU_CAP_NEON))
124 return MixHrtfBlend_<NEONTag>;
125 #endif
126 #ifdef HAVE_SSE
127 if((CPUCapFlags&CPU_CAP_SSE))
128 return MixHrtfBlend_<SSETag>;
129 #endif
130 return MixHrtfBlend_<CTag>;
133 ResamplerFunc SelectResampler(Resampler resampler)
135 switch(resampler)
137 case PointResampler:
138 return Resample_<PointTag,CTag>;
139 case LinearResampler:
140 #ifdef HAVE_NEON
141 if((CPUCapFlags&CPU_CAP_NEON))
142 return Resample_<LerpTag,NEONTag>;
143 #endif
144 #ifdef HAVE_SSE4_1
145 if((CPUCapFlags&CPU_CAP_SSE4_1))
146 return Resample_<LerpTag,SSE4Tag>;
147 #endif
148 #ifdef HAVE_SSE2
149 if((CPUCapFlags&CPU_CAP_SSE2))
150 return Resample_<LerpTag,SSE2Tag>;
151 #endif
152 return Resample_<LerpTag,CTag>;
153 case FIR4Resampler:
154 return Resample_<CubicTag,CTag>;
155 case BSinc12Resampler:
156 case BSinc24Resampler:
157 #ifdef HAVE_NEON
158 if((CPUCapFlags&CPU_CAP_NEON))
159 return Resample_<BSincTag,NEONTag>;
160 #endif
161 #ifdef HAVE_SSE
162 if((CPUCapFlags&CPU_CAP_SSE))
163 return Resample_<BSincTag,SSETag>;
164 #endif
165 return Resample_<BSincTag,CTag>;
168 return Resample_<PointTag,CTag>;
172 void aluInitMixer()
174 if(auto resopt = ConfigValueStr(nullptr, nullptr, "resampler"))
176 const char *str{resopt->c_str()};
177 if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
178 ResamplerDefault = PointResampler;
179 else if(strcasecmp(str, "linear") == 0)
180 ResamplerDefault = LinearResampler;
181 else if(strcasecmp(str, "cubic") == 0)
182 ResamplerDefault = FIR4Resampler;
183 else if(strcasecmp(str, "bsinc12") == 0)
184 ResamplerDefault = BSinc12Resampler;
185 else if(strcasecmp(str, "bsinc24") == 0)
186 ResamplerDefault = BSinc24Resampler;
187 else if(strcasecmp(str, "bsinc") == 0)
189 WARN("Resampler option \"%s\" is deprecated, using bsinc12\n", str);
190 ResamplerDefault = BSinc12Resampler;
192 else if(strcasecmp(str, "sinc4") == 0 || strcasecmp(str, "sinc8") == 0)
194 WARN("Resampler option \"%s\" is deprecated, using cubic\n", str);
195 ResamplerDefault = FIR4Resampler;
197 else
198 ERR("Invalid resampler: %s\n", str);
201 MixHrtfBlendSamples = SelectHrtfBlendMixer();
202 MixHrtfSamples = SelectHrtfMixer();
203 MixSamples = SelectMixer();
204 MixRowSamples = SelectRowMixer();
208 namespace {
210 /* A quick'n'dirty lookup table to decode a muLaw-encoded byte sample into a
211 * signed 16-bit sample */
212 constexpr ALshort muLawDecompressionTable[256] = {
213 -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
214 -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
215 -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
216 -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
217 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
218 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
219 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
220 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
221 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
222 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
223 -876, -844, -812, -780, -748, -716, -684, -652,
224 -620, -588, -556, -524, -492, -460, -428, -396,
225 -372, -356, -340, -324, -308, -292, -276, -260,
226 -244, -228, -212, -196, -180, -164, -148, -132,
227 -120, -112, -104, -96, -88, -80, -72, -64,
228 -56, -48, -40, -32, -24, -16, -8, 0,
229 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
230 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
231 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
232 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
233 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
234 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
235 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
236 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
237 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
238 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
239 876, 844, 812, 780, 748, 716, 684, 652,
240 620, 588, 556, 524, 492, 460, 428, 396,
241 372, 356, 340, 324, 308, 292, 276, 260,
242 244, 228, 212, 196, 180, 164, 148, 132,
243 120, 112, 104, 96, 88, 80, 72, 64,
244 56, 48, 40, 32, 24, 16, 8, 0
247 /* A quick'n'dirty lookup table to decode an aLaw-encoded byte sample into a
248 * signed 16-bit sample */
249 constexpr ALshort aLawDecompressionTable[256] = {
250 -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
251 -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
252 -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
253 -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
254 -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944,
255 -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136,
256 -11008,-10496,-12032,-11520, -8960, -8448, -9984, -9472,
257 -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568,
258 -344, -328, -376, -360, -280, -264, -312, -296,
259 -472, -456, -504, -488, -408, -392, -440, -424,
260 -88, -72, -120, -104, -24, -8, -56, -40,
261 -216, -200, -248, -232, -152, -136, -184, -168,
262 -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
263 -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
264 -688, -656, -752, -720, -560, -528, -624, -592,
265 -944, -912, -1008, -976, -816, -784, -880, -848,
266 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
267 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
268 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
269 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
270 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
271 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
272 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
273 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
274 344, 328, 376, 360, 280, 264, 312, 296,
275 472, 456, 504, 488, 408, 392, 440, 424,
276 88, 72, 120, 104, 24, 8, 56, 40,
277 216, 200, 248, 232, 152, 136, 184, 168,
278 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
279 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
280 688, 656, 752, 720, 560, 528, 624, 592,
281 944, 912, 1008, 976, 816, 784, 880, 848
284 template<FmtType T>
285 struct FmtTypeTraits { };
287 template<>
288 struct FmtTypeTraits<FmtUByte> {
289 using Type = ALubyte;
290 static constexpr ALfloat to_float(const Type val) { return (val-128) * (1.0f/128.0f); }
292 template<>
293 struct FmtTypeTraits<FmtShort> {
294 using Type = ALshort;
295 static constexpr ALfloat to_float(const Type val) { return val * (1.0f/32768.0f); }
297 template<>
298 struct FmtTypeTraits<FmtFloat> {
299 using Type = ALfloat;
300 static constexpr ALfloat to_float(const Type val) { return val; }
302 template<>
303 struct FmtTypeTraits<FmtDouble> {
304 using Type = ALdouble;
305 static constexpr ALfloat to_float(const Type val) { return static_cast<ALfloat>(val); }
307 template<>
308 struct FmtTypeTraits<FmtMulaw> {
309 using Type = ALubyte;
310 static constexpr ALfloat to_float(const Type val)
311 { return muLawDecompressionTable[val] * (1.0f/32768.0f); }
313 template<>
314 struct FmtTypeTraits<FmtAlaw> {
315 using Type = ALubyte;
316 static constexpr ALfloat to_float(const Type val)
317 { return aLawDecompressionTable[val] * (1.0f/32768.0f); }
321 void SendSourceStoppedEvent(ALCcontext *context, ALuint id)
323 RingBuffer *ring{context->mAsyncEvents.get()};
324 auto evt_vec = ring->getWriteVector();
325 if(evt_vec.first.len < 1) return;
327 AsyncEvent *evt{new (evt_vec.first.buf) AsyncEvent{EventType_SourceStateChange}};
328 evt->u.srcstate.id = id;
329 evt->u.srcstate.state = AL_STOPPED;
331 ring->writeAdvance(1);
332 context->mEventSem.post();
336 const ALfloat *DoFilters(BiquadFilter *lpfilter, BiquadFilter *hpfilter, ALfloat *dst,
337 const ALfloat *src, const size_t numsamples, int type)
339 switch(type)
341 case AF_None:
342 lpfilter->clear();
343 hpfilter->clear();
344 break;
346 case AF_LowPass:
347 lpfilter->process(dst, src, numsamples);
348 hpfilter->clear();
349 return dst;
350 case AF_HighPass:
351 lpfilter->clear();
352 hpfilter->process(dst, src, numsamples);
353 return dst;
355 case AF_BandPass:
356 lpfilter->process(dst, src, numsamples);
357 hpfilter->process(dst, dst, numsamples);
358 return dst;
360 return src;
364 template<FmtType T>
365 inline void LoadSampleArray(ALfloat *RESTRICT dst, const al::byte *src, const size_t srcstep,
366 const size_t samples)
368 using SampleType = typename FmtTypeTraits<T>::Type;
370 const SampleType *RESTRICT ssrc{reinterpret_cast<const SampleType*>(src)};
371 for(size_t i{0u};i < samples;i++)
372 dst[i] = FmtTypeTraits<T>::to_float(ssrc[i*srcstep]);
375 void LoadSamples(ALfloat *RESTRICT dst, const al::byte *src, const size_t srcstep, FmtType srctype,
376 const size_t samples)
378 #define HANDLE_FMT(T) case T: LoadSampleArray<T>(dst, src, srcstep, samples); break
379 switch(srctype)
381 HANDLE_FMT(FmtUByte);
382 HANDLE_FMT(FmtShort);
383 HANDLE_FMT(FmtFloat);
384 HANDLE_FMT(FmtDouble);
385 HANDLE_FMT(FmtMulaw);
386 HANDLE_FMT(FmtAlaw);
388 #undef HANDLE_FMT
391 ALfloat *LoadBufferStatic(ALbufferlistitem *BufferListItem, ALbufferlistitem *&BufferLoopItem,
392 const size_t NumChannels, const size_t SampleSize, const size_t chan, size_t DataPosInt,
393 al::span<ALfloat> SrcBuffer)
395 const ALbuffer *Buffer{BufferListItem->mBuffer};
396 const ALuint LoopStart{Buffer->LoopStart};
397 const ALuint LoopEnd{Buffer->LoopEnd};
398 ASSUME(LoopEnd > LoopStart);
400 /* If current pos is beyond the loop range, do not loop */
401 if(!BufferLoopItem || DataPosInt >= LoopEnd)
403 BufferLoopItem = nullptr;
405 /* Load what's left to play from the buffer */
406 const size_t DataSize{minz(SrcBuffer.size(), Buffer->SampleLen-DataPosInt)};
408 const al::byte *Data{Buffer->mData.data()};
409 Data += (DataPosInt*NumChannels + chan)*SampleSize;
411 LoadSamples(SrcBuffer.data(), Data, NumChannels, Buffer->mFmtType, DataSize);
412 SrcBuffer = SrcBuffer.subspan(DataSize);
414 else
416 /* Load what's left of this loop iteration */
417 const size_t DataSize{minz(SrcBuffer.size(), LoopEnd-DataPosInt)};
419 const al::byte *Data{Buffer->mData.data()};
420 Data += (DataPosInt*NumChannels + chan)*SampleSize;
422 LoadSamples(SrcBuffer.data(), Data, NumChannels, Buffer->mFmtType, DataSize);
423 SrcBuffer = SrcBuffer.subspan(DataSize);
425 /* Load any repeats of the loop we can to fill the buffer. */
426 const auto LoopSize = static_cast<size_t>(LoopEnd - LoopStart);
427 while(!SrcBuffer.empty())
429 const size_t DataSize{minz(SrcBuffer.size(), LoopSize)};
431 const al::byte *Data{Buffer->mData.data()};
432 Data += (LoopStart*NumChannels + chan)*SampleSize;
434 LoadSamples(SrcBuffer.data(), Data, NumChannels, Buffer->mFmtType, DataSize);
435 SrcBuffer = SrcBuffer.subspan(DataSize);
438 return SrcBuffer.begin();
441 ALfloat *LoadBufferQueue(ALbufferlistitem *BufferListItem, ALbufferlistitem *BufferLoopItem,
442 const size_t NumChannels, const size_t SampleSize, const size_t chan, size_t DataPosInt,
443 al::span<ALfloat> SrcBuffer)
445 /* Crawl the buffer queue to fill in the temp buffer */
446 while(BufferListItem && !SrcBuffer.empty())
448 ALbuffer *Buffer{BufferListItem->mBuffer};
449 if(!(Buffer && DataPosInt < Buffer->SampleLen))
451 if(Buffer) DataPosInt -= Buffer->SampleLen;
452 BufferListItem = BufferListItem->mNext.load(std::memory_order_acquire);
453 if(!BufferListItem) BufferListItem = BufferLoopItem;
454 continue;
457 const size_t DataSize{minz(SrcBuffer.size(), Buffer->SampleLen-DataPosInt)};
459 const al::byte *Data{Buffer->mData.data()};
460 Data += (DataPosInt*NumChannels + chan)*SampleSize;
462 LoadSamples(SrcBuffer.data(), Data, NumChannels, Buffer->mFmtType, DataSize);
463 SrcBuffer = SrcBuffer.subspan(DataSize);
464 if(SrcBuffer.empty()) break;
466 DataPosInt = 0;
467 BufferListItem = BufferListItem->mNext.load(std::memory_order_acquire);
468 if(!BufferListItem) BufferListItem = BufferLoopItem;
471 return SrcBuffer.begin();
474 } // namespace
476 void ALvoice::mix(State vstate, ALCcontext *Context, const ALuint SamplesToDo)
478 static constexpr ALfloat SilentTarget[MAX_OUTPUT_CHANNELS]{};
480 ASSUME(SamplesToDo > 0);
482 /* Get voice info */
483 const bool isstatic{(mFlags&VOICE_IS_STATIC) != 0};
484 ALuint DataPosInt{mPosition.load(std::memory_order_relaxed)};
485 ALuint DataPosFrac{mPositionFrac.load(std::memory_order_relaxed)};
486 ALbufferlistitem *BufferListItem{mCurrentBuffer.load(std::memory_order_relaxed)};
487 ALbufferlistitem *BufferLoopItem{mLoopBuffer.load(std::memory_order_relaxed)};
488 const ALuint NumChannels{mNumChannels};
489 const ALuint SampleSize{mSampleSize};
490 const ALuint increment{mStep};
491 if(increment < 1) return;
493 ASSUME(NumChannels > 0);
494 ASSUME(SampleSize > 0);
495 ASSUME(increment > 0);
497 ALCdevice *Device{Context->mDevice.get()};
498 const ALuint NumSends{Device->NumAuxSends};
499 const ALuint IrSize{Device->mHrtf ? Device->mHrtf->irSize : 0};
501 ResamplerFunc Resample{(increment == FRACTIONONE && DataPosFrac == 0) ?
502 Resample_<CopyTag,CTag> : mResampler};
504 ALuint Counter{(mFlags&VOICE_IS_FADING) ? SamplesToDo : 0};
505 if(!Counter)
507 /* No fading, just overwrite the old/current params. */
508 for(ALuint chan{0};chan < NumChannels;chan++)
510 ChannelData &chandata = mChans[chan];
511 DirectParams &parms = chandata.mDryParams;
512 if(!(mFlags&VOICE_HAS_HRTF))
513 std::copy(std::begin(parms.Gains.Target), std::end(parms.Gains.Target),
514 std::begin(parms.Gains.Current));
515 else
516 parms.Hrtf.Old = parms.Hrtf.Target;
517 for(ALuint send{0};send < NumSends;++send)
519 if(mSend[send].Buffer.empty())
520 continue;
522 SendParams &parms = chandata.mWetParams[send];
523 std::copy(std::begin(parms.Gains.Target), std::end(parms.Gains.Target),
524 std::begin(parms.Gains.Current));
528 else if((mFlags&VOICE_HAS_HRTF))
530 for(ALuint chan{0};chan < NumChannels;chan++)
532 DirectParams &parms = mChans[chan].mDryParams;
533 if(!(parms.Hrtf.Old.Gain > GAIN_SILENCE_THRESHOLD))
535 /* The old HRTF params are silent, so overwrite the old
536 * coefficients with the new, and reset the old gain to 0. The
537 * future mix will then fade from silence.
539 parms.Hrtf.Old = parms.Hrtf.Target;
540 parms.Hrtf.Old.Gain = 0.0f;
545 ALuint buffers_done{0u};
546 ALuint OutPos{0u};
547 do {
548 /* Figure out how many buffer samples will be needed */
549 ALuint DstBufferSize{SamplesToDo - OutPos};
551 /* Calculate the last written dst sample pos. */
552 uint64_t DataSize64{DstBufferSize - 1};
553 /* Calculate the last read src sample pos. */
554 DataSize64 = (DataSize64*increment + DataPosFrac) >> FRACTIONBITS;
555 /* +1 to get the src sample count, include padding. */
556 DataSize64 += 1 + MAX_RESAMPLE_PADDING*2;
558 auto SrcBufferSize = static_cast<ALuint>(
559 minu64(DataSize64, BUFFERSIZE + MAX_RESAMPLE_PADDING*2 + 1));
560 if(SrcBufferSize > BUFFERSIZE + MAX_RESAMPLE_PADDING*2)
562 SrcBufferSize = BUFFERSIZE + MAX_RESAMPLE_PADDING*2;
563 /* If the source buffer got saturated, we can't fill the desired
564 * dst size. Figure out how many samples we can actually mix from
565 * this.
567 DataSize64 = SrcBufferSize - MAX_RESAMPLE_PADDING*2;
568 DataSize64 = ((DataSize64<<FRACTIONBITS) - DataPosFrac + increment-1) / increment;
569 DstBufferSize = static_cast<ALuint>(minu64(DataSize64, DstBufferSize));
571 /* Some mixers like having a multiple of 4, so try to give that
572 * unless this is the last update.
574 if(DstBufferSize < SamplesToDo-OutPos)
575 DstBufferSize &= ~3u;
578 ASSUME(DstBufferSize > 0);
579 for(ALuint chan{0};chan < NumChannels;chan++)
581 ChannelData &chandata = mChans[chan];
582 const al::span<ALfloat> SrcData{Device->SourceData, SrcBufferSize};
584 /* Load the previous samples into the source data first, then load
585 * what we can from the buffer queue.
587 auto srciter = std::copy_n(chandata.mPrevSamples.begin(), MAX_RESAMPLE_PADDING,
588 SrcData.begin());
590 if UNLIKELY(!BufferListItem)
591 srciter = std::copy(chandata.mPrevSamples.begin()+MAX_RESAMPLE_PADDING,
592 chandata.mPrevSamples.end(), srciter);
593 else if(isstatic)
594 srciter = LoadBufferStatic(BufferListItem, BufferLoopItem, NumChannels,
595 SampleSize, chan, DataPosInt, {srciter, SrcData.end()});
596 else
597 srciter = LoadBufferQueue(BufferListItem, BufferLoopItem, NumChannels,
598 SampleSize, chan, DataPosInt, {srciter, SrcData.end()});
600 if UNLIKELY(srciter != SrcData.end())
602 /* If the source buffer wasn't filled, copy the last sample for
603 * the remaining buffer. Ideally it should have ended with
604 * silence, but if not the gain fading should help avoid clicks
605 * from sudden amplitude changes.
607 const ALfloat sample{*(srciter-1)};
608 std::fill(srciter, SrcData.end(), sample);
611 /* Store the last source samples used for next time. */
612 std::copy_n(&SrcData[(increment*DstBufferSize + DataPosFrac)>>FRACTIONBITS],
613 chandata.mPrevSamples.size(), chandata.mPrevSamples.begin());
615 /* Resample, then apply ambisonic upsampling as needed. */
616 const ALfloat *ResampledData{Resample(&mResampleState, &SrcData[MAX_RESAMPLE_PADDING],
617 DataPosFrac, increment, {Device->ResampledData, DstBufferSize})};
618 if((mFlags&VOICE_IS_AMBISONIC))
620 const ALfloat hfscale{chandata.mAmbiScale};
621 /* Beware the evil const_cast. It's safe since it's pointing to
622 * either SourceData or ResampledData (both non-const), but the
623 * resample method takes the source as const float* and may
624 * return it without copying to output, making it currently
625 * unavoidable.
627 chandata.mAmbiSplitter.applyHfScale(const_cast<ALfloat*>(ResampledData), hfscale,
628 DstBufferSize);
631 /* Now filter and mix to the appropriate outputs. */
632 ALfloat (&FilterBuf)[BUFFERSIZE] = Device->FilteredData;
634 DirectParams &parms = chandata.mDryParams;
635 const ALfloat *samples{DoFilters(&parms.LowPass, &parms.HighPass, FilterBuf,
636 ResampledData, DstBufferSize, mDirect.FilterType)};
638 if((mFlags&VOICE_HAS_HRTF))
640 const ALuint OutLIdx{GetChannelIdxByName(Device->RealOut, FrontLeft)};
641 const ALuint OutRIdx{GetChannelIdxByName(Device->RealOut, FrontRight)};
643 auto &HrtfSamples = Device->HrtfSourceData;
644 auto &AccumSamples = Device->HrtfAccumData;
645 const ALfloat TargetGain{UNLIKELY(vstate == ALvoice::Stopping) ? 0.0f :
646 parms.Hrtf.Target.Gain};
647 ALuint fademix{0u};
649 /* Copy the HRTF history and new input samples into a temp
650 * buffer.
652 auto src_iter = std::copy(parms.Hrtf.State.History.begin(),
653 parms.Hrtf.State.History.end(), std::begin(HrtfSamples));
654 std::copy_n(samples, DstBufferSize, src_iter);
655 /* Copy the last used samples back into the history buffer
656 * for later.
658 std::copy_n(std::begin(HrtfSamples) + DstBufferSize,
659 parms.Hrtf.State.History.size(), parms.Hrtf.State.History.begin());
661 /* Copy the current filtered values being accumulated into
662 * the temp buffer.
664 auto accum_iter = std::copy_n(parms.Hrtf.State.Values.begin(),
665 parms.Hrtf.State.Values.size(), std::begin(AccumSamples));
667 /* Clear the accumulation buffer that will start getting
668 * filled in.
670 std::fill_n(accum_iter, DstBufferSize, float2{});
672 /* If fading, the old gain is not silence, and this is the
673 * first mixing pass, fade between the IRs.
675 if(Counter && (parms.Hrtf.Old.Gain > GAIN_SILENCE_THRESHOLD) && OutPos == 0)
677 fademix = minu(DstBufferSize, 128);
679 ALfloat gain{TargetGain};
681 /* The new coefficients need to fade in completely
682 * since they're replacing the old ones. To keep the
683 * gain fading consistent, interpolate between the old
684 * and new target gains given how much of the fade time
685 * this mix handles.
687 if LIKELY(Counter > fademix)
689 const ALfloat a{static_cast<ALfloat>(fademix) /
690 static_cast<ALfloat>(Counter)};
691 gain = lerp(parms.Hrtf.Old.Gain, TargetGain, a);
693 MixHrtfFilter hrtfparams;
694 hrtfparams.Coeffs = &parms.Hrtf.Target.Coeffs;
695 hrtfparams.Delay[0] = parms.Hrtf.Target.Delay[0];
696 hrtfparams.Delay[1] = parms.Hrtf.Target.Delay[1];
697 hrtfparams.Gain = 0.0f;
698 hrtfparams.GainStep = gain / static_cast<ALfloat>(fademix);
700 MixHrtfBlendSamples(mDirect.Buffer[OutLIdx], mDirect.Buffer[OutRIdx],
701 HrtfSamples, AccumSamples, OutPos, IrSize, &parms.Hrtf.Old,
702 &hrtfparams, fademix);
703 /* Update the old parameters with the result. */
704 parms.Hrtf.Old = parms.Hrtf.Target;
705 if(fademix < Counter)
706 parms.Hrtf.Old.Gain = hrtfparams.Gain;
707 else
708 parms.Hrtf.Old.Gain = TargetGain;
711 if LIKELY(fademix < DstBufferSize)
713 const ALuint todo{DstBufferSize - fademix};
714 ALfloat gain{TargetGain};
716 /* Interpolate the target gain if the gain fading lasts
717 * longer than this mix.
719 if(Counter > DstBufferSize)
721 const ALfloat a{static_cast<ALfloat>(todo) /
722 static_cast<ALfloat>(Counter-fademix)};
723 gain = lerp(parms.Hrtf.Old.Gain, TargetGain, a);
726 MixHrtfFilter hrtfparams;
727 hrtfparams.Coeffs = &parms.Hrtf.Target.Coeffs;
728 hrtfparams.Delay[0] = parms.Hrtf.Target.Delay[0];
729 hrtfparams.Delay[1] = parms.Hrtf.Target.Delay[1];
730 hrtfparams.Gain = parms.Hrtf.Old.Gain;
731 hrtfparams.GainStep = (gain - parms.Hrtf.Old.Gain) /
732 static_cast<ALfloat>(todo);
733 MixHrtfSamples(mDirect.Buffer[OutLIdx], mDirect.Buffer[OutRIdx],
734 HrtfSamples+fademix, AccumSamples+fademix, OutPos+fademix, IrSize,
735 &hrtfparams, todo);
736 /* Store the interpolated gain or the final target gain
737 * depending if the fade is done.
739 if(DstBufferSize < Counter)
740 parms.Hrtf.Old.Gain = gain;
741 else
742 parms.Hrtf.Old.Gain = TargetGain;
745 /* Copy the new in-progress accumulation values back for
746 * the next mix.
748 std::copy_n(std::begin(AccumSamples) + DstBufferSize,
749 parms.Hrtf.State.Values.size(), parms.Hrtf.State.Values.begin());
751 else if((mFlags&VOICE_HAS_NFC))
753 const ALfloat *TargetGains{UNLIKELY(vstate == ALvoice::Stopping) ?
754 SilentTarget : parms.Gains.Target};
756 const size_t outcount{Device->NumChannelsPerOrder[0]};
757 MixSamples({samples, DstBufferSize}, mDirect.Buffer.first(outcount),
758 parms.Gains.Current, TargetGains, Counter, OutPos);
760 const al::span<float> nfcsamples{Device->NfcSampleData, DstBufferSize};
761 size_t chanoffset{outcount};
762 using FilterProc = void (NfcFilter::*)(float*,const float*,const size_t);
763 auto apply_nfc = [this,&parms,samples,TargetGains,Counter,OutPos,&chanoffset,nfcsamples](const FilterProc process, const size_t outcount) -> void
765 if(outcount < 1) return;
766 (parms.NFCtrlFilter.*process)(nfcsamples.data(), samples, nfcsamples.size());
767 MixSamples(nfcsamples, mDirect.Buffer.subspan(chanoffset, outcount),
768 parms.Gains.Current+chanoffset, TargetGains+chanoffset, Counter,
769 OutPos);
770 chanoffset += outcount;
772 apply_nfc(&NfcFilter::process1, Device->NumChannelsPerOrder[1]);
773 apply_nfc(&NfcFilter::process2, Device->NumChannelsPerOrder[2]);
774 apply_nfc(&NfcFilter::process3, Device->NumChannelsPerOrder[3]);
776 else
778 const ALfloat *TargetGains{UNLIKELY(vstate == ALvoice::Stopping) ?
779 SilentTarget : parms.Gains.Target};
780 MixSamples({samples, DstBufferSize}, mDirect.Buffer, parms.Gains.Current,
781 TargetGains, Counter, OutPos);
785 for(ALuint send{0};send < NumSends;++send)
787 if(mSend[send].Buffer.empty())
788 continue;
790 SendParams &parms = chandata.mWetParams[send];
791 const ALfloat *samples{DoFilters(&parms.LowPass, &parms.HighPass, FilterBuf,
792 ResampledData, DstBufferSize, mSend[send].FilterType)};
794 const ALfloat *TargetGains{UNLIKELY(vstate==ALvoice::Stopping) ? SilentTarget :
795 parms.Gains.Target};
796 MixSamples({samples, DstBufferSize}, mSend[send].Buffer, parms.Gains.Current,
797 TargetGains, Counter, OutPos);
800 /* Update positions */
801 DataPosFrac += increment*DstBufferSize;
802 DataPosInt += DataPosFrac>>FRACTIONBITS;
803 DataPosFrac &= FRACTIONMASK;
805 OutPos += DstBufferSize;
806 Counter = maxu(DstBufferSize, Counter) - DstBufferSize;
808 if UNLIKELY(!BufferListItem)
810 /* Do nothing extra when there's no buffers. */
812 else if(isstatic)
814 if(BufferLoopItem)
816 /* Handle looping static source */
817 const ALbuffer *Buffer{BufferListItem->mBuffer};
818 const ALuint LoopStart{Buffer->LoopStart};
819 const ALuint LoopEnd{Buffer->LoopEnd};
820 if(DataPosInt >= LoopEnd)
822 assert(LoopEnd > LoopStart);
823 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
826 else
828 /* Handle non-looping static source */
829 if(DataPosInt >= BufferListItem->mSampleLen)
831 if LIKELY(vstate == ALvoice::Playing)
832 vstate = ALvoice::Stopped;
833 BufferListItem = nullptr;
834 break;
838 else while(1)
840 /* Handle streaming source */
841 if(BufferListItem->mSampleLen > DataPosInt)
842 break;
844 DataPosInt -= BufferListItem->mSampleLen;
846 ++buffers_done;
847 BufferListItem = BufferListItem->mNext.load(std::memory_order_relaxed);
848 if(!BufferListItem && !(BufferListItem=BufferLoopItem))
850 if LIKELY(vstate == ALvoice::Playing)
851 vstate = ALvoice::Stopped;
852 break;
855 } while(OutPos < SamplesToDo);
857 mFlags |= VOICE_IS_FADING;
859 /* Don't update positions and buffers if we were stopping. */
860 if UNLIKELY(vstate == ALvoice::Stopping)
862 mPlayState.store(ALvoice::Stopped, std::memory_order_release);
863 return;
866 /* Capture the source ID in case it's reset for stopping. */
867 const ALuint SourceID{mSourceID.load(std::memory_order_relaxed)};
869 /* Update voice info */
870 mPosition.store(DataPosInt, std::memory_order_relaxed);
871 mPositionFrac.store(DataPosFrac, std::memory_order_relaxed);
872 mCurrentBuffer.store(BufferListItem, std::memory_order_relaxed);
873 if(vstate == ALvoice::Stopped)
875 mLoopBuffer.store(nullptr, std::memory_order_relaxed);
876 mSourceID.store(0u, std::memory_order_relaxed);
878 std::atomic_thread_fence(std::memory_order_release);
880 /* Send any events now, after the position/buffer info was updated. */
881 const ALbitfieldSOFT enabledevt{Context->mEnabledEvts.load(std::memory_order_acquire)};
882 if(buffers_done > 0 && (enabledevt&EventType_BufferCompleted))
884 RingBuffer *ring{Context->mAsyncEvents.get()};
885 auto evt_vec = ring->getWriteVector();
886 if(evt_vec.first.len > 0)
888 AsyncEvent *evt{new (evt_vec.first.buf) AsyncEvent{EventType_BufferCompleted}};
889 evt->u.bufcomp.id = SourceID;
890 evt->u.bufcomp.count = buffers_done;
891 ring->writeAdvance(1);
892 Context->mEventSem.post();
896 if(vstate == ALvoice::Stopped)
898 /* If the voice just ended, set it to Stopping so the next render
899 * ensures any residual noise fades to 0 amplitude.
901 mPlayState.store(ALvoice::Stopping, std::memory_order_release);
902 if((enabledevt&EventType_SourceStateChange))
903 SendSourceStoppedEvent(Context, SourceID);