2
0

panning.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  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 "AL/al.h"
  28. #include "AL/alc.h"
  29. #include "alu.h"
  30. #include "bool.h"
  31. #define ZERO_ORDER_SCALE 0.0f
  32. #define FIRST_ORDER_SCALE 1.0f
  33. #define SECOND_ORDER_SCALE (1.0f / 1.22474f)
  34. #define THIRD_ORDER_SCALE (1.0f / 1.30657f)
  35. static const ALuint FuMa2ACN[MAX_AMBI_COEFFS] = {
  36. 0, /* W */
  37. 3, /* X */
  38. 1, /* Y */
  39. 2, /* Z */
  40. 6, /* R */
  41. 7, /* S */
  42. 5, /* T */
  43. 8, /* U */
  44. 4, /* V */
  45. 12, /* K */
  46. 13, /* L */
  47. 11, /* M */
  48. 14, /* N */
  49. 10, /* O */
  50. 15, /* P */
  51. 9, /* Q */
  52. };
  53. /* NOTE: These are scale factors as applied to Ambisonics content. FuMa
  54. * decoder coefficients should be divided by these values to get N3D decoder
  55. * coefficients.
  56. */
  57. static const ALfloat FuMa2N3DScale[MAX_AMBI_COEFFS] = {
  58. 1.414213562f, /* ACN 0 (W), sqrt(2) */
  59. 1.732050808f, /* ACN 1 (Y), sqrt(3) */
  60. 1.732050808f, /* ACN 2 (Z), sqrt(3) */
  61. 1.732050808f, /* ACN 3 (X), sqrt(3) */
  62. 1.936491673f, /* ACN 4 (V), sqrt(15)/2 */
  63. 1.936491673f, /* ACN 5 (T), sqrt(15)/2 */
  64. 2.236067978f, /* ACN 6 (R), sqrt(5) */
  65. 1.936491673f, /* ACN 7 (S), sqrt(15)/2 */
  66. 1.936491673f, /* ACN 8 (U), sqrt(15)/2 */
  67. 2.091650066f, /* ACN 9 (Q), sqrt(35/8) */
  68. 1.972026594f, /* ACN 10 (O), sqrt(35)/3 */
  69. 2.231093404f, /* ACN 11 (M), sqrt(224/45) */
  70. 2.645751311f, /* ACN 12 (K), sqrt(7) */
  71. 2.231093404f, /* ACN 13 (L), sqrt(224/45) */
  72. 1.972026594f, /* ACN 14 (N), sqrt(35)/3 */
  73. 2.091650066f, /* ACN 15 (P), sqrt(35/8) */
  74. };
  75. void ComputeAmbientGains(const ALCdevice *device, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
  76. {
  77. ALuint i;
  78. for(i = 0;i < device->NumChannels;i++)
  79. {
  80. // The W coefficients are based on a mathematical average of the
  81. // output. The square root of the base average provides for a more
  82. // perceptual average volume, better suited to non-directional gains.
  83. gains[i] = sqrtf(device->AmbiCoeffs[i][0]) * ingain;
  84. }
  85. for(;i < MAX_OUTPUT_CHANNELS;i++)
  86. gains[i] = 0.0f;
  87. }
  88. void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat elevation, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
  89. {
  90. ALfloat dir[3] = {
  91. sinf(angle) * cosf(elevation),
  92. sinf(elevation),
  93. -cosf(angle) * cosf(elevation)
  94. };
  95. ComputeDirectionalGains(device, dir, ingain, gains);
  96. }
  97. void ComputeDirectionalGains(const ALCdevice *device, const ALfloat dir[3], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
  98. {
  99. ALfloat coeffs[MAX_AMBI_COEFFS];
  100. ALuint i, j;
  101. /* Convert from OpenAL coords to Ambisonics. */
  102. ALfloat x = -dir[2];
  103. ALfloat y = -dir[0];
  104. ALfloat z = dir[1];
  105. /* Zeroth-order */
  106. coeffs[0] = 1.0f; /* ACN 0 = 1 */
  107. /* First-order */
  108. coeffs[1] = 1.732050808f * y; /* ACN 1 = sqrt(3) * Y */
  109. coeffs[2] = 1.732050808f * z; /* ACN 2 = sqrt(3) * Z */
  110. coeffs[3] = 1.732050808f * x; /* ACN 3 = sqrt(3) * X */
  111. /* Second-order */
  112. coeffs[4] = 3.872983346f * x * y; /* ACN 4 = sqrt(15) * X * Y */
  113. coeffs[5] = 3.872983346f * y * z; /* ACN 5 = sqrt(15) * Y * Z */
  114. coeffs[6] = 1.118033989f * (3.0f*z*z - 1.0f); /* ACN 6 = sqrt(5)/2 * (3*Z*Z - 1) */
  115. coeffs[7] = 3.872983346f * x * z; /* ACN 7 = sqrt(15) * X * Z */
  116. coeffs[8] = 1.936491673f * (x*x - y*y); /* ACN 8 = sqrt(15)/2 * (X*X - Y*Y) */
  117. /* Third-order */
  118. coeffs[9] = 2.091650066f * y * (3.0f*x*x - y*y); /* ACN 9 = sqrt(35/8) * Y * (3*X*X - Y*Y) */
  119. coeffs[10] = 10.246950766f * z * x * y; /* ACN 10 = sqrt(105) * Z * X * Y */
  120. coeffs[11] = 1.620185175f * y * (5.0f*z*z - 1.0f); /* ACN 11 = sqrt(21/8) * Y * (5*Z*Z - 1) */
  121. coeffs[12] = 1.322875656f * z * (5.0f*z*z - 3.0f); /* ACN 12 = sqrt(7)/2 * Z * (5*Z*Z - 3) */
  122. coeffs[13] = 1.620185175f * x * (5.0f*z*z - 1.0f); /* ACN 13 = sqrt(21/8) * X * (5*Z*Z - 1) */
  123. coeffs[14] = 5.123475383f * z * (x*x - y*y); /* ACN 14 = sqrt(105)/2 * Z * (X*X - Y*Y) */
  124. coeffs[15] = 2.091650066f * x * (x*x - 3.0f*y*y); /* ACN 15 = sqrt(35/8) * X * (X*X - 3*Y*Y) */
  125. for(i = 0;i < device->NumChannels;i++)
  126. {
  127. float gain = 0.0f;
  128. for(j = 0;j < MAX_AMBI_COEFFS;j++)
  129. gain += device->AmbiCoeffs[i][j]*coeffs[j];
  130. gains[i] = gain * ingain;
  131. }
  132. for(;i < MAX_OUTPUT_CHANNELS;i++)
  133. gains[i] = 0.0f;
  134. }
  135. void ComputeBFormatGains(const ALCdevice *device, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
  136. {
  137. ALuint i, j;
  138. for(i = 0;i < device->NumChannels;i++)
  139. {
  140. float gain = 0.0f;
  141. for(j = 0;j < 4;j++)
  142. gain += device->AmbiCoeffs[i][j] * mtx[j];
  143. gains[i] = gain * ingain;
  144. }
  145. for(;i < MAX_OUTPUT_CHANNELS;i++)
  146. gains[i] = 0.0f;
  147. }
  148. DECL_CONST static inline const char *GetLabelFromChannel(enum Channel channel)
  149. {
  150. switch(channel)
  151. {
  152. case FrontLeft: return "front-left";
  153. case FrontRight: return "front-right";
  154. case FrontCenter: return "front-center";
  155. case LFE: return "lfe";
  156. case BackLeft: return "back-left";
  157. case BackRight: return "back-right";
  158. case BackCenter: return "back-center";
  159. case SideLeft: return "side-left";
  160. case SideRight: return "side-right";
  161. case BFormatW: return "bformat-w";
  162. case BFormatX: return "bformat-x";
  163. case BFormatY: return "bformat-y";
  164. case BFormatZ: return "bformat-z";
  165. case InvalidChannel: break;
  166. }
  167. return "(unknown)";
  168. }
  169. typedef struct ChannelMap {
  170. enum Channel ChanName;
  171. ChannelConfig Config;
  172. } ChannelMap;
  173. static void SetChannelMap(ALCdevice *device, const ChannelMap *chanmap, size_t count, ALfloat ambiscale, ALboolean isfuma)
  174. {
  175. size_t j, k;
  176. ALuint i;
  177. device->AmbiScale = ambiscale;
  178. for(i = 0;i < MAX_OUTPUT_CHANNELS && device->ChannelName[i] != InvalidChannel;i++)
  179. {
  180. if(device->ChannelName[i] == LFE)
  181. {
  182. for(j = 0;j < MAX_AMBI_COEFFS;j++)
  183. device->AmbiCoeffs[i][j] = 0.0f;
  184. continue;
  185. }
  186. for(j = 0;j < count;j++)
  187. {
  188. if(device->ChannelName[i] == chanmap[j].ChanName)
  189. {
  190. if(isfuma)
  191. {
  192. /* Reformat FuMa -> ACN/N3D */
  193. for(k = 0;k < MAX_AMBI_COEFFS;++k)
  194. {
  195. ALuint acn = FuMa2ACN[k];
  196. device->AmbiCoeffs[i][acn] = chanmap[j].Config[k] / FuMa2N3DScale[acn];
  197. }
  198. }
  199. else
  200. {
  201. for(k = 0;k < MAX_AMBI_COEFFS;++k)
  202. device->AmbiCoeffs[i][k] = chanmap[j].Config[k];
  203. }
  204. break;
  205. }
  206. }
  207. if(j == count)
  208. ERR("Failed to match %s channel (%u) in config\n", GetLabelFromChannel(device->ChannelName[i]), i);
  209. }
  210. device->NumChannels = i;
  211. }
  212. static bool LoadChannelSetup(ALCdevice *device)
  213. {
  214. static const enum Channel mono_chans[1] = {
  215. FrontCenter
  216. }, stereo_chans[2] = {
  217. FrontLeft, FrontRight
  218. }, quad_chans[4] = {
  219. FrontLeft, FrontRight,
  220. BackLeft, BackRight
  221. }, surround51_chans[5] = {
  222. FrontLeft, FrontRight, FrontCenter,
  223. SideLeft, SideRight
  224. }, surround51rear_chans[5] = {
  225. FrontLeft, FrontRight, FrontCenter,
  226. BackLeft, BackRight
  227. }, surround61_chans[6] = {
  228. FrontLeft, FrontRight,
  229. FrontCenter, BackCenter,
  230. SideLeft, SideRight
  231. }, surround71_chans[7] = {
  232. FrontLeft, FrontRight, FrontCenter,
  233. BackLeft, BackRight,
  234. SideLeft, SideRight
  235. };
  236. ChannelMap chanmap[MAX_OUTPUT_CHANNELS];
  237. const enum Channel *channels = NULL;
  238. const char *layout = NULL;
  239. ALfloat ambiscale = 1.0f;
  240. size_t count = 0;
  241. int isfuma;
  242. int order;
  243. size_t i;
  244. switch(device->FmtChans)
  245. {
  246. case DevFmtMono:
  247. layout = "mono";
  248. channels = mono_chans;
  249. count = COUNTOF(mono_chans);
  250. break;
  251. case DevFmtStereo:
  252. layout = "stereo";
  253. channels = stereo_chans;
  254. count = COUNTOF(stereo_chans);
  255. break;
  256. case DevFmtQuad:
  257. layout = "quad";
  258. channels = quad_chans;
  259. count = COUNTOF(quad_chans);
  260. break;
  261. case DevFmtX51:
  262. layout = "surround51";
  263. channels = surround51_chans;
  264. count = COUNTOF(surround51_chans);
  265. break;
  266. case DevFmtX51Rear:
  267. layout = "surround51rear";
  268. channels = surround51rear_chans;
  269. count = COUNTOF(surround51rear_chans);
  270. break;
  271. case DevFmtX61:
  272. layout = "surround61";
  273. channels = surround61_chans;
  274. count = COUNTOF(surround61_chans);
  275. break;
  276. case DevFmtX71:
  277. layout = "surround71";
  278. channels = surround71_chans;
  279. count = COUNTOF(surround71_chans);
  280. break;
  281. case DevFmtBFormat3D:
  282. break;
  283. }
  284. if(!layout)
  285. return false;
  286. else
  287. {
  288. char name[32] = {0};
  289. const char *type;
  290. char eol;
  291. snprintf(name, sizeof(name), "%s/type", layout);
  292. if(!ConfigValueStr(al_string_get_cstr(device->DeviceName), "layouts", name, &type))
  293. return false;
  294. if(sscanf(type, " %31[^: ] : %d%c", name, &order, &eol) != 2)
  295. {
  296. ERR("Invalid type value '%s' (expected name:order) for layout %s\n", type, layout);
  297. return false;
  298. }
  299. if(strcasecmp(name, "fuma") == 0)
  300. isfuma = 1;
  301. else if(strcasecmp(name, "n3d") == 0)
  302. isfuma = 0;
  303. else
  304. {
  305. ERR("Unhandled type name '%s' (expected FuMa or N3D) for layout %s\n", name, layout);
  306. return false;
  307. }
  308. if(order == 3)
  309. ambiscale = THIRD_ORDER_SCALE;
  310. else if(order == 2)
  311. ambiscale = SECOND_ORDER_SCALE;
  312. else if(order == 1)
  313. ambiscale = FIRST_ORDER_SCALE;
  314. else if(order == 0)
  315. ambiscale = ZERO_ORDER_SCALE;
  316. else
  317. {
  318. ERR("Unhandled type order %d (expected 0, 1, 2, or 3) for layout %s\n", order, layout);
  319. return false;
  320. }
  321. }
  322. for(i = 0;i < count;i++)
  323. {
  324. float coeffs[MAX_AMBI_COEFFS] = {0.0f};
  325. const char *channame;
  326. char chanlayout[32];
  327. const char *value;
  328. int props = 0;
  329. char eol = 0;
  330. int j;
  331. chanmap[i].ChanName = channels[i];
  332. channame = GetLabelFromChannel(channels[i]);
  333. snprintf(chanlayout, sizeof(chanlayout), "%s/%s", layout, channame);
  334. if(!ConfigValueStr(al_string_get_cstr(device->DeviceName), "layouts", chanlayout, &value))
  335. {
  336. ERR("Missing channel %s\n", channame);
  337. return false;
  338. }
  339. if(order == 3)
  340. props = sscanf(value, " %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %c",
  341. &coeffs[0], &coeffs[1], &coeffs[2], &coeffs[3],
  342. &coeffs[4], &coeffs[5], &coeffs[6], &coeffs[7],
  343. &coeffs[8], &coeffs[9], &coeffs[10], &coeffs[11],
  344. &coeffs[12], &coeffs[13], &coeffs[14], &coeffs[15],
  345. &eol
  346. );
  347. else if(order == 2)
  348. props = sscanf(value, " %f %f %f %f %f %f %f %f %f %c",
  349. &coeffs[0], &coeffs[1], &coeffs[2],
  350. &coeffs[3], &coeffs[4], &coeffs[5],
  351. &coeffs[6], &coeffs[7], &coeffs[8],
  352. &eol
  353. );
  354. else if(order == 1)
  355. props = sscanf(value, " %f %f %f %f %c",
  356. &coeffs[0], &coeffs[1],
  357. &coeffs[2], &coeffs[3],
  358. &eol
  359. );
  360. else if(order == 0)
  361. props = sscanf(value, " %f %c", &coeffs[0], &eol);
  362. if(props == 0)
  363. {
  364. ERR("Failed to parse option %s properties\n", chanlayout);
  365. return false;
  366. }
  367. if(props > (order+1)*(order+1))
  368. {
  369. ERR("Excess elements in option %s (expected %d)\n", chanlayout, (order+1)*(order+1));
  370. return false;
  371. }
  372. for(j = 0;j < MAX_AMBI_COEFFS;++j)
  373. chanmap[i].Config[j] = coeffs[j];
  374. }
  375. SetChannelMap(device, chanmap, count, ambiscale, isfuma);
  376. return true;
  377. }
  378. ALvoid aluInitPanning(ALCdevice *device)
  379. {
  380. /* NOTE: These decoder coefficients are using FuMa channel ordering and
  381. * normalization, since that's what was produced by the Ambisonic Decoder
  382. * Toolbox. SetChannelMap will convert them to N3D.
  383. */
  384. static const ChannelMap MonoCfg[1] = {
  385. { FrontCenter, { 1.414213562f } },
  386. }, StereoCfg[2] = {
  387. { FrontLeft, { 0.707106781f, 0.0f, 0.5f, 0.0f } },
  388. { FrontRight, { 0.707106781f, 0.0f, -0.5f, 0.0f } },
  389. }, QuadCfg[4] = {
  390. { FrontLeft, { 0.353553f, 0.306184f, 0.306184f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, 0.117186f } },
  391. { FrontRight, { 0.353553f, 0.306184f, -0.306184f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, -0.117186f } },
  392. { BackLeft, { 0.353553f, -0.306184f, 0.306184f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, -0.117186f } },
  393. { BackRight, { 0.353553f, -0.306184f, -0.306184f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, 0.117186f } },
  394. }, X51SideCfg[5] = {
  395. { FrontLeft, { 0.208954f, 0.212846f, 0.238350f, 0.0f, 0.0f, 0.0f, 0.0f, -0.017738f, 0.204014f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.051023f, 0.047490f } },
  396. { FrontRight, { 0.208954f, 0.212846f, -0.238350f, 0.0f, 0.0f, 0.0f, 0.0f, -0.017738f, -0.204014f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.051023f, -0.047490f } },
  397. { FrontCenter, { 0.109403f, 0.179490f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.142031f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.072024f, 0.000000f } },
  398. { SideLeft, { 0.470936f, -0.369626f, 0.349386f, 0.0f, 0.0f, 0.0f, 0.0f, -0.031375f, -0.058144f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.007119f, -0.043968f } },
  399. { SideRight, { 0.470936f, -0.369626f, -0.349386f, 0.0f, 0.0f, 0.0f, 0.0f, -0.031375f, 0.058144f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.007119f, 0.043968f } },
  400. }, X51RearCfg[5] = {
  401. { FrontLeft, { 0.208954f, 0.212846f, 0.238350f, 0.0f, 0.0f, 0.0f, 0.0f, -0.017738f, 0.204014f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.051023f, 0.047490f } },
  402. { FrontRight, { 0.208954f, 0.212846f, -0.238350f, 0.0f, 0.0f, 0.0f, 0.0f, -0.017738f, -0.204014f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.051023f, -0.047490f } },
  403. { FrontCenter, { 0.109403f, 0.179490f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.142031f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.072024f, 0.000000f } },
  404. { BackLeft, { 0.470936f, -0.369626f, 0.349386f, 0.0f, 0.0f, 0.0f, 0.0f, -0.031375f, -0.058144f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.007119f, -0.043968f } },
  405. { BackRight, { 0.470936f, -0.369626f, -0.349386f, 0.0f, 0.0f, 0.0f, 0.0f, -0.031375f, 0.058144f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.007119f, 0.043968f } },
  406. }, X61Cfg[6] = {
  407. { FrontLeft, { 0.167065f, 0.200583f, 0.172695f, 0.0f, 0.0f, 0.0f, 0.0f, 0.029855f, 0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f, 0.068910f } },
  408. { FrontRight, { 0.167065f, 0.200583f, -0.172695f, 0.0f, 0.0f, 0.0f, 0.0f, 0.029855f, -0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f, -0.068910f } },
  409. { FrontCenter, { 0.109403f, 0.179490f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.142031f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.072024f, 0.000000f } },
  410. { BackCenter, { 0.353556f, -0.461940f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.165723f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, 0.000000f } },
  411. { SideLeft, { 0.289151f, -0.081301f, 0.401292f, 0.0f, 0.0f, 0.0f, 0.0f, -0.188208f, -0.071420f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.010099f, -0.032897f } },
  412. { SideRight, { 0.289151f, -0.081301f, -0.401292f, 0.0f, 0.0f, 0.0f, 0.0f, -0.188208f, 0.071420f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.010099f, 0.032897f } },
  413. }, X71Cfg[7] = {
  414. { FrontLeft, { 0.167065f, 0.200583f, 0.172695f, 0.0f, 0.0f, 0.0f, 0.0f, 0.029855f, 0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f, 0.068910f } },
  415. { FrontRight, { 0.167065f, 0.200583f, -0.172695f, 0.0f, 0.0f, 0.0f, 0.0f, 0.029855f, -0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f, -0.068910f } },
  416. { FrontCenter, { 0.109403f, 0.179490f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.142031f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.072024f, 0.000000f } },
  417. { BackLeft, { 0.224752f, -0.295009f, 0.170325f, 0.0f, 0.0f, 0.0f, 0.0f, 0.105349f, -0.182473f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, 0.065799f } },
  418. { BackRight, { 0.224752f, -0.295009f, -0.170325f, 0.0f, 0.0f, 0.0f, 0.0f, 0.105349f, 0.182473f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, -0.065799f } },
  419. { SideLeft, { 0.224739f, 0.000000f, 0.340644f, 0.0f, 0.0f, 0.0f, 0.0f, -0.210697f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, -0.065795f } },
  420. { SideRight, { 0.224739f, 0.000000f, -0.340644f, 0.0f, 0.0f, 0.0f, 0.0f, -0.210697f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, 0.065795f } },
  421. }, BFormat3D[4] = {
  422. { BFormatW, { 1.0f, 0.0f, 0.0f, 0.0f } },
  423. { BFormatX, { 0.0f, 1.0f, 0.0f, 0.0f } },
  424. { BFormatY, { 0.0f, 0.0f, 1.0f, 0.0f } },
  425. { BFormatZ, { 0.0f, 0.0f, 0.0f, 1.0f } },
  426. };
  427. const ChannelMap *chanmap = NULL;
  428. ALfloat ambiscale = 1.0f;
  429. size_t count = 0;
  430. device->AmbiScale = 1.0f;
  431. memset(device->AmbiCoeffs, 0, sizeof(device->AmbiCoeffs));
  432. device->NumChannels = 0;
  433. if(device->Hrtf)
  434. {
  435. ALfloat (*coeffs_list[4])[2];
  436. ALuint *delay_list[4];
  437. ALuint i;
  438. count = COUNTOF(BFormat3D);
  439. chanmap = BFormat3D;
  440. ambiscale = 1.0f;
  441. for(i = 0;i < count;i++)
  442. device->ChannelName[i] = chanmap[i].ChanName;
  443. for(;i < MAX_OUTPUT_CHANNELS;i++)
  444. device->ChannelName[i] = InvalidChannel;
  445. SetChannelMap(device, chanmap, count, ambiscale, AL_TRUE);
  446. for(i = 0;i < 4;++i)
  447. {
  448. static const enum Channel inputs[4] = { BFormatW, BFormatX, BFormatY, BFormatZ };
  449. int chan = GetChannelIdxByName(device, inputs[i]);
  450. coeffs_list[i] = device->Hrtf_Params[chan].Coeffs;
  451. delay_list[i] = device->Hrtf_Params[chan].Delay;
  452. }
  453. GetBFormatHrtfCoeffs(device->Hrtf, 4, coeffs_list, delay_list);
  454. return;
  455. }
  456. if(LoadChannelSetup(device))
  457. return;
  458. switch(device->FmtChans)
  459. {
  460. case DevFmtMono:
  461. count = COUNTOF(MonoCfg);
  462. chanmap = MonoCfg;
  463. ambiscale = ZERO_ORDER_SCALE;
  464. break;
  465. case DevFmtStereo:
  466. count = COUNTOF(StereoCfg);
  467. chanmap = StereoCfg;
  468. ambiscale = FIRST_ORDER_SCALE;
  469. break;
  470. case DevFmtQuad:
  471. count = COUNTOF(QuadCfg);
  472. chanmap = QuadCfg;
  473. ambiscale = SECOND_ORDER_SCALE;
  474. break;
  475. case DevFmtX51:
  476. count = COUNTOF(X51SideCfg);
  477. chanmap = X51SideCfg;
  478. ambiscale = THIRD_ORDER_SCALE;
  479. break;
  480. case DevFmtX51Rear:
  481. count = COUNTOF(X51RearCfg);
  482. chanmap = X51RearCfg;
  483. ambiscale = THIRD_ORDER_SCALE;
  484. break;
  485. case DevFmtX61:
  486. count = COUNTOF(X61Cfg);
  487. chanmap = X61Cfg;
  488. ambiscale = THIRD_ORDER_SCALE;
  489. break;
  490. case DevFmtX71:
  491. count = COUNTOF(X71Cfg);
  492. chanmap = X71Cfg;
  493. ambiscale = THIRD_ORDER_SCALE;
  494. break;
  495. case DevFmtBFormat3D:
  496. count = COUNTOF(BFormat3D);
  497. chanmap = BFormat3D;
  498. ambiscale = 1.0f;
  499. break;
  500. }
  501. SetChannelMap(device, chanmap, count, ambiscale, AL_TRUE);
  502. }