alu.cpp 74 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018
  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 "alu.h"
  22. #include <algorithm>
  23. #include <array>
  24. #include <atomic>
  25. #include <cassert>
  26. #include <chrono>
  27. #include <climits>
  28. #include <cmath>
  29. #include <cstdarg>
  30. #include <cstdio>
  31. #include <cstdlib>
  32. #include <functional>
  33. #include <iterator>
  34. #include <limits>
  35. #include <memory>
  36. #include <new>
  37. #include <numeric>
  38. #include <utility>
  39. #include "AL/al.h"
  40. #include "AL/alc.h"
  41. #include "AL/efx.h"
  42. #include "alcmain.h"
  43. #include "alcontext.h"
  44. #include "almalloc.h"
  45. #include "alnumeric.h"
  46. #include "alspan.h"
  47. #include "alstring.h"
  48. #include "async_event.h"
  49. #include "atomic.h"
  50. #include "bformatdec.h"
  51. #include "core/ambidefs.h"
  52. #include "core/bs2b.h"
  53. #include "core/bsinc_tables.h"
  54. #include "core/cpu_caps.h"
  55. #include "core/devformat.h"
  56. #include "core/filters/biquad.h"
  57. #include "core/filters/nfc.h"
  58. #include "core/filters/splitter.h"
  59. #include "core/fpu_ctrl.h"
  60. #include "core/mastering.h"
  61. #include "core/mixer/defs.h"
  62. #include "core/uhjfilter.h"
  63. #include "effects/base.h"
  64. #include "effectslot.h"
  65. #include "front_stablizer.h"
  66. #include "hrtf.h"
  67. #include "inprogext.h"
  68. #include "math_defs.h"
  69. #include "opthelpers.h"
  70. #include "ringbuffer.h"
  71. #include "strutils.h"
  72. #include "threads.h"
  73. #include "vecmat.h"
  74. #include "voice.h"
  75. #include "voice_change.h"
  76. struct CTag;
  77. #ifdef HAVE_SSE
  78. struct SSETag;
  79. #endif
  80. #ifdef HAVE_SSE2
  81. struct SSE2Tag;
  82. #endif
  83. #ifdef HAVE_SSE4_1
  84. struct SSE4Tag;
  85. #endif
  86. #ifdef HAVE_NEON
  87. struct NEONTag;
  88. #endif
  89. struct CopyTag;
  90. struct PointTag;
  91. struct LerpTag;
  92. struct CubicTag;
  93. struct BSincTag;
  94. struct FastBSincTag;
  95. static_assert(MaxResamplerPadding >= BSincPointsMax, "MaxResamplerPadding is too small");
  96. static_assert(!(MaxResamplerPadding&1), "MaxResamplerPadding is not a multiple of two");
  97. namespace {
  98. constexpr uint MaxPitch{10};
  99. static_assert((BufferLineSize-1)/MaxPitch > 0, "MaxPitch is too large for BufferLineSize!");
  100. static_assert((INT_MAX>>MixerFracBits)/MaxPitch > BufferLineSize,
  101. "MaxPitch and/or BufferLineSize are too large for MixerFracBits!");
  102. using namespace std::placeholders;
  103. float InitConeScale()
  104. {
  105. float ret{1.0f};
  106. if(auto optval = al::getenv("__ALSOFT_HALF_ANGLE_CONES"))
  107. {
  108. if(al::strcasecmp(optval->c_str(), "true") == 0
  109. || strtol(optval->c_str(), nullptr, 0) == 1)
  110. ret *= 0.5f;
  111. }
  112. return ret;
  113. }
  114. float InitZScale()
  115. {
  116. float ret{1.0f};
  117. if(auto optval = al::getenv("__ALSOFT_REVERSE_Z"))
  118. {
  119. if(al::strcasecmp(optval->c_str(), "true") == 0
  120. || strtol(optval->c_str(), nullptr, 0) == 1)
  121. ret *= -1.0f;
  122. }
  123. return ret;
  124. }
  125. } // namespace
  126. /* Cone scalar */
  127. const float ConeScale{InitConeScale()};
  128. /* Localized Z scalar for mono sources */
  129. const float ZScale{InitZScale()};
  130. namespace {
  131. struct ChanMap {
  132. Channel channel;
  133. float angle;
  134. float elevation;
  135. };
  136. using HrtfDirectMixerFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &RightOut,
  137. const al::span<const FloatBufferLine> InSamples, float2 *AccumSamples,
  138. float *TempBuf, HrtfChannelState *ChanState, const size_t IrSize, const size_t BufferSize);
  139. HrtfDirectMixerFunc MixDirectHrtf{MixDirectHrtf_<CTag>};
  140. inline HrtfDirectMixerFunc SelectHrtfMixer(void)
  141. {
  142. #ifdef HAVE_NEON
  143. if((CPUCapFlags&CPU_CAP_NEON))
  144. return MixDirectHrtf_<NEONTag>;
  145. #endif
  146. #ifdef HAVE_SSE
  147. if((CPUCapFlags&CPU_CAP_SSE))
  148. return MixDirectHrtf_<SSETag>;
  149. #endif
  150. return MixDirectHrtf_<CTag>;
  151. }
  152. inline void BsincPrepare(const uint increment, BsincState *state, const BSincTable *table)
  153. {
  154. size_t si{BSincScaleCount - 1};
  155. float sf{0.0f};
  156. if(increment > MixerFracOne)
  157. {
  158. sf = MixerFracOne / static_cast<float>(increment);
  159. sf = maxf(0.0f, (BSincScaleCount-1) * (sf-table->scaleBase) * table->scaleRange);
  160. si = float2uint(sf);
  161. /* The interpolation factor is fit to this diagonally-symmetric curve
  162. * to reduce the transition ripple caused by interpolating different
  163. * scales of the sinc function.
  164. */
  165. sf = 1.0f - std::cos(std::asin(sf - static_cast<float>(si)));
  166. }
  167. state->sf = sf;
  168. state->m = table->m[si];
  169. state->l = (state->m/2) - 1;
  170. state->filter = table->Tab + table->filterOffset[si];
  171. }
  172. inline ResamplerFunc SelectResampler(Resampler resampler, uint increment)
  173. {
  174. switch(resampler)
  175. {
  176. case Resampler::Point:
  177. return Resample_<PointTag,CTag>;
  178. case Resampler::Linear:
  179. #ifdef HAVE_NEON
  180. if((CPUCapFlags&CPU_CAP_NEON))
  181. return Resample_<LerpTag,NEONTag>;
  182. #endif
  183. #ifdef HAVE_SSE4_1
  184. if((CPUCapFlags&CPU_CAP_SSE4_1))
  185. return Resample_<LerpTag,SSE4Tag>;
  186. #endif
  187. #ifdef HAVE_SSE2
  188. if((CPUCapFlags&CPU_CAP_SSE2))
  189. return Resample_<LerpTag,SSE2Tag>;
  190. #endif
  191. return Resample_<LerpTag,CTag>;
  192. case Resampler::Cubic:
  193. return Resample_<CubicTag,CTag>;
  194. case Resampler::BSinc12:
  195. case Resampler::BSinc24:
  196. if(increment <= MixerFracOne)
  197. {
  198. /* fall-through */
  199. case Resampler::FastBSinc12:
  200. case Resampler::FastBSinc24:
  201. #ifdef HAVE_NEON
  202. if((CPUCapFlags&CPU_CAP_NEON))
  203. return Resample_<FastBSincTag,NEONTag>;
  204. #endif
  205. #ifdef HAVE_SSE
  206. if((CPUCapFlags&CPU_CAP_SSE))
  207. return Resample_<FastBSincTag,SSETag>;
  208. #endif
  209. return Resample_<FastBSincTag,CTag>;
  210. }
  211. #ifdef HAVE_NEON
  212. if((CPUCapFlags&CPU_CAP_NEON))
  213. return Resample_<BSincTag,NEONTag>;
  214. #endif
  215. #ifdef HAVE_SSE
  216. if((CPUCapFlags&CPU_CAP_SSE))
  217. return Resample_<BSincTag,SSETag>;
  218. #endif
  219. return Resample_<BSincTag,CTag>;
  220. }
  221. return Resample_<PointTag,CTag>;
  222. }
  223. } // namespace
  224. void aluInit(void)
  225. {
  226. MixDirectHrtf = SelectHrtfMixer();
  227. }
  228. ResamplerFunc PrepareResampler(Resampler resampler, uint increment, InterpState *state)
  229. {
  230. switch(resampler)
  231. {
  232. case Resampler::Point:
  233. case Resampler::Linear:
  234. case Resampler::Cubic:
  235. break;
  236. case Resampler::FastBSinc12:
  237. case Resampler::BSinc12:
  238. BsincPrepare(increment, &state->bsinc, &bsinc12);
  239. break;
  240. case Resampler::FastBSinc24:
  241. case Resampler::BSinc24:
  242. BsincPrepare(increment, &state->bsinc, &bsinc24);
  243. break;
  244. }
  245. return SelectResampler(resampler, increment);
  246. }
  247. void ALCdevice::ProcessHrtf(const size_t SamplesToDo)
  248. {
  249. /* HRTF is stereo output only. */
  250. const uint lidx{RealOut.ChannelIndex[FrontLeft]};
  251. const uint ridx{RealOut.ChannelIndex[FrontRight]};
  252. MixDirectHrtf(RealOut.Buffer[lidx], RealOut.Buffer[ridx], Dry.Buffer, HrtfAccumData,
  253. mHrtfState->mTemp.data(), mHrtfState->mChannels.data(), mHrtfState->mIrSize, SamplesToDo);
  254. }
  255. void ALCdevice::ProcessAmbiDec(const size_t SamplesToDo)
  256. {
  257. AmbiDecoder->process(RealOut.Buffer, Dry.Buffer.data(), SamplesToDo);
  258. }
  259. void ALCdevice::ProcessAmbiDecStablized(const size_t SamplesToDo)
  260. {
  261. /* Decode with front image stablization. */
  262. const uint lidx{RealOut.ChannelIndex[FrontLeft]};
  263. const uint ridx{RealOut.ChannelIndex[FrontRight]};
  264. const uint cidx{RealOut.ChannelIndex[FrontCenter]};
  265. AmbiDecoder->processStablize(RealOut.Buffer, Dry.Buffer.data(), lidx, ridx, cidx,
  266. SamplesToDo);
  267. }
  268. void ALCdevice::ProcessUhj(const size_t SamplesToDo)
  269. {
  270. /* UHJ is stereo output only. */
  271. const uint lidx{RealOut.ChannelIndex[FrontLeft]};
  272. const uint ridx{RealOut.ChannelIndex[FrontRight]};
  273. /* Encode to stereo-compatible 2-channel UHJ output. */
  274. Uhj_Encoder->encode(RealOut.Buffer[lidx], RealOut.Buffer[ridx], Dry.Buffer.data(),
  275. SamplesToDo);
  276. }
  277. void ALCdevice::ProcessBs2b(const size_t SamplesToDo)
  278. {
  279. /* First, decode the ambisonic mix to the "real" output. */
  280. AmbiDecoder->process(RealOut.Buffer, Dry.Buffer.data(), SamplesToDo);
  281. /* BS2B is stereo output only. */
  282. const uint lidx{RealOut.ChannelIndex[FrontLeft]};
  283. const uint ridx{RealOut.ChannelIndex[FrontRight]};
  284. /* Now apply the BS2B binaural/crossfeed filter. */
  285. bs2b_cross_feed(Bs2b.get(), RealOut.Buffer[lidx].data(), RealOut.Buffer[ridx].data(),
  286. SamplesToDo);
  287. }
  288. namespace {
  289. /* This RNG method was created based on the math found in opusdec. It's quick,
  290. * and starting with a seed value of 22222, is suitable for generating
  291. * whitenoise.
  292. */
  293. inline uint dither_rng(uint *seed) noexcept
  294. {
  295. *seed = (*seed * 96314165) + 907633515;
  296. return *seed;
  297. }
  298. inline auto& GetAmbiScales(AmbiScaling scaletype) noexcept
  299. {
  300. if(scaletype == AmbiScaling::FuMa) return AmbiScale::FromFuMa();
  301. if(scaletype == AmbiScaling::SN3D) return AmbiScale::FromSN3D();
  302. return AmbiScale::FromN3D();
  303. }
  304. inline auto& GetAmbiLayout(AmbiLayout layouttype) noexcept
  305. {
  306. if(layouttype == AmbiLayout::FuMa) return AmbiIndex::FromFuMa();
  307. return AmbiIndex::FromACN();
  308. }
  309. inline auto& GetAmbi2DLayout(AmbiLayout layouttype) noexcept
  310. {
  311. if(layouttype == AmbiLayout::FuMa) return AmbiIndex::FromFuMa2D();
  312. return AmbiIndex::FromACN2D();
  313. }
  314. bool CalcContextParams(ALCcontext *ctx)
  315. {
  316. ContextProps *props{ctx->mParams.ContextUpdate.exchange(nullptr, std::memory_order_acq_rel)};
  317. if(!props) return false;
  318. ctx->mParams.DopplerFactor = props->DopplerFactor;
  319. ctx->mParams.SpeedOfSound = props->SpeedOfSound * props->DopplerVelocity;
  320. ctx->mParams.SourceDistanceModel = props->SourceDistanceModel;
  321. ctx->mParams.mDistanceModel = props->mDistanceModel;
  322. AtomicReplaceHead(ctx->mFreeContextProps, props);
  323. return true;
  324. }
  325. bool CalcListenerParams(ALCcontext *ctx)
  326. {
  327. ListenerProps *props{ctx->mParams.ListenerUpdate.exchange(nullptr,
  328. std::memory_order_acq_rel)};
  329. if(!props) return false;
  330. /* AT then UP */
  331. alu::Vector N{props->OrientAt[0], props->OrientAt[1], props->OrientAt[2], 0.0f};
  332. N.normalize();
  333. alu::Vector V{props->OrientUp[0], props->OrientUp[1], props->OrientUp[2], 0.0f};
  334. V.normalize();
  335. /* Build and normalize right-vector */
  336. alu::Vector U{N.cross_product(V)};
  337. U.normalize();
  338. const alu::MatrixR<double> rot{
  339. U[0], V[0], -N[0], 0.0,
  340. U[1], V[1], -N[1], 0.0,
  341. U[2], V[2], -N[2], 0.0,
  342. 0.0, 0.0, 0.0, 1.0};
  343. const alu::VectorR<double> pos{props->Position[0],props->Position[1],props->Position[2],1.0};
  344. const alu::VectorR<double> vel{props->Velocity[0],props->Velocity[1],props->Velocity[2],0.0};
  345. const alu::Vector P{alu::cast_to<float>(rot * pos)};
  346. ctx->mParams.Matrix = alu::Matrix{
  347. U[0], V[0], -N[0], 0.0f,
  348. U[1], V[1], -N[1], 0.0f,
  349. U[2], V[2], -N[2], 0.0f,
  350. -P[0], -P[1], -P[2], 1.0f};
  351. ctx->mParams.Velocity = alu::cast_to<float>(rot * vel);
  352. ctx->mParams.Gain = props->Gain * ctx->mGainBoost;
  353. ctx->mParams.MetersPerUnit = props->MetersPerUnit;
  354. AtomicReplaceHead(ctx->mFreeListenerProps, props);
  355. return true;
  356. }
  357. bool CalcEffectSlotParams(EffectSlot *slot, EffectSlot **sorted_slots, ALCcontext *context)
  358. {
  359. EffectSlotProps *props{slot->Update.exchange(nullptr, std::memory_order_acq_rel)};
  360. if(!props) return false;
  361. /* If the effect slot target changed, clear the first sorted entry to force
  362. * a re-sort.
  363. */
  364. if(slot->Target != props->Target)
  365. *sorted_slots = nullptr;
  366. slot->Gain = props->Gain;
  367. slot->AuxSendAuto = props->AuxSendAuto;
  368. slot->Target = props->Target;
  369. slot->EffectType = props->Type;
  370. slot->mEffectProps = props->Props;
  371. if(props->Type == EffectSlotType::Reverb || props->Type == EffectSlotType::EAXReverb)
  372. {
  373. slot->RoomRolloff = props->Props.Reverb.RoomRolloffFactor;
  374. slot->DecayTime = props->Props.Reverb.DecayTime;
  375. slot->DecayLFRatio = props->Props.Reverb.DecayLFRatio;
  376. slot->DecayHFRatio = props->Props.Reverb.DecayHFRatio;
  377. slot->DecayHFLimit = props->Props.Reverb.DecayHFLimit;
  378. slot->AirAbsorptionGainHF = props->Props.Reverb.AirAbsorptionGainHF;
  379. }
  380. else
  381. {
  382. slot->RoomRolloff = 0.0f;
  383. slot->DecayTime = 0.0f;
  384. slot->DecayLFRatio = 0.0f;
  385. slot->DecayHFRatio = 0.0f;
  386. slot->DecayHFLimit = false;
  387. slot->AirAbsorptionGainHF = 1.0f;
  388. }
  389. EffectState *state{props->State.release()};
  390. EffectState *oldstate{slot->mEffectState};
  391. slot->mEffectState = state;
  392. /* Only release the old state if it won't get deleted, since we can't be
  393. * deleting/freeing anything in the mixer.
  394. */
  395. if(!oldstate->releaseIfNoDelete())
  396. {
  397. /* Otherwise, if it would be deleted send it off with a release event. */
  398. RingBuffer *ring{context->mAsyncEvents.get()};
  399. auto evt_vec = ring->getWriteVector();
  400. if LIKELY(evt_vec.first.len > 0)
  401. {
  402. AsyncEvent *evt{::new(evt_vec.first.buf) AsyncEvent{EventType_ReleaseEffectState}};
  403. evt->u.mEffectState = oldstate;
  404. ring->writeAdvance(1);
  405. }
  406. else
  407. {
  408. /* If writing the event failed, the queue was probably full. Store
  409. * the old state in the property object where it can eventually be
  410. * cleaned up sometime later (not ideal, but better than blocking
  411. * or leaking).
  412. */
  413. props->State.reset(oldstate);
  414. }
  415. }
  416. AtomicReplaceHead(context->mFreeEffectslotProps, props);
  417. EffectTarget output;
  418. if(EffectSlot *target{slot->Target})
  419. output = EffectTarget{&target->Wet, nullptr};
  420. else
  421. {
  422. ALCdevice *device{context->mDevice.get()};
  423. output = EffectTarget{&device->Dry, &device->RealOut};
  424. }
  425. state->update(context, slot, &slot->mEffectProps, output);
  426. return true;
  427. }
  428. /* Scales the given azimuth toward the side (+/- pi/2 radians) for positions in
  429. * front.
  430. */
  431. inline float ScaleAzimuthFront(float azimuth, float scale)
  432. {
  433. const float abs_azi{std::fabs(azimuth)};
  434. if(!(abs_azi >= al::MathDefs<float>::Pi()*0.5f))
  435. return std::copysign(minf(abs_azi*scale, al::MathDefs<float>::Pi()*0.5f), azimuth);
  436. return azimuth;
  437. }
  438. /* Wraps the given value in radians to stay between [-pi,+pi] */
  439. inline float WrapRadians(float r)
  440. {
  441. constexpr float Pi{al::MathDefs<float>::Pi()};
  442. constexpr float Pi2{al::MathDefs<float>::Tau()};
  443. if(r > Pi) return std::fmod(Pi+r, Pi2) - Pi;
  444. if(r < -Pi) return Pi - std::fmod(Pi-r, Pi2);
  445. return r;
  446. }
  447. /* Begin ambisonic rotation helpers.
  448. *
  449. * Rotating first-order B-Format just needs a straight-forward X/Y/Z rotation
  450. * matrix. Higher orders, however, are more complicated. The method implemented
  451. * here is a recursive algorithm (the rotation for first-order is used to help
  452. * generate the second-order rotation, which helps generate the third-order
  453. * rotation, etc).
  454. *
  455. * Adapted from
  456. * <https://github.com/polarch/Spherical-Harmonic-Transform/blob/master/getSHrotMtx.m>,
  457. * provided under the BSD 3-Clause license.
  458. *
  459. * Copyright (c) 2015, Archontis Politis
  460. * Copyright (c) 2019, Christopher Robinson
  461. *
  462. * The u, v, and w coefficients used for generating higher-order rotations are
  463. * precomputed since they're constant. The second-order coefficients are
  464. * followed by the third-order coefficients, etc.
  465. */
  466. struct RotatorCoeffs {
  467. float u, v, w;
  468. template<size_t N0, size_t N1>
  469. static std::array<RotatorCoeffs,N0+N1> ConcatArrays(const std::array<RotatorCoeffs,N0> &lhs,
  470. const std::array<RotatorCoeffs,N1> &rhs)
  471. {
  472. std::array<RotatorCoeffs,N0+N1> ret;
  473. auto iter = std::copy(lhs.cbegin(), lhs.cend(), ret.begin());
  474. std::copy(rhs.cbegin(), rhs.cend(), iter);
  475. return ret;
  476. }
  477. template<int l, int num_elems=l*2+1>
  478. static std::array<RotatorCoeffs,num_elems*num_elems> GenCoeffs()
  479. {
  480. std::array<RotatorCoeffs,num_elems*num_elems> ret{};
  481. auto coeffs = ret.begin();
  482. for(int m{-l};m <= l;++m)
  483. {
  484. for(int n{-l};n <= l;++n)
  485. {
  486. // compute u,v,w terms of Eq.8.1 (Table I)
  487. const bool d{m == 0}; // the delta function d_m0
  488. const float denom{static_cast<float>((std::abs(n) == l) ?
  489. (2*l) * (2*l - 1) : (l*l - n*n))};
  490. const int abs_m{std::abs(m)};
  491. coeffs->u = std::sqrt(static_cast<float>(l*l - m*m)/denom);
  492. coeffs->v = std::sqrt(static_cast<float>(l+abs_m-1) * static_cast<float>(l+abs_m) /
  493. denom) * (1.0f+d) * (1.0f - 2.0f*d) * 0.5f;
  494. coeffs->w = std::sqrt(static_cast<float>(l-abs_m-1) * static_cast<float>(l-abs_m) /
  495. denom) * (1.0f-d) * -0.5f;
  496. ++coeffs;
  497. }
  498. }
  499. return ret;
  500. }
  501. };
  502. const auto RotatorCoeffArray = RotatorCoeffs::ConcatArrays(RotatorCoeffs::GenCoeffs<2>(),
  503. RotatorCoeffs::GenCoeffs<3>());
  504. /**
  505. * Given the matrix, pre-filled with the (zeroth- and) first-order rotation
  506. * coefficients, this fills in the coefficients for the higher orders up to and
  507. * including the given order. The matrix is in ACN layout.
  508. */
  509. void AmbiRotator(std::array<std::array<float,MaxAmbiChannels>,MaxAmbiChannels> &matrix,
  510. const int order)
  511. {
  512. /* Don't do anything for < 2nd order. */
  513. if(order < 2) return;
  514. auto P = [](const int i, const int l, const int a, const int n, const size_t last_band,
  515. const std::array<std::array<float,MaxAmbiChannels>,MaxAmbiChannels> &R)
  516. {
  517. const float ri1{ R[static_cast<uint>(i+2)][ 1+2]};
  518. const float rim1{R[static_cast<uint>(i+2)][-1+2]};
  519. const float ri0{ R[static_cast<uint>(i+2)][ 0+2]};
  520. auto vec = R[static_cast<uint>(a+l-1) + last_band].cbegin() + last_band;
  521. if(n == -l)
  522. return ri1*vec[0] + rim1*vec[static_cast<uint>(l-1)*size_t{2}];
  523. if(n == l)
  524. return ri1*vec[static_cast<uint>(l-1)*size_t{2}] - rim1*vec[0];
  525. return ri0*vec[static_cast<uint>(n+l-1)];
  526. };
  527. auto U = [P](const int l, const int m, const int n, const size_t last_band,
  528. const std::array<std::array<float,MaxAmbiChannels>,MaxAmbiChannels> &R)
  529. {
  530. return P(0, l, m, n, last_band, R);
  531. };
  532. auto V = [P](const int l, const int m, const int n, const size_t last_band,
  533. const std::array<std::array<float,MaxAmbiChannels>,MaxAmbiChannels> &R)
  534. {
  535. if(m > 0)
  536. {
  537. const bool d{m == 1};
  538. const float p0{P( 1, l, m-1, n, last_band, R)};
  539. const float p1{P(-1, l, -m+1, n, last_band, R)};
  540. return d ? p0*std::sqrt(2.0f) : (p0 - p1);
  541. }
  542. const bool d{m == -1};
  543. const float p0{P( 1, l, m+1, n, last_band, R)};
  544. const float p1{P(-1, l, -m-1, n, last_band, R)};
  545. return d ? p1*std::sqrt(2.0f) : (p0 + p1);
  546. };
  547. auto W = [P](const int l, const int m, const int n, const size_t last_band,
  548. const std::array<std::array<float,MaxAmbiChannels>,MaxAmbiChannels> &R)
  549. {
  550. assert(m != 0);
  551. if(m > 0)
  552. {
  553. const float p0{P( 1, l, m+1, n, last_band, R)};
  554. const float p1{P(-1, l, -m-1, n, last_band, R)};
  555. return p0 + p1;
  556. }
  557. const float p0{P( 1, l, m-1, n, last_band, R)};
  558. const float p1{P(-1, l, -m+1, n, last_band, R)};
  559. return p0 - p1;
  560. };
  561. // compute rotation matrix of each subsequent band recursively
  562. auto coeffs = RotatorCoeffArray.cbegin();
  563. size_t band_idx{4}, last_band{1};
  564. for(int l{2};l <= order;++l)
  565. {
  566. size_t y{band_idx};
  567. for(int m{-l};m <= l;++m,++y)
  568. {
  569. size_t x{band_idx};
  570. for(int n{-l};n <= l;++n,++x)
  571. {
  572. float r{0.0f};
  573. // computes Eq.8.1
  574. const float u{coeffs->u};
  575. if(u != 0.0f) r += u * U(l, m, n, last_band, matrix);
  576. const float v{coeffs->v};
  577. if(v != 0.0f) r += v * V(l, m, n, last_band, matrix);
  578. const float w{coeffs->w};
  579. if(w != 0.0f) r += w * W(l, m, n, last_band, matrix);
  580. matrix[y][x] = r;
  581. ++coeffs;
  582. }
  583. }
  584. last_band = band_idx;
  585. band_idx += static_cast<uint>(l)*size_t{2} + 1;
  586. }
  587. }
  588. /* End ambisonic rotation helpers. */
  589. struct GainTriplet { float Base, HF, LF; };
  590. void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, const float zpos,
  591. const float Distance, const float Spread, const GainTriplet &DryGain,
  592. const al::span<const GainTriplet,MAX_SENDS> WetGain, EffectSlot *(&SendSlots)[MAX_SENDS],
  593. const VoiceProps *props, const ContextParams &Context, const ALCdevice *Device)
  594. {
  595. static const ChanMap MonoMap[1]{
  596. { FrontCenter, 0.0f, 0.0f }
  597. }, RearMap[2]{
  598. { BackLeft, Deg2Rad(-150.0f), Deg2Rad(0.0f) },
  599. { BackRight, Deg2Rad( 150.0f), Deg2Rad(0.0f) }
  600. }, QuadMap[4]{
  601. { FrontLeft, Deg2Rad( -45.0f), Deg2Rad(0.0f) },
  602. { FrontRight, Deg2Rad( 45.0f), Deg2Rad(0.0f) },
  603. { BackLeft, Deg2Rad(-135.0f), Deg2Rad(0.0f) },
  604. { BackRight, Deg2Rad( 135.0f), Deg2Rad(0.0f) }
  605. }, X51Map[6]{
  606. { FrontLeft, Deg2Rad( -30.0f), Deg2Rad(0.0f) },
  607. { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) },
  608. { FrontCenter, Deg2Rad( 0.0f), Deg2Rad(0.0f) },
  609. { LFE, 0.0f, 0.0f },
  610. { SideLeft, Deg2Rad(-110.0f), Deg2Rad(0.0f) },
  611. { SideRight, Deg2Rad( 110.0f), Deg2Rad(0.0f) }
  612. }, X61Map[7]{
  613. { FrontLeft, Deg2Rad(-30.0f), Deg2Rad(0.0f) },
  614. { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) },
  615. { FrontCenter, Deg2Rad( 0.0f), Deg2Rad(0.0f) },
  616. { LFE, 0.0f, 0.0f },
  617. { BackCenter, Deg2Rad(180.0f), Deg2Rad(0.0f) },
  618. { SideLeft, Deg2Rad(-90.0f), Deg2Rad(0.0f) },
  619. { SideRight, Deg2Rad( 90.0f), Deg2Rad(0.0f) }
  620. }, X71Map[8]{
  621. { FrontLeft, Deg2Rad( -30.0f), Deg2Rad(0.0f) },
  622. { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) },
  623. { FrontCenter, Deg2Rad( 0.0f), Deg2Rad(0.0f) },
  624. { LFE, 0.0f, 0.0f },
  625. { BackLeft, Deg2Rad(-150.0f), Deg2Rad(0.0f) },
  626. { BackRight, Deg2Rad( 150.0f), Deg2Rad(0.0f) },
  627. { SideLeft, Deg2Rad( -90.0f), Deg2Rad(0.0f) },
  628. { SideRight, Deg2Rad( 90.0f), Deg2Rad(0.0f) }
  629. };
  630. ChanMap StereoMap[2]{
  631. { FrontLeft, Deg2Rad(-30.0f), Deg2Rad(0.0f) },
  632. { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) }
  633. };
  634. const auto Frequency = static_cast<float>(Device->Frequency);
  635. const uint NumSends{Device->NumAuxSends};
  636. const size_t num_channels{voice->mChans.size()};
  637. ASSUME(num_channels > 0);
  638. for(auto &chandata : voice->mChans)
  639. {
  640. chandata.mDryParams.Hrtf.Target = HrtfFilter{};
  641. chandata.mDryParams.Gains.Target.fill(0.0f);
  642. std::for_each(chandata.mWetParams.begin(), chandata.mWetParams.begin()+NumSends,
  643. [](SendParams &params) -> void { params.Gains.Target.fill(0.0f); });
  644. }
  645. DirectMode DirectChannels{props->DirectChannels};
  646. const ChanMap *chans{nullptr};
  647. float downmix_gain{1.0f};
  648. switch(voice->mFmtChannels)
  649. {
  650. case FmtMono:
  651. chans = MonoMap;
  652. /* Mono buffers are never played direct. */
  653. DirectChannels = DirectMode::Off;
  654. break;
  655. case FmtStereo:
  656. if(DirectChannels == DirectMode::Off)
  657. {
  658. /* Convert counter-clockwise to clock-wise, and wrap between
  659. * [-pi,+pi].
  660. */
  661. StereoMap[0].angle = WrapRadians(-props->StereoPan[0]);
  662. StereoMap[1].angle = WrapRadians(-props->StereoPan[1]);
  663. }
  664. chans = StereoMap;
  665. downmix_gain = 1.0f / 2.0f;
  666. break;
  667. case FmtRear:
  668. chans = RearMap;
  669. downmix_gain = 1.0f / 2.0f;
  670. break;
  671. case FmtQuad:
  672. chans = QuadMap;
  673. downmix_gain = 1.0f / 4.0f;
  674. break;
  675. case FmtX51:
  676. chans = X51Map;
  677. /* NOTE: Excludes LFE. */
  678. downmix_gain = 1.0f / 5.0f;
  679. break;
  680. case FmtX61:
  681. chans = X61Map;
  682. /* NOTE: Excludes LFE. */
  683. downmix_gain = 1.0f / 6.0f;
  684. break;
  685. case FmtX71:
  686. chans = X71Map;
  687. /* NOTE: Excludes LFE. */
  688. downmix_gain = 1.0f / 7.0f;
  689. break;
  690. case FmtBFormat2D:
  691. case FmtBFormat3D:
  692. DirectChannels = DirectMode::Off;
  693. break;
  694. }
  695. voice->mFlags &= ~(VoiceHasHrtf | VoiceHasNfc);
  696. if(voice->mFmtChannels == FmtBFormat2D || voice->mFmtChannels == FmtBFormat3D)
  697. {
  698. /* Special handling for B-Format sources. */
  699. if(Device->AvgSpeakerDist > 0.0f)
  700. {
  701. if(!(Distance > std::numeric_limits<float>::epsilon()))
  702. {
  703. /* NOTE: The NFCtrlFilters were created with a w0 of 0, which
  704. * is what we want for FOA input. The first channel may have
  705. * been previously re-adjusted if panned, so reset it.
  706. */
  707. voice->mChans[0].mDryParams.NFCtrlFilter.adjust(0.0f);
  708. }
  709. else
  710. {
  711. /* Clamp the distance for really close sources, to prevent
  712. * excessive bass.
  713. */
  714. const float mdist{maxf(Distance, Device->AvgSpeakerDist/4.0f)};
  715. const float w0{SpeedOfSoundMetersPerSec / (mdist * Frequency)};
  716. /* Only need to adjust the first channel of a B-Format source. */
  717. voice->mChans[0].mDryParams.NFCtrlFilter.adjust(w0);
  718. }
  719. voice->mFlags |= VoiceHasNfc;
  720. }
  721. /* Panning a B-Format sound toward some direction is easy. Just pan the
  722. * first (W) channel as a normal mono sound. The angular spread is used
  723. * as a directional scalar to blend between full coverage and full
  724. * panning.
  725. */
  726. const float coverage{!(Distance > std::numeric_limits<float>::epsilon()) ? 1.0f :
  727. (Spread * (1.0f/al::MathDefs<float>::Tau()))};
  728. auto calc_coeffs = [xpos,ypos,zpos](RenderMode mode)
  729. {
  730. if(mode != RenderMode::Pairwise)
  731. return CalcDirectionCoeffs({xpos, ypos, zpos}, 0.0f);
  732. /* Clamp Y, in case rounding errors caused it to end up outside
  733. * of -1...+1.
  734. */
  735. const float ev{std::asin(clampf(ypos, -1.0f, 1.0f))};
  736. /* Negate Z for right-handed coords with -Z in front. */
  737. const float az{std::atan2(xpos, -zpos)};
  738. /* A scalar of 1.5 for plain stereo results in +/-60 degrees
  739. * being moved to +/-90 degrees for direct right and left
  740. * speaker responses.
  741. */
  742. return CalcAngleCoeffs(ScaleAzimuthFront(az, 1.5f), ev, 0.0f);
  743. };
  744. auto coeffs = calc_coeffs(Device->mRenderMode);
  745. std::transform(coeffs.begin()+1, coeffs.end(), coeffs.begin()+1,
  746. std::bind(std::multiplies<float>{}, _1, 1.0f-coverage));
  747. /* NOTE: W needs to be scaled according to channel scaling. */
  748. auto&& scales = GetAmbiScales(voice->mAmbiScaling);
  749. ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base*scales[0],
  750. voice->mChans[0].mDryParams.Gains.Target);
  751. for(uint i{0};i < NumSends;i++)
  752. {
  753. if(const EffectSlot *Slot{SendSlots[i]})
  754. ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base*scales[0],
  755. voice->mChans[0].mWetParams[i].Gains.Target);
  756. }
  757. if(coverage > 0.0f)
  758. {
  759. /* Local B-Format sources have their XYZ channels rotated according
  760. * to the orientation.
  761. */
  762. /* AT then UP */
  763. alu::Vector N{props->OrientAt[0], props->OrientAt[1], props->OrientAt[2], 0.0f};
  764. N.normalize();
  765. alu::Vector V{props->OrientUp[0], props->OrientUp[1], props->OrientUp[2], 0.0f};
  766. V.normalize();
  767. if(!props->HeadRelative)
  768. {
  769. N = Context.Matrix * N;
  770. V = Context.Matrix * V;
  771. }
  772. /* Build and normalize right-vector */
  773. alu::Vector U{N.cross_product(V)};
  774. U.normalize();
  775. /* Build a rotation matrix. Manually fill the zeroth- and first-
  776. * order elements, then construct the rotation for the higher
  777. * orders.
  778. */
  779. std::array<std::array<float,MaxAmbiChannels>,MaxAmbiChannels> shrot{};
  780. shrot[0][0] = 1.0f;
  781. shrot[1][1] = U[0]; shrot[1][2] = -V[0]; shrot[1][3] = -N[0];
  782. shrot[2][1] = -U[1]; shrot[2][2] = V[1]; shrot[2][3] = N[1];
  783. shrot[3][1] = U[2]; shrot[3][2] = -V[2]; shrot[3][3] = -N[2];
  784. AmbiRotator(shrot, static_cast<int>(minu(voice->mAmbiOrder, Device->mAmbiOrder)));
  785. /* Convert the rotation matrix for input ordering and scaling, and
  786. * whether input is 2D or 3D.
  787. */
  788. const uint8_t *index_map{(voice->mFmtChannels == FmtBFormat2D) ?
  789. GetAmbi2DLayout(voice->mAmbiLayout).data() :
  790. GetAmbiLayout(voice->mAmbiLayout).data()};
  791. static const uint8_t ChansPerOrder[MaxAmbiOrder+1]{1, 3, 5, 7,};
  792. static const uint8_t OrderOffset[MaxAmbiOrder+1]{0, 1, 4, 9,};
  793. for(size_t c{1};c < num_channels;c++)
  794. {
  795. const size_t acn{index_map[c]};
  796. const size_t order{AmbiIndex::OrderFromChannel()[acn]};
  797. const size_t tocopy{ChansPerOrder[order]};
  798. const size_t offset{OrderOffset[order]};
  799. const float scale{scales[acn] * coverage};
  800. auto in = shrot.cbegin() + offset;
  801. coeffs = std::array<float,MaxAmbiChannels>{};
  802. for(size_t x{0};x < tocopy;++x)
  803. coeffs[offset+x] = in[x][acn] * scale;
  804. ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base,
  805. voice->mChans[c].mDryParams.Gains.Target);
  806. for(uint i{0};i < NumSends;i++)
  807. {
  808. if(const EffectSlot *Slot{SendSlots[i]})
  809. ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base,
  810. voice->mChans[c].mWetParams[i].Gains.Target);
  811. }
  812. }
  813. }
  814. }
  815. else if(DirectChannels != DirectMode::Off && Device->FmtChans != DevFmtAmbi3D)
  816. {
  817. /* Direct source channels always play local. Skip the virtual channels
  818. * and write inputs to the matching real outputs.
  819. */
  820. voice->mDirect.Buffer = Device->RealOut.Buffer;
  821. for(size_t c{0};c < num_channels;c++)
  822. {
  823. uint idx{GetChannelIdxByName(Device->RealOut, chans[c].channel)};
  824. if(idx != INVALID_CHANNEL_INDEX)
  825. voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain.Base;
  826. else if(DirectChannels == DirectMode::RemixMismatch)
  827. {
  828. auto match_channel = [chans,c](const InputRemixMap &map) noexcept -> bool
  829. { return chans[c].channel == map.channel; };
  830. auto remap = std::find_if(Device->RealOut.RemixMap.cbegin(),
  831. Device->RealOut.RemixMap.cend(), match_channel);
  832. if(remap != Device->RealOut.RemixMap.cend())
  833. for(const auto &target : remap->targets)
  834. {
  835. idx = GetChannelIdxByName(Device->RealOut, target.channel);
  836. if(idx != INVALID_CHANNEL_INDEX)
  837. voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain.Base *
  838. target.mix;
  839. }
  840. }
  841. }
  842. /* Auxiliary sends still use normal channel panning since they mix to
  843. * B-Format, which can't channel-match.
  844. */
  845. for(size_t c{0};c < num_channels;c++)
  846. {
  847. const auto coeffs = CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f);
  848. for(uint i{0};i < NumSends;i++)
  849. {
  850. if(const EffectSlot *Slot{SendSlots[i]})
  851. ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base,
  852. voice->mChans[c].mWetParams[i].Gains.Target);
  853. }
  854. }
  855. }
  856. else if(Device->mRenderMode == RenderMode::Hrtf)
  857. {
  858. /* Full HRTF rendering. Skip the virtual channels and render to the
  859. * real outputs.
  860. */
  861. voice->mDirect.Buffer = Device->RealOut.Buffer;
  862. if(Distance > std::numeric_limits<float>::epsilon())
  863. {
  864. const float ev{std::asin(clampf(ypos, -1.0f, 1.0f))};
  865. const float az{std::atan2(xpos, -zpos)};
  866. /* Get the HRIR coefficients and delays just once, for the given
  867. * source direction.
  868. */
  869. GetHrtfCoeffs(Device->mHrtf.get(), ev, az, Distance, Spread,
  870. voice->mChans[0].mDryParams.Hrtf.Target.Coeffs,
  871. voice->mChans[0].mDryParams.Hrtf.Target.Delay);
  872. voice->mChans[0].mDryParams.Hrtf.Target.Gain = DryGain.Base * downmix_gain;
  873. /* Remaining channels use the same results as the first. */
  874. for(size_t c{1};c < num_channels;c++)
  875. {
  876. /* Skip LFE */
  877. if(chans[c].channel == LFE) continue;
  878. voice->mChans[c].mDryParams.Hrtf.Target = voice->mChans[0].mDryParams.Hrtf.Target;
  879. }
  880. /* Calculate the directional coefficients once, which apply to all
  881. * input channels of the source sends.
  882. */
  883. const auto coeffs = CalcDirectionCoeffs({xpos, ypos, zpos}, Spread);
  884. for(size_t c{0};c < num_channels;c++)
  885. {
  886. /* Skip LFE */
  887. if(chans[c].channel == LFE)
  888. continue;
  889. for(uint i{0};i < NumSends;i++)
  890. {
  891. if(const EffectSlot *Slot{SendSlots[i]})
  892. ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base * downmix_gain,
  893. voice->mChans[c].mWetParams[i].Gains.Target);
  894. }
  895. }
  896. }
  897. else
  898. {
  899. /* Local sources on HRTF play with each channel panned to its
  900. * relative location around the listener, providing "virtual
  901. * speaker" responses.
  902. */
  903. for(size_t c{0};c < num_channels;c++)
  904. {
  905. /* Skip LFE */
  906. if(chans[c].channel == LFE)
  907. continue;
  908. /* Get the HRIR coefficients and delays for this channel
  909. * position.
  910. */
  911. GetHrtfCoeffs(Device->mHrtf.get(), chans[c].elevation, chans[c].angle,
  912. std::numeric_limits<float>::infinity(), Spread,
  913. voice->mChans[c].mDryParams.Hrtf.Target.Coeffs,
  914. voice->mChans[c].mDryParams.Hrtf.Target.Delay);
  915. voice->mChans[c].mDryParams.Hrtf.Target.Gain = DryGain.Base;
  916. /* Normal panning for auxiliary sends. */
  917. const auto coeffs = CalcAngleCoeffs(chans[c].angle, chans[c].elevation, Spread);
  918. for(uint i{0};i < NumSends;i++)
  919. {
  920. if(const EffectSlot *Slot{SendSlots[i]})
  921. ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base,
  922. voice->mChans[c].mWetParams[i].Gains.Target);
  923. }
  924. }
  925. }
  926. voice->mFlags |= VoiceHasHrtf;
  927. }
  928. else
  929. {
  930. /* Non-HRTF rendering. Use normal panning to the output. */
  931. if(Distance > std::numeric_limits<float>::epsilon())
  932. {
  933. /* Calculate NFC filter coefficient if needed. */
  934. if(Device->AvgSpeakerDist > 0.0f)
  935. {
  936. /* Clamp the distance for really close sources, to prevent
  937. * excessive bass.
  938. */
  939. const float mdist{maxf(Distance, Device->AvgSpeakerDist/4.0f)};
  940. const float w0{SpeedOfSoundMetersPerSec / (mdist * Frequency)};
  941. /* Adjust NFC filters. */
  942. for(size_t c{0};c < num_channels;c++)
  943. voice->mChans[c].mDryParams.NFCtrlFilter.adjust(w0);
  944. voice->mFlags |= VoiceHasNfc;
  945. }
  946. /* Calculate the directional coefficients once, which apply to all
  947. * input channels.
  948. */
  949. auto calc_coeffs = [xpos,ypos,zpos,Spread](RenderMode mode)
  950. {
  951. if(mode != RenderMode::Pairwise)
  952. return CalcDirectionCoeffs({xpos, ypos, zpos}, Spread);
  953. const float ev{std::asin(clampf(ypos, -1.0f, 1.0f))};
  954. const float az{std::atan2(xpos, -zpos)};
  955. return CalcAngleCoeffs(ScaleAzimuthFront(az, 1.5f), ev, Spread);
  956. };
  957. const auto coeffs = calc_coeffs(Device->mRenderMode);
  958. for(size_t c{0};c < num_channels;c++)
  959. {
  960. /* Special-case LFE */
  961. if(chans[c].channel == LFE)
  962. {
  963. if(Device->Dry.Buffer.data() == Device->RealOut.Buffer.data())
  964. {
  965. const uint idx{GetChannelIdxByName(Device->RealOut, chans[c].channel)};
  966. if(idx != INVALID_CHANNEL_INDEX)
  967. voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain.Base;
  968. }
  969. continue;
  970. }
  971. ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base * downmix_gain,
  972. voice->mChans[c].mDryParams.Gains.Target);
  973. for(uint i{0};i < NumSends;i++)
  974. {
  975. if(const EffectSlot *Slot{SendSlots[i]})
  976. ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base * downmix_gain,
  977. voice->mChans[c].mWetParams[i].Gains.Target);
  978. }
  979. }
  980. }
  981. else
  982. {
  983. if(Device->AvgSpeakerDist > 0.0f)
  984. {
  985. /* If the source distance is 0, simulate a plane-wave by using
  986. * infinite distance, which results in a w0 of 0.
  987. */
  988. constexpr float w0{0.0f};
  989. for(size_t c{0};c < num_channels;c++)
  990. voice->mChans[c].mDryParams.NFCtrlFilter.adjust(w0);
  991. voice->mFlags |= VoiceHasNfc;
  992. }
  993. for(size_t c{0};c < num_channels;c++)
  994. {
  995. /* Special-case LFE */
  996. if(chans[c].channel == LFE)
  997. {
  998. if(Device->Dry.Buffer.data() == Device->RealOut.Buffer.data())
  999. {
  1000. const uint idx{GetChannelIdxByName(Device->RealOut, chans[c].channel)};
  1001. if(idx != INVALID_CHANNEL_INDEX)
  1002. voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain.Base;
  1003. }
  1004. continue;
  1005. }
  1006. const auto coeffs = CalcAngleCoeffs((Device->mRenderMode == RenderMode::Pairwise)
  1007. ? ScaleAzimuthFront(chans[c].angle, 3.0f) : chans[c].angle,
  1008. chans[c].elevation, Spread);
  1009. ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base,
  1010. voice->mChans[c].mDryParams.Gains.Target);
  1011. for(uint i{0};i < NumSends;i++)
  1012. {
  1013. if(const EffectSlot *Slot{SendSlots[i]})
  1014. ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base,
  1015. voice->mChans[c].mWetParams[i].Gains.Target);
  1016. }
  1017. }
  1018. }
  1019. }
  1020. {
  1021. const float hfNorm{props->Direct.HFReference / Frequency};
  1022. const float lfNorm{props->Direct.LFReference / Frequency};
  1023. voice->mDirect.FilterType = AF_None;
  1024. if(DryGain.HF != 1.0f) voice->mDirect.FilterType |= AF_LowPass;
  1025. if(DryGain.LF != 1.0f) voice->mDirect.FilterType |= AF_HighPass;
  1026. auto &lowpass = voice->mChans[0].mDryParams.LowPass;
  1027. auto &highpass = voice->mChans[0].mDryParams.HighPass;
  1028. lowpass.setParamsFromSlope(BiquadType::HighShelf, hfNorm, DryGain.HF, 1.0f);
  1029. highpass.setParamsFromSlope(BiquadType::LowShelf, lfNorm, DryGain.LF, 1.0f);
  1030. for(size_t c{1};c < num_channels;c++)
  1031. {
  1032. voice->mChans[c].mDryParams.LowPass.copyParamsFrom(lowpass);
  1033. voice->mChans[c].mDryParams.HighPass.copyParamsFrom(highpass);
  1034. }
  1035. }
  1036. for(uint i{0};i < NumSends;i++)
  1037. {
  1038. const float hfNorm{props->Send[i].HFReference / Frequency};
  1039. const float lfNorm{props->Send[i].LFReference / Frequency};
  1040. voice->mSend[i].FilterType = AF_None;
  1041. if(WetGain[i].HF != 1.0f) voice->mSend[i].FilterType |= AF_LowPass;
  1042. if(WetGain[i].LF != 1.0f) voice->mSend[i].FilterType |= AF_HighPass;
  1043. auto &lowpass = voice->mChans[0].mWetParams[i].LowPass;
  1044. auto &highpass = voice->mChans[0].mWetParams[i].HighPass;
  1045. lowpass.setParamsFromSlope(BiquadType::HighShelf, hfNorm, WetGain[i].HF, 1.0f);
  1046. highpass.setParamsFromSlope(BiquadType::LowShelf, lfNorm, WetGain[i].LF, 1.0f);
  1047. for(size_t c{1};c < num_channels;c++)
  1048. {
  1049. voice->mChans[c].mWetParams[i].LowPass.copyParamsFrom(lowpass);
  1050. voice->mChans[c].mWetParams[i].HighPass.copyParamsFrom(highpass);
  1051. }
  1052. }
  1053. }
  1054. void CalcNonAttnSourceParams(Voice *voice, const VoiceProps *props, const ALCcontext *context)
  1055. {
  1056. const ALCdevice *Device{context->mDevice.get()};
  1057. EffectSlot *SendSlots[MAX_SENDS];
  1058. voice->mDirect.Buffer = Device->Dry.Buffer;
  1059. for(uint i{0};i < Device->NumAuxSends;i++)
  1060. {
  1061. SendSlots[i] = props->Send[i].Slot;
  1062. if(!SendSlots[i] || SendSlots[i]->EffectType == EffectSlotType::None)
  1063. {
  1064. SendSlots[i] = nullptr;
  1065. voice->mSend[i].Buffer = {};
  1066. }
  1067. else
  1068. voice->mSend[i].Buffer = SendSlots[i]->Wet.Buffer;
  1069. }
  1070. /* Calculate the stepping value */
  1071. const auto Pitch = static_cast<float>(voice->mFrequency) /
  1072. static_cast<float>(Device->Frequency) * props->Pitch;
  1073. if(Pitch > float{MaxPitch})
  1074. voice->mStep = MaxPitch<<MixerFracBits;
  1075. else
  1076. voice->mStep = maxu(fastf2u(Pitch * MixerFracOne), 1);
  1077. voice->mResampler = PrepareResampler(props->mResampler, voice->mStep, &voice->mResampleState);
  1078. /* Calculate gains */
  1079. GainTriplet DryGain;
  1080. DryGain.Base = minf(clampf(props->Gain, props->MinGain, props->MaxGain) * props->Direct.Gain *
  1081. context->mParams.Gain, GainMixMax);
  1082. DryGain.HF = props->Direct.GainHF;
  1083. DryGain.LF = props->Direct.GainLF;
  1084. GainTriplet WetGain[MAX_SENDS];
  1085. for(uint i{0};i < Device->NumAuxSends;i++)
  1086. {
  1087. WetGain[i].Base = minf(clampf(props->Gain, props->MinGain, props->MaxGain) *
  1088. props->Send[i].Gain * context->mParams.Gain, GainMixMax);
  1089. WetGain[i].HF = props->Send[i].GainHF;
  1090. WetGain[i].LF = props->Send[i].GainLF;
  1091. }
  1092. CalcPanningAndFilters(voice, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, DryGain, WetGain, SendSlots, props,
  1093. context->mParams, Device);
  1094. }
  1095. void CalcAttnSourceParams(Voice *voice, const VoiceProps *props, const ALCcontext *context)
  1096. {
  1097. const ALCdevice *Device{context->mDevice.get()};
  1098. const uint NumSends{Device->NumAuxSends};
  1099. /* Set mixing buffers and get send parameters. */
  1100. voice->mDirect.Buffer = Device->Dry.Buffer;
  1101. EffectSlot *SendSlots[MAX_SENDS];
  1102. float RoomRolloff[MAX_SENDS];
  1103. GainTriplet DecayDistance[MAX_SENDS];
  1104. for(uint i{0};i < NumSends;i++)
  1105. {
  1106. SendSlots[i] = props->Send[i].Slot;
  1107. if(!SendSlots[i] || SendSlots[i]->EffectType == EffectSlotType::None)
  1108. {
  1109. SendSlots[i] = nullptr;
  1110. RoomRolloff[i] = 0.0f;
  1111. DecayDistance[i].Base = 0.0f;
  1112. DecayDistance[i].LF = 0.0f;
  1113. DecayDistance[i].HF = 0.0f;
  1114. }
  1115. else if(SendSlots[i]->AuxSendAuto)
  1116. {
  1117. RoomRolloff[i] = SendSlots[i]->RoomRolloff + props->RoomRolloffFactor;
  1118. /* Calculate the distances to where this effect's decay reaches
  1119. * -60dB.
  1120. */
  1121. DecayDistance[i].Base = SendSlots[i]->DecayTime * SpeedOfSoundMetersPerSec;
  1122. DecayDistance[i].LF = DecayDistance[i].Base * SendSlots[i]->DecayLFRatio;
  1123. DecayDistance[i].HF = DecayDistance[i].Base * SendSlots[i]->DecayHFRatio;
  1124. if(SendSlots[i]->DecayHFLimit)
  1125. {
  1126. const float airAbsorption{SendSlots[i]->AirAbsorptionGainHF};
  1127. if(airAbsorption < 1.0f)
  1128. {
  1129. /* Calculate the distance to where this effect's air
  1130. * absorption reaches -60dB, and limit the effect's HF
  1131. * decay distance (so it doesn't take any longer to decay
  1132. * than the air would allow).
  1133. */
  1134. constexpr float log10_decaygain{-3.0f/*std::log10(ReverbDecayGain)*/};
  1135. const float absorb_dist{log10_decaygain / std::log10(airAbsorption)};
  1136. DecayDistance[i].HF = minf(absorb_dist, DecayDistance[i].HF);
  1137. }
  1138. }
  1139. }
  1140. else
  1141. {
  1142. /* If the slot's auxiliary send auto is off, the data sent to the
  1143. * effect slot is the same as the dry path, sans filter effects */
  1144. RoomRolloff[i] = props->RolloffFactor;
  1145. DecayDistance[i].Base = 0.0f;
  1146. DecayDistance[i].LF = 0.0f;
  1147. DecayDistance[i].HF = 0.0f;
  1148. }
  1149. if(!SendSlots[i])
  1150. voice->mSend[i].Buffer = {};
  1151. else
  1152. voice->mSend[i].Buffer = SendSlots[i]->Wet.Buffer;
  1153. }
  1154. /* Transform source to listener space (convert to head relative) */
  1155. alu::Vector Position{props->Position[0], props->Position[1], props->Position[2], 1.0f};
  1156. alu::Vector Velocity{props->Velocity[0], props->Velocity[1], props->Velocity[2], 0.0f};
  1157. alu::Vector Direction{props->Direction[0], props->Direction[1], props->Direction[2], 0.0f};
  1158. if(!props->HeadRelative)
  1159. {
  1160. /* Transform source vectors */
  1161. Position = context->mParams.Matrix * Position;
  1162. Velocity = context->mParams.Matrix * Velocity;
  1163. Direction = context->mParams.Matrix * Direction;
  1164. }
  1165. else
  1166. {
  1167. /* Offset the source velocity to be relative of the listener velocity */
  1168. Velocity += context->mParams.Velocity;
  1169. }
  1170. const bool directional{Direction.normalize() > 0.0f};
  1171. alu::Vector ToSource{Position[0], Position[1], Position[2], 0.0f};
  1172. const float Distance{ToSource.normalize()};
  1173. /* Initial source gain */
  1174. GainTriplet DryGain{props->Gain, 1.0f, 1.0f};
  1175. GainTriplet WetGain[MAX_SENDS];
  1176. for(uint i{0};i < NumSends;i++)
  1177. WetGain[i] = DryGain;
  1178. /* Calculate distance attenuation */
  1179. float ClampedDist{Distance};
  1180. switch(context->mParams.SourceDistanceModel ? props->mDistanceModel
  1181. : context->mParams.mDistanceModel)
  1182. {
  1183. case DistanceModel::InverseClamped:
  1184. ClampedDist = clampf(ClampedDist, props->RefDistance, props->MaxDistance);
  1185. if(props->MaxDistance < props->RefDistance) break;
  1186. /*fall-through*/
  1187. case DistanceModel::Inverse:
  1188. if(!(props->RefDistance > 0.0f))
  1189. ClampedDist = props->RefDistance;
  1190. else
  1191. {
  1192. float dist{lerp(props->RefDistance, ClampedDist, props->RolloffFactor)};
  1193. if(dist > 0.0f) DryGain.Base *= props->RefDistance / dist;
  1194. for(uint i{0};i < NumSends;i++)
  1195. {
  1196. dist = lerp(props->RefDistance, ClampedDist, RoomRolloff[i]);
  1197. if(dist > 0.0f) WetGain[i].Base *= props->RefDistance / dist;
  1198. }
  1199. }
  1200. break;
  1201. case DistanceModel::LinearClamped:
  1202. ClampedDist = clampf(ClampedDist, props->RefDistance, props->MaxDistance);
  1203. if(props->MaxDistance < props->RefDistance) break;
  1204. /*fall-through*/
  1205. case DistanceModel::Linear:
  1206. if(!(props->MaxDistance != props->RefDistance))
  1207. ClampedDist = props->RefDistance;
  1208. else
  1209. {
  1210. float attn{props->RolloffFactor * (ClampedDist-props->RefDistance) /
  1211. (props->MaxDistance-props->RefDistance)};
  1212. DryGain.Base *= maxf(1.0f - attn, 0.0f);
  1213. for(uint i{0};i < NumSends;i++)
  1214. {
  1215. attn = RoomRolloff[i] * (ClampedDist-props->RefDistance) /
  1216. (props->MaxDistance-props->RefDistance);
  1217. WetGain[i].Base *= maxf(1.0f - attn, 0.0f);
  1218. }
  1219. }
  1220. break;
  1221. case DistanceModel::ExponentClamped:
  1222. ClampedDist = clampf(ClampedDist, props->RefDistance, props->MaxDistance);
  1223. if(props->MaxDistance < props->RefDistance) break;
  1224. /*fall-through*/
  1225. case DistanceModel::Exponent:
  1226. if(!(ClampedDist > 0.0f && props->RefDistance > 0.0f))
  1227. ClampedDist = props->RefDistance;
  1228. else
  1229. {
  1230. const float dist_ratio{ClampedDist/props->RefDistance};
  1231. DryGain.Base *= std::pow(dist_ratio, -props->RolloffFactor);
  1232. for(uint i{0};i < NumSends;i++)
  1233. WetGain[i].Base *= std::pow(dist_ratio, -RoomRolloff[i]);
  1234. }
  1235. break;
  1236. case DistanceModel::Disable:
  1237. ClampedDist = props->RefDistance;
  1238. break;
  1239. }
  1240. /* Calculate directional soundcones */
  1241. if(directional && props->InnerAngle < 360.0f)
  1242. {
  1243. const float Angle{Rad2Deg(std::acos(Direction.dot_product(ToSource)) * ConeScale * -2.0f)};
  1244. float ConeGain, ConeHF;
  1245. if(!(Angle > props->InnerAngle))
  1246. {
  1247. ConeGain = 1.0f;
  1248. ConeHF = 1.0f;
  1249. }
  1250. else if(Angle < props->OuterAngle)
  1251. {
  1252. const float scale{(Angle-props->InnerAngle) / (props->OuterAngle-props->InnerAngle)};
  1253. ConeGain = lerp(1.0f, props->OuterGain, scale);
  1254. ConeHF = lerp(1.0f, props->OuterGainHF, scale);
  1255. }
  1256. else
  1257. {
  1258. ConeGain = props->OuterGain;
  1259. ConeHF = props->OuterGainHF;
  1260. }
  1261. DryGain.Base *= ConeGain;
  1262. if(props->DryGainHFAuto)
  1263. DryGain.HF *= ConeHF;
  1264. if(props->WetGainAuto)
  1265. std::for_each(std::begin(WetGain), std::begin(WetGain)+NumSends,
  1266. [ConeGain](GainTriplet &gain) noexcept -> void { gain.Base *= ConeGain; });
  1267. if(props->WetGainHFAuto)
  1268. std::for_each(std::begin(WetGain), std::begin(WetGain)+NumSends,
  1269. [ConeHF](GainTriplet &gain) noexcept -> void { gain.HF *= ConeHF; });
  1270. }
  1271. /* Apply gain and frequency filters */
  1272. DryGain.Base = minf(clampf(DryGain.Base, props->MinGain, props->MaxGain) * props->Direct.Gain *
  1273. context->mParams.Gain, GainMixMax);
  1274. DryGain.HF *= props->Direct.GainHF;
  1275. DryGain.LF *= props->Direct.GainLF;
  1276. for(uint i{0};i < NumSends;i++)
  1277. {
  1278. WetGain[i].Base = minf(clampf(WetGain[i].Base, props->MinGain, props->MaxGain) *
  1279. props->Send[i].Gain * context->mParams.Gain, GainMixMax);
  1280. WetGain[i].HF *= props->Send[i].GainHF;
  1281. WetGain[i].LF *= props->Send[i].GainLF;
  1282. }
  1283. /* Distance-based air absorption and initial send decay. */
  1284. if(ClampedDist > props->RefDistance && props->RolloffFactor > 0.0f)
  1285. {
  1286. const float meters_base{(ClampedDist-props->RefDistance) * props->RolloffFactor *
  1287. context->mParams.MetersPerUnit};
  1288. if(props->AirAbsorptionFactor > 0.0f)
  1289. {
  1290. const float hfattn{std::pow(AirAbsorbGainHF, meters_base*props->AirAbsorptionFactor)};
  1291. DryGain.HF *= hfattn;
  1292. std::for_each(std::begin(WetGain), std::begin(WetGain)+NumSends,
  1293. [hfattn](GainTriplet &gain) noexcept -> void { gain.HF *= hfattn; });
  1294. }
  1295. if(props->WetGainAuto)
  1296. {
  1297. /* Apply a decay-time transformation to the wet path, based on the
  1298. * source distance in meters. The initial decay of the reverb
  1299. * effect is calculated and applied to the wet path.
  1300. */
  1301. for(uint i{0};i < NumSends;i++)
  1302. {
  1303. if(!(DecayDistance[i].Base > 0.0f))
  1304. continue;
  1305. const float gain{std::pow(ReverbDecayGain, meters_base/DecayDistance[i].Base)};
  1306. WetGain[i].Base *= gain;
  1307. /* Yes, the wet path's air absorption is applied with
  1308. * WetGainAuto on, rather than WetGainHFAuto.
  1309. */
  1310. if(gain > 0.0f)
  1311. {
  1312. float gainhf{std::pow(ReverbDecayGain, meters_base/DecayDistance[i].HF)};
  1313. WetGain[i].HF *= minf(gainhf / gain, 1.0f);
  1314. float gainlf{std::pow(ReverbDecayGain, meters_base/DecayDistance[i].LF)};
  1315. WetGain[i].LF *= minf(gainlf / gain, 1.0f);
  1316. }
  1317. }
  1318. }
  1319. }
  1320. /* Initial source pitch */
  1321. float Pitch{props->Pitch};
  1322. /* Calculate velocity-based doppler effect */
  1323. float DopplerFactor{props->DopplerFactor * context->mParams.DopplerFactor};
  1324. if(DopplerFactor > 0.0f)
  1325. {
  1326. const alu::Vector &lvelocity = context->mParams.Velocity;
  1327. float vss{Velocity.dot_product(ToSource) * -DopplerFactor};
  1328. float vls{lvelocity.dot_product(ToSource) * -DopplerFactor};
  1329. const float SpeedOfSound{context->mParams.SpeedOfSound};
  1330. if(!(vls < SpeedOfSound))
  1331. {
  1332. /* Listener moving away from the source at the speed of sound.
  1333. * Sound waves can't catch it.
  1334. */
  1335. Pitch = 0.0f;
  1336. }
  1337. else if(!(vss < SpeedOfSound))
  1338. {
  1339. /* Source moving toward the listener at the speed of sound. Sound
  1340. * waves bunch up to extreme frequencies.
  1341. */
  1342. Pitch = std::numeric_limits<float>::infinity();
  1343. }
  1344. else
  1345. {
  1346. /* Source and listener movement is nominal. Calculate the proper
  1347. * doppler shift.
  1348. */
  1349. Pitch *= (SpeedOfSound-vls) / (SpeedOfSound-vss);
  1350. }
  1351. }
  1352. /* Adjust pitch based on the buffer and output frequencies, and calculate
  1353. * fixed-point stepping value.
  1354. */
  1355. Pitch *= static_cast<float>(voice->mFrequency) / static_cast<float>(Device->Frequency);
  1356. if(Pitch > float{MaxPitch})
  1357. voice->mStep = MaxPitch<<MixerFracBits;
  1358. else
  1359. voice->mStep = maxu(fastf2u(Pitch * MixerFracOne), 1);
  1360. voice->mResampler = PrepareResampler(props->mResampler, voice->mStep, &voice->mResampleState);
  1361. float spread{0.0f};
  1362. if(props->Radius > Distance)
  1363. spread = al::MathDefs<float>::Tau() - Distance/props->Radius*al::MathDefs<float>::Pi();
  1364. else if(Distance > 0.0f)
  1365. spread = std::asin(props->Radius/Distance) * 2.0f;
  1366. CalcPanningAndFilters(voice, ToSource[0], ToSource[1], ToSource[2]*ZScale,
  1367. Distance*context->mParams.MetersPerUnit, spread, DryGain, WetGain, SendSlots, props,
  1368. context->mParams, Device);
  1369. }
  1370. void CalcSourceParams(Voice *voice, ALCcontext *context, bool force)
  1371. {
  1372. VoicePropsItem *props{voice->mUpdate.exchange(nullptr, std::memory_order_acq_rel)};
  1373. if(!props && !force) return;
  1374. if(props)
  1375. {
  1376. voice->mProps = *props;
  1377. AtomicReplaceHead(context->mFreeVoiceProps, props);
  1378. }
  1379. if((voice->mProps.DirectChannels != DirectMode::Off && voice->mFmtChannels != FmtMono
  1380. && voice->mFmtChannels != FmtBFormat2D && voice->mFmtChannels != FmtBFormat3D)
  1381. || voice->mProps.mSpatializeMode==SpatializeMode::Off
  1382. || (voice->mProps.mSpatializeMode==SpatializeMode::Auto && voice->mFmtChannels != FmtMono))
  1383. CalcNonAttnSourceParams(voice, &voice->mProps, context);
  1384. else
  1385. CalcAttnSourceParams(voice, &voice->mProps, context);
  1386. }
  1387. void SendSourceStateEvent(ALCcontext *context, uint id, VChangeState state)
  1388. {
  1389. RingBuffer *ring{context->mAsyncEvents.get()};
  1390. auto evt_vec = ring->getWriteVector();
  1391. if(evt_vec.first.len < 1) return;
  1392. AsyncEvent *evt{::new(evt_vec.first.buf) AsyncEvent{EventType_SourceStateChange}};
  1393. evt->u.srcstate.id = id;
  1394. evt->u.srcstate.state = state;
  1395. ring->writeAdvance(1);
  1396. }
  1397. void ProcessVoiceChanges(ALCcontext *ctx)
  1398. {
  1399. VoiceChange *cur{ctx->mCurrentVoiceChange.load(std::memory_order_acquire)};
  1400. VoiceChange *next{cur->mNext.load(std::memory_order_acquire)};
  1401. if(!next) return;
  1402. const uint enabledevt{ctx->mEnabledEvts.load(std::memory_order_acquire)};
  1403. do {
  1404. cur = next;
  1405. bool sendevt{false};
  1406. if(cur->mState == VChangeState::Reset || cur->mState == VChangeState::Stop)
  1407. {
  1408. if(Voice *voice{cur->mVoice})
  1409. {
  1410. voice->mCurrentBuffer.store(nullptr, std::memory_order_relaxed);
  1411. voice->mLoopBuffer.store(nullptr, std::memory_order_relaxed);
  1412. /* A source ID indicates the voice was playing or paused, which
  1413. * gets a reset/stop event.
  1414. */
  1415. sendevt = voice->mSourceID.exchange(0u, std::memory_order_relaxed) != 0u;
  1416. Voice::State oldvstate{Voice::Playing};
  1417. voice->mPlayState.compare_exchange_strong(oldvstate, Voice::Stopping,
  1418. std::memory_order_relaxed, std::memory_order_acquire);
  1419. voice->mPendingChange.store(false, std::memory_order_release);
  1420. }
  1421. /* Reset state change events are always sent, even if the voice is
  1422. * already stopped or even if there is no voice.
  1423. */
  1424. sendevt |= (cur->mState == VChangeState::Reset);
  1425. }
  1426. else if(cur->mState == VChangeState::Pause)
  1427. {
  1428. Voice *voice{cur->mVoice};
  1429. Voice::State oldvstate{Voice::Playing};
  1430. sendevt = voice->mPlayState.compare_exchange_strong(oldvstate, Voice::Stopping,
  1431. std::memory_order_release, std::memory_order_acquire);
  1432. }
  1433. else if(cur->mState == VChangeState::Play)
  1434. {
  1435. /* NOTE: When playing a voice, sending a source state change event
  1436. * depends if there's an old voice to stop and if that stop is
  1437. * successful. If there is no old voice, a playing event is always
  1438. * sent. If there is an old voice, an event is sent only if the
  1439. * voice is already stopped.
  1440. */
  1441. if(Voice *oldvoice{cur->mOldVoice})
  1442. {
  1443. oldvoice->mCurrentBuffer.store(nullptr, std::memory_order_relaxed);
  1444. oldvoice->mLoopBuffer.store(nullptr, std::memory_order_relaxed);
  1445. oldvoice->mSourceID.store(0u, std::memory_order_relaxed);
  1446. Voice::State oldvstate{Voice::Playing};
  1447. sendevt = !oldvoice->mPlayState.compare_exchange_strong(oldvstate, Voice::Stopping,
  1448. std::memory_order_relaxed, std::memory_order_acquire);
  1449. oldvoice->mPendingChange.store(false, std::memory_order_release);
  1450. }
  1451. else
  1452. sendevt = true;
  1453. Voice *voice{cur->mVoice};
  1454. voice->mPlayState.store(Voice::Playing, std::memory_order_release);
  1455. }
  1456. else if(cur->mState == VChangeState::Restart)
  1457. {
  1458. /* Restarting a voice never sends a source change event. */
  1459. Voice *oldvoice{cur->mOldVoice};
  1460. oldvoice->mCurrentBuffer.store(nullptr, std::memory_order_relaxed);
  1461. oldvoice->mLoopBuffer.store(nullptr, std::memory_order_relaxed);
  1462. /* If there's no sourceID, the old voice finished so don't start
  1463. * the new one at its new offset.
  1464. */
  1465. if(oldvoice->mSourceID.exchange(0u, std::memory_order_relaxed) != 0u)
  1466. {
  1467. /* Otherwise, set the voice to stopping if it's not already (it
  1468. * might already be, if paused), and play the new voice as
  1469. * appropriate.
  1470. */
  1471. Voice::State oldvstate{Voice::Playing};
  1472. oldvoice->mPlayState.compare_exchange_strong(oldvstate, Voice::Stopping,
  1473. std::memory_order_relaxed, std::memory_order_acquire);
  1474. Voice *voice{cur->mVoice};
  1475. voice->mPlayState.store((oldvstate == Voice::Playing) ? Voice::Playing
  1476. : Voice::Stopped, std::memory_order_release);
  1477. }
  1478. oldvoice->mPendingChange.store(false, std::memory_order_release);
  1479. }
  1480. if(sendevt && (enabledevt&EventType_SourceStateChange))
  1481. SendSourceStateEvent(ctx, cur->mSourceID, cur->mState);
  1482. next = cur->mNext.load(std::memory_order_acquire);
  1483. } while(next);
  1484. ctx->mCurrentVoiceChange.store(cur, std::memory_order_release);
  1485. }
  1486. void ProcessParamUpdates(ALCcontext *ctx, const EffectSlotArray &slots,
  1487. const al::span<Voice*> voices)
  1488. {
  1489. ProcessVoiceChanges(ctx);
  1490. IncrementRef(ctx->mUpdateCount);
  1491. if LIKELY(!ctx->mHoldUpdates.load(std::memory_order_acquire))
  1492. {
  1493. bool force{CalcContextParams(ctx)};
  1494. force |= CalcListenerParams(ctx);
  1495. auto sorted_slots = const_cast<EffectSlot**>(slots.data() + slots.size());
  1496. for(EffectSlot *slot : slots)
  1497. force |= CalcEffectSlotParams(slot, sorted_slots, ctx);
  1498. for(Voice *voice : voices)
  1499. {
  1500. /* Only update voices that have a source. */
  1501. if(voice->mSourceID.load(std::memory_order_relaxed) != 0)
  1502. CalcSourceParams(voice, ctx, force);
  1503. }
  1504. }
  1505. IncrementRef(ctx->mUpdateCount);
  1506. }
  1507. void ProcessContexts(ALCdevice *device, const uint SamplesToDo)
  1508. {
  1509. ASSUME(SamplesToDo > 0);
  1510. for(ALCcontext *ctx : *device->mContexts.load(std::memory_order_acquire))
  1511. {
  1512. const EffectSlotArray &auxslots = *ctx->mActiveAuxSlots.load(std::memory_order_acquire);
  1513. const al::span<Voice*> voices{ctx->getVoicesSpanAcquired()};
  1514. /* Process pending propery updates for objects on the context. */
  1515. ProcessParamUpdates(ctx, auxslots, voices);
  1516. /* Clear auxiliary effect slot mixing buffers. */
  1517. for(EffectSlot *slot : auxslots)
  1518. {
  1519. for(auto &buffer : slot->Wet.Buffer)
  1520. buffer.fill(0.0f);
  1521. }
  1522. /* Process voices that have a playing source. */
  1523. for(Voice *voice : voices)
  1524. {
  1525. const Voice::State vstate{voice->mPlayState.load(std::memory_order_acquire)};
  1526. if(vstate != Voice::Stopped && vstate != Voice::Pending)
  1527. voice->mix(vstate, ctx, SamplesToDo);
  1528. }
  1529. /* Process effects. */
  1530. if(const size_t num_slots{auxslots.size()})
  1531. {
  1532. auto slots = auxslots.data();
  1533. auto slots_end = slots + num_slots;
  1534. /* Sort the slots into extra storage, so that effect slots come
  1535. * before their effect slot target (or their targets' target).
  1536. */
  1537. const al::span<EffectSlot*> sorted_slots{const_cast<EffectSlot**>(slots_end),
  1538. num_slots};
  1539. /* Skip sorting if it has already been done. */
  1540. if(!sorted_slots[0])
  1541. {
  1542. /* First, copy the slots to the sorted list, then partition the
  1543. * sorted list so that all slots without a target slot go to
  1544. * the end.
  1545. */
  1546. std::copy(slots, slots_end, sorted_slots.begin());
  1547. auto split_point = std::partition(sorted_slots.begin(), sorted_slots.end(),
  1548. [](const EffectSlot *slot) noexcept -> bool
  1549. { return slot->Target != nullptr; });
  1550. /* There must be at least one slot without a slot target. */
  1551. assert(split_point != sorted_slots.end());
  1552. /* Simple case: no more than 1 slot has a target slot. Either
  1553. * all slots go right to the output, or the remaining one must
  1554. * target an already-partitioned slot.
  1555. */
  1556. if(split_point - sorted_slots.begin() > 1)
  1557. {
  1558. /* At least two slots target other slots. Starting from the
  1559. * back of the sorted list, continue partitioning the front
  1560. * of the list given each target until all targets are
  1561. * accounted for. This ensures all slots without a target
  1562. * go last, all slots directly targeting those last slots
  1563. * go second-to-last, all slots directly targeting those
  1564. * second-last slots go third-to-last, etc.
  1565. */
  1566. auto next_target = sorted_slots.end();
  1567. do {
  1568. /* This shouldn't happen, but if there's unsorted slots
  1569. * left that don't target any sorted slots, they can't
  1570. * contribute to the output, so leave them.
  1571. */
  1572. if UNLIKELY(next_target == split_point)
  1573. break;
  1574. --next_target;
  1575. split_point = std::partition(sorted_slots.begin(), split_point,
  1576. [next_target](const EffectSlot *slot) noexcept -> bool
  1577. { return slot->Target != *next_target; });
  1578. } while(split_point - sorted_slots.begin() > 1);
  1579. }
  1580. }
  1581. for(const EffectSlot *slot : sorted_slots)
  1582. {
  1583. EffectState *state{slot->mEffectState};
  1584. state->process(SamplesToDo, slot->Wet.Buffer, state->mOutTarget);
  1585. }
  1586. }
  1587. /* Signal the event handler if there are any events to read. */
  1588. RingBuffer *ring{ctx->mAsyncEvents.get()};
  1589. if(ring->readSpace() > 0)
  1590. ctx->mEventSem.post();
  1591. }
  1592. }
  1593. void ApplyDistanceComp(const al::span<FloatBufferLine> Samples, const size_t SamplesToDo,
  1594. const DistanceComp::ChanData *distcomp)
  1595. {
  1596. ASSUME(SamplesToDo > 0);
  1597. for(auto &chanbuffer : Samples)
  1598. {
  1599. const float gain{distcomp->Gain};
  1600. const size_t base{distcomp->Length};
  1601. float *distbuf{al::assume_aligned<16>(distcomp->Buffer)};
  1602. ++distcomp;
  1603. if(base < 1)
  1604. continue;
  1605. float *inout{al::assume_aligned<16>(chanbuffer.data())};
  1606. auto inout_end = inout + SamplesToDo;
  1607. if LIKELY(SamplesToDo >= base)
  1608. {
  1609. auto delay_end = std::rotate(inout, inout_end - base, inout_end);
  1610. std::swap_ranges(inout, delay_end, distbuf);
  1611. }
  1612. else
  1613. {
  1614. auto delay_start = std::swap_ranges(inout, inout_end, distbuf);
  1615. std::rotate(distbuf, delay_start, distbuf + base);
  1616. }
  1617. std::transform(inout, inout_end, inout, std::bind(std::multiplies<float>{}, _1, gain));
  1618. }
  1619. }
  1620. void ApplyDither(const al::span<FloatBufferLine> Samples, uint *dither_seed,
  1621. const float quant_scale, const size_t SamplesToDo)
  1622. {
  1623. ASSUME(SamplesToDo > 0);
  1624. /* Dithering. Generate whitenoise (uniform distribution of random values
  1625. * between -1 and +1) and add it to the sample values, after scaling up to
  1626. * the desired quantization depth amd before rounding.
  1627. */
  1628. const float invscale{1.0f / quant_scale};
  1629. uint seed{*dither_seed};
  1630. auto dither_sample = [&seed,invscale,quant_scale](const float sample) noexcept -> float
  1631. {
  1632. float val{sample * quant_scale};
  1633. uint rng0{dither_rng(&seed)};
  1634. uint rng1{dither_rng(&seed)};
  1635. val += static_cast<float>(rng0*(1.0/UINT_MAX) - rng1*(1.0/UINT_MAX));
  1636. return fast_roundf(val) * invscale;
  1637. };
  1638. for(FloatBufferLine &inout : Samples)
  1639. std::transform(inout.begin(), inout.begin()+SamplesToDo, inout.begin(), dither_sample);
  1640. *dither_seed = seed;
  1641. }
  1642. /* Base template left undefined. Should be marked =delete, but Clang 3.8.1
  1643. * chokes on that given the inline specializations.
  1644. */
  1645. template<typename T>
  1646. inline T SampleConv(float) noexcept;
  1647. template<> inline float SampleConv(float val) noexcept
  1648. { return val; }
  1649. template<> inline int32_t SampleConv(float val) noexcept
  1650. {
  1651. /* Floats have a 23-bit mantissa, plus an implied 1 bit and a sign bit.
  1652. * This means a normalized float has at most 25 bits of signed precision.
  1653. * When scaling and clamping for a signed 32-bit integer, these following
  1654. * values are the best a float can give.
  1655. */
  1656. return fastf2i(clampf(val*2147483648.0f, -2147483648.0f, 2147483520.0f));
  1657. }
  1658. template<> inline int16_t SampleConv(float val) noexcept
  1659. { return static_cast<int16_t>(fastf2i(clampf(val*32768.0f, -32768.0f, 32767.0f))); }
  1660. template<> inline int8_t SampleConv(float val) noexcept
  1661. { return static_cast<int8_t>(fastf2i(clampf(val*128.0f, -128.0f, 127.0f))); }
  1662. /* Define unsigned output variations. */
  1663. template<> inline uint32_t SampleConv(float val) noexcept
  1664. { return static_cast<uint32_t>(SampleConv<int32_t>(val)) + 2147483648u; }
  1665. template<> inline uint16_t SampleConv(float val) noexcept
  1666. { return static_cast<uint16_t>(SampleConv<int16_t>(val) + 32768); }
  1667. template<> inline uint8_t SampleConv(float val) noexcept
  1668. { return static_cast<uint8_t>(SampleConv<int8_t>(val) + 128); }
  1669. template<DevFmtType T>
  1670. void Write(const al::span<const FloatBufferLine> InBuffer, void *OutBuffer, const size_t Offset,
  1671. const size_t SamplesToDo, const size_t FrameStep)
  1672. {
  1673. ASSUME(FrameStep > 0);
  1674. ASSUME(SamplesToDo > 0);
  1675. DevFmtType_t<T> *outbase = static_cast<DevFmtType_t<T>*>(OutBuffer) + Offset*FrameStep;
  1676. for(const FloatBufferLine &inbuf : InBuffer)
  1677. {
  1678. DevFmtType_t<T> *out{outbase++};
  1679. auto conv_sample = [FrameStep,&out](const float s) noexcept -> void
  1680. {
  1681. *out = SampleConv<DevFmtType_t<T>>(s);
  1682. out += FrameStep;
  1683. };
  1684. std::for_each(inbuf.begin(), inbuf.begin()+SamplesToDo, conv_sample);
  1685. }
  1686. }
  1687. } // namespace
  1688. void ALCdevice::renderSamples(void *outBuffer, const uint numSamples, const size_t frameStep)
  1689. {
  1690. FPUCtl mixer_mode{};
  1691. for(uint written{0u};written < numSamples;)
  1692. {
  1693. const uint samplesToDo{minu(numSamples-written, BufferLineSize)};
  1694. /* Clear main mixing buffers. */
  1695. for(FloatBufferLine &buffer : MixBuffer)
  1696. buffer.fill(0.0f);
  1697. /* Increment the mix count at the start (lsb should now be 1). */
  1698. IncrementRef(MixCount);
  1699. /* Process and mix each context's sources and effects. */
  1700. ProcessContexts(this, samplesToDo);
  1701. /* Increment the clock time. Every second's worth of samples is
  1702. * converted and added to clock base so that large sample counts don't
  1703. * overflow during conversion. This also guarantees a stable
  1704. * conversion.
  1705. */
  1706. SamplesDone += samplesToDo;
  1707. ClockBase += std::chrono::seconds{SamplesDone / Frequency};
  1708. SamplesDone %= Frequency;
  1709. /* Increment the mix count at the end (lsb should now be 0). */
  1710. IncrementRef(MixCount);
  1711. /* Apply any needed post-process for finalizing the Dry mix to the
  1712. * RealOut (Ambisonic decode, UHJ encode, etc).
  1713. */
  1714. postProcess(samplesToDo);
  1715. /* Apply compression, limiting sample amplitude if needed or desired. */
  1716. if(Limiter) Limiter->process(samplesToDo, RealOut.Buffer.data());
  1717. /* Apply delays and attenuation for mismatched speaker distances. */
  1718. if(ChannelDelays)
  1719. ApplyDistanceComp(RealOut.Buffer, samplesToDo, ChannelDelays->mChannels.data());
  1720. /* Apply dithering. The compressor should have left enough headroom for
  1721. * the dither noise to not saturate.
  1722. */
  1723. if(DitherDepth > 0.0f)
  1724. ApplyDither(RealOut.Buffer, &DitherSeed, DitherDepth, samplesToDo);
  1725. if LIKELY(outBuffer)
  1726. {
  1727. /* Finally, interleave and convert samples, writing to the device's
  1728. * output buffer.
  1729. */
  1730. switch(FmtType)
  1731. {
  1732. #define HANDLE_WRITE(T) case T: \
  1733. Write<T>(RealOut.Buffer, outBuffer, written, samplesToDo, frameStep); break;
  1734. HANDLE_WRITE(DevFmtByte)
  1735. HANDLE_WRITE(DevFmtUByte)
  1736. HANDLE_WRITE(DevFmtShort)
  1737. HANDLE_WRITE(DevFmtUShort)
  1738. HANDLE_WRITE(DevFmtInt)
  1739. HANDLE_WRITE(DevFmtUInt)
  1740. HANDLE_WRITE(DevFmtFloat)
  1741. #undef HANDLE_WRITE
  1742. }
  1743. }
  1744. written += samplesToDo;
  1745. }
  1746. }
  1747. void ALCdevice::handleDisconnect(const char *msg, ...)
  1748. {
  1749. if(!Connected.exchange(false, std::memory_order_acq_rel))
  1750. return;
  1751. AsyncEvent evt{EventType_Disconnected};
  1752. va_list args;
  1753. va_start(args, msg);
  1754. int msglen{vsnprintf(evt.u.disconnect.msg, sizeof(evt.u.disconnect.msg), msg, args)};
  1755. va_end(args);
  1756. if(msglen < 0 || static_cast<size_t>(msglen) >= sizeof(evt.u.disconnect.msg))
  1757. evt.u.disconnect.msg[sizeof(evt.u.disconnect.msg)-1] = 0;
  1758. IncrementRef(MixCount);
  1759. for(ALCcontext *ctx : *mContexts.load())
  1760. {
  1761. const uint enabledevt{ctx->mEnabledEvts.load(std::memory_order_acquire)};
  1762. if((enabledevt&EventType_Disconnected))
  1763. {
  1764. RingBuffer *ring{ctx->mAsyncEvents.get()};
  1765. auto evt_data = ring->getWriteVector().first;
  1766. if(evt_data.len > 0)
  1767. {
  1768. ::new(evt_data.buf) AsyncEvent{evt};
  1769. ring->writeAdvance(1);
  1770. ctx->mEventSem.post();
  1771. }
  1772. }
  1773. auto voicelist = ctx->getVoicesSpanAcquired();
  1774. auto stop_voice = [](Voice *voice) -> void
  1775. {
  1776. voice->mCurrentBuffer.store(nullptr, std::memory_order_relaxed);
  1777. voice->mLoopBuffer.store(nullptr, std::memory_order_relaxed);
  1778. voice->mSourceID.store(0u, std::memory_order_relaxed);
  1779. voice->mPlayState.store(Voice::Stopped, std::memory_order_release);
  1780. };
  1781. std::for_each(voicelist.begin(), voicelist.end(), stop_voice);
  1782. }
  1783. IncrementRef(MixCount);
  1784. }