2
0

ALu.c 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657
  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 "uhjfilter.h"
  35. #include "bformatdec.h"
  36. #include "static_assert.h"
  37. #include "mixer_defs.h"
  38. #include "backends/base.h"
  39. struct ChanMap {
  40. enum Channel channel;
  41. ALfloat angle;
  42. ALfloat elevation;
  43. };
  44. /* Cone scalar */
  45. ALfloat ConeScale = 1.0f;
  46. /* Localized Z scalar for mono sources */
  47. ALfloat ZScale = 1.0f;
  48. extern inline ALfloat minf(ALfloat a, ALfloat b);
  49. extern inline ALfloat maxf(ALfloat a, ALfloat b);
  50. extern inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max);
  51. extern inline ALdouble mind(ALdouble a, ALdouble b);
  52. extern inline ALdouble maxd(ALdouble a, ALdouble b);
  53. extern inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max);
  54. extern inline ALuint minu(ALuint a, ALuint b);
  55. extern inline ALuint maxu(ALuint a, ALuint b);
  56. extern inline ALuint clampu(ALuint val, ALuint min, ALuint max);
  57. extern inline ALint mini(ALint a, ALint b);
  58. extern inline ALint maxi(ALint a, ALint b);
  59. extern inline ALint clampi(ALint val, ALint min, ALint max);
  60. extern inline ALint64 mini64(ALint64 a, ALint64 b);
  61. extern inline ALint64 maxi64(ALint64 a, ALint64 b);
  62. extern inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max);
  63. extern inline ALuint64 minu64(ALuint64 a, ALuint64 b);
  64. extern inline ALuint64 maxu64(ALuint64 a, ALuint64 b);
  65. extern inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max);
  66. extern inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu);
  67. extern inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALuint frac);
  68. extern inline ALfloat resample_fir8(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat val5, ALfloat val6, ALfloat val7, ALuint frac);
  69. extern inline void aluVectorSet(aluVector *restrict vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w);
  70. extern inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
  71. ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3);
  72. extern inline void aluMatrixfSet(aluMatrixf *matrix,
  73. ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
  74. ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
  75. ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
  76. ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33);
  77. const aluMatrixf IdentityMatrixf = {{
  78. { 1.0f, 0.0f, 0.0f, 0.0f },
  79. { 0.0f, 1.0f, 0.0f, 0.0f },
  80. { 0.0f, 0.0f, 1.0f, 0.0f },
  81. { 0.0f, 0.0f, 0.0f, 1.0f },
  82. }};
  83. static inline HrtfDirectMixerFunc SelectHrtfMixer(void)
  84. {
  85. #ifdef HAVE_SSE
  86. if((CPUCapFlags&CPU_CAP_SSE))
  87. return MixDirectHrtf_SSE;
  88. #endif
  89. #ifdef HAVE_NEON
  90. if((CPUCapFlags&CPU_CAP_NEON))
  91. return MixDirectHrtf_Neon;
  92. #endif
  93. return MixDirectHrtf_C;
  94. }
  95. static inline void aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector)
  96. {
  97. outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
  98. outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
  99. outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
  100. }
  101. static inline ALfloat aluDotproduct(const aluVector *vec1, const aluVector *vec2)
  102. {
  103. return vec1->v[0]*vec2->v[0] + vec1->v[1]*vec2->v[1] + vec1->v[2]*vec2->v[2];
  104. }
  105. static ALfloat aluNormalize(ALfloat *vec)
  106. {
  107. ALfloat length = sqrtf(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
  108. if(length > 0.0f)
  109. {
  110. ALfloat inv_length = 1.0f/length;
  111. vec[0] *= inv_length;
  112. vec[1] *= inv_length;
  113. vec[2] *= inv_length;
  114. }
  115. return length;
  116. }
  117. static void aluMatrixfFloat3(ALfloat *vec, ALfloat w, const aluMatrixf *mtx)
  118. {
  119. ALfloat v[4] = { vec[0], vec[1], vec[2], w };
  120. 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];
  121. 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];
  122. 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];
  123. }
  124. static aluVector aluMatrixfVector(const aluMatrixf *mtx, const aluVector *vec)
  125. {
  126. aluVector v;
  127. 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];
  128. 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];
  129. 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];
  130. 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];
  131. return v;
  132. }
  133. /* Prepares the interpolator for a given rate (determined by increment). A
  134. * result of AL_FALSE indicates that the filter output will completely cut
  135. * the input signal.
  136. *
  137. * With a bit of work, and a trade of memory for CPU cost, this could be
  138. * modified for use with an interpolated increment for buttery-smooth pitch
  139. * changes.
  140. */
  141. static ALboolean BsincPrepare(const ALuint increment, BsincState *state)
  142. {
  143. static const ALfloat scaleBase = 1.510578918e-01f, scaleRange = 1.177936623e+00f;
  144. static const ALuint m[BSINC_SCALE_COUNT] = { 24, 24, 24, 24, 24, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 12 };
  145. static const ALuint to[4][BSINC_SCALE_COUNT] =
  146. {
  147. { 0, 24, 408, 792, 1176, 1560, 1944, 2328, 2648, 2968, 3288, 3544, 3800, 4056, 4248, 4440 },
  148. { 4632, 5016, 5400, 5784, 6168, 6552, 6936, 7320, 7640, 7960, 8280, 8536, 8792, 9048, 9240, 0 },
  149. { 0, 9432, 9816, 10200, 10584, 10968, 11352, 11736, 12056, 12376, 12696, 12952, 13208, 13464, 13656, 13848 },
  150. { 14040, 14424, 14808, 15192, 15576, 15960, 16344, 16728, 17048, 17368, 17688, 17944, 18200, 18456, 18648, 0 }
  151. };
  152. static const ALuint tm[2][BSINC_SCALE_COUNT] =
  153. {
  154. { 0, 24, 24, 24, 24, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 12 },
  155. { 24, 24, 24, 24, 24, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 0 }
  156. };
  157. ALfloat sf;
  158. ALuint si, pi;
  159. ALboolean uncut = AL_TRUE;
  160. if(increment > FRACTIONONE)
  161. {
  162. sf = (ALfloat)FRACTIONONE / increment;
  163. if(sf < scaleBase)
  164. {
  165. /* Signal has been completely cut. The return result can be used
  166. * to skip the filter (and output zeros) as an optimization.
  167. */
  168. sf = 0.0f;
  169. si = 0;
  170. uncut = AL_FALSE;
  171. }
  172. else
  173. {
  174. sf = (BSINC_SCALE_COUNT - 1) * (sf - scaleBase) * scaleRange;
  175. si = fastf2u(sf);
  176. /* The interpolation factor is fit to this diagonally-symmetric
  177. * curve to reduce the transition ripple caused by interpolating
  178. * different scales of the sinc function.
  179. */
  180. sf = 1.0f - cosf(asinf(sf - si));
  181. }
  182. }
  183. else
  184. {
  185. sf = 0.0f;
  186. si = BSINC_SCALE_COUNT - 1;
  187. }
  188. state->sf = sf;
  189. state->m = m[si];
  190. state->l = -(ALint)((m[si] / 2) - 1);
  191. /* The CPU cost of this table re-mapping could be traded for the memory
  192. * cost of a complete table map (1024 elements large).
  193. */
  194. for(pi = 0;pi < BSINC_PHASE_COUNT;pi++)
  195. {
  196. state->coeffs[pi].filter = &bsincTab[to[0][si] + tm[0][si]*pi];
  197. state->coeffs[pi].scDelta = &bsincTab[to[1][si] + tm[1][si]*pi];
  198. state->coeffs[pi].phDelta = &bsincTab[to[2][si] + tm[0][si]*pi];
  199. state->coeffs[pi].spDelta = &bsincTab[to[3][si] + tm[1][si]*pi];
  200. }
  201. return uncut;
  202. }
  203. static ALboolean CalcListenerParams(ALCcontext *Context)
  204. {
  205. ALlistener *Listener = Context->Listener;
  206. ALfloat N[3], V[3], U[3], P[3];
  207. struct ALlistenerProps *first;
  208. struct ALlistenerProps *props;
  209. aluVector vel;
  210. props = ATOMIC_EXCHANGE(struct ALlistenerProps*, &Listener->Update, NULL, almemory_order_acq_rel);
  211. if(!props) return AL_FALSE;
  212. /* AT then UP */
  213. N[0] = ATOMIC_LOAD(&props->Forward[0], almemory_order_relaxed);
  214. N[1] = ATOMIC_LOAD(&props->Forward[1], almemory_order_relaxed);
  215. N[2] = ATOMIC_LOAD(&props->Forward[2], almemory_order_relaxed);
  216. aluNormalize(N);
  217. V[0] = ATOMIC_LOAD(&props->Up[0], almemory_order_relaxed);
  218. V[1] = ATOMIC_LOAD(&props->Up[1], almemory_order_relaxed);
  219. V[2] = ATOMIC_LOAD(&props->Up[2], almemory_order_relaxed);
  220. aluNormalize(V);
  221. /* Build and normalize right-vector */
  222. aluCrossproduct(N, V, U);
  223. aluNormalize(U);
  224. aluMatrixfSet(&Listener->Params.Matrix,
  225. U[0], V[0], -N[0], 0.0,
  226. U[1], V[1], -N[1], 0.0,
  227. U[2], V[2], -N[2], 0.0,
  228. 0.0, 0.0, 0.0, 1.0
  229. );
  230. P[0] = ATOMIC_LOAD(&props->Position[0], almemory_order_relaxed);
  231. P[1] = ATOMIC_LOAD(&props->Position[1], almemory_order_relaxed);
  232. P[2] = ATOMIC_LOAD(&props->Position[2], almemory_order_relaxed);
  233. aluMatrixfFloat3(P, 1.0, &Listener->Params.Matrix);
  234. aluMatrixfSetRow(&Listener->Params.Matrix, 3, -P[0], -P[1], -P[2], 1.0f);
  235. aluVectorSet(&vel, ATOMIC_LOAD(&props->Velocity[0], almemory_order_relaxed),
  236. ATOMIC_LOAD(&props->Velocity[1], almemory_order_relaxed),
  237. ATOMIC_LOAD(&props->Velocity[2], almemory_order_relaxed),
  238. 0.0f);
  239. Listener->Params.Velocity = aluMatrixfVector(&Listener->Params.Matrix, &vel);
  240. Listener->Params.Gain = ATOMIC_LOAD(&props->Gain, almemory_order_relaxed) * Context->GainBoost;
  241. Listener->Params.MetersPerUnit = ATOMIC_LOAD(&props->MetersPerUnit, almemory_order_relaxed);
  242. Listener->Params.DopplerFactor = ATOMIC_LOAD(&props->DopplerFactor, almemory_order_relaxed);
  243. Listener->Params.SpeedOfSound = ATOMIC_LOAD(&props->SpeedOfSound, almemory_order_relaxed) *
  244. ATOMIC_LOAD(&props->DopplerVelocity, almemory_order_relaxed);
  245. Listener->Params.SourceDistanceModel = ATOMIC_LOAD(&props->SourceDistanceModel, almemory_order_relaxed);
  246. Listener->Params.DistanceModel = ATOMIC_LOAD(&props->DistanceModel, almemory_order_relaxed);
  247. /* WARNING: A livelock is theoretically possible if another thread keeps
  248. * changing the freelist head without giving this a chance to actually swap
  249. * in the old container (practically impossible with this little code,
  250. * but...).
  251. */
  252. first = ATOMIC_LOAD(&Listener->FreeList);
  253. do {
  254. ATOMIC_STORE(&props->next, first, almemory_order_relaxed);
  255. } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALlistenerProps*,
  256. &Listener->FreeList, &first, props) == 0);
  257. return AL_TRUE;
  258. }
  259. static ALboolean CalcEffectSlotParams(ALeffectslot *slot, ALCdevice *device)
  260. {
  261. struct ALeffectslotProps *first;
  262. struct ALeffectslotProps *props;
  263. ALeffectState *state;
  264. props = ATOMIC_EXCHANGE(struct ALeffectslotProps*, &slot->Update, NULL, almemory_order_acq_rel);
  265. if(!props) return AL_FALSE;
  266. slot->Params.Gain = ATOMIC_LOAD(&props->Gain, almemory_order_relaxed);
  267. slot->Params.AuxSendAuto = ATOMIC_LOAD(&props->AuxSendAuto, almemory_order_relaxed);
  268. slot->Params.EffectType = ATOMIC_LOAD(&props->Type, almemory_order_relaxed);
  269. if(IsReverbEffect(slot->Params.EffectType))
  270. {
  271. slot->Params.RoomRolloff = props->Props.Reverb.RoomRolloffFactor;
  272. slot->Params.DecayTime = props->Props.Reverb.DecayTime;
  273. slot->Params.AirAbsorptionGainHF = props->Props.Reverb.AirAbsorptionGainHF;
  274. }
  275. else
  276. {
  277. slot->Params.RoomRolloff = 0.0f;
  278. slot->Params.DecayTime = 0.0f;
  279. slot->Params.AirAbsorptionGainHF = 1.0f;
  280. }
  281. /* Swap effect states. No need to play with the ref counts since they keep
  282. * the same number of refs.
  283. */
  284. state = ATOMIC_EXCHANGE(ALeffectState*, &props->State, slot->Params.EffectState,
  285. almemory_order_relaxed);
  286. slot->Params.EffectState = state;
  287. V(state,update)(device, slot, &props->Props);
  288. /* WARNING: A livelock is theoretically possible if another thread keeps
  289. * changing the freelist head without giving this a chance to actually swap
  290. * in the old container (practically impossible with this little code,
  291. * but...).
  292. */
  293. first = ATOMIC_LOAD(&slot->FreeList);
  294. do {
  295. ATOMIC_STORE(&props->next, first, almemory_order_relaxed);
  296. } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*,
  297. &slot->FreeList, &first, props) == 0);
  298. return AL_TRUE;
  299. }
  300. static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALsourceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext)
  301. {
  302. static const struct ChanMap MonoMap[1] = {
  303. { FrontCenter, 0.0f, 0.0f }
  304. }, RearMap[2] = {
  305. { BackLeft, DEG2RAD(-150.0f), DEG2RAD(0.0f) },
  306. { BackRight, DEG2RAD( 150.0f), DEG2RAD(0.0f) }
  307. }, QuadMap[4] = {
  308. { FrontLeft, DEG2RAD( -45.0f), DEG2RAD(0.0f) },
  309. { FrontRight, DEG2RAD( 45.0f), DEG2RAD(0.0f) },
  310. { BackLeft, DEG2RAD(-135.0f), DEG2RAD(0.0f) },
  311. { BackRight, DEG2RAD( 135.0f), DEG2RAD(0.0f) }
  312. }, X51Map[6] = {
  313. { FrontLeft, DEG2RAD( -30.0f), DEG2RAD(0.0f) },
  314. { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) },
  315. { FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) },
  316. { LFE, 0.0f, 0.0f },
  317. { SideLeft, DEG2RAD(-110.0f), DEG2RAD(0.0f) },
  318. { SideRight, DEG2RAD( 110.0f), DEG2RAD(0.0f) }
  319. }, X61Map[7] = {
  320. { FrontLeft, DEG2RAD(-30.0f), DEG2RAD(0.0f) },
  321. { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) },
  322. { FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) },
  323. { LFE, 0.0f, 0.0f },
  324. { BackCenter, DEG2RAD(180.0f), DEG2RAD(0.0f) },
  325. { SideLeft, DEG2RAD(-90.0f), DEG2RAD(0.0f) },
  326. { SideRight, DEG2RAD( 90.0f), DEG2RAD(0.0f) }
  327. }, X71Map[8] = {
  328. { FrontLeft, DEG2RAD( -30.0f), DEG2RAD(0.0f) },
  329. { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) },
  330. { FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) },
  331. { LFE, 0.0f, 0.0f },
  332. { BackLeft, DEG2RAD(-150.0f), DEG2RAD(0.0f) },
  333. { BackRight, DEG2RAD( 150.0f), DEG2RAD(0.0f) },
  334. { SideLeft, DEG2RAD( -90.0f), DEG2RAD(0.0f) },
  335. { SideRight, DEG2RAD( 90.0f), DEG2RAD(0.0f) }
  336. };
  337. const ALCdevice *Device = ALContext->Device;
  338. const ALlistener *Listener = ALContext->Listener;
  339. ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume;
  340. ALfloat DryGain, DryGainHF, DryGainLF;
  341. ALfloat WetGain[MAX_SENDS];
  342. ALfloat WetGainHF[MAX_SENDS];
  343. ALfloat WetGainLF[MAX_SENDS];
  344. ALeffectslot *SendSlots[MAX_SENDS];
  345. ALuint NumSends, Frequency;
  346. ALboolean Relative;
  347. const struct ChanMap *chans = NULL;
  348. struct ChanMap StereoMap[2] = {
  349. { FrontLeft, DEG2RAD(-30.0f), DEG2RAD(0.0f) },
  350. { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) }
  351. };
  352. ALuint num_channels = 0;
  353. ALboolean DirectChannels;
  354. ALboolean isbformat = AL_FALSE;
  355. ALfloat Pitch;
  356. ALuint i, j, c;
  357. /* Get device properties */
  358. NumSends = Device->NumAuxSends;
  359. Frequency = Device->Frequency;
  360. /* Get listener properties */
  361. ListenerGain = Listener->Params.Gain;
  362. /* Get source properties */
  363. SourceVolume = ATOMIC_LOAD(&props->Gain, almemory_order_relaxed);
  364. MinVolume = ATOMIC_LOAD(&props->MinGain, almemory_order_relaxed);
  365. MaxVolume = ATOMIC_LOAD(&props->MaxGain, almemory_order_relaxed);
  366. Pitch = ATOMIC_LOAD(&props->Pitch, almemory_order_relaxed);
  367. Relative = ATOMIC_LOAD(&props->HeadRelative, almemory_order_relaxed);
  368. DirectChannels = ATOMIC_LOAD(&props->DirectChannels, almemory_order_relaxed);
  369. /* Convert counter-clockwise to clockwise. */
  370. StereoMap[0].angle = -ATOMIC_LOAD(&props->StereoPan[0], almemory_order_relaxed);
  371. StereoMap[1].angle = -ATOMIC_LOAD(&props->StereoPan[1], almemory_order_relaxed);
  372. voice->DirectOut.Buffer = Device->Dry.Buffer;
  373. voice->DirectOut.Channels = Device->Dry.NumChannels;
  374. for(i = 0;i < NumSends;i++)
  375. {
  376. SendSlots[i] = ATOMIC_LOAD(&props->Send[i].Slot, almemory_order_relaxed);
  377. if(!SendSlots[i] && i == 0)
  378. SendSlots[i] = Device->DefaultSlot;
  379. if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL)
  380. {
  381. SendSlots[i] = NULL;
  382. voice->SendOut[i].Buffer = NULL;
  383. voice->SendOut[i].Channels = 0;
  384. }
  385. else
  386. {
  387. voice->SendOut[i].Buffer = SendSlots[i]->WetBuffer;
  388. voice->SendOut[i].Channels = SendSlots[i]->NumChannels;
  389. }
  390. }
  391. /* Calculate the stepping value */
  392. Pitch *= (ALfloat)ALBuffer->Frequency / Frequency;
  393. if(Pitch > (ALfloat)MAX_PITCH)
  394. voice->Step = MAX_PITCH<<FRACTIONBITS;
  395. else
  396. voice->Step = maxi(fastf2i(Pitch*FRACTIONONE + 0.5f), 1);
  397. BsincPrepare(voice->Step, &voice->SincState);
  398. /* Calculate gains */
  399. DryGain = clampf(SourceVolume, MinVolume, MaxVolume);
  400. DryGain *= ATOMIC_LOAD(&props->Direct.Gain, almemory_order_relaxed) * ListenerGain;
  401. DryGain = minf(DryGain, GAIN_MIX_MAX);
  402. DryGainHF = ATOMIC_LOAD(&props->Direct.GainHF, almemory_order_relaxed);
  403. DryGainLF = ATOMIC_LOAD(&props->Direct.GainLF, almemory_order_relaxed);
  404. for(i = 0;i < NumSends;i++)
  405. {
  406. WetGain[i] = clampf(SourceVolume, MinVolume, MaxVolume);
  407. WetGain[i] *= ATOMIC_LOAD(&props->Send[i].Gain, almemory_order_relaxed) * ListenerGain;
  408. WetGain[i] = minf(WetGain[i], GAIN_MIX_MAX);
  409. WetGainHF[i] = ATOMIC_LOAD(&props->Send[i].GainHF, almemory_order_relaxed);
  410. WetGainLF[i] = ATOMIC_LOAD(&props->Send[i].GainLF, almemory_order_relaxed);
  411. }
  412. switch(ALBuffer->FmtChannels)
  413. {
  414. case FmtMono:
  415. chans = MonoMap;
  416. num_channels = 1;
  417. break;
  418. case FmtStereo:
  419. chans = StereoMap;
  420. num_channels = 2;
  421. break;
  422. case FmtRear:
  423. chans = RearMap;
  424. num_channels = 2;
  425. break;
  426. case FmtQuad:
  427. chans = QuadMap;
  428. num_channels = 4;
  429. break;
  430. case FmtX51:
  431. chans = X51Map;
  432. num_channels = 6;
  433. break;
  434. case FmtX61:
  435. chans = X61Map;
  436. num_channels = 7;
  437. break;
  438. case FmtX71:
  439. chans = X71Map;
  440. num_channels = 8;
  441. break;
  442. case FmtBFormat2D:
  443. num_channels = 3;
  444. isbformat = AL_TRUE;
  445. DirectChannels = AL_FALSE;
  446. break;
  447. case FmtBFormat3D:
  448. num_channels = 4;
  449. isbformat = AL_TRUE;
  450. DirectChannels = AL_FALSE;
  451. break;
  452. }
  453. if(isbformat)
  454. {
  455. ALfloat N[3], V[3], U[3];
  456. aluMatrixf matrix;
  457. ALfloat scale;
  458. /* AT then UP */
  459. N[0] = ATOMIC_LOAD(&props->Orientation[0][0], almemory_order_relaxed);
  460. N[1] = ATOMIC_LOAD(&props->Orientation[0][1], almemory_order_relaxed);
  461. N[2] = ATOMIC_LOAD(&props->Orientation[0][2], almemory_order_relaxed);
  462. aluNormalize(N);
  463. V[0] = ATOMIC_LOAD(&props->Orientation[1][0], almemory_order_relaxed);
  464. V[1] = ATOMIC_LOAD(&props->Orientation[1][1], almemory_order_relaxed);
  465. V[2] = ATOMIC_LOAD(&props->Orientation[1][2], almemory_order_relaxed);
  466. aluNormalize(V);
  467. if(!Relative)
  468. {
  469. const aluMatrixf *lmatrix = &Listener->Params.Matrix;
  470. aluMatrixfFloat3(N, 0.0f, lmatrix);
  471. aluMatrixfFloat3(V, 0.0f, lmatrix);
  472. }
  473. /* Build and normalize right-vector */
  474. aluCrossproduct(N, V, U);
  475. aluNormalize(U);
  476. /* Build a rotate + conversion matrix (FuMa -> ACN+N3D). */
  477. scale = 1.732050808f;
  478. aluMatrixfSet(&matrix,
  479. 1.414213562f, 0.0f, 0.0f, 0.0f,
  480. 0.0f, -N[0]*scale, N[1]*scale, -N[2]*scale,
  481. 0.0f, U[0]*scale, -U[1]*scale, U[2]*scale,
  482. 0.0f, -V[0]*scale, V[1]*scale, -V[2]*scale
  483. );
  484. voice->DirectOut.Buffer = Device->FOAOut.Buffer;
  485. voice->DirectOut.Channels = Device->FOAOut.NumChannels;
  486. for(c = 0;c < num_channels;c++)
  487. ComputeFirstOrderGains(Device->FOAOut, matrix.m[c], DryGain,
  488. voice->Chan[c].Direct.Gains.Target);
  489. for(i = 0;i < NumSends;i++)
  490. {
  491. if(!SendSlots[i])
  492. {
  493. for(c = 0;c < num_channels;c++)
  494. {
  495. for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
  496. voice->Chan[c].Send[i].Gains.Target[j] = 0.0f;
  497. }
  498. }
  499. else
  500. {
  501. for(c = 0;c < num_channels;c++)
  502. {
  503. const ALeffectslot *Slot = SendSlots[i];
  504. ComputeFirstOrderGainsBF(Slot->ChanMap, Slot->NumChannels, matrix.m[c],
  505. WetGain[i], voice->Chan[c].Send[i].Gains.Target);
  506. }
  507. }
  508. }
  509. voice->IsHrtf = AL_FALSE;
  510. }
  511. else
  512. {
  513. ALfloat coeffs[MAX_AMBI_COEFFS];
  514. if(DirectChannels)
  515. {
  516. /* Skip the virtual channels and write inputs to the real output. */
  517. voice->DirectOut.Buffer = Device->RealOut.Buffer;
  518. voice->DirectOut.Channels = Device->RealOut.NumChannels;
  519. for(c = 0;c < num_channels;c++)
  520. {
  521. int idx;
  522. for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
  523. voice->Chan[c].Direct.Gains.Target[j] = 0.0f;
  524. if((idx=GetChannelIdxByName(Device->RealOut, chans[c].channel)) != -1)
  525. voice->Chan[c].Direct.Gains.Target[idx] = DryGain;
  526. }
  527. /* Auxiliary sends still use normal panning since they mix to B-Format, which can't
  528. * channel-match. */
  529. for(c = 0;c < num_channels;c++)
  530. {
  531. CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
  532. for(i = 0;i < NumSends;i++)
  533. {
  534. if(!SendSlots[i])
  535. {
  536. for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
  537. voice->Chan[c].Send[i].Gains.Target[j] = 0.0f;
  538. }
  539. else
  540. {
  541. const ALeffectslot *Slot = SendSlots[i];
  542. ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels, coeffs,
  543. WetGain[i], voice->Chan[c].Send[i].Gains.Target);
  544. }
  545. }
  546. }
  547. voice->IsHrtf = AL_FALSE;
  548. }
  549. else if(Device->Render_Mode == HrtfRender)
  550. {
  551. /* Full HRTF rendering. Skip the virtual channels and render each
  552. * input channel to the real outputs.
  553. */
  554. voice->DirectOut.Buffer = Device->RealOut.Buffer;
  555. voice->DirectOut.Channels = Device->RealOut.NumChannels;
  556. for(c = 0;c < num_channels;c++)
  557. {
  558. if(chans[c].channel == LFE)
  559. {
  560. /* Skip LFE */
  561. voice->Chan[c].Direct.Hrtf.Target.Delay[0] = 0;
  562. voice->Chan[c].Direct.Hrtf.Target.Delay[1] = 0;
  563. for(i = 0;i < HRIR_LENGTH;i++)
  564. {
  565. voice->Chan[c].Direct.Hrtf.Target.Coeffs[i][0] = 0.0f;
  566. voice->Chan[c].Direct.Hrtf.Target.Coeffs[i][1] = 0.0f;
  567. }
  568. for(i = 0;i < NumSends;i++)
  569. {
  570. for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
  571. voice->Chan[c].Send[i].Gains.Target[j] = 0.0f;
  572. }
  573. continue;
  574. }
  575. /* Get the static HRIR coefficients and delays for this channel. */
  576. GetHrtfCoeffs(Device->Hrtf.Handle,
  577. chans[c].elevation, chans[c].angle, 0.0f, DryGain,
  578. voice->Chan[c].Direct.Hrtf.Target.Coeffs,
  579. voice->Chan[c].Direct.Hrtf.Target.Delay
  580. );
  581. /* Normal panning for auxiliary sends. */
  582. CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
  583. for(i = 0;i < NumSends;i++)
  584. {
  585. if(!SendSlots[i])
  586. {
  587. for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
  588. voice->Chan[c].Send[i].Gains.Target[j] = 0.0f;
  589. }
  590. else
  591. {
  592. const ALeffectslot *Slot = SendSlots[i];
  593. ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels, coeffs,
  594. WetGain[i], voice->Chan[c].Send[i].Gains.Target);
  595. }
  596. }
  597. }
  598. voice->IsHrtf = AL_TRUE;
  599. }
  600. else
  601. {
  602. /* Non-HRTF rendering. Use normal panning to the output. */
  603. for(c = 0;c < num_channels;c++)
  604. {
  605. /* Special-case LFE */
  606. if(chans[c].channel == LFE)
  607. {
  608. for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
  609. voice->Chan[c].Direct.Gains.Target[j] = 0.0f;
  610. if(Device->Dry.Buffer == Device->RealOut.Buffer)
  611. {
  612. int idx;
  613. if((idx=GetChannelIdxByName(Device->RealOut, chans[c].channel)) != -1)
  614. voice->Chan[c].Direct.Gains.Target[idx] = DryGain;
  615. }
  616. for(i = 0;i < NumSends;i++)
  617. {
  618. ALuint j;
  619. for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
  620. voice->Chan[c].Send[i].Gains.Target[j] = 0.0f;
  621. }
  622. continue;
  623. }
  624. if(Device->Render_Mode == StereoPair)
  625. {
  626. /* Clamp X so it remains within 30 degrees of 0 or 180 degree azimuth. */
  627. ALfloat x = sinf(chans[c].angle) * cosf(chans[c].elevation);
  628. coeffs[0] = clampf(-x, -0.5f, 0.5f) + 0.5f;
  629. voice->Chan[c].Direct.Gains.Target[0] = coeffs[0] * DryGain;
  630. voice->Chan[c].Direct.Gains.Target[1] = (1.0f-coeffs[0]) * DryGain;
  631. for(j = 2;j < MAX_OUTPUT_CHANNELS;j++)
  632. voice->Chan[c].Direct.Gains.Target[j] = 0.0f;
  633. CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
  634. }
  635. else
  636. {
  637. CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
  638. ComputePanningGains(Device->Dry, coeffs, DryGain,
  639. voice->Chan[c].Direct.Gains.Target);
  640. }
  641. for(i = 0;i < NumSends;i++)
  642. {
  643. if(!SendSlots[i])
  644. {
  645. ALuint j;
  646. for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
  647. voice->Chan[c].Send[i].Gains.Target[j] = 0.0f;
  648. }
  649. else
  650. {
  651. const ALeffectslot *Slot = SendSlots[i];
  652. ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels, coeffs,
  653. WetGain[i], voice->Chan[c].Send[i].Gains.Target);
  654. }
  655. }
  656. }
  657. voice->IsHrtf = AL_FALSE;
  658. }
  659. }
  660. {
  661. ALfloat hfscale = ATOMIC_LOAD(&props->Direct.HFReference, almemory_order_relaxed) /
  662. Frequency;
  663. ALfloat lfscale = ATOMIC_LOAD(&props->Direct.LFReference, almemory_order_relaxed) /
  664. Frequency;
  665. DryGainHF = maxf(DryGainHF, 0.0001f);
  666. DryGainLF = maxf(DryGainLF, 0.0001f);
  667. for(c = 0;c < num_channels;c++)
  668. {
  669. voice->Chan[c].Direct.FilterType = AF_None;
  670. if(DryGainHF != 1.0f) voice->Chan[c].Direct.FilterType |= AF_LowPass;
  671. if(DryGainLF != 1.0f) voice->Chan[c].Direct.FilterType |= AF_HighPass;
  672. ALfilterState_setParams(
  673. &voice->Chan[c].Direct.LowPass, ALfilterType_HighShelf,
  674. DryGainHF, hfscale, calc_rcpQ_from_slope(DryGainHF, 0.75f)
  675. );
  676. ALfilterState_setParams(
  677. &voice->Chan[c].Direct.HighPass, ALfilterType_LowShelf,
  678. DryGainLF, lfscale, calc_rcpQ_from_slope(DryGainLF, 0.75f)
  679. );
  680. }
  681. }
  682. for(i = 0;i < NumSends;i++)
  683. {
  684. ALfloat hfscale = ATOMIC_LOAD(&props->Send[i].HFReference, almemory_order_relaxed) /
  685. Frequency;
  686. ALfloat lfscale = ATOMIC_LOAD(&props->Send[i].LFReference, almemory_order_relaxed) /
  687. Frequency;
  688. WetGainHF[i] = maxf(WetGainHF[i], 0.0001f);
  689. WetGainLF[i] = maxf(WetGainLF[i], 0.0001f);
  690. for(c = 0;c < num_channels;c++)
  691. {
  692. voice->Chan[c].Send[i].FilterType = AF_None;
  693. if(WetGainHF[i] != 1.0f) voice->Chan[c].Send[i].FilterType |= AF_LowPass;
  694. if(WetGainLF[i] != 1.0f) voice->Chan[c].Send[i].FilterType |= AF_HighPass;
  695. ALfilterState_setParams(
  696. &voice->Chan[c].Send[i].LowPass, ALfilterType_HighShelf,
  697. WetGainHF[i], hfscale, calc_rcpQ_from_slope(WetGainHF[i], 0.75f)
  698. );
  699. ALfilterState_setParams(
  700. &voice->Chan[c].Send[i].HighPass, ALfilterType_LowShelf,
  701. WetGainLF[i], lfscale, calc_rcpQ_from_slope(WetGainLF[i], 0.75f)
  702. );
  703. }
  704. }
  705. }
  706. static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext)
  707. {
  708. const ALCdevice *Device = ALContext->Device;
  709. const ALlistener *Listener = ALContext->Listener;
  710. aluVector Position, Velocity, Direction, SourceToListener;
  711. ALfloat InnerAngle,OuterAngle,Distance,ClampedDist;
  712. ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff;
  713. ALfloat SourceVolume,ListenerGain;
  714. ALfloat DopplerFactor, SpeedOfSound;
  715. ALfloat AirAbsorptionFactor;
  716. ALfloat RoomAirAbsorption[MAX_SENDS];
  717. ALeffectslot *SendSlots[MAX_SENDS];
  718. ALfloat Attenuation;
  719. ALfloat RoomAttenuation[MAX_SENDS];
  720. ALfloat MetersPerUnit;
  721. ALfloat RoomRolloffBase;
  722. ALfloat RoomRolloff[MAX_SENDS];
  723. ALfloat DecayDistance[MAX_SENDS];
  724. ALfloat DryGain;
  725. ALfloat DryGainHF;
  726. ALfloat DryGainLF;
  727. ALboolean DryGainHFAuto;
  728. ALfloat WetGain[MAX_SENDS];
  729. ALfloat WetGainHF[MAX_SENDS];
  730. ALfloat WetGainLF[MAX_SENDS];
  731. ALboolean WetGainAuto;
  732. ALboolean WetGainHFAuto;
  733. ALfloat Pitch;
  734. ALuint Frequency;
  735. ALint NumSends;
  736. ALint i;
  737. DryGainHF = 1.0f;
  738. DryGainLF = 1.0f;
  739. for(i = 0;i < MAX_SENDS;i++)
  740. {
  741. WetGainHF[i] = 1.0f;
  742. WetGainLF[i] = 1.0f;
  743. }
  744. /* Get context/device properties */
  745. DopplerFactor = Listener->Params.DopplerFactor;
  746. SpeedOfSound = Listener->Params.SpeedOfSound;
  747. NumSends = Device->NumAuxSends;
  748. Frequency = Device->Frequency;
  749. /* Get listener properties */
  750. ListenerGain = Listener->Params.Gain;
  751. MetersPerUnit = Listener->Params.MetersPerUnit;
  752. /* Get source properties */
  753. SourceVolume = ATOMIC_LOAD(&props->Gain, almemory_order_relaxed);
  754. MinVolume = ATOMIC_LOAD(&props->MinGain, almemory_order_relaxed);
  755. MaxVolume = ATOMIC_LOAD(&props->MaxGain, almemory_order_relaxed);
  756. Pitch = ATOMIC_LOAD(&props->Pitch, almemory_order_relaxed);
  757. aluVectorSet(&Position, ATOMIC_LOAD(&props->Position[0], almemory_order_relaxed),
  758. ATOMIC_LOAD(&props->Position[1], almemory_order_relaxed),
  759. ATOMIC_LOAD(&props->Position[2], almemory_order_relaxed),
  760. 1.0f);
  761. aluVectorSet(&Direction, ATOMIC_LOAD(&props->Direction[0], almemory_order_relaxed),
  762. ATOMIC_LOAD(&props->Direction[1], almemory_order_relaxed),
  763. ATOMIC_LOAD(&props->Direction[2], almemory_order_relaxed),
  764. 0.0f);
  765. aluVectorSet(&Velocity, ATOMIC_LOAD(&props->Velocity[0], almemory_order_relaxed),
  766. ATOMIC_LOAD(&props->Velocity[1], almemory_order_relaxed),
  767. ATOMIC_LOAD(&props->Velocity[2], almemory_order_relaxed),
  768. 0.0f);
  769. MinDist = ATOMIC_LOAD(&props->RefDistance, almemory_order_relaxed);
  770. MaxDist = ATOMIC_LOAD(&props->MaxDistance, almemory_order_relaxed);
  771. Rolloff = ATOMIC_LOAD(&props->RollOffFactor, almemory_order_relaxed);
  772. DopplerFactor *= ATOMIC_LOAD(&props->DopplerFactor, almemory_order_relaxed);
  773. InnerAngle = ATOMIC_LOAD(&props->InnerAngle, almemory_order_relaxed);
  774. OuterAngle = ATOMIC_LOAD(&props->OuterAngle, almemory_order_relaxed);
  775. AirAbsorptionFactor = ATOMIC_LOAD(&props->AirAbsorptionFactor, almemory_order_relaxed);
  776. DryGainHFAuto = ATOMIC_LOAD(&props->DryGainHFAuto, almemory_order_relaxed);
  777. WetGainAuto = ATOMIC_LOAD(&props->WetGainAuto, almemory_order_relaxed);
  778. WetGainHFAuto = ATOMIC_LOAD(&props->WetGainHFAuto, almemory_order_relaxed);
  779. RoomRolloffBase = ATOMIC_LOAD(&props->RoomRolloffFactor, almemory_order_relaxed);
  780. voice->DirectOut.Buffer = Device->Dry.Buffer;
  781. voice->DirectOut.Channels = Device->Dry.NumChannels;
  782. for(i = 0;i < NumSends;i++)
  783. {
  784. SendSlots[i] = ATOMIC_LOAD(&props->Send[i].Slot, almemory_order_relaxed);
  785. if(!SendSlots[i] && i == 0)
  786. SendSlots[i] = Device->DefaultSlot;
  787. if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL)
  788. {
  789. SendSlots[i] = NULL;
  790. RoomRolloff[i] = 0.0f;
  791. DecayDistance[i] = 0.0f;
  792. RoomAirAbsorption[i] = 1.0f;
  793. }
  794. else if(SendSlots[i]->Params.AuxSendAuto)
  795. {
  796. RoomRolloff[i] = SendSlots[i]->Params.RoomRolloff + RoomRolloffBase;
  797. DecayDistance[i] = SendSlots[i]->Params.DecayTime *
  798. SPEEDOFSOUNDMETRESPERSEC;
  799. RoomAirAbsorption[i] = SendSlots[i]->Params.AirAbsorptionGainHF;
  800. }
  801. else
  802. {
  803. /* If the slot's auxiliary send auto is off, the data sent to the
  804. * effect slot is the same as the dry path, sans filter effects */
  805. RoomRolloff[i] = Rolloff;
  806. DecayDistance[i] = 0.0f;
  807. RoomAirAbsorption[i] = AIRABSORBGAINHF;
  808. }
  809. if(!SendSlots[i])
  810. {
  811. voice->SendOut[i].Buffer = NULL;
  812. voice->SendOut[i].Channels = 0;
  813. }
  814. else
  815. {
  816. voice->SendOut[i].Buffer = SendSlots[i]->WetBuffer;
  817. voice->SendOut[i].Channels = SendSlots[i]->NumChannels;
  818. }
  819. }
  820. /* Transform source to listener space (convert to head relative) */
  821. if(ATOMIC_LOAD(&props->HeadRelative, almemory_order_relaxed) == AL_FALSE)
  822. {
  823. const aluMatrixf *Matrix = &Listener->Params.Matrix;
  824. /* Transform source vectors */
  825. Position = aluMatrixfVector(Matrix, &Position);
  826. Velocity = aluMatrixfVector(Matrix, &Velocity);
  827. Direction = aluMatrixfVector(Matrix, &Direction);
  828. }
  829. else
  830. {
  831. const aluVector *lvelocity = &Listener->Params.Velocity;
  832. /* Offset the source velocity to be relative of the listener velocity */
  833. Velocity.v[0] += lvelocity->v[0];
  834. Velocity.v[1] += lvelocity->v[1];
  835. Velocity.v[2] += lvelocity->v[2];
  836. }
  837. aluNormalize(Direction.v);
  838. SourceToListener.v[0] = -Position.v[0];
  839. SourceToListener.v[1] = -Position.v[1];
  840. SourceToListener.v[2] = -Position.v[2];
  841. SourceToListener.v[3] = 0.0f;
  842. Distance = aluNormalize(SourceToListener.v);
  843. /* Calculate distance attenuation */
  844. ClampedDist = Distance;
  845. Attenuation = 1.0f;
  846. for(i = 0;i < NumSends;i++)
  847. RoomAttenuation[i] = 1.0f;
  848. switch(Listener->Params.SourceDistanceModel ?
  849. ATOMIC_LOAD(&props->DistanceModel, almemory_order_relaxed) :
  850. Listener->Params.DistanceModel)
  851. {
  852. case InverseDistanceClamped:
  853. ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
  854. if(MaxDist < MinDist)
  855. break;
  856. /*fall-through*/
  857. case InverseDistance:
  858. if(MinDist > 0.0f)
  859. {
  860. ALfloat dist = lerp(MinDist, ClampedDist, Rolloff);
  861. if(dist > 0.0f) Attenuation = MinDist / dist;
  862. for(i = 0;i < NumSends;i++)
  863. {
  864. dist = lerp(MinDist, ClampedDist, RoomRolloff[i]);
  865. if(dist > 0.0f) RoomAttenuation[i] = MinDist / dist;
  866. }
  867. }
  868. break;
  869. case LinearDistanceClamped:
  870. ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
  871. if(MaxDist < MinDist)
  872. break;
  873. /*fall-through*/
  874. case LinearDistance:
  875. if(MaxDist != MinDist)
  876. {
  877. Attenuation = 1.0f - (Rolloff*(ClampedDist-MinDist)/(MaxDist - MinDist));
  878. Attenuation = maxf(Attenuation, 0.0f);
  879. for(i = 0;i < NumSends;i++)
  880. {
  881. RoomAttenuation[i] = 1.0f - (RoomRolloff[i]*(ClampedDist-MinDist)/(MaxDist - MinDist));
  882. RoomAttenuation[i] = maxf(RoomAttenuation[i], 0.0f);
  883. }
  884. }
  885. break;
  886. case ExponentDistanceClamped:
  887. ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
  888. if(MaxDist < MinDist)
  889. break;
  890. /*fall-through*/
  891. case ExponentDistance:
  892. if(ClampedDist > 0.0f && MinDist > 0.0f)
  893. {
  894. Attenuation = powf(ClampedDist/MinDist, -Rolloff);
  895. for(i = 0;i < NumSends;i++)
  896. RoomAttenuation[i] = powf(ClampedDist/MinDist, -RoomRolloff[i]);
  897. }
  898. break;
  899. case DisableDistance:
  900. ClampedDist = MinDist;
  901. break;
  902. }
  903. /* Source Gain + Attenuation */
  904. DryGain = SourceVolume * Attenuation;
  905. for(i = 0;i < NumSends;i++)
  906. WetGain[i] = SourceVolume * RoomAttenuation[i];
  907. /* Distance-based air absorption */
  908. if(AirAbsorptionFactor > 0.0f && ClampedDist > MinDist)
  909. {
  910. ALfloat meters = (ClampedDist-MinDist) * MetersPerUnit;
  911. DryGainHF *= powf(AIRABSORBGAINHF, AirAbsorptionFactor*meters);
  912. for(i = 0;i < NumSends;i++)
  913. WetGainHF[i] *= powf(RoomAirAbsorption[i], AirAbsorptionFactor*meters);
  914. }
  915. if(WetGainAuto)
  916. {
  917. ALfloat ApparentDist = 1.0f/maxf(Attenuation, 0.00001f) - 1.0f;
  918. /* Apply a decay-time transformation to the wet path, based on the
  919. * attenuation of the dry path.
  920. *
  921. * Using the apparent distance, based on the distance attenuation, the
  922. * initial decay of the reverb effect is calculated and applied to the
  923. * wet path.
  924. */
  925. for(i = 0;i < NumSends;i++)
  926. {
  927. if(DecayDistance[i] > 0.0f)
  928. WetGain[i] *= powf(0.001f/*-60dB*/, ApparentDist/DecayDistance[i]);
  929. }
  930. }
  931. /* Calculate directional soundcones */
  932. if(InnerAngle < 360.0f)
  933. {
  934. ALfloat ConeVolume;
  935. ALfloat ConeHF;
  936. ALfloat Angle;
  937. ALfloat scale;
  938. Angle = RAD2DEG(acosf(aluDotproduct(&Direction, &SourceToListener)) * ConeScale) * 2.0f;
  939. if(Angle > InnerAngle)
  940. {
  941. if(Angle < OuterAngle)
  942. {
  943. scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle);
  944. ConeVolume = lerp(
  945. 1.0f, ATOMIC_LOAD(&props->OuterGain, almemory_order_relaxed), scale
  946. );
  947. ConeHF = lerp(
  948. 1.0f, ATOMIC_LOAD(&props->OuterGainHF, almemory_order_relaxed), scale
  949. );
  950. }
  951. else
  952. {
  953. ConeVolume = ATOMIC_LOAD(&props->OuterGain, almemory_order_relaxed);
  954. ConeHF = ATOMIC_LOAD(&props->OuterGainHF, almemory_order_relaxed);
  955. }
  956. DryGain *= ConeVolume;
  957. if(DryGainHFAuto)
  958. DryGainHF *= ConeHF;
  959. }
  960. /* Wet path uses the total area of the cone emitter (the room will
  961. * receive the same amount of sound regardless of its direction).
  962. */
  963. scale = (asinf(maxf((OuterAngle-InnerAngle)/360.0f, 0.0f)) / F_PI) +
  964. (InnerAngle/360.0f);
  965. if(WetGainAuto)
  966. {
  967. ConeVolume = lerp(
  968. 1.0f, ATOMIC_LOAD(&props->OuterGain, almemory_order_relaxed), scale
  969. );
  970. for(i = 0;i < NumSends;i++)
  971. WetGain[i] *= ConeVolume;
  972. }
  973. if(WetGainHFAuto)
  974. {
  975. ConeHF = lerp(
  976. 1.0f, ATOMIC_LOAD(&props->OuterGainHF, almemory_order_relaxed), scale
  977. );
  978. for(i = 0;i < NumSends;i++)
  979. WetGainHF[i] *= ConeHF;
  980. }
  981. }
  982. /* Apply gain and frequency filters */
  983. DryGain = clampf(DryGain, MinVolume, MaxVolume);
  984. DryGain *= ATOMIC_LOAD(&props->Direct.Gain, almemory_order_relaxed) * ListenerGain;
  985. DryGain = minf(DryGain, GAIN_MIX_MAX);
  986. DryGainHF *= ATOMIC_LOAD(&props->Direct.GainHF, almemory_order_relaxed);
  987. DryGainLF *= ATOMIC_LOAD(&props->Direct.GainLF, almemory_order_relaxed);
  988. for(i = 0;i < NumSends;i++)
  989. {
  990. WetGain[i] = clampf(WetGain[i], MinVolume, MaxVolume);
  991. WetGain[i] *= ATOMIC_LOAD(&props->Send[i].Gain, almemory_order_relaxed) * ListenerGain;
  992. WetGain[i] = minf(WetGain[i], GAIN_MIX_MAX);
  993. WetGainHF[i] *= ATOMIC_LOAD(&props->Send[i].GainHF, almemory_order_relaxed);
  994. WetGainLF[i] *= ATOMIC_LOAD(&props->Send[i].GainLF, almemory_order_relaxed);
  995. }
  996. /* Calculate velocity-based doppler effect */
  997. if(DopplerFactor > 0.0f)
  998. {
  999. const aluVector *lvelocity = &Listener->Params.Velocity;
  1000. ALfloat VSS, VLS;
  1001. if(SpeedOfSound < 1.0f)
  1002. {
  1003. DopplerFactor *= 1.0f/SpeedOfSound;
  1004. SpeedOfSound = 1.0f;
  1005. }
  1006. VSS = aluDotproduct(&Velocity, &SourceToListener) * DopplerFactor;
  1007. VLS = aluDotproduct(lvelocity, &SourceToListener) * DopplerFactor;
  1008. Pitch *= clampf(SpeedOfSound-VLS, 1.0f, SpeedOfSound*2.0f - 1.0f) /
  1009. clampf(SpeedOfSound-VSS, 1.0f, SpeedOfSound*2.0f - 1.0f);
  1010. }
  1011. /* Calculate fixed-point stepping value, based on the pitch, buffer
  1012. * frequency, and output frequency.
  1013. */
  1014. Pitch *= (ALfloat)ALBuffer->Frequency / Frequency;
  1015. if(Pitch > (ALfloat)MAX_PITCH)
  1016. voice->Step = MAX_PITCH<<FRACTIONBITS;
  1017. else
  1018. voice->Step = maxi(fastf2i(Pitch*FRACTIONONE + 0.5f), 1);
  1019. BsincPrepare(voice->Step, &voice->SincState);
  1020. if(Device->Render_Mode == HrtfRender)
  1021. {
  1022. /* Full HRTF rendering. Skip the virtual channels and render to the
  1023. * real outputs.
  1024. */
  1025. ALfloat dir[3] = { 0.0f, 0.0f, -1.0f };
  1026. ALfloat ev = 0.0f, az = 0.0f;
  1027. ALfloat radius = ATOMIC_LOAD(&props->Radius, almemory_order_relaxed);
  1028. ALfloat coeffs[MAX_AMBI_COEFFS];
  1029. ALfloat spread = 0.0f;
  1030. voice->DirectOut.Buffer = Device->RealOut.Buffer;
  1031. voice->DirectOut.Channels = Device->RealOut.NumChannels;
  1032. if(Distance > FLT_EPSILON)
  1033. {
  1034. dir[0] = -SourceToListener.v[0];
  1035. dir[1] = -SourceToListener.v[1];
  1036. dir[2] = -SourceToListener.v[2] * ZScale;
  1037. /* Calculate elevation and azimuth only when the source is not at
  1038. * the listener. This prevents +0 and -0 Z from producing
  1039. * inconsistent panning. Also, clamp Y in case FP precision errors
  1040. * cause it to land outside of -1..+1. */
  1041. ev = asinf(clampf(dir[1], -1.0f, 1.0f));
  1042. az = atan2f(dir[0], -dir[2]);
  1043. }
  1044. if(radius > Distance)
  1045. spread = F_TAU - Distance/radius*F_PI;
  1046. else if(Distance > FLT_EPSILON)
  1047. spread = asinf(radius / Distance) * 2.0f;
  1048. /* Get the HRIR coefficients and delays. */
  1049. GetHrtfCoeffs(Device->Hrtf.Handle, ev, az, spread, DryGain,
  1050. voice->Chan[0].Direct.Hrtf.Target.Coeffs,
  1051. voice->Chan[0].Direct.Hrtf.Target.Delay);
  1052. CalcDirectionCoeffs(dir, spread, coeffs);
  1053. for(i = 0;i < NumSends;i++)
  1054. {
  1055. if(!SendSlots[i])
  1056. {
  1057. ALuint j;
  1058. for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
  1059. voice->Chan[0].Send[i].Gains.Target[j] = 0.0f;
  1060. }
  1061. else
  1062. {
  1063. const ALeffectslot *Slot = SendSlots[i];
  1064. ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels, coeffs,
  1065. WetGain[i], voice->Chan[0].Send[i].Gains.Target);
  1066. }
  1067. }
  1068. voice->IsHrtf = AL_TRUE;
  1069. }
  1070. else
  1071. {
  1072. /* Non-HRTF rendering. */
  1073. ALfloat dir[3] = { 0.0f, 0.0f, -1.0f };
  1074. ALfloat radius = ATOMIC_LOAD(&props->Radius, almemory_order_relaxed);
  1075. ALfloat coeffs[MAX_AMBI_COEFFS];
  1076. ALfloat spread = 0.0f;
  1077. /* Get the localized direction, and compute panned gains. */
  1078. if(Distance > FLT_EPSILON)
  1079. {
  1080. dir[0] = -SourceToListener.v[0];
  1081. dir[1] = -SourceToListener.v[1];
  1082. dir[2] = -SourceToListener.v[2] * ZScale;
  1083. }
  1084. if(radius > Distance)
  1085. spread = F_TAU - Distance/radius*F_PI;
  1086. else if(Distance > FLT_EPSILON)
  1087. spread = asinf(radius / Distance) * 2.0f;
  1088. if(Device->Render_Mode == StereoPair)
  1089. {
  1090. /* Clamp X so it remains within 30 degrees of 0 or 180 degree azimuth. */
  1091. ALfloat x = -dir[0] * (0.5f * (cosf(spread*0.5f) + 1.0f));
  1092. x = clampf(x, -0.5f, 0.5f) + 0.5f;
  1093. voice->Chan[0].Direct.Gains.Target[0] = x * DryGain;
  1094. voice->Chan[0].Direct.Gains.Target[1] = (1.0f-x) * DryGain;
  1095. for(i = 2;i < MAX_OUTPUT_CHANNELS;i++)
  1096. voice->Chan[0].Direct.Gains.Target[i] = 0.0f;
  1097. CalcDirectionCoeffs(dir, spread, coeffs);
  1098. }
  1099. else
  1100. {
  1101. CalcDirectionCoeffs(dir, spread, coeffs);
  1102. ComputePanningGains(Device->Dry, coeffs, DryGain,
  1103. voice->Chan[0].Direct.Gains.Target);
  1104. }
  1105. for(i = 0;i < NumSends;i++)
  1106. {
  1107. if(!SendSlots[i])
  1108. {
  1109. ALuint j;
  1110. for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
  1111. voice->Chan[0].Send[i].Gains.Target[j] = 0.0f;
  1112. }
  1113. else
  1114. {
  1115. const ALeffectslot *Slot = SendSlots[i];
  1116. ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels, coeffs,
  1117. WetGain[i], voice->Chan[0].Send[i].Gains.Target);
  1118. }
  1119. }
  1120. voice->IsHrtf = AL_FALSE;
  1121. }
  1122. {
  1123. ALfloat hfscale = ATOMIC_LOAD(&props->Direct.HFReference, almemory_order_relaxed) /
  1124. Frequency;
  1125. ALfloat lfscale = ATOMIC_LOAD(&props->Direct.LFReference, almemory_order_relaxed) /
  1126. Frequency;
  1127. DryGainHF = maxf(DryGainHF, 0.0001f);
  1128. DryGainLF = maxf(DryGainLF, 0.0001f);
  1129. voice->Chan[0].Direct.FilterType = AF_None;
  1130. if(DryGainHF != 1.0f) voice->Chan[0].Direct.FilterType |= AF_LowPass;
  1131. if(DryGainLF != 1.0f) voice->Chan[0].Direct.FilterType |= AF_HighPass;
  1132. ALfilterState_setParams(
  1133. &voice->Chan[0].Direct.LowPass, ALfilterType_HighShelf,
  1134. DryGainHF, hfscale, calc_rcpQ_from_slope(DryGainHF, 0.75f)
  1135. );
  1136. ALfilterState_setParams(
  1137. &voice->Chan[0].Direct.HighPass, ALfilterType_LowShelf,
  1138. DryGainLF, lfscale, calc_rcpQ_from_slope(DryGainLF, 0.75f)
  1139. );
  1140. }
  1141. for(i = 0;i < NumSends;i++)
  1142. {
  1143. ALfloat hfscale = ATOMIC_LOAD(&props->Send[i].HFReference, almemory_order_relaxed) /
  1144. Frequency;
  1145. ALfloat lfscale = ATOMIC_LOAD(&props->Send[i].LFReference, almemory_order_relaxed) /
  1146. Frequency;
  1147. WetGainHF[i] = maxf(WetGainHF[i], 0.0001f);
  1148. WetGainLF[i] = maxf(WetGainLF[i], 0.0001f);
  1149. voice->Chan[0].Send[i].FilterType = AF_None;
  1150. if(WetGainHF[i] != 1.0f) voice->Chan[0].Send[i].FilterType |= AF_LowPass;
  1151. if(WetGainLF[i] != 1.0f) voice->Chan[0].Send[i].FilterType |= AF_HighPass;
  1152. ALfilterState_setParams(
  1153. &voice->Chan[0].Send[i].LowPass, ALfilterType_HighShelf,
  1154. WetGainHF[i], hfscale, calc_rcpQ_from_slope(WetGainHF[i], 0.75f)
  1155. );
  1156. ALfilterState_setParams(
  1157. &voice->Chan[0].Send[i].HighPass, ALfilterType_LowShelf,
  1158. WetGainLF[i], lfscale, calc_rcpQ_from_slope(WetGainLF[i], 0.75f)
  1159. );
  1160. }
  1161. }
  1162. static void CalcSourceParams(ALvoice *voice, ALCcontext *context, ALboolean force)
  1163. {
  1164. ALsource *source = voice->Source;
  1165. const ALbufferlistitem *BufferListItem;
  1166. struct ALsourceProps *first;
  1167. struct ALsourceProps *props;
  1168. props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->Update, NULL, almemory_order_acq_rel);
  1169. if(!props && !force) return;
  1170. if(props)
  1171. {
  1172. voice->Props = *props;
  1173. /* WARNING: A livelock is theoretically possible if another thread
  1174. * keeps changing the freelist head without giving this a chance to
  1175. * actually swap in the old container (practically impossible with this
  1176. * little code, but...).
  1177. */
  1178. first = ATOMIC_LOAD(&source->FreeList);
  1179. do {
  1180. ATOMIC_STORE(&props->next, first, almemory_order_relaxed);
  1181. } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALsourceProps*,
  1182. &source->FreeList, &first, props) == 0);
  1183. }
  1184. BufferListItem = ATOMIC_LOAD(&source->queue, almemory_order_relaxed);
  1185. while(BufferListItem != NULL)
  1186. {
  1187. const ALbuffer *buffer;
  1188. if((buffer=BufferListItem->buffer) != NULL)
  1189. {
  1190. if(buffer->FmtChannels == FmtMono)
  1191. CalcAttnSourceParams(voice, &voice->Props, buffer, context);
  1192. else
  1193. CalcNonAttnSourceParams(voice, &voice->Props, buffer, context);
  1194. break;
  1195. }
  1196. BufferListItem = BufferListItem->next;
  1197. }
  1198. }
  1199. static void UpdateContextSources(ALCcontext *ctx, ALeffectslot *slot)
  1200. {
  1201. ALvoice *voice, *voice_end;
  1202. ALsource *source;
  1203. IncrementRef(&ctx->UpdateCount);
  1204. if(!ATOMIC_LOAD(&ctx->HoldUpdates))
  1205. {
  1206. ALboolean force = CalcListenerParams(ctx);
  1207. while(slot)
  1208. {
  1209. force |= CalcEffectSlotParams(slot, ctx->Device);
  1210. slot = ATOMIC_LOAD(&slot->next, almemory_order_relaxed);
  1211. }
  1212. voice = ctx->Voices;
  1213. voice_end = voice + ctx->VoiceCount;
  1214. for(;voice != voice_end;++voice)
  1215. {
  1216. if(!(source=voice->Source)) continue;
  1217. if(source->state != AL_PLAYING && source->state != AL_PAUSED)
  1218. voice->Source = NULL;
  1219. else
  1220. CalcSourceParams(voice, ctx, force);
  1221. }
  1222. }
  1223. IncrementRef(&ctx->UpdateCount);
  1224. }
  1225. /* Specialized function to clamp to [-1, +1] with only one branch. This also
  1226. * converts NaN to 0. */
  1227. static inline ALfloat aluClampf(ALfloat val)
  1228. {
  1229. if(fabsf(val) <= 1.0f) return val;
  1230. return (ALfloat)((0.0f < val) - (val < 0.0f));
  1231. }
  1232. static inline ALfloat aluF2F(ALfloat val)
  1233. { return val; }
  1234. static inline ALint aluF2I(ALfloat val)
  1235. {
  1236. /* Floats only have a 24-bit mantissa, so [-16777215, +16777215] is the max
  1237. * integer range normalized floats can be safely converted to.
  1238. */
  1239. return fastf2i(aluClampf(val)*16777215.0f)<<7;
  1240. }
  1241. static inline ALuint aluF2UI(ALfloat val)
  1242. { return aluF2I(val)+2147483648u; }
  1243. static inline ALshort aluF2S(ALfloat val)
  1244. { return fastf2i(aluClampf(val)*32767.0f); }
  1245. static inline ALushort aluF2US(ALfloat val)
  1246. { return aluF2S(val)+32768; }
  1247. static inline ALbyte aluF2B(ALfloat val)
  1248. { return fastf2i(aluClampf(val)*127.0f); }
  1249. static inline ALubyte aluF2UB(ALfloat val)
  1250. { return aluF2B(val)+128; }
  1251. #define DECL_TEMPLATE(T, func) \
  1252. static void Write_##T(ALfloatBUFFERSIZE *InBuffer, ALvoid *OutBuffer, \
  1253. ALuint SamplesToDo, ALuint numchans) \
  1254. { \
  1255. ALuint i, j; \
  1256. for(j = 0;j < numchans;j++) \
  1257. { \
  1258. const ALfloat *in = InBuffer[j]; \
  1259. T *restrict out = (T*)OutBuffer + j; \
  1260. for(i = 0;i < SamplesToDo;i++) \
  1261. out[i*numchans] = func(in[i]); \
  1262. } \
  1263. }
  1264. DECL_TEMPLATE(ALfloat, aluF2F)
  1265. DECL_TEMPLATE(ALuint, aluF2UI)
  1266. DECL_TEMPLATE(ALint, aluF2I)
  1267. DECL_TEMPLATE(ALushort, aluF2US)
  1268. DECL_TEMPLATE(ALshort, aluF2S)
  1269. DECL_TEMPLATE(ALubyte, aluF2UB)
  1270. DECL_TEMPLATE(ALbyte, aluF2B)
  1271. #undef DECL_TEMPLATE
  1272. ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
  1273. {
  1274. ALuint SamplesToDo;
  1275. ALvoice *voice, *voice_end;
  1276. ALeffectslot *slot;
  1277. ALsource *source;
  1278. ALCcontext *ctx;
  1279. FPUCtl oldMode;
  1280. ALuint i, c;
  1281. SetMixerFPUMode(&oldMode);
  1282. while(size > 0)
  1283. {
  1284. SamplesToDo = minu(size, BUFFERSIZE);
  1285. for(c = 0;c < device->Dry.NumChannels;c++)
  1286. memset(device->Dry.Buffer[c], 0, SamplesToDo*sizeof(ALfloat));
  1287. if(device->Dry.Buffer != device->RealOut.Buffer)
  1288. for(c = 0;c < device->RealOut.NumChannels;c++)
  1289. memset(device->RealOut.Buffer[c], 0, SamplesToDo*sizeof(ALfloat));
  1290. if(device->Dry.Buffer != device->FOAOut.Buffer)
  1291. for(c = 0;c < device->FOAOut.NumChannels;c++)
  1292. memset(device->FOAOut.Buffer[c], 0, SamplesToDo*sizeof(ALfloat));
  1293. IncrementRef(&device->MixCount);
  1294. V0(device->Backend,lock)();
  1295. if((slot=device->DefaultSlot) != NULL)
  1296. {
  1297. CalcEffectSlotParams(device->DefaultSlot, device);
  1298. for(i = 0;i < slot->NumChannels;i++)
  1299. memset(slot->WetBuffer[i], 0, SamplesToDo*sizeof(ALfloat));
  1300. }
  1301. ctx = ATOMIC_LOAD(&device->ContextList);
  1302. while(ctx)
  1303. {
  1304. ALeffectslot *slotroot;
  1305. slotroot = ATOMIC_LOAD(&ctx->ActiveAuxSlotList);
  1306. UpdateContextSources(ctx, slotroot);
  1307. slot = slotroot;
  1308. while(slot)
  1309. {
  1310. for(i = 0;i < slot->NumChannels;i++)
  1311. memset(slot->WetBuffer[i], 0, SamplesToDo*sizeof(ALfloat));
  1312. slot = ATOMIC_LOAD(&slot->next, almemory_order_relaxed);
  1313. }
  1314. /* source processing */
  1315. voice = ctx->Voices;
  1316. voice_end = voice + ctx->VoiceCount;
  1317. for(;voice != voice_end;++voice)
  1318. {
  1319. ALboolean IsVoiceInit = (voice->Step > 0);
  1320. source = voice->Source;
  1321. if(source && source->state == AL_PLAYING && IsVoiceInit)
  1322. MixSource(voice, source, device, SamplesToDo);
  1323. }
  1324. /* effect slot processing */
  1325. slot = slotroot;
  1326. while(slot)
  1327. {
  1328. ALeffectState *state = slot->Params.EffectState;
  1329. V(state,process)(SamplesToDo, SAFE_CONST(ALfloatBUFFERSIZE*,slot->WetBuffer),
  1330. state->OutBuffer, state->OutChannels);
  1331. slot = ATOMIC_LOAD(&slot->next, almemory_order_relaxed);
  1332. }
  1333. ctx = ctx->next;
  1334. }
  1335. if(device->DefaultSlot != NULL)
  1336. {
  1337. const ALeffectslot *slot = device->DefaultSlot;
  1338. ALeffectState *state = slot->Params.EffectState;
  1339. V(state,process)(SamplesToDo, slot->WetBuffer, state->OutBuffer,
  1340. state->OutChannels);
  1341. }
  1342. /* Increment the clock time. Every second's worth of samples is
  1343. * converted and added to clock base so that large sample counts don't
  1344. * overflow during conversion. This also guarantees an exact, stable
  1345. * conversion. */
  1346. device->SamplesDone += SamplesToDo;
  1347. device->ClockBase += (device->SamplesDone/device->Frequency) * DEVICE_CLOCK_RES;
  1348. device->SamplesDone %= device->Frequency;
  1349. V0(device->Backend,unlock)();
  1350. IncrementRef(&device->MixCount);
  1351. if(device->Hrtf.Handle)
  1352. {
  1353. int lidx = GetChannelIdxByName(device->RealOut, FrontLeft);
  1354. int ridx = GetChannelIdxByName(device->RealOut, FrontRight);
  1355. if(lidx != -1 && ridx != -1)
  1356. {
  1357. HrtfDirectMixerFunc HrtfMix = SelectHrtfMixer();
  1358. ALuint irsize = device->Hrtf.IrSize;
  1359. for(c = 0;c < device->Dry.NumChannels;c++)
  1360. {
  1361. HrtfMix(device->RealOut.Buffer, lidx, ridx,
  1362. device->Dry.Buffer[c], device->Hrtf.Offset, irsize,
  1363. device->Hrtf.Coeffs[c], device->Hrtf.Values[c],
  1364. SamplesToDo
  1365. );
  1366. }
  1367. device->Hrtf.Offset += SamplesToDo;
  1368. }
  1369. }
  1370. else if(device->AmbiDecoder)
  1371. {
  1372. if(device->Dry.Buffer != device->FOAOut.Buffer)
  1373. bformatdec_upSample(device->AmbiDecoder,
  1374. device->Dry.Buffer, SAFE_CONST(ALfloatBUFFERSIZE*,device->FOAOut.Buffer),
  1375. device->FOAOut.NumChannels, SamplesToDo
  1376. );
  1377. bformatdec_process(device->AmbiDecoder,
  1378. device->RealOut.Buffer, device->RealOut.NumChannels,
  1379. SAFE_CONST(ALfloatBUFFERSIZE*,device->Dry.Buffer), SamplesToDo
  1380. );
  1381. }
  1382. else if(device->AmbiUp)
  1383. {
  1384. ambiup_process(device->AmbiUp,
  1385. device->RealOut.Buffer, device->RealOut.NumChannels,
  1386. SAFE_CONST(ALfloatBUFFERSIZE*,device->FOAOut.Buffer), SamplesToDo
  1387. );
  1388. }
  1389. else if(device->Uhj_Encoder)
  1390. {
  1391. int lidx = GetChannelIdxByName(device->RealOut, FrontLeft);
  1392. int ridx = GetChannelIdxByName(device->RealOut, FrontRight);
  1393. if(lidx != -1 && ridx != -1)
  1394. {
  1395. /* Encode to stereo-compatible 2-channel UHJ output. */
  1396. EncodeUhj2(device->Uhj_Encoder,
  1397. device->RealOut.Buffer[lidx], device->RealOut.Buffer[ridx],
  1398. device->Dry.Buffer, SamplesToDo
  1399. );
  1400. }
  1401. }
  1402. else if(device->Bs2b)
  1403. {
  1404. int lidx = GetChannelIdxByName(device->RealOut, FrontLeft);
  1405. int ridx = GetChannelIdxByName(device->RealOut, FrontRight);
  1406. if(lidx != -1 && ridx != -1)
  1407. {
  1408. /* Apply binaural/crossfeed filter */
  1409. bs2b_cross_feed(device->Bs2b, device->RealOut.Buffer[lidx],
  1410. device->RealOut.Buffer[ridx], SamplesToDo);
  1411. }
  1412. }
  1413. if(buffer)
  1414. {
  1415. ALfloat (*OutBuffer)[BUFFERSIZE] = device->RealOut.Buffer;
  1416. ALuint OutChannels = device->RealOut.NumChannels;
  1417. #define WRITE(T, a, b, c, d) do { \
  1418. Write_##T((a), (b), (c), (d)); \
  1419. buffer = (T*)buffer + (c)*(d); \
  1420. } while(0)
  1421. switch(device->FmtType)
  1422. {
  1423. case DevFmtByte:
  1424. WRITE(ALbyte, OutBuffer, buffer, SamplesToDo, OutChannels);
  1425. break;
  1426. case DevFmtUByte:
  1427. WRITE(ALubyte, OutBuffer, buffer, SamplesToDo, OutChannels);
  1428. break;
  1429. case DevFmtShort:
  1430. WRITE(ALshort, OutBuffer, buffer, SamplesToDo, OutChannels);
  1431. break;
  1432. case DevFmtUShort:
  1433. WRITE(ALushort, OutBuffer, buffer, SamplesToDo, OutChannels);
  1434. break;
  1435. case DevFmtInt:
  1436. WRITE(ALint, OutBuffer, buffer, SamplesToDo, OutChannels);
  1437. break;
  1438. case DevFmtUInt:
  1439. WRITE(ALuint, OutBuffer, buffer, SamplesToDo, OutChannels);
  1440. break;
  1441. case DevFmtFloat:
  1442. WRITE(ALfloat, OutBuffer, buffer, SamplesToDo, OutChannels);
  1443. break;
  1444. }
  1445. #undef WRITE
  1446. }
  1447. size -= SamplesToDo;
  1448. }
  1449. RestoreFPUMode(&oldMode);
  1450. }
  1451. ALvoid aluHandleDisconnect(ALCdevice *device)
  1452. {
  1453. ALCcontext *Context;
  1454. device->Connected = ALC_FALSE;
  1455. Context = ATOMIC_LOAD(&device->ContextList);
  1456. while(Context)
  1457. {
  1458. ALvoice *voice, *voice_end;
  1459. voice = Context->Voices;
  1460. voice_end = voice + Context->VoiceCount;
  1461. while(voice != voice_end)
  1462. {
  1463. ALsource *source = voice->Source;
  1464. voice->Source = NULL;
  1465. if(source && source->state == AL_PLAYING)
  1466. {
  1467. source->state = AL_STOPPED;
  1468. ATOMIC_STORE(&source->current_buffer, NULL);
  1469. ATOMIC_STORE(&source->position, 0);
  1470. ATOMIC_STORE(&source->position_fraction, 0);
  1471. }
  1472. voice++;
  1473. }
  1474. Context->VoiceCount = 0;
  1475. Context = Context->next;
  1476. }
  1477. }