panning.c 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 1999-2010 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 "alAuxEffectSlot.h"
  28. #include "alu.h"
  29. #include "alconfig.h"
  30. #include "bool.h"
  31. #include "ambdec.h"
  32. #include "bformatdec.h"
  33. #include "filters/splitter.h"
  34. #include "uhjfilter.h"
  35. #include "bs2b.h"
  36. extern inline void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
  37. extern inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
  38. extern inline float ScaleAzimuthFront(float azimuth, float scale);
  39. extern inline void ComputePanGains(const MixParams *dry, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
  40. static const ALsizei FuMa2ACN[MAX_AMBI_COEFFS] = {
  41. 0, /* W */
  42. 3, /* X */
  43. 1, /* Y */
  44. 2, /* Z */
  45. 6, /* R */
  46. 7, /* S */
  47. 5, /* T */
  48. 8, /* U */
  49. 4, /* V */
  50. 12, /* K */
  51. 13, /* L */
  52. 11, /* M */
  53. 14, /* N */
  54. 10, /* O */
  55. 15, /* P */
  56. 9, /* Q */
  57. };
  58. static const ALsizei ACN2ACN[MAX_AMBI_COEFFS] = {
  59. 0, 1, 2, 3, 4, 5, 6, 7,
  60. 8, 9, 10, 11, 12, 13, 14, 15
  61. };
  62. void CalcAmbiCoeffs(const ALfloat y, const ALfloat z, const ALfloat x, const ALfloat spread,
  63. ALfloat coeffs[MAX_AMBI_COEFFS])
  64. {
  65. /* Zeroth-order */
  66. coeffs[0] = 1.0f; /* ACN 0 = 1 */
  67. /* First-order */
  68. coeffs[1] = SQRTF_3 * y; /* ACN 1 = sqrt(3) * Y */
  69. coeffs[2] = SQRTF_3 * z; /* ACN 2 = sqrt(3) * Z */
  70. coeffs[3] = SQRTF_3 * x; /* ACN 3 = sqrt(3) * X */
  71. /* Second-order */
  72. coeffs[4] = 3.872983346f * x * y; /* ACN 4 = sqrt(15) * X * Y */
  73. coeffs[5] = 3.872983346f * y * z; /* ACN 5 = sqrt(15) * Y * Z */
  74. coeffs[6] = 1.118033989f * (3.0f*z*z - 1.0f); /* ACN 6 = sqrt(5)/2 * (3*Z*Z - 1) */
  75. coeffs[7] = 3.872983346f * x * z; /* ACN 7 = sqrt(15) * X * Z */
  76. coeffs[8] = 1.936491673f * (x*x - y*y); /* ACN 8 = sqrt(15)/2 * (X*X - Y*Y) */
  77. /* Third-order */
  78. coeffs[9] = 2.091650066f * y * (3.0f*x*x - y*y); /* ACN 9 = sqrt(35/8) * Y * (3*X*X - Y*Y) */
  79. coeffs[10] = 10.246950766f * z * x * y; /* ACN 10 = sqrt(105) * Z * X * Y */
  80. coeffs[11] = 1.620185175f * y * (5.0f*z*z - 1.0f); /* ACN 11 = sqrt(21/8) * Y * (5*Z*Z - 1) */
  81. coeffs[12] = 1.322875656f * z * (5.0f*z*z - 3.0f); /* ACN 12 = sqrt(7)/2 * Z * (5*Z*Z - 3) */
  82. coeffs[13] = 1.620185175f * x * (5.0f*z*z - 1.0f); /* ACN 13 = sqrt(21/8) * X * (5*Z*Z - 1) */
  83. coeffs[14] = 5.123475383f * z * (x*x - y*y); /* ACN 14 = sqrt(105)/2 * Z * (X*X - Y*Y) */
  84. coeffs[15] = 2.091650066f * x * (x*x - 3.0f*y*y); /* ACN 15 = sqrt(35/8) * X * (X*X - 3*Y*Y) */
  85. if(spread > 0.0f)
  86. {
  87. /* Implement the spread by using a spherical source that subtends the
  88. * angle spread. See:
  89. * http://www.ppsloan.org/publications/StupidSH36.pdf - Appendix A3
  90. *
  91. * When adjusted for N3D normalization instead of SN3D, these
  92. * calculations are:
  93. *
  94. * ZH0 = -sqrt(pi) * (-1+ca);
  95. * ZH1 = 0.5*sqrt(pi) * sa*sa;
  96. * ZH2 = -0.5*sqrt(pi) * ca*(-1+ca)*(ca+1);
  97. * ZH3 = -0.125*sqrt(pi) * (-1+ca)*(ca+1)*(5*ca*ca - 1);
  98. * ZH4 = -0.125*sqrt(pi) * ca*(-1+ca)*(ca+1)*(7*ca*ca - 3);
  99. * ZH5 = -0.0625*sqrt(pi) * (-1+ca)*(ca+1)*(21*ca*ca*ca*ca - 14*ca*ca + 1);
  100. *
  101. * The gain of the source is compensated for size, so that the
  102. * loundness doesn't depend on the spread. Thus:
  103. *
  104. * ZH0 = 1.0f;
  105. * ZH1 = 0.5f * (ca+1.0f);
  106. * ZH2 = 0.5f * (ca+1.0f)*ca;
  107. * ZH3 = 0.125f * (ca+1.0f)*(5.0f*ca*ca - 1.0f);
  108. * ZH4 = 0.125f * (ca+1.0f)*(7.0f*ca*ca - 3.0f)*ca;
  109. * ZH5 = 0.0625f * (ca+1.0f)*(21.0f*ca*ca*ca*ca - 14.0f*ca*ca + 1.0f);
  110. */
  111. ALfloat ca = cosf(spread * 0.5f);
  112. /* Increase the source volume by up to +3dB for a full spread. */
  113. ALfloat scale = sqrtf(1.0f + spread/F_TAU);
  114. ALfloat ZH0_norm = scale;
  115. ALfloat ZH1_norm = 0.5f * (ca+1.f) * scale;
  116. ALfloat ZH2_norm = 0.5f * (ca+1.f)*ca * scale;
  117. ALfloat ZH3_norm = 0.125f * (ca+1.f)*(5.f*ca*ca-1.f) * scale;
  118. /* Zeroth-order */
  119. coeffs[0] *= ZH0_norm;
  120. /* First-order */
  121. coeffs[1] *= ZH1_norm;
  122. coeffs[2] *= ZH1_norm;
  123. coeffs[3] *= ZH1_norm;
  124. /* Second-order */
  125. coeffs[4] *= ZH2_norm;
  126. coeffs[5] *= ZH2_norm;
  127. coeffs[6] *= ZH2_norm;
  128. coeffs[7] *= ZH2_norm;
  129. coeffs[8] *= ZH2_norm;
  130. /* Third-order */
  131. coeffs[9] *= ZH3_norm;
  132. coeffs[10] *= ZH3_norm;
  133. coeffs[11] *= ZH3_norm;
  134. coeffs[12] *= ZH3_norm;
  135. coeffs[13] *= ZH3_norm;
  136. coeffs[14] *= ZH3_norm;
  137. coeffs[15] *= ZH3_norm;
  138. }
  139. }
  140. void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
  141. {
  142. ALsizei i, j;
  143. for(i = 0;i < numchans;i++)
  144. {
  145. float gain = 0.0f;
  146. for(j = 0;j < numcoeffs;j++)
  147. gain += chancoeffs[i][j]*coeffs[j];
  148. gains[i] = clampf(gain, 0.0f, 1.0f) * ingain;
  149. }
  150. for(;i < MAX_OUTPUT_CHANNELS;i++)
  151. gains[i] = 0.0f;
  152. }
  153. void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
  154. {
  155. ALsizei i;
  156. for(i = 0;i < numchans;i++)
  157. gains[i] = chanmap[i].Scale * coeffs[chanmap[i].Index] * ingain;
  158. for(;i < MAX_OUTPUT_CHANNELS;i++)
  159. gains[i] = 0.0f;
  160. }
  161. static inline const char *GetLabelFromChannel(enum Channel channel)
  162. {
  163. switch(channel)
  164. {
  165. case FrontLeft: return "front-left";
  166. case FrontRight: return "front-right";
  167. case FrontCenter: return "front-center";
  168. case LFE: return "lfe";
  169. case BackLeft: return "back-left";
  170. case BackRight: return "back-right";
  171. case BackCenter: return "back-center";
  172. case SideLeft: return "side-left";
  173. case SideRight: return "side-right";
  174. case UpperFrontLeft: return "upper-front-left";
  175. case UpperFrontRight: return "upper-front-right";
  176. case UpperBackLeft: return "upper-back-left";
  177. case UpperBackRight: return "upper-back-right";
  178. case LowerFrontLeft: return "lower-front-left";
  179. case LowerFrontRight: return "lower-front-right";
  180. case LowerBackLeft: return "lower-back-left";
  181. case LowerBackRight: return "lower-back-right";
  182. case Aux0: return "aux-0";
  183. case Aux1: return "aux-1";
  184. case Aux2: return "aux-2";
  185. case Aux3: return "aux-3";
  186. case Aux4: return "aux-4";
  187. case Aux5: return "aux-5";
  188. case Aux6: return "aux-6";
  189. case Aux7: return "aux-7";
  190. case Aux8: return "aux-8";
  191. case Aux9: return "aux-9";
  192. case Aux10: return "aux-10";
  193. case Aux11: return "aux-11";
  194. case Aux12: return "aux-12";
  195. case Aux13: return "aux-13";
  196. case Aux14: return "aux-14";
  197. case Aux15: return "aux-15";
  198. case InvalidChannel: break;
  199. }
  200. return "(unknown)";
  201. }
  202. typedef struct ChannelMap {
  203. enum Channel ChanName;
  204. ChannelConfig Config;
  205. } ChannelMap;
  206. static void SetChannelMap(const enum Channel devchans[MAX_OUTPUT_CHANNELS],
  207. ChannelConfig *ambicoeffs, const ChannelMap *chanmap,
  208. ALsizei count, ALsizei *outcount)
  209. {
  210. ALsizei maxchans = 0;
  211. ALsizei i, j;
  212. for(i = 0;i < count;i++)
  213. {
  214. ALint idx = GetChannelIndex(devchans, chanmap[i].ChanName);
  215. if(idx < 0)
  216. {
  217. ERR("Failed to find %s channel in device\n",
  218. GetLabelFromChannel(chanmap[i].ChanName));
  219. continue;
  220. }
  221. maxchans = maxi(maxchans, idx+1);
  222. for(j = 0;j < MAX_AMBI_COEFFS;j++)
  223. ambicoeffs[idx][j] = chanmap[i].Config[j];
  224. }
  225. *outcount = mini(maxchans, MAX_OUTPUT_CHANNELS);
  226. }
  227. static bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALsizei speakermap[MAX_OUTPUT_CHANNELS])
  228. {
  229. ALsizei i;
  230. for(i = 0;i < conf->NumSpeakers;i++)
  231. {
  232. enum Channel ch;
  233. int chidx = -1;
  234. /* NOTE: AmbDec does not define any standard speaker names, however
  235. * for this to work we have to by able to find the output channel
  236. * the speaker definition corresponds to. Therefore, OpenAL Soft
  237. * requires these channel labels to be recognized:
  238. *
  239. * LF = Front left
  240. * RF = Front right
  241. * LS = Side left
  242. * RS = Side right
  243. * LB = Back left
  244. * RB = Back right
  245. * CE = Front center
  246. * CB = Back center
  247. *
  248. * Additionally, surround51 will acknowledge back speakers for side
  249. * channels, and surround51rear will acknowledge side speakers for
  250. * back channels, to avoid issues with an ambdec expecting 5.1 to
  251. * use the side channels when the device is configured for back,
  252. * and vice-versa.
  253. */
  254. if(alstr_cmp_cstr(conf->Speakers[i].Name, "LF") == 0)
  255. ch = FrontLeft;
  256. else if(alstr_cmp_cstr(conf->Speakers[i].Name, "RF") == 0)
  257. ch = FrontRight;
  258. else if(alstr_cmp_cstr(conf->Speakers[i].Name, "CE") == 0)
  259. ch = FrontCenter;
  260. else if(alstr_cmp_cstr(conf->Speakers[i].Name, "LS") == 0)
  261. {
  262. if(device->FmtChans == DevFmtX51Rear)
  263. ch = BackLeft;
  264. else
  265. ch = SideLeft;
  266. }
  267. else if(alstr_cmp_cstr(conf->Speakers[i].Name, "RS") == 0)
  268. {
  269. if(device->FmtChans == DevFmtX51Rear)
  270. ch = BackRight;
  271. else
  272. ch = SideRight;
  273. }
  274. else if(alstr_cmp_cstr(conf->Speakers[i].Name, "LB") == 0)
  275. {
  276. if(device->FmtChans == DevFmtX51)
  277. ch = SideLeft;
  278. else
  279. ch = BackLeft;
  280. }
  281. else if(alstr_cmp_cstr(conf->Speakers[i].Name, "RB") == 0)
  282. {
  283. if(device->FmtChans == DevFmtX51)
  284. ch = SideRight;
  285. else
  286. ch = BackRight;
  287. }
  288. else if(alstr_cmp_cstr(conf->Speakers[i].Name, "CB") == 0)
  289. ch = BackCenter;
  290. else
  291. {
  292. const char *name = alstr_get_cstr(conf->Speakers[i].Name);
  293. unsigned int n;
  294. char c;
  295. if(sscanf(name, "AUX%u%c", &n, &c) == 1 && n < 16)
  296. ch = Aux0+n;
  297. else
  298. {
  299. ERR("AmbDec speaker label \"%s\" not recognized\n", name);
  300. return false;
  301. }
  302. }
  303. chidx = GetChannelIdxByName(&device->RealOut, ch);
  304. if(chidx == -1)
  305. {
  306. ERR("Failed to lookup AmbDec speaker label %s\n",
  307. alstr_get_cstr(conf->Speakers[i].Name));
  308. return false;
  309. }
  310. speakermap[i] = chidx;
  311. }
  312. return true;
  313. }
  314. static const ChannelMap MonoCfg[1] = {
  315. { FrontCenter, { 1.0f } },
  316. }, StereoCfg[2] = {
  317. { FrontLeft, { 5.00000000e-1f, 2.88675135e-1f, 0.0f, 5.52305643e-2f } },
  318. { FrontRight, { 5.00000000e-1f, -2.88675135e-1f, 0.0f, 5.52305643e-2f } },
  319. }, QuadCfg[4] = {
  320. { BackLeft, { 3.53553391e-1f, 2.04124145e-1f, 0.0f, -2.04124145e-1f } },
  321. { FrontLeft, { 3.53553391e-1f, 2.04124145e-1f, 0.0f, 2.04124145e-1f } },
  322. { FrontRight, { 3.53553391e-1f, -2.04124145e-1f, 0.0f, 2.04124145e-1f } },
  323. { BackRight, { 3.53553391e-1f, -2.04124145e-1f, 0.0f, -2.04124145e-1f } },
  324. }, X51SideCfg[4] = {
  325. { SideLeft, { 3.33000782e-1f, 1.89084803e-1f, 0.0f, -2.00042375e-1f, -2.12307769e-2f, 0.0f, 0.0f, 0.0f, -1.14579885e-2f } },
  326. { FrontLeft, { 1.88542860e-1f, 1.27709292e-1f, 0.0f, 1.66295695e-1f, 7.30571517e-2f, 0.0f, 0.0f, 0.0f, 2.10901184e-2f } },
  327. { FrontRight, { 1.88542860e-1f, -1.27709292e-1f, 0.0f, 1.66295695e-1f, -7.30571517e-2f, 0.0f, 0.0f, 0.0f, 2.10901184e-2f } },
  328. { SideRight, { 3.33000782e-1f, -1.89084803e-1f, 0.0f, -2.00042375e-1f, 2.12307769e-2f, 0.0f, 0.0f, 0.0f, -1.14579885e-2f } },
  329. }, X51RearCfg[4] = {
  330. { BackLeft, { 3.33000782e-1f, 1.89084803e-1f, 0.0f, -2.00042375e-1f, -2.12307769e-2f, 0.0f, 0.0f, 0.0f, -1.14579885e-2f } },
  331. { FrontLeft, { 1.88542860e-1f, 1.27709292e-1f, 0.0f, 1.66295695e-1f, 7.30571517e-2f, 0.0f, 0.0f, 0.0f, 2.10901184e-2f } },
  332. { FrontRight, { 1.88542860e-1f, -1.27709292e-1f, 0.0f, 1.66295695e-1f, -7.30571517e-2f, 0.0f, 0.0f, 0.0f, 2.10901184e-2f } },
  333. { BackRight, { 3.33000782e-1f, -1.89084803e-1f, 0.0f, -2.00042375e-1f, 2.12307769e-2f, 0.0f, 0.0f, 0.0f, -1.14579885e-2f } },
  334. }, X61Cfg[6] = {
  335. { SideLeft, { 2.04460341e-1f, 2.17177926e-1f, 0.0f, -4.39996780e-2f, -2.60790269e-2f, 0.0f, 0.0f, 0.0f, -6.87239792e-2f } },
  336. { FrontLeft, { 1.58923161e-1f, 9.21772680e-2f, 0.0f, 1.59658796e-1f, 6.66278083e-2f, 0.0f, 0.0f, 0.0f, 3.84686854e-2f } },
  337. { FrontRight, { 1.58923161e-1f, -9.21772680e-2f, 0.0f, 1.59658796e-1f, -6.66278083e-2f, 0.0f, 0.0f, 0.0f, 3.84686854e-2f } },
  338. { SideRight, { 2.04460341e-1f, -2.17177926e-1f, 0.0f, -4.39996780e-2f, 2.60790269e-2f, 0.0f, 0.0f, 0.0f, -6.87239792e-2f } },
  339. { BackCenter, { 2.50001688e-1f, 0.00000000e+0f, 0.0f, -2.50000094e-1f, 0.00000000e+0f, 0.0f, 0.0f, 0.0f, 6.05133395e-2f } },
  340. }, X71Cfg[6] = {
  341. { BackLeft, { 2.04124145e-1f, 1.08880247e-1f, 0.0f, -1.88586120e-1f, -1.29099444e-1f, 0.0f, 0.0f, 0.0f, 7.45355993e-2f, 3.73460789e-2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.00000000e+0f } },
  342. { SideLeft, { 2.04124145e-1f, 2.17760495e-1f, 0.0f, 0.00000000e+0f, 0.00000000e+0f, 0.0f, 0.0f, 0.0f, -1.49071198e-1f, -3.73460789e-2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.00000000e+0f } },
  343. { FrontLeft, { 2.04124145e-1f, 1.08880247e-1f, 0.0f, 1.88586120e-1f, 1.29099444e-1f, 0.0f, 0.0f, 0.0f, 7.45355993e-2f, 3.73460789e-2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.00000000e+0f } },
  344. { FrontRight, { 2.04124145e-1f, -1.08880247e-1f, 0.0f, 1.88586120e-1f, -1.29099444e-1f, 0.0f, 0.0f, 0.0f, 7.45355993e-2f, -3.73460789e-2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.00000000e+0f } },
  345. { SideRight, { 2.04124145e-1f, -2.17760495e-1f, 0.0f, 0.00000000e+0f, 0.00000000e+0f, 0.0f, 0.0f, 0.0f, -1.49071198e-1f, 3.73460789e-2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.00000000e+0f } },
  346. { BackRight, { 2.04124145e-1f, -1.08880247e-1f, 0.0f, -1.88586120e-1f, 1.29099444e-1f, 0.0f, 0.0f, 0.0f, 7.45355993e-2f, -3.73460789e-2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.00000000e+0f } },
  347. };
  348. static void InitNearFieldCtrl(ALCdevice *device, ALfloat ctrl_dist, ALsizei order,
  349. const ALsizei *restrict chans_per_order)
  350. {
  351. const char *devname = alstr_get_cstr(device->DeviceName);
  352. ALsizei i;
  353. if(GetConfigValueBool(devname, "decoder", "nfc", 1) && ctrl_dist > 0.0f)
  354. {
  355. /* NFC is only used when AvgSpeakerDist is greater than 0, and can only
  356. * be used when rendering to an ambisonic buffer.
  357. */
  358. device->AvgSpeakerDist = minf(ctrl_dist, 10.0f);
  359. TRACE("Using near-field reference distance: %.2f meters\n", device->AvgSpeakerDist);
  360. for(i = 0;i < order+1;i++)
  361. device->NumChannelsPerOrder[i] = chans_per_order[i];
  362. for(;i < MAX_AMBI_ORDER+1;i++)
  363. device->NumChannelsPerOrder[i] = 0;
  364. }
  365. }
  366. static void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const ALsizei speakermap[MAX_OUTPUT_CHANNELS])
  367. {
  368. const char *devname = alstr_get_cstr(device->DeviceName);
  369. ALfloat maxdist = 0.0f;
  370. size_t total = 0;
  371. ALsizei i;
  372. for(i = 0;i < conf->NumSpeakers;i++)
  373. maxdist = maxf(maxdist, conf->Speakers[i].Distance);
  374. if(GetConfigValueBool(devname, "decoder", "distance-comp", 1) && maxdist > 0.0f)
  375. {
  376. ALfloat srate = (ALfloat)device->Frequency;
  377. for(i = 0;i < conf->NumSpeakers;i++)
  378. {
  379. ALsizei chan = speakermap[i];
  380. ALfloat delay;
  381. /* Distance compensation only delays in steps of the sample rate.
  382. * This is a bit less accurate since the delay time falls to the
  383. * nearest sample time, but it's far simpler as it doesn't have to
  384. * deal with phase offsets. This means at 48khz, for instance, the
  385. * distance delay will be in steps of about 7 millimeters.
  386. */
  387. delay = floorf((maxdist-conf->Speakers[i].Distance) / SPEEDOFSOUNDMETRESPERSEC *
  388. srate + 0.5f);
  389. if(delay >= (ALfloat)MAX_DELAY_LENGTH)
  390. ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n",
  391. alstr_get_cstr(conf->Speakers[i].Name), delay, MAX_DELAY_LENGTH);
  392. device->ChannelDelay[chan].Length = (ALsizei)clampf(
  393. delay, 0.0f, (ALfloat)(MAX_DELAY_LENGTH-1)
  394. );
  395. device->ChannelDelay[chan].Gain = conf->Speakers[i].Distance / maxdist;
  396. TRACE("Channel %u \"%s\" distance compensation: %d samples, %f gain\n", chan,
  397. alstr_get_cstr(conf->Speakers[i].Name), device->ChannelDelay[chan].Length,
  398. device->ChannelDelay[chan].Gain
  399. );
  400. /* Round up to the next 4th sample, so each channel buffer starts
  401. * 16-byte aligned.
  402. */
  403. total += RoundUp(device->ChannelDelay[chan].Length, 4);
  404. }
  405. }
  406. if(total > 0)
  407. {
  408. device->ChannelDelay[0].Buffer = al_calloc(16, total * sizeof(ALfloat));
  409. for(i = 1;i < MAX_OUTPUT_CHANNELS;i++)
  410. {
  411. size_t len = RoundUp(device->ChannelDelay[i-1].Length, 4);
  412. device->ChannelDelay[i].Buffer = device->ChannelDelay[i-1].Buffer + len;
  413. }
  414. }
  415. }
  416. static void InitPanning(ALCdevice *device)
  417. {
  418. const ChannelMap *chanmap = NULL;
  419. ALsizei coeffcount = 0;
  420. ALsizei count = 0;
  421. ALsizei i, j;
  422. switch(device->FmtChans)
  423. {
  424. case DevFmtMono:
  425. count = COUNTOF(MonoCfg);
  426. chanmap = MonoCfg;
  427. coeffcount = 1;
  428. break;
  429. case DevFmtStereo:
  430. count = COUNTOF(StereoCfg);
  431. chanmap = StereoCfg;
  432. coeffcount = 4;
  433. break;
  434. case DevFmtQuad:
  435. count = COUNTOF(QuadCfg);
  436. chanmap = QuadCfg;
  437. coeffcount = 4;
  438. break;
  439. case DevFmtX51:
  440. count = COUNTOF(X51SideCfg);
  441. chanmap = X51SideCfg;
  442. coeffcount = 9;
  443. break;
  444. case DevFmtX51Rear:
  445. count = COUNTOF(X51RearCfg);
  446. chanmap = X51RearCfg;
  447. coeffcount = 9;
  448. break;
  449. case DevFmtX61:
  450. count = COUNTOF(X61Cfg);
  451. chanmap = X61Cfg;
  452. coeffcount = 9;
  453. break;
  454. case DevFmtX71:
  455. count = COUNTOF(X71Cfg);
  456. chanmap = X71Cfg;
  457. coeffcount = 16;
  458. break;
  459. case DevFmtAmbi3D:
  460. break;
  461. }
  462. if(device->FmtChans == DevFmtAmbi3D)
  463. {
  464. const char *devname = alstr_get_cstr(device->DeviceName);
  465. const ALsizei *acnmap = (device->AmbiLayout == AmbiLayout_FuMa) ? FuMa2ACN : ACN2ACN;
  466. const ALfloat *n3dscale = (device->AmbiScale == AmbiNorm_FuMa) ? FuMa2N3DScale :
  467. (device->AmbiScale == AmbiNorm_SN3D) ? SN3D2N3DScale :
  468. /*(device->AmbiScale == AmbiNorm_N3D) ?*/ N3D2N3DScale;
  469. ALfloat nfc_delay = 0.0f;
  470. count = (device->AmbiOrder == 3) ? 16 :
  471. (device->AmbiOrder == 2) ? 9 :
  472. (device->AmbiOrder == 1) ? 4 : 1;
  473. for(i = 0;i < count;i++)
  474. {
  475. ALsizei acn = acnmap[i];
  476. device->Dry.Ambi.Map[i].Scale = 1.0f/n3dscale[acn];
  477. device->Dry.Ambi.Map[i].Index = acn;
  478. }
  479. device->Dry.CoeffCount = 0;
  480. device->Dry.NumChannels = count;
  481. if(device->AmbiOrder < 2)
  482. {
  483. device->FOAOut.Ambi = device->Dry.Ambi;
  484. device->FOAOut.CoeffCount = device->Dry.CoeffCount;
  485. device->FOAOut.NumChannels = 0;
  486. }
  487. else
  488. {
  489. ALfloat w_scale=1.0f, xyz_scale=1.0f;
  490. /* FOA output is always ACN+N3D for higher-order ambisonic output.
  491. * The upsampler expects this and will convert it for output.
  492. */
  493. memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi));
  494. for(i = 0;i < 4;i++)
  495. {
  496. device->FOAOut.Ambi.Map[i].Scale = 1.0f;
  497. device->FOAOut.Ambi.Map[i].Index = i;
  498. }
  499. device->FOAOut.CoeffCount = 0;
  500. device->FOAOut.NumChannels = 4;
  501. if(device->AmbiOrder >= 3)
  502. {
  503. w_scale = W_SCALE_3H3P;
  504. xyz_scale = XYZ_SCALE_3H3P;
  505. }
  506. else
  507. {
  508. w_scale = W_SCALE_2H2P;
  509. xyz_scale = XYZ_SCALE_2H2P;
  510. }
  511. ambiup_reset(device->AmbiUp, device, w_scale, xyz_scale);
  512. }
  513. if(ConfigValueFloat(devname, "decoder", "nfc-ref-delay", &nfc_delay) && nfc_delay > 0.0f)
  514. {
  515. static const ALsizei chans_per_order[MAX_AMBI_ORDER+1] = {
  516. 1, 3, 5, 7
  517. };
  518. nfc_delay = clampf(nfc_delay, 0.001f, 1000.0f);
  519. InitNearFieldCtrl(device, nfc_delay * SPEEDOFSOUNDMETRESPERSEC,
  520. device->AmbiOrder, chans_per_order);
  521. }
  522. }
  523. else
  524. {
  525. ALfloat w_scale, xyz_scale;
  526. SetChannelMap(device->RealOut.ChannelName, device->Dry.Ambi.Coeffs,
  527. chanmap, count, &device->Dry.NumChannels);
  528. device->Dry.CoeffCount = coeffcount;
  529. w_scale = (device->Dry.CoeffCount > 9) ? W_SCALE_3H0P :
  530. (device->Dry.CoeffCount > 4) ? W_SCALE_2H0P : 1.0f;
  531. xyz_scale = (device->Dry.CoeffCount > 9) ? XYZ_SCALE_3H0P :
  532. (device->Dry.CoeffCount > 4) ? XYZ_SCALE_2H0P : 1.0f;
  533. memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi));
  534. for(i = 0;i < device->Dry.NumChannels;i++)
  535. {
  536. device->FOAOut.Ambi.Coeffs[i][0] = device->Dry.Ambi.Coeffs[i][0] * w_scale;
  537. for(j = 1;j < 4;j++)
  538. device->FOAOut.Ambi.Coeffs[i][j] = device->Dry.Ambi.Coeffs[i][j] * xyz_scale;
  539. }
  540. device->FOAOut.CoeffCount = 4;
  541. device->FOAOut.NumChannels = 0;
  542. }
  543. device->RealOut.NumChannels = 0;
  544. }
  545. static void InitCustomPanning(ALCdevice *device, const AmbDecConf *conf, const ALsizei speakermap[MAX_OUTPUT_CHANNELS])
  546. {
  547. ChannelMap chanmap[MAX_OUTPUT_CHANNELS];
  548. const ALfloat *coeff_scale = N3D2N3DScale;
  549. ALfloat w_scale = 1.0f;
  550. ALfloat xyz_scale = 1.0f;
  551. ALsizei i, j;
  552. if(conf->FreqBands != 1)
  553. ERR("Basic renderer uses the high-frequency matrix as single-band (xover_freq = %.0fhz)\n",
  554. conf->XOverFreq);
  555. if((conf->ChanMask&AMBI_PERIPHONIC_MASK))
  556. {
  557. if(conf->ChanMask > 0x1ff)
  558. {
  559. w_scale = W_SCALE_3H3P;
  560. xyz_scale = XYZ_SCALE_3H3P;
  561. }
  562. else if(conf->ChanMask > 0xf)
  563. {
  564. w_scale = W_SCALE_2H2P;
  565. xyz_scale = XYZ_SCALE_2H2P;
  566. }
  567. }
  568. else
  569. {
  570. if(conf->ChanMask > 0x1ff)
  571. {
  572. w_scale = W_SCALE_3H0P;
  573. xyz_scale = XYZ_SCALE_3H0P;
  574. }
  575. else if(conf->ChanMask > 0xf)
  576. {
  577. w_scale = W_SCALE_2H0P;
  578. xyz_scale = XYZ_SCALE_2H0P;
  579. }
  580. }
  581. if(conf->CoeffScale == ADS_SN3D)
  582. coeff_scale = SN3D2N3DScale;
  583. else if(conf->CoeffScale == ADS_FuMa)
  584. coeff_scale = FuMa2N3DScale;
  585. for(i = 0;i < conf->NumSpeakers;i++)
  586. {
  587. ALsizei chan = speakermap[i];
  588. ALfloat gain;
  589. ALsizei k = 0;
  590. for(j = 0;j < MAX_AMBI_COEFFS;j++)
  591. chanmap[i].Config[j] = 0.0f;
  592. chanmap[i].ChanName = device->RealOut.ChannelName[chan];
  593. for(j = 0;j < MAX_AMBI_COEFFS;j++)
  594. {
  595. if(j == 0) gain = conf->HFOrderGain[0];
  596. else if(j == 1) gain = conf->HFOrderGain[1];
  597. else if(j == 4) gain = conf->HFOrderGain[2];
  598. else if(j == 9) gain = conf->HFOrderGain[3];
  599. if((conf->ChanMask&(1<<j)))
  600. chanmap[i].Config[j] = conf->HFMatrix[i][k++] / coeff_scale[j] * gain;
  601. }
  602. }
  603. SetChannelMap(device->RealOut.ChannelName, device->Dry.Ambi.Coeffs, chanmap,
  604. conf->NumSpeakers, &device->Dry.NumChannels);
  605. device->Dry.CoeffCount = (conf->ChanMask > 0x1ff) ? 16 :
  606. (conf->ChanMask > 0xf) ? 9 : 4;
  607. memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi));
  608. for(i = 0;i < device->Dry.NumChannels;i++)
  609. {
  610. device->FOAOut.Ambi.Coeffs[i][0] = device->Dry.Ambi.Coeffs[i][0] * w_scale;
  611. for(j = 1;j < 4;j++)
  612. device->FOAOut.Ambi.Coeffs[i][j] = device->Dry.Ambi.Coeffs[i][j] * xyz_scale;
  613. }
  614. device->FOAOut.CoeffCount = 4;
  615. device->FOAOut.NumChannels = 0;
  616. device->RealOut.NumChannels = 0;
  617. InitDistanceComp(device, conf, speakermap);
  618. }
  619. static void InitHQPanning(ALCdevice *device, const AmbDecConf *conf, const ALsizei speakermap[MAX_OUTPUT_CHANNELS])
  620. {
  621. static const ALsizei chans_per_order2d[MAX_AMBI_ORDER+1] = { 1, 2, 2, 2 };
  622. static const ALsizei chans_per_order3d[MAX_AMBI_ORDER+1] = { 1, 3, 5, 7 };
  623. ALfloat avg_dist;
  624. ALsizei count;
  625. ALsizei i;
  626. if((conf->ChanMask&AMBI_PERIPHONIC_MASK))
  627. {
  628. count = (conf->ChanMask > 0x1ff) ? 16 :
  629. (conf->ChanMask > 0xf) ? 9 : 4;
  630. for(i = 0;i < count;i++)
  631. {
  632. device->Dry.Ambi.Map[i].Scale = 1.0f;
  633. device->Dry.Ambi.Map[i].Index = i;
  634. }
  635. }
  636. else
  637. {
  638. static const int map[MAX_AMBI2D_COEFFS] = { 0, 1, 3, 4, 8, 9, 15 };
  639. count = (conf->ChanMask > 0x1ff) ? 7 :
  640. (conf->ChanMask > 0xf) ? 5 : 3;
  641. for(i = 0;i < count;i++)
  642. {
  643. device->Dry.Ambi.Map[i].Scale = 1.0f;
  644. device->Dry.Ambi.Map[i].Index = map[i];
  645. }
  646. }
  647. device->Dry.CoeffCount = 0;
  648. device->Dry.NumChannels = count;
  649. TRACE("Enabling %s-band %s-order%s ambisonic decoder\n",
  650. (conf->FreqBands == 1) ? "single" : "dual",
  651. (conf->ChanMask > 0xf) ? (conf->ChanMask > 0x1ff) ? "third" : "second" : "first",
  652. (conf->ChanMask&AMBI_PERIPHONIC_MASK) ? " periphonic" : ""
  653. );
  654. bformatdec_reset(device->AmbiDecoder, conf, count, device->Frequency, speakermap);
  655. if(!(conf->ChanMask > 0xf))
  656. {
  657. device->FOAOut.Ambi = device->Dry.Ambi;
  658. device->FOAOut.CoeffCount = device->Dry.CoeffCount;
  659. device->FOAOut.NumChannels = 0;
  660. }
  661. else
  662. {
  663. memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi));
  664. if((conf->ChanMask&AMBI_PERIPHONIC_MASK))
  665. {
  666. count = 4;
  667. for(i = 0;i < count;i++)
  668. {
  669. device->FOAOut.Ambi.Map[i].Scale = 1.0f;
  670. device->FOAOut.Ambi.Map[i].Index = i;
  671. }
  672. }
  673. else
  674. {
  675. static const int map[3] = { 0, 1, 3 };
  676. count = 3;
  677. for(i = 0;i < count;i++)
  678. {
  679. device->FOAOut.Ambi.Map[i].Scale = 1.0f;
  680. device->FOAOut.Ambi.Map[i].Index = map[i];
  681. }
  682. }
  683. device->FOAOut.CoeffCount = 0;
  684. device->FOAOut.NumChannels = count;
  685. }
  686. device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
  687. avg_dist = 0.0f;
  688. for(i = 0;i < conf->NumSpeakers;i++)
  689. avg_dist += conf->Speakers[i].Distance;
  690. avg_dist /= (ALfloat)conf->NumSpeakers;
  691. InitNearFieldCtrl(device, avg_dist,
  692. (conf->ChanMask > 0x1ff) ? 3 : (conf->ChanMask > 0xf) ? 2 : 1,
  693. (conf->ChanMask&AMBI_PERIPHONIC_MASK) ? chans_per_order3d : chans_per_order2d
  694. );
  695. InitDistanceComp(device, conf, speakermap);
  696. }
  697. static void InitHrtfPanning(ALCdevice *device)
  698. {
  699. /* NOTE: azimuth goes clockwise. */
  700. static const struct AngularPoint AmbiPoints[] = {
  701. { DEG2RAD( 90.0f), DEG2RAD( 0.0f) },
  702. { DEG2RAD( 35.2643897f), DEG2RAD( 45.0f) },
  703. { DEG2RAD( 35.2643897f), DEG2RAD( 135.0f) },
  704. { DEG2RAD( 35.2643897f), DEG2RAD(-135.0f) },
  705. { DEG2RAD( 35.2643897f), DEG2RAD( -45.0f) },
  706. { DEG2RAD( 0.0f), DEG2RAD( 0.0f) },
  707. { DEG2RAD( 0.0f), DEG2RAD( 45.0f) },
  708. { DEG2RAD( 0.0f), DEG2RAD( 90.0f) },
  709. { DEG2RAD( 0.0f), DEG2RAD( 135.0f) },
  710. { DEG2RAD( 0.0f), DEG2RAD( 180.0f) },
  711. { DEG2RAD( 0.0f), DEG2RAD(-135.0f) },
  712. { DEG2RAD( 0.0f), DEG2RAD( -90.0f) },
  713. { DEG2RAD( 0.0f), DEG2RAD( -45.0f) },
  714. { DEG2RAD(-35.2643897f), DEG2RAD( 45.0f) },
  715. { DEG2RAD(-35.2643897f), DEG2RAD( 135.0f) },
  716. { DEG2RAD(-35.2643897f), DEG2RAD(-135.0f) },
  717. { DEG2RAD(-35.2643897f), DEG2RAD( -45.0f) },
  718. { DEG2RAD(-90.0f), DEG2RAD( 0.0f) },
  719. };
  720. static const ALfloat AmbiMatrixFOA[][MAX_AMBI_COEFFS] = {
  721. { 5.55555556e-02f, 0.00000000e+00f, 1.23717915e-01f, 0.00000000e+00f },
  722. { 5.55555556e-02f, -5.00000000e-02f, 7.14285715e-02f, 5.00000000e-02f },
  723. { 5.55555556e-02f, -5.00000000e-02f, 7.14285715e-02f, -5.00000000e-02f },
  724. { 5.55555556e-02f, 5.00000000e-02f, 7.14285715e-02f, -5.00000000e-02f },
  725. { 5.55555556e-02f, 5.00000000e-02f, 7.14285715e-02f, 5.00000000e-02f },
  726. { 5.55555556e-02f, 0.00000000e+00f, 0.00000000e+00f, 8.66025404e-02f },
  727. { 5.55555556e-02f, -6.12372435e-02f, 0.00000000e+00f, 6.12372435e-02f },
  728. { 5.55555556e-02f, -8.66025404e-02f, 0.00000000e+00f, 0.00000000e+00f },
  729. { 5.55555556e-02f, -6.12372435e-02f, 0.00000000e+00f, -6.12372435e-02f },
  730. { 5.55555556e-02f, 0.00000000e+00f, 0.00000000e+00f, -8.66025404e-02f },
  731. { 5.55555556e-02f, 6.12372435e-02f, 0.00000000e+00f, -6.12372435e-02f },
  732. { 5.55555556e-02f, 8.66025404e-02f, 0.00000000e+00f, 0.00000000e+00f },
  733. { 5.55555556e-02f, 6.12372435e-02f, 0.00000000e+00f, 6.12372435e-02f },
  734. { 5.55555556e-02f, -5.00000000e-02f, -7.14285715e-02f, 5.00000000e-02f },
  735. { 5.55555556e-02f, -5.00000000e-02f, -7.14285715e-02f, -5.00000000e-02f },
  736. { 5.55555556e-02f, 5.00000000e-02f, -7.14285715e-02f, -5.00000000e-02f },
  737. { 5.55555556e-02f, 5.00000000e-02f, -7.14285715e-02f, 5.00000000e-02f },
  738. { 5.55555556e-02f, 0.00000000e+00f, -1.23717915e-01f, 0.00000000e+00f },
  739. }, AmbiMatrixHOA[][MAX_AMBI_COEFFS] = {
  740. { 5.55555556e-02f, 0.00000000e+00f, 1.23717915e-01f, 0.00000000e+00f, 0.00000000e+00f, 0.00000000e+00f },
  741. { 5.55555556e-02f, -5.00000000e-02f, 7.14285715e-02f, 5.00000000e-02f, -4.55645099e-02f, 0.00000000e+00f },
  742. { 5.55555556e-02f, -5.00000000e-02f, 7.14285715e-02f, -5.00000000e-02f, 4.55645099e-02f, 0.00000000e+00f },
  743. { 5.55555556e-02f, 5.00000000e-02f, 7.14285715e-02f, -5.00000000e-02f, -4.55645099e-02f, 0.00000000e+00f },
  744. { 5.55555556e-02f, 5.00000000e-02f, 7.14285715e-02f, 5.00000000e-02f, 4.55645099e-02f, 0.00000000e+00f },
  745. { 5.55555556e-02f, 0.00000000e+00f, 0.00000000e+00f, 8.66025404e-02f, 0.00000000e+00f, 1.29099445e-01f },
  746. { 5.55555556e-02f, -6.12372435e-02f, 0.00000000e+00f, 6.12372435e-02f, -6.83467648e-02f, 0.00000000e+00f },
  747. { 5.55555556e-02f, -8.66025404e-02f, 0.00000000e+00f, 0.00000000e+00f, 0.00000000e+00f, -1.29099445e-01f },
  748. { 5.55555556e-02f, -6.12372435e-02f, 0.00000000e+00f, -6.12372435e-02f, 6.83467648e-02f, 0.00000000e+00f },
  749. { 5.55555556e-02f, 0.00000000e+00f, 0.00000000e+00f, -8.66025404e-02f, 0.00000000e+00f, 1.29099445e-01f },
  750. { 5.55555556e-02f, 6.12372435e-02f, 0.00000000e+00f, -6.12372435e-02f, -6.83467648e-02f, 0.00000000e+00f },
  751. { 5.55555556e-02f, 8.66025404e-02f, 0.00000000e+00f, 0.00000000e+00f, 0.00000000e+00f, -1.29099445e-01f },
  752. { 5.55555556e-02f, 6.12372435e-02f, 0.00000000e+00f, 6.12372435e-02f, 6.83467648e-02f, 0.00000000e+00f },
  753. { 5.55555556e-02f, -5.00000000e-02f, -7.14285715e-02f, 5.00000000e-02f, -4.55645099e-02f, 0.00000000e+00f },
  754. { 5.55555556e-02f, -5.00000000e-02f, -7.14285715e-02f, -5.00000000e-02f, 4.55645099e-02f, 0.00000000e+00f },
  755. { 5.55555556e-02f, 5.00000000e-02f, -7.14285715e-02f, -5.00000000e-02f, -4.55645099e-02f, 0.00000000e+00f },
  756. { 5.55555556e-02f, 5.00000000e-02f, -7.14285715e-02f, 5.00000000e-02f, 4.55645099e-02f, 0.00000000e+00f },
  757. { 5.55555556e-02f, 0.00000000e+00f, -1.23717915e-01f, 0.00000000e+00f, 0.00000000e+00f, 0.00000000e+00f },
  758. };
  759. static const ALfloat AmbiOrderHFGainFOA[MAX_AMBI_ORDER+1] = {
  760. 3.00000000e+00f, 1.73205081e+00f
  761. }, AmbiOrderHFGainHOA[MAX_AMBI_ORDER+1] = {
  762. 2.40192231e+00f, 1.86052102e+00f, 9.60768923e-01f
  763. };
  764. static const ALsizei IndexMap[6] = { 0, 1, 2, 3, 4, 8 };
  765. static const ALsizei ChansPerOrder[MAX_AMBI_ORDER+1] = { 1, 3, 2, 0 };
  766. const ALfloat (*restrict AmbiMatrix)[MAX_AMBI_COEFFS] = AmbiMatrixFOA;
  767. const ALfloat *restrict AmbiOrderHFGain = AmbiOrderHFGainFOA;
  768. ALsizei count = 4;
  769. ALsizei i;
  770. static_assert(COUNTOF(AmbiPoints) == COUNTOF(AmbiMatrixFOA), "FOA Ambisonic HRTF mismatch");
  771. static_assert(COUNTOF(AmbiPoints) == COUNTOF(AmbiMatrixHOA), "HOA Ambisonic HRTF mismatch");
  772. if(device->AmbiUp)
  773. {
  774. AmbiMatrix = AmbiMatrixHOA;
  775. AmbiOrderHFGain = AmbiOrderHFGainHOA;
  776. count = COUNTOF(IndexMap);
  777. }
  778. device->Hrtf = al_calloc(16, FAM_SIZE(DirectHrtfState, Chan, count));
  779. for(i = 0;i < count;i++)
  780. {
  781. device->Dry.Ambi.Map[i].Scale = 1.0f;
  782. device->Dry.Ambi.Map[i].Index = IndexMap[i];
  783. }
  784. device->Dry.CoeffCount = 0;
  785. device->Dry.NumChannels = count;
  786. if(device->AmbiUp)
  787. {
  788. memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi));
  789. for(i = 0;i < 4;i++)
  790. {
  791. device->FOAOut.Ambi.Map[i].Scale = 1.0f;
  792. device->FOAOut.Ambi.Map[i].Index = i;
  793. }
  794. device->FOAOut.CoeffCount = 0;
  795. device->FOAOut.NumChannels = 4;
  796. ambiup_reset(device->AmbiUp, device, AmbiOrderHFGainFOA[0] / AmbiOrderHFGain[0],
  797. AmbiOrderHFGainFOA[1] / AmbiOrderHFGain[1]);
  798. }
  799. else
  800. {
  801. device->FOAOut.Ambi = device->Dry.Ambi;
  802. device->FOAOut.CoeffCount = device->Dry.CoeffCount;
  803. device->FOAOut.NumChannels = 0;
  804. }
  805. device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
  806. BuildBFormatHrtf(device->HrtfHandle,
  807. device->Hrtf, device->Dry.NumChannels, AmbiPoints, AmbiMatrix, COUNTOF(AmbiPoints),
  808. AmbiOrderHFGain
  809. );
  810. InitNearFieldCtrl(device, device->HrtfHandle->distance, device->AmbiUp ? 2 : 1,
  811. ChansPerOrder);
  812. }
  813. static void InitUhjPanning(ALCdevice *device)
  814. {
  815. ALsizei count = 3;
  816. ALsizei i;
  817. for(i = 0;i < count;i++)
  818. {
  819. ALsizei acn = FuMa2ACN[i];
  820. device->Dry.Ambi.Map[i].Scale = 1.0f/FuMa2N3DScale[acn];
  821. device->Dry.Ambi.Map[i].Index = acn;
  822. }
  823. device->Dry.CoeffCount = 0;
  824. device->Dry.NumChannels = count;
  825. device->FOAOut.Ambi = device->Dry.Ambi;
  826. device->FOAOut.CoeffCount = device->Dry.CoeffCount;
  827. device->FOAOut.NumChannels = 0;
  828. device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
  829. }
  830. void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq)
  831. {
  832. /* Hold the HRTF the device last used, in case it's used again. */
  833. struct Hrtf *old_hrtf = device->HrtfHandle;
  834. const char *mode;
  835. bool headphones;
  836. int bs2blevel;
  837. size_t i;
  838. al_free(device->Hrtf);
  839. device->Hrtf = NULL;
  840. device->HrtfHandle = NULL;
  841. alstr_clear(&device->HrtfName);
  842. device->Render_Mode = NormalRender;
  843. memset(&device->Dry.Ambi, 0, sizeof(device->Dry.Ambi));
  844. device->Dry.CoeffCount = 0;
  845. device->Dry.NumChannels = 0;
  846. for(i = 0;i < MAX_AMBI_ORDER+1;i++)
  847. device->NumChannelsPerOrder[i] = 0;
  848. device->AvgSpeakerDist = 0.0f;
  849. memset(device->ChannelDelay, 0, sizeof(device->ChannelDelay));
  850. for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
  851. {
  852. device->ChannelDelay[i].Gain = 1.0f;
  853. device->ChannelDelay[i].Length = 0;
  854. }
  855. al_free(device->Stablizer);
  856. device->Stablizer = NULL;
  857. if(device->FmtChans != DevFmtStereo)
  858. {
  859. ALsizei speakermap[MAX_OUTPUT_CHANNELS];
  860. const char *devname, *layout = NULL;
  861. AmbDecConf conf, *pconf = NULL;
  862. if(old_hrtf)
  863. Hrtf_DecRef(old_hrtf);
  864. old_hrtf = NULL;
  865. if(hrtf_appreq == Hrtf_Enable)
  866. device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
  867. ambdec_init(&conf);
  868. devname = alstr_get_cstr(device->DeviceName);
  869. switch(device->FmtChans)
  870. {
  871. case DevFmtQuad: layout = "quad"; break;
  872. case DevFmtX51: /* fall-through */
  873. case DevFmtX51Rear: layout = "surround51"; break;
  874. case DevFmtX61: layout = "surround61"; break;
  875. case DevFmtX71: layout = "surround71"; break;
  876. /* Mono, Stereo, and Ambisonics output don't use custom decoders. */
  877. case DevFmtMono:
  878. case DevFmtStereo:
  879. case DevFmtAmbi3D:
  880. break;
  881. }
  882. if(layout)
  883. {
  884. const char *fname;
  885. if(ConfigValueStr(devname, "decoder", layout, &fname))
  886. {
  887. if(!ambdec_load(&conf, fname))
  888. ERR("Failed to load layout file %s\n", fname);
  889. else
  890. {
  891. if(conf.ChanMask > 0xffff)
  892. ERR("Unsupported channel mask 0x%04x (max 0xffff)\n", conf.ChanMask);
  893. else
  894. {
  895. if(MakeSpeakerMap(device, &conf, speakermap))
  896. pconf = &conf;
  897. }
  898. }
  899. }
  900. }
  901. if(pconf && GetConfigValueBool(devname, "decoder", "hq-mode", 0))
  902. {
  903. ambiup_free(&device->AmbiUp);
  904. if(!device->AmbiDecoder)
  905. device->AmbiDecoder = bformatdec_alloc();
  906. }
  907. else
  908. {
  909. bformatdec_free(&device->AmbiDecoder);
  910. if(device->FmtChans != DevFmtAmbi3D || device->AmbiOrder < 2)
  911. ambiup_free(&device->AmbiUp);
  912. else
  913. {
  914. if(!device->AmbiUp)
  915. device->AmbiUp = ambiup_alloc();
  916. }
  917. }
  918. if(!pconf)
  919. InitPanning(device);
  920. else if(device->AmbiDecoder)
  921. InitHQPanning(device, pconf, speakermap);
  922. else
  923. InitCustomPanning(device, pconf, speakermap);
  924. /* Enable the stablizer only for formats that have front-left, front-
  925. * right, and front-center outputs.
  926. */
  927. switch(device->FmtChans)
  928. {
  929. case DevFmtX51:
  930. case DevFmtX51Rear:
  931. case DevFmtX61:
  932. case DevFmtX71:
  933. if(GetConfigValueBool(devname, NULL, "front-stablizer", 0))
  934. {
  935. /* Initialize band-splitting filters for the front-left and
  936. * front-right channels, with a crossover at 5khz (could be
  937. * higher).
  938. */
  939. ALfloat scale = (ALfloat)(5000.0 / device->Frequency);
  940. FrontStablizer *stablizer = al_calloc(16, sizeof(*stablizer));
  941. bandsplit_init(&stablizer->LFilter, scale);
  942. stablizer->RFilter = stablizer->LFilter;
  943. /* Initialize all-pass filters for all other channels. */
  944. splitterap_init(&stablizer->APFilter[0], scale);
  945. for(i = 1;i < (size_t)device->RealOut.NumChannels;i++)
  946. stablizer->APFilter[i] = stablizer->APFilter[0];
  947. device->Stablizer = stablizer;
  948. }
  949. break;
  950. case DevFmtMono:
  951. case DevFmtStereo:
  952. case DevFmtQuad:
  953. case DevFmtAmbi3D:
  954. break;
  955. }
  956. TRACE("Front stablizer %s\n", device->Stablizer ? "enabled" : "disabled");
  957. ambdec_deinit(&conf);
  958. return;
  959. }
  960. bformatdec_free(&device->AmbiDecoder);
  961. headphones = device->IsHeadphones;
  962. if(device->Type != Loopback)
  963. {
  964. const char *mode;
  965. if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "stereo-mode", &mode))
  966. {
  967. if(strcasecmp(mode, "headphones") == 0)
  968. headphones = true;
  969. else if(strcasecmp(mode, "speakers") == 0)
  970. headphones = false;
  971. else if(strcasecmp(mode, "auto") != 0)
  972. ERR("Unexpected stereo-mode: %s\n", mode);
  973. }
  974. }
  975. if(hrtf_userreq == Hrtf_Default)
  976. {
  977. bool usehrtf = (headphones && hrtf_appreq != Hrtf_Disable) ||
  978. (hrtf_appreq == Hrtf_Enable);
  979. if(!usehrtf) goto no_hrtf;
  980. device->HrtfStatus = ALC_HRTF_ENABLED_SOFT;
  981. if(headphones && hrtf_appreq != Hrtf_Disable)
  982. device->HrtfStatus = ALC_HRTF_HEADPHONES_DETECTED_SOFT;
  983. }
  984. else
  985. {
  986. if(hrtf_userreq != Hrtf_Enable)
  987. {
  988. if(hrtf_appreq == Hrtf_Enable)
  989. device->HrtfStatus = ALC_HRTF_DENIED_SOFT;
  990. goto no_hrtf;
  991. }
  992. device->HrtfStatus = ALC_HRTF_REQUIRED_SOFT;
  993. }
  994. if(VECTOR_SIZE(device->HrtfList) == 0)
  995. {
  996. VECTOR_DEINIT(device->HrtfList);
  997. device->HrtfList = EnumerateHrtf(device->DeviceName);
  998. }
  999. if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
  1000. {
  1001. const EnumeratedHrtf *entry = &VECTOR_ELEM(device->HrtfList, hrtf_id);
  1002. struct Hrtf *hrtf = GetLoadedHrtf(entry->hrtf);
  1003. if(hrtf && hrtf->sampleRate == device->Frequency)
  1004. {
  1005. device->HrtfHandle = hrtf;
  1006. alstr_copy(&device->HrtfName, entry->name);
  1007. }
  1008. else if(hrtf)
  1009. Hrtf_DecRef(hrtf);
  1010. }
  1011. for(i = 0;!device->HrtfHandle && i < VECTOR_SIZE(device->HrtfList);i++)
  1012. {
  1013. const EnumeratedHrtf *entry = &VECTOR_ELEM(device->HrtfList, i);
  1014. struct Hrtf *hrtf = GetLoadedHrtf(entry->hrtf);
  1015. if(hrtf && hrtf->sampleRate == device->Frequency)
  1016. {
  1017. device->HrtfHandle = hrtf;
  1018. alstr_copy(&device->HrtfName, entry->name);
  1019. }
  1020. else if(hrtf)
  1021. Hrtf_DecRef(hrtf);
  1022. }
  1023. if(device->HrtfHandle)
  1024. {
  1025. if(old_hrtf)
  1026. Hrtf_DecRef(old_hrtf);
  1027. old_hrtf = NULL;
  1028. device->Render_Mode = HrtfRender;
  1029. if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "hrtf-mode", &mode))
  1030. {
  1031. if(strcasecmp(mode, "full") == 0)
  1032. device->Render_Mode = HrtfRender;
  1033. else if(strcasecmp(mode, "basic") == 0)
  1034. device->Render_Mode = NormalRender;
  1035. else
  1036. ERR("Unexpected hrtf-mode: %s\n", mode);
  1037. }
  1038. if(device->Render_Mode == HrtfRender)
  1039. {
  1040. /* Don't bother with HOA when using full HRTF rendering. Nothing
  1041. * needs it, and it eases the CPU/memory load.
  1042. */
  1043. ambiup_free(&device->AmbiUp);
  1044. }
  1045. else
  1046. {
  1047. if(!device->AmbiUp)
  1048. device->AmbiUp = ambiup_alloc();
  1049. }
  1050. TRACE("%s HRTF rendering enabled, using \"%s\"\n",
  1051. ((device->Render_Mode == HrtfRender) ? "Full" : "Basic"),
  1052. alstr_get_cstr(device->HrtfName)
  1053. );
  1054. InitHrtfPanning(device);
  1055. return;
  1056. }
  1057. device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
  1058. no_hrtf:
  1059. if(old_hrtf)
  1060. Hrtf_DecRef(old_hrtf);
  1061. old_hrtf = NULL;
  1062. TRACE("HRTF disabled\n");
  1063. device->Render_Mode = StereoPair;
  1064. ambiup_free(&device->AmbiUp);
  1065. bs2blevel = ((headphones && hrtf_appreq != Hrtf_Disable) ||
  1066. (hrtf_appreq == Hrtf_Enable)) ? 5 : 0;
  1067. if(device->Type != Loopback)
  1068. ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "cf_level", &bs2blevel);
  1069. if(bs2blevel > 0 && bs2blevel <= 6)
  1070. {
  1071. device->Bs2b = al_calloc(16, sizeof(*device->Bs2b));
  1072. bs2b_set_params(device->Bs2b, bs2blevel, device->Frequency);
  1073. TRACE("BS2B enabled\n");
  1074. InitPanning(device);
  1075. return;
  1076. }
  1077. TRACE("BS2B disabled\n");
  1078. if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "stereo-encoding", &mode))
  1079. {
  1080. if(strcasecmp(mode, "uhj") == 0)
  1081. device->Render_Mode = NormalRender;
  1082. else if(strcasecmp(mode, "panpot") != 0)
  1083. ERR("Unexpected stereo-encoding: %s\n", mode);
  1084. }
  1085. if(device->Render_Mode == NormalRender)
  1086. {
  1087. device->Uhj_Encoder = al_calloc(16, sizeof(Uhj2Encoder));
  1088. TRACE("UHJ enabled\n");
  1089. InitUhjPanning(device);
  1090. return;
  1091. }
  1092. TRACE("UHJ disabled\n");
  1093. InitPanning(device);
  1094. }
  1095. void aluInitEffectPanning(ALeffectslot *slot)
  1096. {
  1097. ALsizei i;
  1098. memset(slot->ChanMap, 0, sizeof(slot->ChanMap));
  1099. slot->NumChannels = 0;
  1100. for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
  1101. {
  1102. slot->ChanMap[i].Scale = 1.0f;
  1103. slot->ChanMap[i].Index = i;
  1104. }
  1105. slot->NumChannels = i;
  1106. }