🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

878 lines
34 KiB

  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.
  8. *
  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.
  13. *
  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
  19. */
  20. #include "config.h"
  21. #include <cmath>
  22. #include <cstdlib>
  23. #include <cstring>
  24. #include <cctype>
  25. #include <cassert>
  26. #include <numeric>
  27. #include <algorithm>
  28. #include "AL/al.h"
  29. #include "AL/alc.h"
  30. #include "alMain.h"
  31. #include "alcontext.h"
  32. #include "alSource.h"
  33. #include "alBuffer.h"
  34. #include "alListener.h"
  35. #include "alAuxEffectSlot.h"
  36. #include "sample_cvt.h"
  37. #include "alu.h"
  38. #include "alconfig.h"
  39. #include "ringbuffer.h"
  40. #include "cpu_caps.h"
  41. #include "mixer/defs.h"
  42. static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
  43. "MAX_PITCH and/or BUFFERSIZE are too large for FRACTIONBITS!");
  44. /* BSinc24 requires up to 23 extra samples before the current position, and 24 after. */
  45. static_assert(MAX_RESAMPLE_PADDING >= 24, "MAX_RESAMPLE_PADDING must be at least 24!");
  46. Resampler ResamplerDefault = LinearResampler;
  47. MixerFunc MixSamples = Mix_<CTag>;
  48. RowMixerFunc MixRowSamples = MixRow_<CTag>;
  49. static HrtfMixerFunc MixHrtfSamples = MixHrtf_<CTag>;
  50. static HrtfMixerBlendFunc MixHrtfBlendSamples = MixHrtfBlend_<CTag>;
  51. static MixerFunc SelectMixer()
  52. {
  53. #ifdef HAVE_NEON
  54. if((CPUCapFlags&CPU_CAP_NEON))
  55. return Mix_<NEONTag>;
  56. #endif
  57. #ifdef HAVE_SSE
  58. if((CPUCapFlags&CPU_CAP_SSE))
  59. return Mix_<SSETag>;
  60. #endif
  61. return Mix_<CTag>;
  62. }
  63. static RowMixerFunc SelectRowMixer()
  64. {
  65. #ifdef HAVE_NEON
  66. if((CPUCapFlags&CPU_CAP_NEON))
  67. return MixRow_<NEONTag>;
  68. #endif
  69. #ifdef HAVE_SSE
  70. if((CPUCapFlags&CPU_CAP_SSE))
  71. return MixRow_<SSETag>;
  72. #endif
  73. return MixRow_<CTag>;
  74. }
  75. static inline HrtfMixerFunc SelectHrtfMixer()
  76. {
  77. #ifdef HAVE_NEON
  78. if((CPUCapFlags&CPU_CAP_NEON))
  79. return MixHrtf_<NEONTag>;
  80. #endif
  81. #ifdef HAVE_SSE
  82. if((CPUCapFlags&CPU_CAP_SSE))
  83. return MixHrtf_<SSETag>;
  84. #endif
  85. return MixHrtf_<CTag>;
  86. }
  87. static inline HrtfMixerBlendFunc SelectHrtfBlendMixer()
  88. {
  89. #ifdef HAVE_NEON
  90. if((CPUCapFlags&CPU_CAP_NEON))
  91. return MixHrtfBlend_<NEONTag>;
  92. #endif
  93. #ifdef HAVE_SSE
  94. if((CPUCapFlags&CPU_CAP_SSE))
  95. return MixHrtfBlend_<SSETag>;
  96. #endif
  97. return MixHrtfBlend_<CTag>;
  98. }
  99. ResamplerFunc SelectResampler(Resampler resampler)
  100. {
  101. switch(resampler)
  102. {
  103. case PointResampler:
  104. return Resample_<PointTag,CTag>;
  105. case LinearResampler:
  106. #ifdef HAVE_NEON
  107. if((CPUCapFlags&CPU_CAP_NEON))
  108. return Resample_<LerpTag,NEONTag>;
  109. #endif
  110. #ifdef HAVE_SSE4_1
  111. if((CPUCapFlags&CPU_CAP_SSE4_1))
  112. return Resample_<LerpTag,SSE4Tag>;
  113. #endif
  114. #ifdef HAVE_SSE2
  115. if((CPUCapFlags&CPU_CAP_SSE2))
  116. return Resample_<LerpTag,SSE2Tag>;
  117. #endif
  118. return Resample_<LerpTag,CTag>;
  119. case FIR4Resampler:
  120. return Resample_<CubicTag,CTag>;
  121. case BSinc12Resampler:
  122. case BSinc24Resampler:
  123. #ifdef HAVE_NEON
  124. if((CPUCapFlags&CPU_CAP_NEON))
  125. return Resample_<BSincTag,NEONTag>;
  126. #endif
  127. #ifdef HAVE_SSE
  128. if((CPUCapFlags&CPU_CAP_SSE))
  129. return Resample_<BSincTag,SSETag>;
  130. #endif
  131. return Resample_<BSincTag,CTag>;
  132. }
  133. return Resample_<PointTag,CTag>;
  134. }
  135. void aluInitMixer()
  136. {
  137. const char *str;
  138. if(ConfigValueStr(nullptr, nullptr, "resampler", &str))
  139. {
  140. if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
  141. ResamplerDefault = PointResampler;
  142. else if(strcasecmp(str, "linear") == 0)
  143. ResamplerDefault = LinearResampler;
  144. else if(strcasecmp(str, "cubic") == 0)
  145. ResamplerDefault = FIR4Resampler;
  146. else if(strcasecmp(str, "bsinc12") == 0)
  147. ResamplerDefault = BSinc12Resampler;
  148. else if(strcasecmp(str, "bsinc24") == 0)
  149. ResamplerDefault = BSinc24Resampler;
  150. else if(strcasecmp(str, "bsinc") == 0)
  151. {
  152. WARN("Resampler option \"%s\" is deprecated, using bsinc12\n", str);
  153. ResamplerDefault = BSinc12Resampler;
  154. }
  155. else if(strcasecmp(str, "sinc4") == 0 || strcasecmp(str, "sinc8") == 0)
  156. {
  157. WARN("Resampler option \"%s\" is deprecated, using cubic\n", str);
  158. ResamplerDefault = FIR4Resampler;
  159. }
  160. else
  161. {
  162. char *end;
  163. long n = strtol(str, &end, 0);
  164. if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == FIR4Resampler))
  165. ResamplerDefault = static_cast<Resampler>(n);
  166. else
  167. WARN("Invalid resampler: %s\n", str);
  168. }
  169. }
  170. MixHrtfBlendSamples = SelectHrtfBlendMixer();
  171. MixHrtfSamples = SelectHrtfMixer();
  172. MixSamples = SelectMixer();
  173. MixRowSamples = SelectRowMixer();
  174. }
  175. namespace {
  176. void SendSourceStoppedEvent(ALCcontext *context, ALuint id)
  177. {
  178. ALbitfieldSOFT enabledevt{context->EnabledEvts.load(std::memory_order_acquire)};
  179. if(!(enabledevt&EventType_SourceStateChange)) return;
  180. RingBuffer *ring{context->AsyncEvents.get()};
  181. auto evt_vec = ring->getWriteVector();
  182. if(evt_vec.first.len < 1) return;
  183. AsyncEvent *evt{new (evt_vec.first.buf) AsyncEvent{EventType_SourceStateChange}};
  184. evt->u.srcstate.id = id;
  185. evt->u.srcstate.state = AL_STOPPED;
  186. ring->writeAdvance(1);
  187. context->EventSem.post();
  188. }
  189. const ALfloat *DoFilters(BiquadFilter *lpfilter, BiquadFilter *hpfilter,
  190. ALfloat *RESTRICT dst, const ALfloat *RESTRICT src, ALsizei numsamples, int type)
  191. {
  192. switch(type)
  193. {
  194. case AF_None:
  195. lpfilter->passthru(numsamples);
  196. hpfilter->passthru(numsamples);
  197. break;
  198. case AF_LowPass:
  199. lpfilter->process(dst, src, numsamples);
  200. hpfilter->passthru(numsamples);
  201. return dst;
  202. case AF_HighPass:
  203. lpfilter->passthru(numsamples);
  204. hpfilter->process(dst, src, numsamples);
  205. return dst;
  206. case AF_BandPass:
  207. for(ALsizei i{0};i < numsamples;)
  208. {
  209. ALfloat temp[256];
  210. ALsizei todo = mini(256, numsamples-i);
  211. lpfilter->process(temp, src+i, todo);
  212. hpfilter->process(dst+i, temp, todo);
  213. i += todo;
  214. }
  215. return dst;
  216. }
  217. return src;
  218. }
  219. /* Base template left undefined. Should be marked =delete, but Clang 3.8.1
  220. * chokes on that given the inline specializations.
  221. */
  222. template<FmtType T>
  223. inline ALfloat LoadSample(typename FmtTypeTraits<T>::Type val);
  224. template<> inline ALfloat LoadSample<FmtUByte>(FmtTypeTraits<FmtUByte>::Type val)
  225. { return (val-128) * (1.0f/128.0f); }
  226. template<> inline ALfloat LoadSample<FmtShort>(FmtTypeTraits<FmtShort>::Type val)
  227. { return val * (1.0f/32768.0f); }
  228. template<> inline ALfloat LoadSample<FmtFloat>(FmtTypeTraits<FmtFloat>::Type val)
  229. { return val; }
  230. template<> inline ALfloat LoadSample<FmtDouble>(FmtTypeTraits<FmtDouble>::Type val)
  231. { return static_cast<ALfloat>(val); }
  232. template<> inline ALfloat LoadSample<FmtMulaw>(FmtTypeTraits<FmtMulaw>::Type val)
  233. { return muLawDecompressionTable[val] * (1.0f/32768.0f); }
  234. template<> inline ALfloat LoadSample<FmtAlaw>(FmtTypeTraits<FmtAlaw>::Type val)
  235. { return aLawDecompressionTable[val] * (1.0f/32768.0f); }
  236. template<FmtType T>
  237. inline void LoadSampleArray(ALfloat *RESTRICT dst, const void *src, ALint srcstep,
  238. const ptrdiff_t samples)
  239. {
  240. using SampleType = typename FmtTypeTraits<T>::Type;
  241. const SampleType *ssrc = static_cast<const SampleType*>(src);
  242. for(ALsizei i{0};i < samples;i++)
  243. dst[i] += LoadSample<T>(ssrc[i*srcstep]);
  244. }
  245. void LoadSamples(ALfloat *RESTRICT dst, const ALvoid *RESTRICT src, ALint srcstep, FmtType srctype,
  246. const ptrdiff_t samples)
  247. {
  248. #define HANDLE_FMT(T) case T: LoadSampleArray<T>(dst, src, srcstep, samples); break
  249. switch(srctype)
  250. {
  251. HANDLE_FMT(FmtUByte);
  252. HANDLE_FMT(FmtShort);
  253. HANDLE_FMT(FmtFloat);
  254. HANDLE_FMT(FmtDouble);
  255. HANDLE_FMT(FmtMulaw);
  256. HANDLE_FMT(FmtAlaw);
  257. }
  258. #undef HANDLE_FMT
  259. }
  260. ALfloat *LoadBufferStatic(ALbufferlistitem *BufferListItem, ALbufferlistitem *&BufferLoopItem,
  261. const ALsizei NumChannels, const ALsizei SampleSize, const ALsizei chan, ALsizei DataPosInt,
  262. ALfloat *SrcData, const ALfloat *const SrcDataEnd)
  263. {
  264. /* TODO: For static sources, loop points are taken from the first buffer
  265. * (should be adjusted by any buffer offset, to possibly be added later).
  266. */
  267. const ALbuffer *Buffer0{BufferListItem->buffers[0]};
  268. const ALsizei LoopStart{Buffer0->LoopStart};
  269. const ALsizei LoopEnd{Buffer0->LoopEnd};
  270. ASSUME(LoopStart >= 0);
  271. ASSUME(LoopEnd > LoopStart);
  272. /* If current pos is beyond the loop range, do not loop */
  273. if(!BufferLoopItem || DataPosInt >= LoopEnd)
  274. {
  275. const ptrdiff_t SizeToDo{SrcDataEnd - SrcData};
  276. ASSUME(SizeToDo > 0);
  277. BufferLoopItem = nullptr;
  278. auto load_buffer = [DataPosInt,SrcData,NumChannels,SampleSize,chan,SizeToDo](ptrdiff_t CompLen, const ALbuffer *buffer) -> ptrdiff_t
  279. {
  280. if(DataPosInt >= buffer->SampleLen)
  281. return CompLen;
  282. /* Load what's left to play from the buffer */
  283. const ptrdiff_t DataSize{std::min<ptrdiff_t>(SizeToDo, buffer->SampleLen-DataPosInt)};
  284. CompLen = std::max<ptrdiff_t>(CompLen, DataSize);
  285. const ALbyte *Data{buffer->mData.data()};
  286. Data += (DataPosInt*NumChannels + chan)*SampleSize;
  287. LoadSamples(SrcData, Data, NumChannels, buffer->mFmtType, DataSize);
  288. return CompLen;
  289. };
  290. /* It's impossible to have a buffer list item with no entries. */
  291. ASSUME(BufferListItem->num_buffers > 0);
  292. auto buffers_end = BufferListItem->buffers + BufferListItem->num_buffers;
  293. SrcData += std::accumulate(BufferListItem->buffers, buffers_end, ptrdiff_t{0},
  294. load_buffer);
  295. }
  296. else
  297. {
  298. const ptrdiff_t SizeToDo{std::min<ptrdiff_t>(SrcDataEnd-SrcData, LoopEnd-DataPosInt)};
  299. ASSUME(SizeToDo > 0);
  300. auto load_buffer = [DataPosInt,SrcData,NumChannels,SampleSize,chan,SizeToDo](ptrdiff_t CompLen, const ALbuffer *buffer) -> ptrdiff_t
  301. {
  302. if(DataPosInt >= buffer->SampleLen)
  303. return CompLen;
  304. /* Load what's left of this loop iteration */
  305. const ptrdiff_t DataSize{std::min<ptrdiff_t>(SizeToDo, buffer->SampleLen-DataPosInt)};
  306. CompLen = std::max<ptrdiff_t>(CompLen, DataSize);
  307. const ALbyte *Data{buffer->mData.data()};
  308. Data += (DataPosInt*NumChannels + chan)*SampleSize;
  309. LoadSamples(SrcData, Data, NumChannels, buffer->mFmtType, DataSize);
  310. return CompLen;
  311. };
  312. ASSUME(BufferListItem->num_buffers > 0);
  313. auto buffers_end = BufferListItem->buffers + BufferListItem->num_buffers;
  314. SrcData += std::accumulate(BufferListItem->buffers, buffers_end, ptrdiff_t{0},
  315. load_buffer);
  316. const auto LoopSize = static_cast<ptrdiff_t>(LoopEnd - LoopStart);
  317. while(SrcData != SrcDataEnd)
  318. {
  319. const ptrdiff_t SizeToDo{std::min<ptrdiff_t>(SrcDataEnd-SrcData, LoopSize)};
  320. ASSUME(SizeToDo > 0);
  321. auto load_buffer_loop = [LoopStart,SrcData,NumChannels,SampleSize,chan,SizeToDo](ptrdiff_t CompLen, const ALbuffer *buffer) -> ptrdiff_t
  322. {
  323. if(LoopStart >= buffer->SampleLen)
  324. return CompLen;
  325. const ptrdiff_t DataSize{std::min<ptrdiff_t>(SizeToDo,
  326. buffer->SampleLen-LoopStart)};
  327. CompLen = std::max<ptrdiff_t>(CompLen, DataSize);
  328. const ALbyte *Data{buffer->mData.data()};
  329. Data += (LoopStart*NumChannels + chan)*SampleSize;
  330. LoadSamples(SrcData, Data, NumChannels, buffer->mFmtType, DataSize);
  331. return CompLen;
  332. };
  333. SrcData += std::accumulate(BufferListItem->buffers, buffers_end, ptrdiff_t{0},
  334. load_buffer_loop);
  335. }
  336. }
  337. return SrcData;
  338. }
  339. ALfloat *LoadBufferQueue(ALbufferlistitem *BufferListItem, ALbufferlistitem *BufferLoopItem,
  340. const ALsizei NumChannels, const ALsizei SampleSize, const ALsizei chan, ALsizei DataPosInt,
  341. ALfloat *SrcData, const ALfloat *const SrcDataEnd)
  342. {
  343. /* Crawl the buffer queue to fill in the temp buffer */
  344. while(BufferListItem && SrcData != SrcDataEnd)
  345. {
  346. if(DataPosInt >= BufferListItem->max_samples)
  347. {
  348. DataPosInt -= BufferListItem->max_samples;
  349. BufferListItem = BufferListItem->next.load(std::memory_order_acquire);
  350. if(!BufferListItem) BufferListItem = BufferLoopItem;
  351. continue;
  352. }
  353. const ptrdiff_t SizeToDo{SrcDataEnd - SrcData};
  354. ASSUME(SizeToDo > 0);
  355. auto load_buffer = [DataPosInt,SrcData,NumChannels,SampleSize,chan,SizeToDo](ptrdiff_t CompLen, const ALbuffer *buffer) -> ptrdiff_t
  356. {
  357. if(!buffer) return CompLen;
  358. if(DataPosInt >= buffer->SampleLen)
  359. return CompLen;
  360. const ptrdiff_t DataSize{std::min<ptrdiff_t>(SizeToDo, buffer->SampleLen-DataPosInt)};
  361. CompLen = std::max<ptrdiff_t>(CompLen, DataSize);
  362. const ALbyte *Data{buffer->mData.data()};
  363. Data += (DataPosInt*NumChannels + chan)*SampleSize;
  364. LoadSamples(SrcData, Data, NumChannels, buffer->mFmtType, DataSize);
  365. return CompLen;
  366. };
  367. ASSUME(BufferListItem->num_buffers > 0);
  368. auto buffers_end = BufferListItem->buffers + BufferListItem->num_buffers;
  369. SrcData += std::accumulate(BufferListItem->buffers, buffers_end, ptrdiff_t{0u},
  370. load_buffer);
  371. if(SrcData == SrcDataEnd)
  372. break;
  373. DataPosInt = 0;
  374. BufferListItem = BufferListItem->next.load(std::memory_order_acquire);
  375. if(!BufferListItem) BufferListItem = BufferLoopItem;
  376. }
  377. return SrcData;
  378. }
  379. } // namespace
  380. void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCcontext *Context, const ALsizei SamplesToDo)
  381. {
  382. static constexpr ALfloat SilentTarget[MAX_OUTPUT_CHANNELS]{};
  383. ASSUME(SamplesToDo > 0);
  384. /* Get voice info */
  385. const bool isstatic{(voice->mFlags&VOICE_IS_STATIC) != 0};
  386. ALsizei DataPosInt{static_cast<ALsizei>(voice->mPosition.load(std::memory_order_relaxed))};
  387. ALsizei DataPosFrac{voice->mPositionFrac.load(std::memory_order_relaxed)};
  388. ALbufferlistitem *BufferListItem{voice->mCurrentBuffer.load(std::memory_order_relaxed)};
  389. ALbufferlistitem *BufferLoopItem{voice->mLoopBuffer.load(std::memory_order_relaxed)};
  390. const ALsizei NumChannels{voice->mNumChannels};
  391. const ALsizei SampleSize{voice->mSampleSize};
  392. const ALint increment{voice->mStep};
  393. ASSUME(DataPosInt >= 0);
  394. ASSUME(DataPosFrac >= 0);
  395. ASSUME(NumChannels > 0);
  396. ASSUME(SampleSize > 0);
  397. ASSUME(increment > 0);
  398. ALCdevice *Device{Context->Device};
  399. const ALsizei IrSize{Device->mHrtf ? Device->mHrtf->irSize : 0};
  400. ASSUME(IrSize >= 0);
  401. ResamplerFunc Resample{(increment == FRACTIONONE && DataPosFrac == 0) ?
  402. Resample_<CopyTag,CTag> : voice->mResampler};
  403. ALsizei Counter{(voice->mFlags&VOICE_IS_FADING) ? SamplesToDo : 0};
  404. if(!Counter)
  405. {
  406. /* No fading, just overwrite the old/current params. */
  407. for(ALsizei chan{0};chan < NumChannels;chan++)
  408. {
  409. DirectParams &parms = voice->mDirect.Params[chan];
  410. if(!(voice->mFlags&VOICE_HAS_HRTF))
  411. std::copy(std::begin(parms.Gains.Target), std::end(parms.Gains.Target),
  412. std::begin(parms.Gains.Current));
  413. else
  414. parms.Hrtf.Old = parms.Hrtf.Target;
  415. auto set_current = [chan](ALvoice::SendData &send) -> void
  416. {
  417. if(!send.Buffer)
  418. return;
  419. SendParams &parms = send.Params[chan];
  420. std::copy(std::begin(parms.Gains.Target), std::end(parms.Gains.Target),
  421. std::begin(parms.Gains.Current));
  422. };
  423. std::for_each(voice->mSend.begin(), voice->mSend.end(), set_current);
  424. }
  425. }
  426. else if((voice->mFlags&VOICE_HAS_HRTF))
  427. {
  428. for(ALsizei chan{0};chan < NumChannels;chan++)
  429. {
  430. DirectParams &parms = voice->mDirect.Params[chan];
  431. if(!(parms.Hrtf.Old.Gain > GAIN_SILENCE_THRESHOLD))
  432. {
  433. /* The old HRTF params are silent, so overwrite the old
  434. * coefficients with the new, and reset the old gain to 0. The
  435. * future mix will then fade from silence.
  436. */
  437. parms.Hrtf.Old = parms.Hrtf.Target;
  438. parms.Hrtf.Old.Gain = 0.0f;
  439. }
  440. }
  441. }
  442. ALsizei buffers_done{0};
  443. ALsizei OutPos{0};
  444. do {
  445. /* Figure out how many buffer samples will be needed */
  446. ALsizei DstBufferSize{SamplesToDo - OutPos};
  447. /* Calculate the last written dst sample pos. */
  448. int64_t DataSize64{DstBufferSize - 1};
  449. /* Calculate the last read src sample pos. */
  450. DataSize64 = (DataSize64*increment + DataPosFrac) >> FRACTIONBITS;
  451. /* +1 to get the src sample count, include padding. */
  452. DataSize64 += 1 + MAX_RESAMPLE_PADDING*2;
  453. auto SrcBufferSize = static_cast<ALsizei>(
  454. mini64(DataSize64, BUFFERSIZE + MAX_RESAMPLE_PADDING*2 + 1));
  455. if(SrcBufferSize > BUFFERSIZE + MAX_RESAMPLE_PADDING*2)
  456. {
  457. SrcBufferSize = BUFFERSIZE + MAX_RESAMPLE_PADDING*2;
  458. /* If the source buffer got saturated, we can't fill the desired
  459. * dst size. Figure out how many samples we can actually mix from
  460. * this.
  461. */
  462. DataSize64 = SrcBufferSize - MAX_RESAMPLE_PADDING*2;
  463. DataSize64 = ((DataSize64<<FRACTIONBITS) - DataPosFrac + increment-1) / increment;
  464. DstBufferSize = static_cast<ALsizei>(mini64(DataSize64, DstBufferSize));
  465. /* Some mixers like having a multiple of 4, so try to give that
  466. * unless this is the last update.
  467. */
  468. if(DstBufferSize < SamplesToDo-OutPos)
  469. DstBufferSize &= ~3;
  470. }
  471. for(ALsizei chan{0};chan < NumChannels;chan++)
  472. {
  473. auto &SrcData = Device->SourceData;
  474. /* Load the previous samples into the source data first, and clear the rest. */
  475. auto srciter = std::copy_n(voice->mResampleData[chan].mPrevSamples.begin(),
  476. MAX_RESAMPLE_PADDING, std::begin(SrcData));
  477. std::fill(srciter, std::end(SrcData), 0.0f);
  478. auto srcdata_end = std::begin(SrcData) + SrcBufferSize;
  479. if(UNLIKELY(!BufferListItem))
  480. srciter = std::copy(
  481. voice->mResampleData[chan].mPrevSamples.begin()+MAX_RESAMPLE_PADDING,
  482. voice->mResampleData[chan].mPrevSamples.end(), srciter);
  483. else if(isstatic)
  484. srciter = LoadBufferStatic(BufferListItem, BufferLoopItem, NumChannels,
  485. SampleSize, chan, DataPosInt, srciter, srcdata_end);
  486. else
  487. srciter = LoadBufferQueue(BufferListItem, BufferLoopItem, NumChannels,
  488. SampleSize, chan, DataPosInt, srciter, srcdata_end);
  489. if(UNLIKELY(srciter != srcdata_end))
  490. {
  491. /* If the source buffer wasn't filled, copy the last sample for
  492. * the remaining buffer. Ideally it should have ended with
  493. * silence, but if not the gain fading should help avoid clicks
  494. * from sudden amplitude changes.
  495. */
  496. const ALfloat sample{*(srciter-1)};
  497. std::fill(srciter, srcdata_end, sample);
  498. }
  499. /* Store the last source samples used for next time. */
  500. std::copy_n(&SrcData[(increment*DstBufferSize + DataPosFrac)>>FRACTIONBITS],
  501. voice->mResampleData[chan].mPrevSamples.size(),
  502. voice->mResampleData[chan].mPrevSamples.begin());
  503. /* Resample, then apply ambisonic upsampling as needed. */
  504. const ALfloat *ResampledData{Resample(&voice->mResampleState,
  505. &SrcData[MAX_RESAMPLE_PADDING], DataPosFrac, increment,
  506. Device->ResampledData, DstBufferSize)};
  507. if((voice->mFlags&VOICE_IS_AMBISONIC))
  508. {
  509. const ALfloat hfscale{voice->mResampleData[chan].mAmbiScale};
  510. /* Beware the evil const_cast. It's safe since it's pointing to
  511. * either SrcData or Device->ResampledData (both non-const),
  512. * but the resample method takes its input as const float* and
  513. * may return it without copying to output, making it currently
  514. * unavoidable.
  515. */
  516. voice->mResampleData[chan].mAmbiSplitter.applyHfScale(
  517. const_cast<ALfloat*>(ResampledData), hfscale, DstBufferSize);
  518. }
  519. /* Now filter and mix to the appropriate outputs. */
  520. {
  521. DirectParams &parms = voice->mDirect.Params[chan];
  522. const ALfloat *samples{DoFilters(&parms.LowPass, &parms.HighPass,
  523. Device->FilteredData, ResampledData, DstBufferSize,
  524. voice->mDirect.FilterType)};
  525. if((voice->mFlags&VOICE_HAS_HRTF))
  526. {
  527. const int OutLIdx{GetChannelIdxByName(Device->RealOut, FrontLeft)};
  528. const int OutRIdx{GetChannelIdxByName(Device->RealOut, FrontRight)};
  529. ASSUME(OutLIdx >= 0 && OutRIdx >= 0);
  530. auto &HrtfSamples = Device->HrtfSourceData;
  531. auto &AccumSamples = Device->HrtfAccumData;
  532. const ALfloat TargetGain{UNLIKELY(vstate == ALvoice::Stopping) ? 0.0f :
  533. parms.Hrtf.Target.Gain};
  534. ALsizei fademix{0};
  535. /* Copy the HRTF history and new input samples into a temp
  536. * buffer.
  537. */
  538. auto src_iter = std::copy(parms.Hrtf.State.History.begin(),
  539. parms.Hrtf.State.History.end(), std::begin(HrtfSamples));
  540. std::copy_n(samples, DstBufferSize, src_iter);
  541. /* Copy the last used samples back into the history buffer
  542. * for later.
  543. */
  544. std::copy_n(std::begin(HrtfSamples) + DstBufferSize,
  545. parms.Hrtf.State.History.size(), parms.Hrtf.State.History.begin());
  546. /* Copy the current filtered values being accumulated into
  547. * the temp buffer.
  548. */
  549. auto accum_iter = std::copy_n(parms.Hrtf.State.Values.begin(),
  550. parms.Hrtf.State.Values.size(), std::begin(AccumSamples));
  551. /* Clear the accumulation buffer that will start getting
  552. * filled in.
  553. */
  554. std::fill_n(accum_iter, DstBufferSize, float2{});
  555. /* If fading, the old gain is not silence, and this is the
  556. * first mixing pass, fade between the IRs.
  557. */
  558. if(Counter && (parms.Hrtf.Old.Gain > GAIN_SILENCE_THRESHOLD) && OutPos == 0)
  559. {
  560. fademix = mini(DstBufferSize, 128);
  561. ALfloat gain{TargetGain};
  562. /* The new coefficients need to fade in completely
  563. * since they're replacing the old ones. To keep the
  564. * gain fading consistent, interpolate between the old
  565. * and new target gains given how much of the fade time
  566. * this mix handles.
  567. */
  568. if(LIKELY(Counter > fademix))
  569. {
  570. const ALfloat a{static_cast<ALfloat>(fademix) /
  571. static_cast<ALfloat>(Counter)};
  572. gain = lerp(parms.Hrtf.Old.Gain, TargetGain, a);
  573. }
  574. MixHrtfParams hrtfparams;
  575. hrtfparams.Coeffs = &parms.Hrtf.Target.Coeffs;
  576. hrtfparams.Delay[0] = parms.Hrtf.Target.Delay[0];
  577. hrtfparams.Delay[1] = parms.Hrtf.Target.Delay[1];
  578. hrtfparams.Gain = 0.0f;
  579. hrtfparams.GainStep = gain / static_cast<ALfloat>(fademix);
  580. MixHrtfBlendSamples(
  581. voice->mDirect.Buffer[OutLIdx], voice->mDirect.Buffer[OutRIdx],
  582. HrtfSamples, AccumSamples, OutPos, IrSize, &parms.Hrtf.Old,
  583. &hrtfparams, fademix);
  584. /* Update the old parameters with the result. */
  585. parms.Hrtf.Old = parms.Hrtf.Target;
  586. if(fademix < Counter)
  587. parms.Hrtf.Old.Gain = hrtfparams.Gain;
  588. else
  589. parms.Hrtf.Old.Gain = TargetGain;
  590. }
  591. if(LIKELY(fademix < DstBufferSize))
  592. {
  593. const ALsizei todo{DstBufferSize - fademix};
  594. ALfloat gain{TargetGain};
  595. /* Interpolate the target gain if the gain fading lasts
  596. * longer than this mix.
  597. */
  598. if(Counter > DstBufferSize)
  599. {
  600. const ALfloat a{static_cast<ALfloat>(todo) /
  601. static_cast<ALfloat>(Counter-fademix)};
  602. gain = lerp(parms.Hrtf.Old.Gain, TargetGain, a);
  603. }
  604. MixHrtfParams hrtfparams;
  605. hrtfparams.Coeffs = &parms.Hrtf.Target.Coeffs;
  606. hrtfparams.Delay[0] = parms.Hrtf.Target.Delay[0];
  607. hrtfparams.Delay[1] = parms.Hrtf.Target.Delay[1];
  608. hrtfparams.Gain = parms.Hrtf.Old.Gain;
  609. hrtfparams.GainStep = (gain - parms.Hrtf.Old.Gain) /
  610. static_cast<ALfloat>(todo);
  611. MixHrtfSamples(
  612. voice->mDirect.Buffer[OutLIdx], voice->mDirect.Buffer[OutRIdx],
  613. HrtfSamples+fademix, AccumSamples+fademix, OutPos+fademix, IrSize,
  614. &hrtfparams, todo);
  615. /* Store the interpolated gain or the final target gain
  616. * depending if the fade is done.
  617. */
  618. if(DstBufferSize < Counter)
  619. parms.Hrtf.Old.Gain = gain;
  620. else
  621. parms.Hrtf.Old.Gain = TargetGain;
  622. }
  623. /* Copy the new in-progress accumulation values back for
  624. * the next mix.
  625. */
  626. std::copy_n(std::begin(AccumSamples) + DstBufferSize,
  627. parms.Hrtf.State.Values.size(), parms.Hrtf.State.Values.begin());
  628. }
  629. else if((voice->mFlags&VOICE_HAS_NFC))
  630. {
  631. const ALfloat *TargetGains{UNLIKELY(vstate == ALvoice::Stopping) ?
  632. SilentTarget : parms.Gains.Target};
  633. MixSamples(samples, voice->mDirect.ChannelsPerOrder[0],
  634. voice->mDirect.Buffer, parms.Gains.Current, TargetGains, Counter,
  635. OutPos, DstBufferSize);
  636. ALfloat (&nfcsamples)[BUFFERSIZE] = Device->NfcSampleData;
  637. ALsizei chanoffset{voice->mDirect.ChannelsPerOrder[0]};
  638. using FilterProc = void (NfcFilter::*)(float*,const float*,int);
  639. auto apply_nfc = [voice,&parms,samples,TargetGains,DstBufferSize,Counter,OutPos,&chanoffset,&nfcsamples](FilterProc process, ALsizei order) -> void
  640. {
  641. if(voice->mDirect.ChannelsPerOrder[order] < 1)
  642. return;
  643. (parms.NFCtrlFilter.*process)(nfcsamples, samples, DstBufferSize);
  644. MixSamples(nfcsamples, voice->mDirect.ChannelsPerOrder[order],
  645. voice->mDirect.Buffer+chanoffset, parms.Gains.Current+chanoffset,
  646. TargetGains+chanoffset, Counter, OutPos, DstBufferSize);
  647. chanoffset += voice->mDirect.ChannelsPerOrder[order];
  648. };
  649. apply_nfc(&NfcFilter::process1, 1);
  650. apply_nfc(&NfcFilter::process2, 2);
  651. apply_nfc(&NfcFilter::process3, 3);
  652. }
  653. else
  654. {
  655. const ALfloat *TargetGains{UNLIKELY(vstate == ALvoice::Stopping) ?
  656. SilentTarget : parms.Gains.Target};
  657. MixSamples(samples, voice->mDirect.Channels, voice->mDirect.Buffer,
  658. parms.Gains.Current, TargetGains, Counter, OutPos, DstBufferSize);
  659. }
  660. }
  661. ALfloat (&FilterBuf)[BUFFERSIZE] = Device->FilteredData;
  662. auto mix_send = [vstate,Counter,OutPos,DstBufferSize,chan,ResampledData,&FilterBuf](ALvoice::SendData &send) -> void
  663. {
  664. if(!send.Buffer)
  665. return;
  666. SendParams &parms = send.Params[chan];
  667. const ALfloat *samples{DoFilters(&parms.LowPass, &parms.HighPass,
  668. FilterBuf, ResampledData, DstBufferSize, send.FilterType)};
  669. const ALfloat *TargetGains{UNLIKELY(vstate==ALvoice::Stopping) ? SilentTarget :
  670. parms.Gains.Target};
  671. MixSamples(samples, send.Channels, send.Buffer, parms.Gains.Current,
  672. TargetGains, Counter, OutPos, DstBufferSize);
  673. };
  674. std::for_each(voice->mSend.begin(), voice->mSend.end(), mix_send);
  675. }
  676. /* Update positions */
  677. DataPosFrac += increment*DstBufferSize;
  678. DataPosInt += DataPosFrac>>FRACTIONBITS;
  679. DataPosFrac &= FRACTIONMASK;
  680. OutPos += DstBufferSize;
  681. Counter = maxi(DstBufferSize, Counter) - DstBufferSize;
  682. if(UNLIKELY(!BufferListItem))
  683. {
  684. /* Do nothing extra when there's no buffers. */
  685. }
  686. else if(isstatic)
  687. {
  688. if(BufferLoopItem)
  689. {
  690. /* Handle looping static source */
  691. const ALbuffer *Buffer{BufferListItem->buffers[0]};
  692. const ALsizei LoopStart{Buffer->LoopStart};
  693. const ALsizei LoopEnd{Buffer->LoopEnd};
  694. if(DataPosInt >= LoopEnd)
  695. {
  696. assert(LoopEnd > LoopStart);
  697. DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
  698. }
  699. }
  700. else
  701. {
  702. /* Handle non-looping static source */
  703. if(DataPosInt >= BufferListItem->max_samples)
  704. {
  705. if(LIKELY(vstate == ALvoice::Playing))
  706. vstate = ALvoice::Stopped;
  707. BufferListItem = nullptr;
  708. break;
  709. }
  710. }
  711. }
  712. else while(1)
  713. {
  714. /* Handle streaming source */
  715. if(BufferListItem->max_samples > DataPosInt)
  716. break;
  717. DataPosInt -= BufferListItem->max_samples;
  718. buffers_done += BufferListItem->num_buffers;
  719. BufferListItem = BufferListItem->next.load(std::memory_order_relaxed);
  720. if(!BufferListItem && !(BufferListItem=BufferLoopItem))
  721. {
  722. if(LIKELY(vstate == ALvoice::Playing))
  723. vstate = ALvoice::Stopped;
  724. break;
  725. }
  726. }
  727. } while(OutPos < SamplesToDo);
  728. voice->mFlags |= VOICE_IS_FADING;
  729. /* Don't update positions and buffers if we were stopping. */
  730. if(UNLIKELY(vstate == ALvoice::Stopping))
  731. {
  732. voice->mPlayState.store(ALvoice::Stopped, std::memory_order_release);
  733. return;
  734. }
  735. /* Update voice info */
  736. voice->mPosition.store(DataPosInt, std::memory_order_relaxed);
  737. voice->mPositionFrac.store(DataPosFrac, std::memory_order_relaxed);
  738. voice->mCurrentBuffer.store(BufferListItem, std::memory_order_relaxed);
  739. if(vstate == ALvoice::Stopped)
  740. {
  741. voice->mLoopBuffer.store(nullptr, std::memory_order_relaxed);
  742. voice->mSourceID.store(0u, std::memory_order_relaxed);
  743. }
  744. std::atomic_thread_fence(std::memory_order_release);
  745. /* Send any events now, after the position/buffer info was updated. */
  746. ALbitfieldSOFT enabledevt{Context->EnabledEvts.load(std::memory_order_acquire)};
  747. if(buffers_done > 0 && (enabledevt&EventType_BufferCompleted))
  748. {
  749. RingBuffer *ring{Context->AsyncEvents.get()};
  750. auto evt_vec = ring->getWriteVector();
  751. if(evt_vec.first.len > 0)
  752. {
  753. AsyncEvent *evt{new (evt_vec.first.buf) AsyncEvent{EventType_BufferCompleted}};
  754. evt->u.bufcomp.id = SourceID;
  755. evt->u.bufcomp.count = buffers_done;
  756. ring->writeAdvance(1);
  757. Context->EventSem.post();
  758. }
  759. }
  760. if(vstate == ALvoice::Stopped)
  761. {
  762. /* If the voice just ended, set it to Stopping so the next render
  763. * ensures any residual noise fades to 0 amplitude.
  764. */
  765. voice->mPlayState.store(ALvoice::Stopping, std::memory_order_release);
  766. SendSourceStoppedEvent(Context, SourceID);
  767. }
  768. }