panning.c 47 KB

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