panning.c 47 KB

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