ALu.c 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927
  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 <math.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <ctype.h>
  25. #include <assert.h>
  26. #include "alMain.h"
  27. #include "alSource.h"
  28. #include "alBuffer.h"
  29. #include "alListener.h"
  30. #include "alAuxEffectSlot.h"
  31. #include "alu.h"
  32. #include "bs2b.h"
  33. #include "hrtf.h"
  34. #include "mastering.h"
  35. #include "uhjfilter.h"
  36. #include "bformatdec.h"
  37. #include "static_assert.h"
  38. #include "ringbuffer.h"
  39. #include "filters/splitter.h"
  40. #include "mixer/defs.h"
  41. #include "fpu_modes.h"
  42. #include "cpu_caps.h"
  43. #include "bsinc_inc.h"
  44. #include "backends/base.h"
  45. extern inline ALfloat minf(ALfloat a, ALfloat b);
  46. extern inline ALfloat maxf(ALfloat a, ALfloat b);
  47. extern inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max);
  48. extern inline ALdouble mind(ALdouble a, ALdouble b);
  49. extern inline ALdouble maxd(ALdouble a, ALdouble b);
  50. extern inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max);
  51. extern inline ALuint minu(ALuint a, ALuint b);
  52. extern inline ALuint maxu(ALuint a, ALuint b);
  53. extern inline ALuint clampu(ALuint val, ALuint min, ALuint max);
  54. extern inline ALint mini(ALint a, ALint b);
  55. extern inline ALint maxi(ALint a, ALint b);
  56. extern inline ALint clampi(ALint val, ALint min, ALint max);
  57. extern inline ALint64 mini64(ALint64 a, ALint64 b);
  58. extern inline ALint64 maxi64(ALint64 a, ALint64 b);
  59. extern inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max);
  60. extern inline ALuint64 minu64(ALuint64 a, ALuint64 b);
  61. extern inline ALuint64 maxu64(ALuint64 a, ALuint64 b);
  62. extern inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max);
  63. extern inline size_t minz(size_t a, size_t b);
  64. extern inline size_t maxz(size_t a, size_t b);
  65. extern inline size_t clampz(size_t val, size_t min, size_t max);
  66. extern inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu);
  67. extern inline ALfloat cubic(ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat mu);
  68. extern inline void aluVectorSet(aluVector *restrict vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w);
  69. extern inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
  70. ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3);
  71. extern inline void aluMatrixfSet(aluMatrixf *matrix,
  72. ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
  73. ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
  74. ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
  75. ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33);
  76. /* Cone scalar */
  77. ALfloat ConeScale = 1.0f;
  78. /* Localized Z scalar for mono sources */
  79. ALfloat ZScale = 1.0f;
  80. /* Force default speed of sound for distance-related reverb decay. */
  81. ALboolean OverrideReverbSpeedOfSound = AL_FALSE;
  82. const aluMatrixf IdentityMatrixf = {{
  83. { 1.0f, 0.0f, 0.0f, 0.0f },
  84. { 0.0f, 1.0f, 0.0f, 0.0f },
  85. { 0.0f, 0.0f, 1.0f, 0.0f },
  86. { 0.0f, 0.0f, 0.0f, 1.0f },
  87. }};
  88. static void ClearArray(ALfloat f[MAX_OUTPUT_CHANNELS])
  89. {
  90. size_t i;
  91. for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
  92. f[i] = 0.0f;
  93. }
  94. struct ChanMap {
  95. enum Channel channel;
  96. ALfloat angle;
  97. ALfloat elevation;
  98. };
  99. static HrtfDirectMixerFunc MixDirectHrtf = MixDirectHrtf_C;
  100. void DeinitVoice(ALvoice *voice)
  101. {
  102. al_free(ATOMIC_EXCHANGE_PTR_SEQ(&voice->Update, NULL));
  103. }
  104. static inline HrtfDirectMixerFunc SelectHrtfMixer(void)
  105. {
  106. #ifdef HAVE_NEON
  107. if((CPUCapFlags&CPU_CAP_NEON))
  108. return MixDirectHrtf_Neon;
  109. #endif
  110. #ifdef HAVE_SSE
  111. if((CPUCapFlags&CPU_CAP_SSE))
  112. return MixDirectHrtf_SSE;
  113. #endif
  114. return MixDirectHrtf_C;
  115. }
  116. /* Prior to VS2013, MSVC lacks the round() family of functions. */
  117. #if defined(_MSC_VER) && _MSC_VER < 1800
  118. static float roundf(float val)
  119. {
  120. if(val < 0.0f)
  121. return ceilf(val-0.5f);
  122. return floorf(val+0.5f);
  123. }
  124. #endif
  125. /* This RNG method was created based on the math found in opusdec. It's quick,
  126. * and starting with a seed value of 22222, is suitable for generating
  127. * whitenoise.
  128. */
  129. static inline ALuint dither_rng(ALuint *seed)
  130. {
  131. *seed = (*seed * 96314165) + 907633515;
  132. return *seed;
  133. }
  134. static inline void aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector)
  135. {
  136. outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
  137. outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
  138. outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
  139. }
  140. static inline ALfloat aluDotproduct(const aluVector *vec1, const aluVector *vec2)
  141. {
  142. return vec1->v[0]*vec2->v[0] + vec1->v[1]*vec2->v[1] + vec1->v[2]*vec2->v[2];
  143. }
  144. static ALfloat aluNormalize(ALfloat *vec)
  145. {
  146. ALfloat length = sqrtf(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
  147. if(length > FLT_EPSILON)
  148. {
  149. ALfloat inv_length = 1.0f/length;
  150. vec[0] *= inv_length;
  151. vec[1] *= inv_length;
  152. vec[2] *= inv_length;
  153. return length;
  154. }
  155. vec[0] = vec[1] = vec[2] = 0.0f;
  156. return 0.0f;
  157. }
  158. static void aluMatrixfFloat3(ALfloat *vec, ALfloat w, const aluMatrixf *mtx)
  159. {
  160. ALfloat v[4] = { vec[0], vec[1], vec[2], w };
  161. vec[0] = v[0]*mtx->m[0][0] + v[1]*mtx->m[1][0] + v[2]*mtx->m[2][0] + v[3]*mtx->m[3][0];
  162. vec[1] = v[0]*mtx->m[0][1] + v[1]*mtx->m[1][1] + v[2]*mtx->m[2][1] + v[3]*mtx->m[3][1];
  163. vec[2] = v[0]*mtx->m[0][2] + v[1]*mtx->m[1][2] + v[2]*mtx->m[2][2] + v[3]*mtx->m[3][2];
  164. }
  165. static aluVector aluMatrixfVector(const aluMatrixf *mtx, const aluVector *vec)
  166. {
  167. aluVector v;
  168. v.v[0] = vec->v[0]*mtx->m[0][0] + vec->v[1]*mtx->m[1][0] + vec->v[2]*mtx->m[2][0] + vec->v[3]*mtx->m[3][0];
  169. v.v[1] = vec->v[0]*mtx->m[0][1] + vec->v[1]*mtx->m[1][1] + vec->v[2]*mtx->m[2][1] + vec->v[3]*mtx->m[3][1];
  170. v.v[2] = vec->v[0]*mtx->m[0][2] + vec->v[1]*mtx->m[1][2] + vec->v[2]*mtx->m[2][2] + vec->v[3]*mtx->m[3][2];
  171. v.v[3] = vec->v[0]*mtx->m[0][3] + vec->v[1]*mtx->m[1][3] + vec->v[2]*mtx->m[2][3] + vec->v[3]*mtx->m[3][3];
  172. return v;
  173. }
  174. void aluInit(void)
  175. {
  176. MixDirectHrtf = SelectHrtfMixer();
  177. }
  178. static void SendSourceStoppedEvent(ALCcontext *context, ALuint id)
  179. {
  180. ALbitfieldSOFT enabledevt;
  181. AsyncEvent evt;
  182. size_t strpos;
  183. ALuint scale;
  184. enabledevt = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_acquire);
  185. if(!(enabledevt&EventType_SourceStateChange)) return;
  186. evt.EnumType = EventType_SourceStateChange;
  187. evt.Type = AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT;
  188. evt.ObjectId = id;
  189. evt.Param = AL_STOPPED;
  190. /* Normally snprintf would be used, but this is called from the mixer and
  191. * that function's not real-time safe, so we have to construct it manually.
  192. */
  193. strcpy(evt.Message, "Source ID "); strpos = 10;
  194. scale = 1000000000;
  195. while(scale > 0 && scale > id)
  196. scale /= 10;
  197. while(scale > 0)
  198. {
  199. evt.Message[strpos++] = '0' + ((id/scale)%10);
  200. scale /= 10;
  201. }
  202. strcpy(evt.Message+strpos, " state changed to AL_STOPPED");
  203. if(ll_ringbuffer_write(context->AsyncEvents, (const char*)&evt, 1) == 1)
  204. alsem_post(&context->EventSem);
  205. }
  206. static void ProcessHrtf(ALCdevice *device, ALsizei SamplesToDo)
  207. {
  208. DirectHrtfState *state;
  209. int lidx, ridx;
  210. ALsizei c;
  211. if(device->AmbiUp)
  212. ambiup_process(device->AmbiUp,
  213. device->Dry.Buffer, device->Dry.NumChannels, device->FOAOut.Buffer,
  214. SamplesToDo
  215. );
  216. lidx = GetChannelIdxByName(&device->RealOut, FrontLeft);
  217. ridx = GetChannelIdxByName(&device->RealOut, FrontRight);
  218. assert(lidx != -1 && ridx != -1);
  219. state = device->Hrtf;
  220. for(c = 0;c < device->Dry.NumChannels;c++)
  221. {
  222. MixDirectHrtf(device->RealOut.Buffer[lidx], device->RealOut.Buffer[ridx],
  223. device->Dry.Buffer[c], state->Offset, state->IrSize,
  224. state->Chan[c].Coeffs, state->Chan[c].Values, SamplesToDo
  225. );
  226. }
  227. state->Offset += SamplesToDo;
  228. }
  229. static void ProcessAmbiDec(ALCdevice *device, ALsizei SamplesToDo)
  230. {
  231. if(device->Dry.Buffer != device->FOAOut.Buffer)
  232. bformatdec_upSample(device->AmbiDecoder,
  233. device->Dry.Buffer, device->FOAOut.Buffer, device->FOAOut.NumChannels,
  234. SamplesToDo
  235. );
  236. bformatdec_process(device->AmbiDecoder,
  237. device->RealOut.Buffer, device->RealOut.NumChannels, device->Dry.Buffer,
  238. SamplesToDo
  239. );
  240. }
  241. static void ProcessAmbiUp(ALCdevice *device, ALsizei SamplesToDo)
  242. {
  243. ambiup_process(device->AmbiUp,
  244. device->RealOut.Buffer, device->RealOut.NumChannels, device->FOAOut.Buffer,
  245. SamplesToDo
  246. );
  247. }
  248. static void ProcessUhj(ALCdevice *device, ALsizei SamplesToDo)
  249. {
  250. int lidx = GetChannelIdxByName(&device->RealOut, FrontLeft);
  251. int ridx = GetChannelIdxByName(&device->RealOut, FrontRight);
  252. assert(lidx != -1 && ridx != -1);
  253. /* Encode to stereo-compatible 2-channel UHJ output. */
  254. EncodeUhj2(device->Uhj_Encoder,
  255. device->RealOut.Buffer[lidx], device->RealOut.Buffer[ridx],
  256. device->Dry.Buffer, SamplesToDo
  257. );
  258. }
  259. static void ProcessBs2b(ALCdevice *device, ALsizei SamplesToDo)
  260. {
  261. int lidx = GetChannelIdxByName(&device->RealOut, FrontLeft);
  262. int ridx = GetChannelIdxByName(&device->RealOut, FrontRight);
  263. assert(lidx != -1 && ridx != -1);
  264. /* Apply binaural/crossfeed filter */
  265. bs2b_cross_feed(device->Bs2b, device->RealOut.Buffer[lidx],
  266. device->RealOut.Buffer[ridx], SamplesToDo);
  267. }
  268. void aluSelectPostProcess(ALCdevice *device)
  269. {
  270. if(device->HrtfHandle)
  271. device->PostProcess = ProcessHrtf;
  272. else if(device->AmbiDecoder)
  273. device->PostProcess = ProcessAmbiDec;
  274. else if(device->AmbiUp)
  275. device->PostProcess = ProcessAmbiUp;
  276. else if(device->Uhj_Encoder)
  277. device->PostProcess = ProcessUhj;
  278. else if(device->Bs2b)
  279. device->PostProcess = ProcessBs2b;
  280. else
  281. device->PostProcess = NULL;
  282. }
  283. /* Prepares the interpolator for a given rate (determined by increment). A
  284. * result of AL_FALSE indicates that the filter output will completely cut
  285. * the input signal.
  286. *
  287. * With a bit of work, and a trade of memory for CPU cost, this could be
  288. * modified for use with an interpolated increment for buttery-smooth pitch
  289. * changes.
  290. */
  291. void BsincPrepare(const ALuint increment, BsincState *state, const BSincTable *table)
  292. {
  293. ALfloat sf = 0.0f;
  294. ALsizei si = BSINC_SCALE_COUNT-1;
  295. if(increment > FRACTIONONE)
  296. {
  297. sf = (ALfloat)FRACTIONONE / increment;
  298. sf = maxf(0.0f, (BSINC_SCALE_COUNT-1) * (sf-table->scaleBase) * table->scaleRange);
  299. si = float2int(sf);
  300. /* The interpolation factor is fit to this diagonally-symmetric curve
  301. * to reduce the transition ripple caused by interpolating different
  302. * scales of the sinc function.
  303. */
  304. sf = 1.0f - cosf(asinf(sf - si));
  305. }
  306. state->sf = sf;
  307. state->m = table->m[si];
  308. state->l = -((state->m/2) - 1);
  309. state->filter = table->Tab + table->filterOffset[si];
  310. }
  311. static bool CalcContextParams(ALCcontext *Context)
  312. {
  313. ALlistener *Listener = Context->Listener;
  314. struct ALcontextProps *props;
  315. props = ATOMIC_EXCHANGE_PTR(&Context->Update, NULL, almemory_order_acq_rel);
  316. if(!props) return false;
  317. Listener->Params.MetersPerUnit = props->MetersPerUnit;
  318. Listener->Params.DopplerFactor = props->DopplerFactor;
  319. Listener->Params.SpeedOfSound = props->SpeedOfSound * props->DopplerVelocity;
  320. if(!OverrideReverbSpeedOfSound)
  321. Listener->Params.ReverbSpeedOfSound = Listener->Params.SpeedOfSound *
  322. Listener->Params.MetersPerUnit;
  323. Listener->Params.SourceDistanceModel = props->SourceDistanceModel;
  324. Listener->Params.DistanceModel = props->DistanceModel;
  325. ATOMIC_REPLACE_HEAD(struct ALcontextProps*, &Context->FreeContextProps, props);
  326. return true;
  327. }
  328. static bool CalcListenerParams(ALCcontext *Context)
  329. {
  330. ALlistener *Listener = Context->Listener;
  331. ALfloat N[3], V[3], U[3], P[3];
  332. struct ALlistenerProps *props;
  333. aluVector vel;
  334. props = ATOMIC_EXCHANGE_PTR(&Listener->Update, NULL, almemory_order_acq_rel);
  335. if(!props) return false;
  336. /* AT then UP */
  337. N[0] = props->Forward[0];
  338. N[1] = props->Forward[1];
  339. N[2] = props->Forward[2];
  340. aluNormalize(N);
  341. V[0] = props->Up[0];
  342. V[1] = props->Up[1];
  343. V[2] = props->Up[2];
  344. aluNormalize(V);
  345. /* Build and normalize right-vector */
  346. aluCrossproduct(N, V, U);
  347. aluNormalize(U);
  348. aluMatrixfSet(&Listener->Params.Matrix,
  349. U[0], V[0], -N[0], 0.0,
  350. U[1], V[1], -N[1], 0.0,
  351. U[2], V[2], -N[2], 0.0,
  352. 0.0, 0.0, 0.0, 1.0
  353. );
  354. P[0] = props->Position[0];
  355. P[1] = props->Position[1];
  356. P[2] = props->Position[2];
  357. aluMatrixfFloat3(P, 1.0, &Listener->Params.Matrix);
  358. aluMatrixfSetRow(&Listener->Params.Matrix, 3, -P[0], -P[1], -P[2], 1.0f);
  359. aluVectorSet(&vel, props->Velocity[0], props->Velocity[1], props->Velocity[2], 0.0f);
  360. Listener->Params.Velocity = aluMatrixfVector(&Listener->Params.Matrix, &vel);
  361. Listener->Params.Gain = props->Gain * Context->GainBoost;
  362. ATOMIC_REPLACE_HEAD(struct ALlistenerProps*, &Context->FreeListenerProps, props);
  363. return true;
  364. }
  365. static bool CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context, bool force)
  366. {
  367. struct ALeffectslotProps *props;
  368. ALeffectState *state;
  369. props = ATOMIC_EXCHANGE_PTR(&slot->Update, NULL, almemory_order_acq_rel);
  370. if(!props && !force) return false;
  371. if(props)
  372. {
  373. slot->Params.Gain = props->Gain;
  374. slot->Params.AuxSendAuto = props->AuxSendAuto;
  375. slot->Params.EffectType = props->Type;
  376. slot->Params.EffectProps = props->Props;
  377. if(IsReverbEffect(props->Type))
  378. {
  379. slot->Params.RoomRolloff = props->Props.Reverb.RoomRolloffFactor;
  380. slot->Params.DecayTime = props->Props.Reverb.DecayTime;
  381. slot->Params.DecayLFRatio = props->Props.Reverb.DecayLFRatio;
  382. slot->Params.DecayHFRatio = props->Props.Reverb.DecayHFRatio;
  383. slot->Params.DecayHFLimit = props->Props.Reverb.DecayHFLimit;
  384. slot->Params.AirAbsorptionGainHF = props->Props.Reverb.AirAbsorptionGainHF;
  385. }
  386. else
  387. {
  388. slot->Params.RoomRolloff = 0.0f;
  389. slot->Params.DecayTime = 0.0f;
  390. slot->Params.DecayLFRatio = 0.0f;
  391. slot->Params.DecayHFRatio = 0.0f;
  392. slot->Params.DecayHFLimit = AL_FALSE;
  393. slot->Params.AirAbsorptionGainHF = 1.0f;
  394. }
  395. /* Swap effect states. No need to play with the ref counts since they
  396. * keep the same number of refs.
  397. */
  398. state = props->State;
  399. props->State = slot->Params.EffectState;
  400. slot->Params.EffectState = state;
  401. ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &context->FreeEffectslotProps, props);
  402. }
  403. else
  404. state = slot->Params.EffectState;
  405. V(state,update)(context, slot, &slot->Params.EffectProps);
  406. return true;
  407. }
  408. static const struct ChanMap MonoMap[1] = {
  409. { FrontCenter, 0.0f, 0.0f }
  410. }, RearMap[2] = {
  411. { BackLeft, DEG2RAD(-150.0f), DEG2RAD(0.0f) },
  412. { BackRight, DEG2RAD( 150.0f), DEG2RAD(0.0f) }
  413. }, QuadMap[4] = {
  414. { FrontLeft, DEG2RAD( -45.0f), DEG2RAD(0.0f) },
  415. { FrontRight, DEG2RAD( 45.0f), DEG2RAD(0.0f) },
  416. { BackLeft, DEG2RAD(-135.0f), DEG2RAD(0.0f) },
  417. { BackRight, DEG2RAD( 135.0f), DEG2RAD(0.0f) }
  418. }, X51Map[6] = {
  419. { FrontLeft, DEG2RAD( -30.0f), DEG2RAD(0.0f) },
  420. { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) },
  421. { FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) },
  422. { LFE, 0.0f, 0.0f },
  423. { SideLeft, DEG2RAD(-110.0f), DEG2RAD(0.0f) },
  424. { SideRight, DEG2RAD( 110.0f), DEG2RAD(0.0f) }
  425. }, X61Map[7] = {
  426. { FrontLeft, DEG2RAD(-30.0f), DEG2RAD(0.0f) },
  427. { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) },
  428. { FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) },
  429. { LFE, 0.0f, 0.0f },
  430. { BackCenter, DEG2RAD(180.0f), DEG2RAD(0.0f) },
  431. { SideLeft, DEG2RAD(-90.0f), DEG2RAD(0.0f) },
  432. { SideRight, DEG2RAD( 90.0f), DEG2RAD(0.0f) }
  433. }, X71Map[8] = {
  434. { FrontLeft, DEG2RAD( -30.0f), DEG2RAD(0.0f) },
  435. { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) },
  436. { FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) },
  437. { LFE, 0.0f, 0.0f },
  438. { BackLeft, DEG2RAD(-150.0f), DEG2RAD(0.0f) },
  439. { BackRight, DEG2RAD( 150.0f), DEG2RAD(0.0f) },
  440. { SideLeft, DEG2RAD( -90.0f), DEG2RAD(0.0f) },
  441. { SideRight, DEG2RAD( 90.0f), DEG2RAD(0.0f) }
  442. };
  443. static void CalcPanningAndFilters(ALvoice *voice, const ALfloat Azi, const ALfloat Elev,
  444. const ALfloat Distance, const ALfloat Spread,
  445. const ALfloat DryGain, const ALfloat DryGainHF,
  446. const ALfloat DryGainLF, const ALfloat *WetGain,
  447. const ALfloat *WetGainLF, const ALfloat *WetGainHF,
  448. ALeffectslot **SendSlots, const ALbuffer *Buffer,
  449. const struct ALvoiceProps *props, const ALlistener *Listener,
  450. const ALCdevice *Device)
  451. {
  452. struct ChanMap StereoMap[2] = {
  453. { FrontLeft, DEG2RAD(-30.0f), DEG2RAD(0.0f) },
  454. { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) }
  455. };
  456. bool DirectChannels = props->DirectChannels;
  457. const ALsizei NumSends = Device->NumAuxSends;
  458. const ALuint Frequency = Device->Frequency;
  459. const struct ChanMap *chans = NULL;
  460. ALsizei num_channels = 0;
  461. bool isbformat = false;
  462. ALfloat downmix_gain = 1.0f;
  463. ALsizei c, i;
  464. switch(Buffer->FmtChannels)
  465. {
  466. case FmtMono:
  467. chans = MonoMap;
  468. num_channels = 1;
  469. /* Mono buffers are never played direct. */
  470. DirectChannels = false;
  471. break;
  472. case FmtStereo:
  473. /* Convert counter-clockwise to clockwise. */
  474. StereoMap[0].angle = -props->StereoPan[0];
  475. StereoMap[1].angle = -props->StereoPan[1];
  476. chans = StereoMap;
  477. num_channels = 2;
  478. downmix_gain = 1.0f / 2.0f;
  479. break;
  480. case FmtRear:
  481. chans = RearMap;
  482. num_channels = 2;
  483. downmix_gain = 1.0f / 2.0f;
  484. break;
  485. case FmtQuad:
  486. chans = QuadMap;
  487. num_channels = 4;
  488. downmix_gain = 1.0f / 4.0f;
  489. break;
  490. case FmtX51:
  491. chans = X51Map;
  492. num_channels = 6;
  493. /* NOTE: Excludes LFE. */
  494. downmix_gain = 1.0f / 5.0f;
  495. break;
  496. case FmtX61:
  497. chans = X61Map;
  498. num_channels = 7;
  499. /* NOTE: Excludes LFE. */
  500. downmix_gain = 1.0f / 6.0f;
  501. break;
  502. case FmtX71:
  503. chans = X71Map;
  504. num_channels = 8;
  505. /* NOTE: Excludes LFE. */
  506. downmix_gain = 1.0f / 7.0f;
  507. break;
  508. case FmtBFormat2D:
  509. num_channels = 3;
  510. isbformat = true;
  511. DirectChannels = false;
  512. break;
  513. case FmtBFormat3D:
  514. num_channels = 4;
  515. isbformat = true;
  516. DirectChannels = false;
  517. break;
  518. }
  519. for(c = 0;c < num_channels;c++)
  520. {
  521. memset(&voice->Direct.Params[c].Hrtf.Target, 0,
  522. sizeof(voice->Direct.Params[c].Hrtf.Target));
  523. ClearArray(voice->Direct.Params[c].Gains.Target);
  524. }
  525. for(i = 0;i < NumSends;i++)
  526. {
  527. for(c = 0;c < num_channels;c++)
  528. ClearArray(voice->Send[i].Params[c].Gains.Target);
  529. }
  530. voice->Flags &= ~(VOICE_HAS_HRTF | VOICE_HAS_NFC);
  531. if(isbformat)
  532. {
  533. /* Special handling for B-Format sources. */
  534. if(Distance > FLT_EPSILON)
  535. {
  536. /* Panning a B-Format sound toward some direction is easy. Just pan
  537. * the first (W) channel as a normal mono sound and silence the
  538. * others.
  539. */
  540. ALfloat coeffs[MAX_AMBI_COEFFS];
  541. if(Device->AvgSpeakerDist > 0.0f)
  542. {
  543. ALfloat mdist = Distance * Listener->Params.MetersPerUnit;
  544. ALfloat w0 = SPEEDOFSOUNDMETRESPERSEC /
  545. (mdist * (ALfloat)Device->Frequency);
  546. ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
  547. (Device->AvgSpeakerDist * (ALfloat)Device->Frequency);
  548. /* Clamp w0 for really close distances, to prevent excessive
  549. * bass.
  550. */
  551. w0 = minf(w0, w1*4.0f);
  552. /* Only need to adjust the first channel of a B-Format source. */
  553. NfcFilterAdjust(&voice->Direct.Params[0].NFCtrlFilter, w0);
  554. for(i = 0;i < MAX_AMBI_ORDER+1;i++)
  555. voice->Direct.ChannelsPerOrder[i] = Device->Dry.NumChannelsPerOrder[i];
  556. voice->Flags |= VOICE_HAS_NFC;
  557. }
  558. if(Device->Render_Mode == StereoPair)
  559. CalcAnglePairwiseCoeffs(Azi, Elev, Spread, coeffs);
  560. else
  561. CalcAngleCoeffs(Azi, Elev, Spread, coeffs);
  562. /* NOTE: W needs to be scaled by sqrt(2) due to FuMa normalization. */
  563. ComputeDryPanGains(&Device->Dry, coeffs, DryGain*1.414213562f,
  564. voice->Direct.Params[0].Gains.Target);
  565. for(i = 0;i < NumSends;i++)
  566. {
  567. const ALeffectslot *Slot = SendSlots[i];
  568. if(Slot)
  569. ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
  570. coeffs, WetGain[i]*1.414213562f, voice->Send[i].Params[0].Gains.Target
  571. );
  572. }
  573. }
  574. else
  575. {
  576. /* Local B-Format sources have their XYZ channels rotated according
  577. * to the orientation.
  578. */
  579. const ALfloat sqrt_2 = sqrtf(2.0f);
  580. const ALfloat sqrt_3 = sqrtf(3.0f);
  581. ALfloat N[3], V[3], U[3];
  582. aluMatrixf matrix;
  583. if(Device->AvgSpeakerDist > 0.0f)
  584. {
  585. /* NOTE: The NFCtrlFilters were created with a w0 of 0, which
  586. * is what we want for FOA input. The first channel may have
  587. * been previously re-adjusted if panned, so reset it.
  588. */
  589. NfcFilterAdjust(&voice->Direct.Params[0].NFCtrlFilter, 0.0f);
  590. voice->Direct.ChannelsPerOrder[0] = 1;
  591. voice->Direct.ChannelsPerOrder[1] = mini(voice->Direct.Channels-1, 3);
  592. for(i = 2;i < MAX_AMBI_ORDER+1;i++)
  593. voice->Direct.ChannelsPerOrder[i] = 0;
  594. voice->Flags |= VOICE_HAS_NFC;
  595. }
  596. /* AT then UP */
  597. N[0] = props->Orientation[0][0];
  598. N[1] = props->Orientation[0][1];
  599. N[2] = props->Orientation[0][2];
  600. aluNormalize(N);
  601. V[0] = props->Orientation[1][0];
  602. V[1] = props->Orientation[1][1];
  603. V[2] = props->Orientation[1][2];
  604. aluNormalize(V);
  605. if(!props->HeadRelative)
  606. {
  607. const aluMatrixf *lmatrix = &Listener->Params.Matrix;
  608. aluMatrixfFloat3(N, 0.0f, lmatrix);
  609. aluMatrixfFloat3(V, 0.0f, lmatrix);
  610. }
  611. /* Build and normalize right-vector */
  612. aluCrossproduct(N, V, U);
  613. aluNormalize(U);
  614. /* Build a rotate + conversion matrix (FuMa -> ACN+N3D). NOTE: This
  615. * matrix is transposed, for the inputs to align on the rows and
  616. * outputs on the columns.
  617. */
  618. aluMatrixfSet(&matrix,
  619. // ACN0 ACN1 ACN2 ACN3
  620. sqrt_2, 0.0f, 0.0f, 0.0f, // Ambi W
  621. 0.0f, -N[0]*sqrt_3, N[1]*sqrt_3, -N[2]*sqrt_3, // Ambi X
  622. 0.0f, U[0]*sqrt_3, -U[1]*sqrt_3, U[2]*sqrt_3, // Ambi Y
  623. 0.0f, -V[0]*sqrt_3, V[1]*sqrt_3, -V[2]*sqrt_3 // Ambi Z
  624. );
  625. voice->Direct.Buffer = Device->FOAOut.Buffer;
  626. voice->Direct.Channels = Device->FOAOut.NumChannels;
  627. for(c = 0;c < num_channels;c++)
  628. ComputeFirstOrderGains(&Device->FOAOut, matrix.m[c], DryGain,
  629. voice->Direct.Params[c].Gains.Target);
  630. for(i = 0;i < NumSends;i++)
  631. {
  632. const ALeffectslot *Slot = SendSlots[i];
  633. if(Slot)
  634. {
  635. for(c = 0;c < num_channels;c++)
  636. ComputeFirstOrderGainsBF(Slot->ChanMap, Slot->NumChannels,
  637. matrix.m[c], WetGain[i], voice->Send[i].Params[c].Gains.Target
  638. );
  639. }
  640. }
  641. }
  642. }
  643. else if(DirectChannels)
  644. {
  645. /* Direct source channels always play local. Skip the virtual channels
  646. * and write inputs to the matching real outputs.
  647. */
  648. voice->Direct.Buffer = Device->RealOut.Buffer;
  649. voice->Direct.Channels = Device->RealOut.NumChannels;
  650. for(c = 0;c < num_channels;c++)
  651. {
  652. int idx = GetChannelIdxByName(&Device->RealOut, chans[c].channel);
  653. if(idx != -1) voice->Direct.Params[c].Gains.Target[idx] = DryGain;
  654. }
  655. /* Auxiliary sends still use normal channel panning since they mix to
  656. * B-Format, which can't channel-match.
  657. */
  658. for(c = 0;c < num_channels;c++)
  659. {
  660. ALfloat coeffs[MAX_AMBI_COEFFS];
  661. CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
  662. for(i = 0;i < NumSends;i++)
  663. {
  664. const ALeffectslot *Slot = SendSlots[i];
  665. if(Slot)
  666. ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
  667. coeffs, WetGain[i], voice->Send[i].Params[c].Gains.Target
  668. );
  669. }
  670. }
  671. }
  672. else if(Device->Render_Mode == HrtfRender)
  673. {
  674. /* Full HRTF rendering. Skip the virtual channels and render to the
  675. * real outputs.
  676. */
  677. voice->Direct.Buffer = Device->RealOut.Buffer;
  678. voice->Direct.Channels = Device->RealOut.NumChannels;
  679. if(Distance > FLT_EPSILON)
  680. {
  681. ALfloat coeffs[MAX_AMBI_COEFFS];
  682. /* Get the HRIR coefficients and delays just once, for the given
  683. * source direction.
  684. */
  685. GetHrtfCoeffs(Device->HrtfHandle, Elev, Azi, Spread,
  686. voice->Direct.Params[0].Hrtf.Target.Coeffs,
  687. voice->Direct.Params[0].Hrtf.Target.Delay);
  688. voice->Direct.Params[0].Hrtf.Target.Gain = DryGain * downmix_gain;
  689. /* Remaining channels use the same results as the first. */
  690. for(c = 1;c < num_channels;c++)
  691. {
  692. /* Skip LFE */
  693. if(chans[c].channel != LFE)
  694. voice->Direct.Params[c].Hrtf.Target = voice->Direct.Params[0].Hrtf.Target;
  695. }
  696. /* Calculate the directional coefficients once, which apply to all
  697. * input channels of the source sends.
  698. */
  699. CalcAngleCoeffs(Azi, Elev, Spread, coeffs);
  700. for(i = 0;i < NumSends;i++)
  701. {
  702. const ALeffectslot *Slot = SendSlots[i];
  703. if(Slot)
  704. for(c = 0;c < num_channels;c++)
  705. {
  706. /* Skip LFE */
  707. if(chans[c].channel != LFE)
  708. ComputePanningGainsBF(Slot->ChanMap,
  709. Slot->NumChannels, coeffs, WetGain[i] * downmix_gain,
  710. voice->Send[i].Params[c].Gains.Target
  711. );
  712. }
  713. }
  714. }
  715. else
  716. {
  717. /* Local sources on HRTF play with each channel panned to its
  718. * relative location around the listener, providing "virtual
  719. * speaker" responses.
  720. */
  721. for(c = 0;c < num_channels;c++)
  722. {
  723. ALfloat coeffs[MAX_AMBI_COEFFS];
  724. if(chans[c].channel == LFE)
  725. {
  726. /* Skip LFE */
  727. continue;
  728. }
  729. /* Get the HRIR coefficients and delays for this channel
  730. * position.
  731. */
  732. GetHrtfCoeffs(Device->HrtfHandle,
  733. chans[c].elevation, chans[c].angle, Spread,
  734. voice->Direct.Params[c].Hrtf.Target.Coeffs,
  735. voice->Direct.Params[c].Hrtf.Target.Delay
  736. );
  737. voice->Direct.Params[c].Hrtf.Target.Gain = DryGain;
  738. /* Normal panning for auxiliary sends. */
  739. CalcAngleCoeffs(chans[c].angle, chans[c].elevation, Spread, coeffs);
  740. for(i = 0;i < NumSends;i++)
  741. {
  742. const ALeffectslot *Slot = SendSlots[i];
  743. if(Slot)
  744. ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
  745. coeffs, WetGain[i], voice->Send[i].Params[c].Gains.Target
  746. );
  747. }
  748. }
  749. }
  750. voice->Flags |= VOICE_HAS_HRTF;
  751. }
  752. else
  753. {
  754. /* Non-HRTF rendering. Use normal panning to the output. */
  755. if(Distance > FLT_EPSILON)
  756. {
  757. ALfloat coeffs[MAX_AMBI_COEFFS];
  758. ALfloat w0 = 0.0f;
  759. /* Calculate NFC filter coefficient if needed. */
  760. if(Device->AvgSpeakerDist > 0.0f)
  761. {
  762. ALfloat mdist = Distance * Listener->Params.MetersPerUnit;
  763. ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
  764. (Device->AvgSpeakerDist * (ALfloat)Device->Frequency);
  765. w0 = SPEEDOFSOUNDMETRESPERSEC /
  766. (mdist * (ALfloat)Device->Frequency);
  767. /* Clamp w0 for really close distances, to prevent excessive
  768. * bass.
  769. */
  770. w0 = minf(w0, w1*4.0f);
  771. /* Adjust NFC filters. */
  772. for(c = 0;c < num_channels;c++)
  773. NfcFilterAdjust(&voice->Direct.Params[c].NFCtrlFilter, w0);
  774. for(i = 0;i < MAX_AMBI_ORDER+1;i++)
  775. voice->Direct.ChannelsPerOrder[i] = Device->Dry.NumChannelsPerOrder[i];
  776. voice->Flags |= VOICE_HAS_NFC;
  777. }
  778. /* Calculate the directional coefficients once, which apply to all
  779. * input channels.
  780. */
  781. if(Device->Render_Mode == StereoPair)
  782. CalcAnglePairwiseCoeffs(Azi, Elev, Spread, coeffs);
  783. else
  784. CalcAngleCoeffs(Azi, Elev, Spread, coeffs);
  785. for(c = 0;c < num_channels;c++)
  786. {
  787. /* Special-case LFE */
  788. if(chans[c].channel == LFE)
  789. {
  790. if(Device->Dry.Buffer == Device->RealOut.Buffer)
  791. {
  792. int idx = GetChannelIdxByName(&Device->RealOut, chans[c].channel);
  793. if(idx != -1) voice->Direct.Params[c].Gains.Target[idx] = DryGain;
  794. }
  795. continue;
  796. }
  797. ComputeDryPanGains(&Device->Dry,
  798. coeffs, DryGain * downmix_gain, voice->Direct.Params[c].Gains.Target
  799. );
  800. }
  801. for(i = 0;i < NumSends;i++)
  802. {
  803. const ALeffectslot *Slot = SendSlots[i];
  804. if(Slot)
  805. for(c = 0;c < num_channels;c++)
  806. {
  807. /* Skip LFE */
  808. if(chans[c].channel != LFE)
  809. ComputePanningGainsBF(Slot->ChanMap,
  810. Slot->NumChannels, coeffs, WetGain[i] * downmix_gain,
  811. voice->Send[i].Params[c].Gains.Target
  812. );
  813. }
  814. }
  815. }
  816. else
  817. {
  818. ALfloat w0 = 0.0f;
  819. if(Device->AvgSpeakerDist > 0.0f)
  820. {
  821. /* If the source distance is 0, set w0 to w1 to act as a pass-
  822. * through. We still want to pass the signal through the
  823. * filters so they keep an appropriate history, in case the
  824. * source moves away from the listener.
  825. */
  826. w0 = SPEEDOFSOUNDMETRESPERSEC /
  827. (Device->AvgSpeakerDist * (ALfloat)Device->Frequency);
  828. for(c = 0;c < num_channels;c++)
  829. NfcFilterAdjust(&voice->Direct.Params[c].NFCtrlFilter, w0);
  830. for(i = 0;i < MAX_AMBI_ORDER+1;i++)
  831. voice->Direct.ChannelsPerOrder[i] = Device->Dry.NumChannelsPerOrder[i];
  832. voice->Flags |= VOICE_HAS_NFC;
  833. }
  834. for(c = 0;c < num_channels;c++)
  835. {
  836. ALfloat coeffs[MAX_AMBI_COEFFS];
  837. /* Special-case LFE */
  838. if(chans[c].channel == LFE)
  839. {
  840. if(Device->Dry.Buffer == Device->RealOut.Buffer)
  841. {
  842. int idx = GetChannelIdxByName(&Device->RealOut, chans[c].channel);
  843. if(idx != -1) voice->Direct.Params[c].Gains.Target[idx] = DryGain;
  844. }
  845. continue;
  846. }
  847. if(Device->Render_Mode == StereoPair)
  848. CalcAnglePairwiseCoeffs(chans[c].angle, chans[c].elevation, Spread, coeffs);
  849. else
  850. CalcAngleCoeffs(chans[c].angle, chans[c].elevation, Spread, coeffs);
  851. ComputeDryPanGains(&Device->Dry,
  852. coeffs, DryGain, voice->Direct.Params[c].Gains.Target
  853. );
  854. for(i = 0;i < NumSends;i++)
  855. {
  856. const ALeffectslot *Slot = SendSlots[i];
  857. if(Slot)
  858. ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
  859. coeffs, WetGain[i], voice->Send[i].Params[c].Gains.Target
  860. );
  861. }
  862. }
  863. }
  864. }
  865. {
  866. ALfloat hfScale = props->Direct.HFReference / Frequency;
  867. ALfloat lfScale = props->Direct.LFReference / Frequency;
  868. ALfloat gainHF = maxf(DryGainHF, 0.001f); /* Limit -60dB */
  869. ALfloat gainLF = maxf(DryGainLF, 0.001f);
  870. voice->Direct.FilterType = AF_None;
  871. if(gainHF != 1.0f) voice->Direct.FilterType |= AF_LowPass;
  872. if(gainLF != 1.0f) voice->Direct.FilterType |= AF_HighPass;
  873. BiquadFilter_setParams(
  874. &voice->Direct.Params[0].LowPass, BiquadType_HighShelf,
  875. gainHF, hfScale, calc_rcpQ_from_slope(gainHF, 1.0f)
  876. );
  877. BiquadFilter_setParams(
  878. &voice->Direct.Params[0].HighPass, BiquadType_LowShelf,
  879. gainLF, lfScale, calc_rcpQ_from_slope(gainLF, 1.0f)
  880. );
  881. for(c = 1;c < num_channels;c++)
  882. {
  883. BiquadFilter_copyParams(&voice->Direct.Params[c].LowPass,
  884. &voice->Direct.Params[0].LowPass);
  885. BiquadFilter_copyParams(&voice->Direct.Params[c].HighPass,
  886. &voice->Direct.Params[0].HighPass);
  887. }
  888. }
  889. for(i = 0;i < NumSends;i++)
  890. {
  891. ALfloat hfScale = props->Send[i].HFReference / Frequency;
  892. ALfloat lfScale = props->Send[i].LFReference / Frequency;
  893. ALfloat gainHF = maxf(WetGainHF[i], 0.001f);
  894. ALfloat gainLF = maxf(WetGainLF[i], 0.001f);
  895. voice->Send[i].FilterType = AF_None;
  896. if(gainHF != 1.0f) voice->Send[i].FilterType |= AF_LowPass;
  897. if(gainLF != 1.0f) voice->Send[i].FilterType |= AF_HighPass;
  898. BiquadFilter_setParams(
  899. &voice->Send[i].Params[0].LowPass, BiquadType_HighShelf,
  900. gainHF, hfScale, calc_rcpQ_from_slope(gainHF, 1.0f)
  901. );
  902. BiquadFilter_setParams(
  903. &voice->Send[i].Params[0].HighPass, BiquadType_LowShelf,
  904. gainLF, lfScale, calc_rcpQ_from_slope(gainLF, 1.0f)
  905. );
  906. for(c = 1;c < num_channels;c++)
  907. {
  908. BiquadFilter_copyParams(&voice->Send[i].Params[c].LowPass,
  909. &voice->Send[i].Params[0].LowPass);
  910. BiquadFilter_copyParams(&voice->Send[i].Params[c].HighPass,
  911. &voice->Send[i].Params[0].HighPass);
  912. }
  913. }
  914. }
  915. static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext)
  916. {
  917. const ALCdevice *Device = ALContext->Device;
  918. const ALlistener *Listener = ALContext->Listener;
  919. ALfloat DryGain, DryGainHF, DryGainLF;
  920. ALfloat WetGain[MAX_SENDS];
  921. ALfloat WetGainHF[MAX_SENDS];
  922. ALfloat WetGainLF[MAX_SENDS];
  923. ALeffectslot *SendSlots[MAX_SENDS];
  924. ALfloat Pitch;
  925. ALsizei i;
  926. voice->Direct.Buffer = Device->Dry.Buffer;
  927. voice->Direct.Channels = Device->Dry.NumChannels;
  928. for(i = 0;i < Device->NumAuxSends;i++)
  929. {
  930. SendSlots[i] = props->Send[i].Slot;
  931. if(!SendSlots[i] && i == 0)
  932. SendSlots[i] = ALContext->DefaultSlot;
  933. if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL)
  934. {
  935. SendSlots[i] = NULL;
  936. voice->Send[i].Buffer = NULL;
  937. voice->Send[i].Channels = 0;
  938. }
  939. else
  940. {
  941. voice->Send[i].Buffer = SendSlots[i]->WetBuffer;
  942. voice->Send[i].Channels = SendSlots[i]->NumChannels;
  943. }
  944. }
  945. /* Calculate the stepping value */
  946. Pitch = (ALfloat)ALBuffer->Frequency/(ALfloat)Device->Frequency * props->Pitch;
  947. if(Pitch > (ALfloat)MAX_PITCH)
  948. voice->Step = MAX_PITCH<<FRACTIONBITS;
  949. else
  950. voice->Step = maxi(fastf2i(Pitch * FRACTIONONE), 1);
  951. if(props->Resampler == BSinc24Resampler)
  952. BsincPrepare(voice->Step, &voice->ResampleState.bsinc, &bsinc24);
  953. else if(props->Resampler == BSinc12Resampler)
  954. BsincPrepare(voice->Step, &voice->ResampleState.bsinc, &bsinc12);
  955. voice->Resampler = SelectResampler(props->Resampler);
  956. /* Calculate gains */
  957. DryGain = clampf(props->Gain, props->MinGain, props->MaxGain);
  958. DryGain *= props->Direct.Gain * Listener->Params.Gain;
  959. DryGain = minf(DryGain, GAIN_MIX_MAX);
  960. DryGainHF = props->Direct.GainHF;
  961. DryGainLF = props->Direct.GainLF;
  962. for(i = 0;i < Device->NumAuxSends;i++)
  963. {
  964. WetGain[i] = clampf(props->Gain, props->MinGain, props->MaxGain);
  965. WetGain[i] *= props->Send[i].Gain * Listener->Params.Gain;
  966. WetGain[i] = minf(WetGain[i], GAIN_MIX_MAX);
  967. WetGainHF[i] = props->Send[i].GainHF;
  968. WetGainLF[i] = props->Send[i].GainLF;
  969. }
  970. CalcPanningAndFilters(voice, 0.0f, 0.0f, 0.0f, 0.0f, DryGain, DryGainHF, DryGainLF, WetGain,
  971. WetGainLF, WetGainHF, SendSlots, ALBuffer, props, Listener, Device);
  972. }
  973. static void CalcAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext)
  974. {
  975. const ALCdevice *Device = ALContext->Device;
  976. const ALlistener *Listener = ALContext->Listener;
  977. const ALsizei NumSends = Device->NumAuxSends;
  978. aluVector Position, Velocity, Direction, SourceToListener;
  979. ALfloat Distance, ClampedDist, DopplerFactor;
  980. ALeffectslot *SendSlots[MAX_SENDS];
  981. ALfloat RoomRolloff[MAX_SENDS];
  982. ALfloat DecayDistance[MAX_SENDS];
  983. ALfloat DecayLFDistance[MAX_SENDS];
  984. ALfloat DecayHFDistance[MAX_SENDS];
  985. ALfloat DryGain, DryGainHF, DryGainLF;
  986. ALfloat WetGain[MAX_SENDS];
  987. ALfloat WetGainHF[MAX_SENDS];
  988. ALfloat WetGainLF[MAX_SENDS];
  989. bool directional;
  990. ALfloat ev, az;
  991. ALfloat spread;
  992. ALfloat Pitch;
  993. ALint i;
  994. /* Set mixing buffers and get send parameters. */
  995. voice->Direct.Buffer = Device->Dry.Buffer;
  996. voice->Direct.Channels = Device->Dry.NumChannels;
  997. for(i = 0;i < NumSends;i++)
  998. {
  999. SendSlots[i] = props->Send[i].Slot;
  1000. if(!SendSlots[i] && i == 0)
  1001. SendSlots[i] = ALContext->DefaultSlot;
  1002. if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL)
  1003. {
  1004. SendSlots[i] = NULL;
  1005. RoomRolloff[i] = 0.0f;
  1006. DecayDistance[i] = 0.0f;
  1007. DecayLFDistance[i] = 0.0f;
  1008. DecayHFDistance[i] = 0.0f;
  1009. }
  1010. else if(SendSlots[i]->Params.AuxSendAuto)
  1011. {
  1012. RoomRolloff[i] = SendSlots[i]->Params.RoomRolloff + props->RoomRolloffFactor;
  1013. /* Calculate the distances to where this effect's decay reaches
  1014. * -60dB.
  1015. */
  1016. DecayDistance[i] = SendSlots[i]->Params.DecayTime *
  1017. Listener->Params.ReverbSpeedOfSound;
  1018. DecayLFDistance[i] = DecayDistance[i] * SendSlots[i]->Params.DecayLFRatio;
  1019. DecayHFDistance[i] = DecayDistance[i] * SendSlots[i]->Params.DecayHFRatio;
  1020. if(SendSlots[i]->Params.DecayHFLimit)
  1021. {
  1022. ALfloat airAbsorption = SendSlots[i]->Params.AirAbsorptionGainHF;
  1023. if(airAbsorption < 1.0f)
  1024. {
  1025. /* Calculate the distance to where this effect's air
  1026. * absorption reaches -60dB, and limit the effect's HF
  1027. * decay distance (so it doesn't take any longer to decay
  1028. * than the air would allow).
  1029. */
  1030. ALfloat absorb_dist = log10f(REVERB_DECAY_GAIN) / log10f(airAbsorption);
  1031. DecayHFDistance[i] = minf(absorb_dist, DecayHFDistance[i]);
  1032. }
  1033. }
  1034. }
  1035. else
  1036. {
  1037. /* If the slot's auxiliary send auto is off, the data sent to the
  1038. * effect slot is the same as the dry path, sans filter effects */
  1039. RoomRolloff[i] = props->RolloffFactor;
  1040. DecayDistance[i] = 0.0f;
  1041. DecayLFDistance[i] = 0.0f;
  1042. DecayHFDistance[i] = 0.0f;
  1043. }
  1044. if(!SendSlots[i])
  1045. {
  1046. voice->Send[i].Buffer = NULL;
  1047. voice->Send[i].Channels = 0;
  1048. }
  1049. else
  1050. {
  1051. voice->Send[i].Buffer = SendSlots[i]->WetBuffer;
  1052. voice->Send[i].Channels = SendSlots[i]->NumChannels;
  1053. }
  1054. }
  1055. /* Transform source to listener space (convert to head relative) */
  1056. aluVectorSet(&Position, props->Position[0], props->Position[1], props->Position[2], 1.0f);
  1057. aluVectorSet(&Direction, props->Direction[0], props->Direction[1], props->Direction[2], 0.0f);
  1058. aluVectorSet(&Velocity, props->Velocity[0], props->Velocity[1], props->Velocity[2], 0.0f);
  1059. if(props->HeadRelative == AL_FALSE)
  1060. {
  1061. const aluMatrixf *Matrix = &Listener->Params.Matrix;
  1062. /* Transform source vectors */
  1063. Position = aluMatrixfVector(Matrix, &Position);
  1064. Velocity = aluMatrixfVector(Matrix, &Velocity);
  1065. Direction = aluMatrixfVector(Matrix, &Direction);
  1066. }
  1067. else
  1068. {
  1069. const aluVector *lvelocity = &Listener->Params.Velocity;
  1070. /* Offset the source velocity to be relative of the listener velocity */
  1071. Velocity.v[0] += lvelocity->v[0];
  1072. Velocity.v[1] += lvelocity->v[1];
  1073. Velocity.v[2] += lvelocity->v[2];
  1074. }
  1075. directional = aluNormalize(Direction.v) > 0.0f;
  1076. SourceToListener.v[0] = -Position.v[0];
  1077. SourceToListener.v[1] = -Position.v[1];
  1078. SourceToListener.v[2] = -Position.v[2];
  1079. SourceToListener.v[3] = 0.0f;
  1080. Distance = aluNormalize(SourceToListener.v);
  1081. /* Initial source gain */
  1082. DryGain = props->Gain;
  1083. DryGainHF = 1.0f;
  1084. DryGainLF = 1.0f;
  1085. for(i = 0;i < NumSends;i++)
  1086. {
  1087. WetGain[i] = props->Gain;
  1088. WetGainHF[i] = 1.0f;
  1089. WetGainLF[i] = 1.0f;
  1090. }
  1091. /* Calculate distance attenuation */
  1092. ClampedDist = Distance;
  1093. switch(Listener->Params.SourceDistanceModel ?
  1094. props->DistanceModel : Listener->Params.DistanceModel)
  1095. {
  1096. case InverseDistanceClamped:
  1097. ClampedDist = clampf(ClampedDist, props->RefDistance, props->MaxDistance);
  1098. if(props->MaxDistance < props->RefDistance)
  1099. break;
  1100. /*fall-through*/
  1101. case InverseDistance:
  1102. if(!(props->RefDistance > 0.0f))
  1103. ClampedDist = props->RefDistance;
  1104. else
  1105. {
  1106. ALfloat dist = lerp(props->RefDistance, ClampedDist, props->RolloffFactor);
  1107. if(dist > 0.0f) DryGain *= props->RefDistance / dist;
  1108. for(i = 0;i < NumSends;i++)
  1109. {
  1110. dist = lerp(props->RefDistance, ClampedDist, RoomRolloff[i]);
  1111. if(dist > 0.0f) WetGain[i] *= props->RefDistance / dist;
  1112. }
  1113. }
  1114. break;
  1115. case LinearDistanceClamped:
  1116. ClampedDist = clampf(ClampedDist, props->RefDistance, props->MaxDistance);
  1117. if(props->MaxDistance < props->RefDistance)
  1118. break;
  1119. /*fall-through*/
  1120. case LinearDistance:
  1121. if(!(props->MaxDistance != props->RefDistance))
  1122. ClampedDist = props->RefDistance;
  1123. else
  1124. {
  1125. ALfloat attn = props->RolloffFactor * (ClampedDist-props->RefDistance) /
  1126. (props->MaxDistance-props->RefDistance);
  1127. DryGain *= maxf(1.0f - attn, 0.0f);
  1128. for(i = 0;i < NumSends;i++)
  1129. {
  1130. attn = RoomRolloff[i] * (ClampedDist-props->RefDistance) /
  1131. (props->MaxDistance-props->RefDistance);
  1132. WetGain[i] *= maxf(1.0f - attn, 0.0f);
  1133. }
  1134. }
  1135. break;
  1136. case ExponentDistanceClamped:
  1137. ClampedDist = clampf(ClampedDist, props->RefDistance, props->MaxDistance);
  1138. if(props->MaxDistance < props->RefDistance)
  1139. break;
  1140. /*fall-through*/
  1141. case ExponentDistance:
  1142. if(!(ClampedDist > 0.0f && props->RefDistance > 0.0f))
  1143. ClampedDist = props->RefDistance;
  1144. else
  1145. {
  1146. DryGain *= powf(ClampedDist/props->RefDistance, -props->RolloffFactor);
  1147. for(i = 0;i < NumSends;i++)
  1148. WetGain[i] *= powf(ClampedDist/props->RefDistance, -RoomRolloff[i]);
  1149. }
  1150. break;
  1151. case DisableDistance:
  1152. ClampedDist = props->RefDistance;
  1153. break;
  1154. }
  1155. /* Calculate directional soundcones */
  1156. if(directional && props->InnerAngle < 360.0f)
  1157. {
  1158. ALfloat ConeVolume;
  1159. ALfloat ConeHF;
  1160. ALfloat Angle;
  1161. Angle = acosf(aluDotproduct(&Direction, &SourceToListener));
  1162. Angle = RAD2DEG(Angle * ConeScale * 2.0f);
  1163. if(!(Angle > props->InnerAngle))
  1164. {
  1165. ConeVolume = 1.0f;
  1166. ConeHF = 1.0f;
  1167. }
  1168. else if(Angle < props->OuterAngle)
  1169. {
  1170. ALfloat scale = ( Angle-props->InnerAngle) /
  1171. (props->OuterAngle-props->InnerAngle);
  1172. ConeVolume = lerp(1.0f, props->OuterGain, scale);
  1173. ConeHF = lerp(1.0f, props->OuterGainHF, scale);
  1174. }
  1175. else
  1176. {
  1177. ConeVolume = props->OuterGain;
  1178. ConeHF = props->OuterGainHF;
  1179. }
  1180. DryGain *= ConeVolume;
  1181. if(props->DryGainHFAuto)
  1182. DryGainHF *= ConeHF;
  1183. if(props->WetGainAuto)
  1184. {
  1185. for(i = 0;i < NumSends;i++)
  1186. WetGain[i] *= ConeVolume;
  1187. }
  1188. if(props->WetGainHFAuto)
  1189. {
  1190. for(i = 0;i < NumSends;i++)
  1191. WetGainHF[i] *= ConeHF;
  1192. }
  1193. }
  1194. /* Apply gain and frequency filters */
  1195. DryGain = clampf(DryGain, props->MinGain, props->MaxGain);
  1196. DryGain = minf(DryGain*props->Direct.Gain*Listener->Params.Gain, GAIN_MIX_MAX);
  1197. DryGainHF *= props->Direct.GainHF;
  1198. DryGainLF *= props->Direct.GainLF;
  1199. for(i = 0;i < NumSends;i++)
  1200. {
  1201. WetGain[i] = clampf(WetGain[i], props->MinGain, props->MaxGain);
  1202. WetGain[i] = minf(WetGain[i]*props->Send[i].Gain*Listener->Params.Gain, GAIN_MIX_MAX);
  1203. WetGainHF[i] *= props->Send[i].GainHF;
  1204. WetGainLF[i] *= props->Send[i].GainLF;
  1205. }
  1206. /* Distance-based air absorption and initial send decay. */
  1207. if(ClampedDist > props->RefDistance && props->RolloffFactor > 0.0f)
  1208. {
  1209. ALfloat meters_base = (ClampedDist-props->RefDistance) * props->RolloffFactor *
  1210. Listener->Params.MetersPerUnit;
  1211. if(props->AirAbsorptionFactor > 0.0f)
  1212. {
  1213. ALfloat hfattn = powf(AIRABSORBGAINHF, meters_base * props->AirAbsorptionFactor);
  1214. DryGainHF *= hfattn;
  1215. for(i = 0;i < NumSends;i++)
  1216. WetGainHF[i] *= hfattn;
  1217. }
  1218. if(props->WetGainAuto)
  1219. {
  1220. /* Apply a decay-time transformation to the wet path, based on the
  1221. * source distance in meters. The initial decay of the reverb
  1222. * effect is calculated and applied to the wet path.
  1223. */
  1224. for(i = 0;i < NumSends;i++)
  1225. {
  1226. ALfloat gain, gainhf, gainlf;
  1227. if(!(DecayDistance[i] > 0.0f))
  1228. continue;
  1229. gain = powf(REVERB_DECAY_GAIN, meters_base/DecayDistance[i]);
  1230. WetGain[i] *= gain;
  1231. /* Yes, the wet path's air absorption is applied with
  1232. * WetGainAuto on, rather than WetGainHFAuto.
  1233. */
  1234. if(gain > 0.0f)
  1235. {
  1236. gainhf = powf(REVERB_DECAY_GAIN, meters_base/DecayHFDistance[i]);
  1237. WetGainHF[i] *= minf(gainhf / gain, 1.0f);
  1238. gainlf = powf(REVERB_DECAY_GAIN, meters_base/DecayLFDistance[i]);
  1239. WetGainLF[i] *= minf(gainlf / gain, 1.0f);
  1240. }
  1241. }
  1242. }
  1243. }
  1244. /* Initial source pitch */
  1245. Pitch = props->Pitch;
  1246. /* Calculate velocity-based doppler effect */
  1247. DopplerFactor = props->DopplerFactor * Listener->Params.DopplerFactor;
  1248. if(DopplerFactor > 0.0f)
  1249. {
  1250. const aluVector *lvelocity = &Listener->Params.Velocity;
  1251. const ALfloat SpeedOfSound = Listener->Params.SpeedOfSound;
  1252. ALfloat vss, vls;
  1253. vss = aluDotproduct(&Velocity, &SourceToListener) * DopplerFactor;
  1254. vls = aluDotproduct(lvelocity, &SourceToListener) * DopplerFactor;
  1255. if(!(vls < SpeedOfSound))
  1256. {
  1257. /* Listener moving away from the source at the speed of sound.
  1258. * Sound waves can't catch it.
  1259. */
  1260. Pitch = 0.0f;
  1261. }
  1262. else if(!(vss < SpeedOfSound))
  1263. {
  1264. /* Source moving toward the listener at the speed of sound. Sound
  1265. * waves bunch up to extreme frequencies.
  1266. */
  1267. Pitch = HUGE_VALF;
  1268. }
  1269. else
  1270. {
  1271. /* Source and listener movement is nominal. Calculate the proper
  1272. * doppler shift.
  1273. */
  1274. Pitch *= (SpeedOfSound-vls) / (SpeedOfSound-vss);
  1275. }
  1276. }
  1277. /* Adjust pitch based on the buffer and output frequencies, and calculate
  1278. * fixed-point stepping value.
  1279. */
  1280. Pitch *= (ALfloat)ALBuffer->Frequency/(ALfloat)Device->Frequency;
  1281. if(Pitch > (ALfloat)MAX_PITCH)
  1282. voice->Step = MAX_PITCH<<FRACTIONBITS;
  1283. else
  1284. voice->Step = maxi(fastf2i(Pitch * FRACTIONONE), 1);
  1285. if(props->Resampler == BSinc24Resampler)
  1286. BsincPrepare(voice->Step, &voice->ResampleState.bsinc, &bsinc24);
  1287. else if(props->Resampler == BSinc12Resampler)
  1288. BsincPrepare(voice->Step, &voice->ResampleState.bsinc, &bsinc12);
  1289. voice->Resampler = SelectResampler(props->Resampler);
  1290. if(Distance > 0.0f)
  1291. {
  1292. /* Clamp Y, in case rounding errors caused it to end up outside of
  1293. * -1...+1.
  1294. */
  1295. ev = asinf(clampf(-SourceToListener.v[1], -1.0f, 1.0f));
  1296. /* Double negation on Z cancels out; negate once for changing source-
  1297. * to-listener to listener-to-source, and again for right-handed coords
  1298. * with -Z in front.
  1299. */
  1300. az = atan2f(-SourceToListener.v[0], SourceToListener.v[2]*ZScale);
  1301. }
  1302. else
  1303. ev = az = 0.0f;
  1304. if(props->Radius > Distance)
  1305. spread = F_TAU - Distance/props->Radius*F_PI;
  1306. else if(Distance > 0.0f)
  1307. spread = asinf(props->Radius / Distance) * 2.0f;
  1308. else
  1309. spread = 0.0f;
  1310. CalcPanningAndFilters(voice, az, ev, Distance, spread, DryGain, DryGainHF, DryGainLF, WetGain,
  1311. WetGainLF, WetGainHF, SendSlots, ALBuffer, props, Listener, Device);
  1312. }
  1313. static void CalcSourceParams(ALvoice *voice, ALCcontext *context, bool force)
  1314. {
  1315. ALbufferlistitem *BufferListItem;
  1316. struct ALvoiceProps *props;
  1317. props = ATOMIC_EXCHANGE_PTR(&voice->Update, NULL, almemory_order_acq_rel);
  1318. if(!props && !force) return;
  1319. if(props)
  1320. {
  1321. memcpy(voice->Props, props,
  1322. FAM_SIZE(struct ALvoiceProps, Send, context->Device->NumAuxSends)
  1323. );
  1324. ATOMIC_REPLACE_HEAD(struct ALvoiceProps*, &context->FreeVoiceProps, props);
  1325. }
  1326. props = voice->Props;
  1327. BufferListItem = ATOMIC_LOAD(&voice->current_buffer, almemory_order_relaxed);
  1328. while(BufferListItem != NULL)
  1329. {
  1330. const ALbuffer *buffer = NULL;
  1331. ALsizei i = 0;
  1332. while(!buffer && i < BufferListItem->num_buffers)
  1333. buffer = BufferListItem->buffers[i];
  1334. if(LIKELY(buffer))
  1335. {
  1336. if(props->SpatializeMode == SpatializeOn ||
  1337. (props->SpatializeMode == SpatializeAuto && buffer->FmtChannels == FmtMono))
  1338. CalcAttnSourceParams(voice, props, buffer, context);
  1339. else
  1340. CalcNonAttnSourceParams(voice, props, buffer, context);
  1341. break;
  1342. }
  1343. BufferListItem = ATOMIC_LOAD(&BufferListItem->next, almemory_order_acquire);
  1344. }
  1345. }
  1346. static void ProcessParamUpdates(ALCcontext *ctx, const struct ALeffectslotArray *slots)
  1347. {
  1348. ALvoice **voice, **voice_end;
  1349. ALsource *source;
  1350. ALsizei i;
  1351. IncrementRef(&ctx->UpdateCount);
  1352. if(!ATOMIC_LOAD(&ctx->HoldUpdates, almemory_order_acquire))
  1353. {
  1354. bool cforce = CalcContextParams(ctx);
  1355. bool force = CalcListenerParams(ctx) | cforce;
  1356. for(i = 0;i < slots->count;i++)
  1357. force |= CalcEffectSlotParams(slots->slot[i], ctx, cforce);
  1358. voice = ctx->Voices;
  1359. voice_end = voice + ctx->VoiceCount;
  1360. for(;voice != voice_end;++voice)
  1361. {
  1362. source = ATOMIC_LOAD(&(*voice)->Source, almemory_order_acquire);
  1363. if(source) CalcSourceParams(*voice, ctx, force);
  1364. }
  1365. }
  1366. IncrementRef(&ctx->UpdateCount);
  1367. }
  1368. static void ApplyStablizer(FrontStablizer *Stablizer, ALfloat (*restrict Buffer)[BUFFERSIZE],
  1369. int lidx, int ridx, int cidx, ALsizei SamplesToDo,
  1370. ALsizei NumChannels)
  1371. {
  1372. ALfloat (*restrict lsplit)[BUFFERSIZE] = ASSUME_ALIGNED(Stablizer->LSplit, 16);
  1373. ALfloat (*restrict rsplit)[BUFFERSIZE] = ASSUME_ALIGNED(Stablizer->RSplit, 16);
  1374. ALsizei i;
  1375. /* Apply an all-pass to all channels, except the front-left and front-
  1376. * right, so they maintain the same relative phase.
  1377. */
  1378. for(i = 0;i < NumChannels;i++)
  1379. {
  1380. if(i == lidx || i == ridx)
  1381. continue;
  1382. splitterap_process(&Stablizer->APFilter[i], Buffer[i], SamplesToDo);
  1383. }
  1384. bandsplit_process(&Stablizer->LFilter, lsplit[1], lsplit[0], Buffer[lidx], SamplesToDo);
  1385. bandsplit_process(&Stablizer->RFilter, rsplit[1], rsplit[0], Buffer[ridx], SamplesToDo);
  1386. for(i = 0;i < SamplesToDo;i++)
  1387. {
  1388. ALfloat lfsum, hfsum;
  1389. ALfloat m, s, c;
  1390. lfsum = lsplit[0][i] + rsplit[0][i];
  1391. hfsum = lsplit[1][i] + rsplit[1][i];
  1392. s = lsplit[0][i] + lsplit[1][i] - rsplit[0][i] - rsplit[1][i];
  1393. /* This pans the separate low- and high-frequency sums between being on
  1394. * the center channel and the left/right channels. The low-frequency
  1395. * sum is 1/3rd toward center (2/3rds on left/right) and the high-
  1396. * frequency sum is 1/4th toward center (3/4ths on left/right). These
  1397. * values can be tweaked.
  1398. */
  1399. m = lfsum*cosf(1.0f/3.0f * F_PI_2) + hfsum*cosf(1.0f/4.0f * F_PI_2);
  1400. c = lfsum*sinf(1.0f/3.0f * F_PI_2) + hfsum*sinf(1.0f/4.0f * F_PI_2);
  1401. /* The generated center channel signal adds to the existing signal,
  1402. * while the modified left and right channels replace.
  1403. */
  1404. Buffer[lidx][i] = (m + s) * 0.5f;
  1405. Buffer[ridx][i] = (m - s) * 0.5f;
  1406. Buffer[cidx][i] += c * 0.5f;
  1407. }
  1408. }
  1409. static void ApplyDistanceComp(ALfloat (*restrict Samples)[BUFFERSIZE], DistanceComp *distcomp,
  1410. ALfloat *restrict Values, ALsizei SamplesToDo, ALsizei numchans)
  1411. {
  1412. ALsizei i, c;
  1413. Values = ASSUME_ALIGNED(Values, 16);
  1414. for(c = 0;c < numchans;c++)
  1415. {
  1416. ALfloat *restrict inout = ASSUME_ALIGNED(Samples[c], 16);
  1417. const ALfloat gain = distcomp[c].Gain;
  1418. const ALsizei base = distcomp[c].Length;
  1419. ALfloat *restrict distbuf = ASSUME_ALIGNED(distcomp[c].Buffer, 16);
  1420. if(base == 0)
  1421. {
  1422. if(gain < 1.0f)
  1423. {
  1424. for(i = 0;i < SamplesToDo;i++)
  1425. inout[i] *= gain;
  1426. }
  1427. continue;
  1428. }
  1429. if(SamplesToDo >= base)
  1430. {
  1431. for(i = 0;i < base;i++)
  1432. Values[i] = distbuf[i];
  1433. for(;i < SamplesToDo;i++)
  1434. Values[i] = inout[i-base];
  1435. memcpy(distbuf, &inout[SamplesToDo-base], base*sizeof(ALfloat));
  1436. }
  1437. else
  1438. {
  1439. for(i = 0;i < SamplesToDo;i++)
  1440. Values[i] = distbuf[i];
  1441. memmove(distbuf, distbuf+SamplesToDo, (base-SamplesToDo)*sizeof(ALfloat));
  1442. memcpy(distbuf+base-SamplesToDo, inout, SamplesToDo*sizeof(ALfloat));
  1443. }
  1444. for(i = 0;i < SamplesToDo;i++)
  1445. inout[i] = Values[i]*gain;
  1446. }
  1447. }
  1448. static void ApplyDither(ALfloat (*restrict Samples)[BUFFERSIZE], ALuint *dither_seed,
  1449. const ALfloat quant_scale, const ALsizei SamplesToDo,
  1450. const ALsizei numchans)
  1451. {
  1452. const ALfloat invscale = 1.0f / quant_scale;
  1453. ALuint seed = *dither_seed;
  1454. ALsizei c, i;
  1455. /* Dithering. Step 1, generate whitenoise (uniform distribution of random
  1456. * values between -1 and +1). Step 2 is to add the noise to the samples,
  1457. * before rounding and after scaling up to the desired quantization depth.
  1458. */
  1459. for(c = 0;c < numchans;c++)
  1460. {
  1461. ALfloat *restrict samples = Samples[c];
  1462. for(i = 0;i < SamplesToDo;i++)
  1463. {
  1464. ALfloat val = samples[i] * quant_scale;
  1465. ALuint rng0 = dither_rng(&seed);
  1466. ALuint rng1 = dither_rng(&seed);
  1467. val += (ALfloat)(rng0*(1.0/UINT_MAX) - rng1*(1.0/UINT_MAX));
  1468. samples[i] = fastf2i(val) * invscale;
  1469. }
  1470. }
  1471. *dither_seed = seed;
  1472. }
  1473. static inline ALfloat Conv_ALfloat(ALfloat val)
  1474. { return val; }
  1475. static inline ALint Conv_ALint(ALfloat val)
  1476. {
  1477. /* Floats have a 23-bit mantissa. A bit of the exponent helps out along
  1478. * with the sign bit, giving 25 bits. So [-16777216, +16777216] is the max
  1479. * integer range normalized floats can be converted to before losing
  1480. * precision.
  1481. */
  1482. return fastf2i(clampf(val*16777216.0f, -16777216.0f, 16777215.0f))<<7;
  1483. }
  1484. static inline ALshort Conv_ALshort(ALfloat val)
  1485. { return fastf2i(clampf(val*32768.0f, -32768.0f, 32767.0f)); }
  1486. static inline ALbyte Conv_ALbyte(ALfloat val)
  1487. { return fastf2i(clampf(val*128.0f, -128.0f, 127.0f)); }
  1488. /* Define unsigned output variations. */
  1489. #define DECL_TEMPLATE(T, func, O) \
  1490. static inline T Conv_##T(ALfloat val) { return func(val)+O; }
  1491. DECL_TEMPLATE(ALubyte, Conv_ALbyte, 128)
  1492. DECL_TEMPLATE(ALushort, Conv_ALshort, 32768)
  1493. DECL_TEMPLATE(ALuint, Conv_ALint, 2147483648u)
  1494. #undef DECL_TEMPLATE
  1495. #define DECL_TEMPLATE(T, A) \
  1496. static void Write##A(const ALfloat (*restrict InBuffer)[BUFFERSIZE], \
  1497. ALvoid *OutBuffer, ALsizei Offset, ALsizei SamplesToDo, \
  1498. ALsizei numchans) \
  1499. { \
  1500. ALsizei i, j; \
  1501. for(j = 0;j < numchans;j++) \
  1502. { \
  1503. const ALfloat *restrict in = ASSUME_ALIGNED(InBuffer[j], 16); \
  1504. T *restrict out = (T*)OutBuffer + Offset*numchans + j; \
  1505. \
  1506. for(i = 0;i < SamplesToDo;i++) \
  1507. out[i*numchans] = Conv_##T(in[i]); \
  1508. } \
  1509. }
  1510. DECL_TEMPLATE(ALfloat, F32)
  1511. DECL_TEMPLATE(ALuint, UI32)
  1512. DECL_TEMPLATE(ALint, I32)
  1513. DECL_TEMPLATE(ALushort, UI16)
  1514. DECL_TEMPLATE(ALshort, I16)
  1515. DECL_TEMPLATE(ALubyte, UI8)
  1516. DECL_TEMPLATE(ALbyte, I8)
  1517. #undef DECL_TEMPLATE
  1518. void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples)
  1519. {
  1520. ALsizei SamplesToDo;
  1521. ALsizei SamplesDone;
  1522. ALCcontext *ctx;
  1523. ALsizei i, c;
  1524. START_MIXER_MODE();
  1525. for(SamplesDone = 0;SamplesDone < NumSamples;)
  1526. {
  1527. SamplesToDo = mini(NumSamples-SamplesDone, BUFFERSIZE);
  1528. for(c = 0;c < device->Dry.NumChannels;c++)
  1529. memset(device->Dry.Buffer[c], 0, SamplesToDo*sizeof(ALfloat));
  1530. if(device->Dry.Buffer != device->FOAOut.Buffer)
  1531. for(c = 0;c < device->FOAOut.NumChannels;c++)
  1532. memset(device->FOAOut.Buffer[c], 0, SamplesToDo*sizeof(ALfloat));
  1533. if(device->Dry.Buffer != device->RealOut.Buffer)
  1534. for(c = 0;c < device->RealOut.NumChannels;c++)
  1535. memset(device->RealOut.Buffer[c], 0, SamplesToDo*sizeof(ALfloat));
  1536. IncrementRef(&device->MixCount);
  1537. ctx = ATOMIC_LOAD(&device->ContextList, almemory_order_acquire);
  1538. while(ctx)
  1539. {
  1540. const struct ALeffectslotArray *auxslots;
  1541. auxslots = ATOMIC_LOAD(&ctx->ActiveAuxSlots, almemory_order_acquire);
  1542. ProcessParamUpdates(ctx, auxslots);
  1543. for(i = 0;i < auxslots->count;i++)
  1544. {
  1545. ALeffectslot *slot = auxslots->slot[i];
  1546. for(c = 0;c < slot->NumChannels;c++)
  1547. memset(slot->WetBuffer[c], 0, SamplesToDo*sizeof(ALfloat));
  1548. }
  1549. /* source processing */
  1550. for(i = 0;i < ctx->VoiceCount;i++)
  1551. {
  1552. ALvoice *voice = ctx->Voices[i];
  1553. ALsource *source = ATOMIC_LOAD(&voice->Source, almemory_order_acquire);
  1554. if(source && ATOMIC_LOAD(&voice->Playing, almemory_order_relaxed) &&
  1555. voice->Step > 0)
  1556. {
  1557. if(!MixSource(voice, source->id, ctx, SamplesToDo))
  1558. {
  1559. ATOMIC_STORE(&voice->Source, NULL, almemory_order_relaxed);
  1560. ATOMIC_STORE(&voice->Playing, false, almemory_order_release);
  1561. SendSourceStoppedEvent(ctx, source->id);
  1562. }
  1563. }
  1564. }
  1565. /* effect slot processing */
  1566. for(i = 0;i < auxslots->count;i++)
  1567. {
  1568. const ALeffectslot *slot = auxslots->slot[i];
  1569. ALeffectState *state = slot->Params.EffectState;
  1570. V(state,process)(SamplesToDo, slot->WetBuffer, state->OutBuffer,
  1571. state->OutChannels);
  1572. }
  1573. ctx = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
  1574. }
  1575. /* Increment the clock time. Every second's worth of samples is
  1576. * converted and added to clock base so that large sample counts don't
  1577. * overflow during conversion. This also guarantees an exact, stable
  1578. * conversion. */
  1579. device->SamplesDone += SamplesToDo;
  1580. device->ClockBase += (device->SamplesDone/device->Frequency) * DEVICE_CLOCK_RES;
  1581. device->SamplesDone %= device->Frequency;
  1582. IncrementRef(&device->MixCount);
  1583. /* Apply post-process for finalizing the Dry mix to the RealOut
  1584. * (Ambisonic decode, UHJ encode, etc).
  1585. */
  1586. if(LIKELY(device->PostProcess))
  1587. device->PostProcess(device, SamplesToDo);
  1588. if(device->Stablizer)
  1589. {
  1590. int lidx = GetChannelIdxByName(&device->RealOut, FrontLeft);
  1591. int ridx = GetChannelIdxByName(&device->RealOut, FrontRight);
  1592. int cidx = GetChannelIdxByName(&device->RealOut, FrontCenter);
  1593. assert(lidx >= 0 && ridx >= 0 && cidx >= 0);
  1594. ApplyStablizer(device->Stablizer, device->RealOut.Buffer, lidx, ridx, cidx,
  1595. SamplesToDo, device->RealOut.NumChannels);
  1596. }
  1597. ApplyDistanceComp(device->RealOut.Buffer, device->ChannelDelay, device->TempBuffer[0],
  1598. SamplesToDo, device->RealOut.NumChannels);
  1599. if(device->Limiter)
  1600. ApplyCompression(device->Limiter, device->RealOut.NumChannels, SamplesToDo,
  1601. device->RealOut.Buffer);
  1602. if(device->DitherDepth > 0.0f)
  1603. ApplyDither(device->RealOut.Buffer, &device->DitherSeed, device->DitherDepth,
  1604. SamplesToDo, device->RealOut.NumChannels);
  1605. if(LIKELY(OutBuffer))
  1606. {
  1607. ALfloat (*Buffer)[BUFFERSIZE] = device->RealOut.Buffer;
  1608. ALsizei Channels = device->RealOut.NumChannels;
  1609. switch(device->FmtType)
  1610. {
  1611. case DevFmtByte:
  1612. WriteI8(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
  1613. break;
  1614. case DevFmtUByte:
  1615. WriteUI8(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
  1616. break;
  1617. case DevFmtShort:
  1618. WriteI16(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
  1619. break;
  1620. case DevFmtUShort:
  1621. WriteUI16(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
  1622. break;
  1623. case DevFmtInt:
  1624. WriteI32(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
  1625. break;
  1626. case DevFmtUInt:
  1627. WriteUI32(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
  1628. break;
  1629. case DevFmtFloat:
  1630. WriteF32(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
  1631. break;
  1632. }
  1633. }
  1634. SamplesDone += SamplesToDo;
  1635. }
  1636. END_MIXER_MODE();
  1637. }
  1638. void aluHandleDisconnect(ALCdevice *device, const char *msg, ...)
  1639. {
  1640. ALCcontext *ctx;
  1641. AsyncEvent evt;
  1642. va_list args;
  1643. int msglen;
  1644. if(!ATOMIC_EXCHANGE(&device->Connected, AL_FALSE, almemory_order_acq_rel))
  1645. return;
  1646. evt.EnumType = EventType_Disconnected;
  1647. evt.Type = AL_EVENT_TYPE_DISCONNECTED_SOFT;
  1648. evt.ObjectId = 0;
  1649. evt.Param = 0;
  1650. va_start(args, msg);
  1651. msglen = vsnprintf(evt.Message, sizeof(evt.Message), msg, args);
  1652. va_end(args);
  1653. if(msglen < 0 || (size_t)msglen >= sizeof(evt.Message))
  1654. {
  1655. evt.Message[sizeof(evt.Message)-1] = 0;
  1656. msglen = (int)strlen(evt.Message);
  1657. }
  1658. if(msglen > 0)
  1659. msg = evt.Message;
  1660. else
  1661. {
  1662. msg = "<internal error constructing message>";
  1663. msglen = (int)strlen(msg);
  1664. }
  1665. ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
  1666. while(ctx)
  1667. {
  1668. ALbitfieldSOFT enabledevt = ATOMIC_LOAD(&ctx->EnabledEvts, almemory_order_acquire);
  1669. ALsizei i;
  1670. if((enabledevt&EventType_Disconnected) &&
  1671. ll_ringbuffer_write(ctx->AsyncEvents, (const char*)&evt, 1) == 1)
  1672. alsem_post(&ctx->EventSem);
  1673. for(i = 0;i < ctx->VoiceCount;i++)
  1674. {
  1675. ALvoice *voice = ctx->Voices[i];
  1676. ALsource *source;
  1677. source = ATOMIC_EXCHANGE_PTR(&voice->Source, NULL, almemory_order_relaxed);
  1678. if(source && ATOMIC_LOAD(&voice->Playing, almemory_order_relaxed))
  1679. {
  1680. /* If the source's voice was playing, it's now effectively
  1681. * stopped (the source state will be updated the next time it's
  1682. * checked).
  1683. */
  1684. SendSourceStoppedEvent(ctx, source->id);
  1685. }
  1686. ATOMIC_STORE(&voice->Playing, false, almemory_order_release);
  1687. }
  1688. ctx = ATOMIC_LOAD(&ctx->next, almemory_order_relaxed);
  1689. }
  1690. }