ALu.c 55 KB

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