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.
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.
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
30 #include "alAuxEffectSlot.h"
35 extern inline void CalcXYZCoeffs(ALfloat x
, ALfloat y
, ALfloat z
, ALfloat coeffs
[MAX_AMBI_COEFFS
]);
38 #define ZERO_ORDER_SCALE 0.0f
39 #define FIRST_ORDER_SCALE 1.0f
40 #define SECOND_ORDER_SCALE (1.0f / 1.22474f)
41 #define THIRD_ORDER_SCALE (1.0f / 1.30657f)
44 static const ALuint FuMa2ACN
[MAX_AMBI_COEFFS
] = {
63 /* NOTE: These are scale factors as applied to Ambisonics content. FuMa
64 * decoder coefficients should be divided by these values to get N3D decoder
67 static const ALfloat FuMa2N3DScale
[MAX_AMBI_COEFFS
] = {
68 1.414213562f
, /* ACN 0 (W), sqrt(2) */
69 1.732050808f
, /* ACN 1 (Y), sqrt(3) */
70 1.732050808f
, /* ACN 2 (Z), sqrt(3) */
71 1.732050808f
, /* ACN 3 (X), sqrt(3) */
72 1.936491673f
, /* ACN 4 (V), sqrt(15)/2 */
73 1.936491673f
, /* ACN 5 (T), sqrt(15)/2 */
74 2.236067978f
, /* ACN 6 (R), sqrt(5) */
75 1.936491673f
, /* ACN 7 (S), sqrt(15)/2 */
76 1.936491673f
, /* ACN 8 (U), sqrt(15)/2 */
77 2.091650066f
, /* ACN 9 (Q), sqrt(35/8) */
78 1.972026594f
, /* ACN 10 (O), sqrt(35)/3 */
79 2.231093404f
, /* ACN 11 (M), sqrt(224/45) */
80 2.645751311f
, /* ACN 12 (K), sqrt(7) */
81 2.231093404f
, /* ACN 13 (L), sqrt(224/45) */
82 1.972026594f
, /* ACN 14 (N), sqrt(35)/3 */
83 2.091650066f
, /* ACN 15 (P), sqrt(35/8) */
87 void CalcDirectionCoeffs(const ALfloat dir
[3], ALfloat coeffs
[MAX_AMBI_COEFFS
])
89 /* Convert from OpenAL coords to Ambisonics. */
95 coeffs
[0] = 1.0f
; /* ACN 0 = 1 */
97 coeffs
[1] = 1.732050808f
* y
; /* ACN 1 = sqrt(3) * Y */
98 coeffs
[2] = 1.732050808f
* z
; /* ACN 2 = sqrt(3) * Z */
99 coeffs
[3] = 1.732050808f
* x
; /* ACN 3 = sqrt(3) * X */
101 coeffs
[4] = 3.872983346f
* x
* y
; /* ACN 4 = sqrt(15) * X * Y */
102 coeffs
[5] = 3.872983346f
* y
* z
; /* ACN 5 = sqrt(15) * Y * Z */
103 coeffs
[6] = 1.118033989f
* (3.0f
*z
*z
- 1.0f
); /* ACN 6 = sqrt(5)/2 * (3*Z*Z - 1) */
104 coeffs
[7] = 3.872983346f
* x
* z
; /* ACN 7 = sqrt(15) * X * Z */
105 coeffs
[8] = 1.936491673f
* (x
*x
- y
*y
); /* ACN 8 = sqrt(15)/2 * (X*X - Y*Y) */
107 coeffs
[9] = 2.091650066f
* y
* (3.0f
*x
*x
- y
*y
); /* ACN 9 = sqrt(35/8) * Y * (3*X*X - Y*Y) */
108 coeffs
[10] = 10.246950766f
* z
* x
* y
; /* ACN 10 = sqrt(105) * Z * X * Y */
109 coeffs
[11] = 1.620185175f
* y
* (5.0f
*z
*z
- 1.0f
); /* ACN 11 = sqrt(21/8) * Y * (5*Z*Z - 1) */
110 coeffs
[12] = 1.322875656f
* z
* (5.0f
*z
*z
- 3.0f
); /* ACN 12 = sqrt(7)/2 * Z * (5*Z*Z - 3) */
111 coeffs
[13] = 1.620185175f
* x
* (5.0f
*z
*z
- 1.0f
); /* ACN 13 = sqrt(21/8) * X * (5*Z*Z - 1) */
112 coeffs
[14] = 5.123475383f
* z
* (x
*x
- y
*y
); /* ACN 14 = sqrt(105)/2 * Z * (X*X - Y*Y) */
113 coeffs
[15] = 2.091650066f
* x
* (x
*x
- 3.0f
*y
*y
); /* ACN 15 = sqrt(35/8) * X * (X*X - 3*Y*Y) */
116 void CalcAngleCoeffs(ALfloat angle
, ALfloat elevation
, ALfloat coeffs
[MAX_AMBI_COEFFS
])
119 sinf(angle
) * cosf(elevation
),
121 -cosf(angle
) * cosf(elevation
)
123 CalcDirectionCoeffs(dir
, coeffs
);
127 void ComputeAmbientGains(const ChannelConfig
*chancoeffs
, ALuint numchans
, ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
])
131 for(i
= 0;i
< numchans
;i
++)
133 // The W coefficients are based on a mathematical average of the
134 // output. The square root of the base average provides for a more
135 // perceptual average volume, better suited to non-directional gains.
136 gains
[i
] = sqrtf(chancoeffs
[i
][0]) * ingain
;
138 for(;i
< MAX_OUTPUT_CHANNELS
;i
++)
142 void ComputePanningGains(const ChannelConfig
*chancoeffs
, ALuint numchans
, const ALfloat coeffs
[MAX_AMBI_COEFFS
], ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
])
146 for(i
= 0;i
< numchans
;i
++)
149 for(j
= 0;j
< MAX_AMBI_COEFFS
;j
++)
150 gain
+= chancoeffs
[i
][j
]*coeffs
[j
];
151 gains
[i
] = gain
* ingain
;
153 for(;i
< MAX_OUTPUT_CHANNELS
;i
++)
157 void ComputeFirstOrderGains(const ChannelConfig
*chancoeffs
, ALuint numchans
, const ALfloat mtx
[4], ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
])
161 for(i
= 0;i
< numchans
;i
++)
165 gain
+= chancoeffs
[i
][j
] * mtx
[j
];
166 gains
[i
] = gain
* ingain
;
168 for(;i
< MAX_OUTPUT_CHANNELS
;i
++)
173 DECL_CONST
static inline const char *GetLabelFromChannel(enum Channel channel
)
177 case FrontLeft
: return "front-left";
178 case FrontRight
: return "front-right";
179 case FrontCenter
: return "front-center";
180 case LFE
: return "lfe";
181 case BackLeft
: return "back-left";
182 case BackRight
: return "back-right";
183 case BackCenter
: return "back-center";
184 case SideLeft
: return "side-left";
185 case SideRight
: return "side-right";
187 case BFormatW
: return "bformat-w";
188 case BFormatX
: return "bformat-x";
189 case BFormatY
: return "bformat-y";
190 case BFormatZ
: return "bformat-z";
192 case InvalidChannel
: break;
198 typedef struct ChannelMap
{
199 enum Channel ChanName
;
200 ChannelConfig Config
;
203 static void SetChannelMap(const enum Channel
*devchans
, ChannelConfig
*ambicoeffs
,
204 const ChannelMap
*chanmap
, size_t count
, ALuint
*outcount
,
210 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
&& devchans
[i
] != InvalidChannel
;i
++)
212 if(devchans
[i
] == LFE
)
214 for(j
= 0;j
< MAX_AMBI_COEFFS
;j
++)
215 ambicoeffs
[i
][j
] = 0.0f
;
219 for(j
= 0;j
< count
;j
++)
221 if(devchans
[i
] != chanmap
[j
].ChanName
)
226 /* Reformat FuMa -> ACN/N3D */
227 for(k
= 0;k
< MAX_AMBI_COEFFS
;++k
)
229 ALuint acn
= FuMa2ACN
[k
];
230 ambicoeffs
[i
][acn
] = chanmap
[j
].Config
[k
] / FuMa2N3DScale
[acn
];
235 for(k
= 0;k
< MAX_AMBI_COEFFS
;++k
)
236 ambicoeffs
[i
][k
] = chanmap
[j
].Config
[k
];
241 ERR("Failed to match %s channel (%u) in channel map\n", GetLabelFromChannel(devchans
[i
]), i
);
246 static bool LoadChannelSetup(ALCdevice
*device
)
248 static const enum Channel mono_chans
[1] = {
250 }, stereo_chans
[2] = {
251 FrontLeft
, FrontRight
253 FrontLeft
, FrontRight
,
255 }, surround51_chans
[5] = {
256 FrontLeft
, FrontRight
, FrontCenter
,
258 }, surround51rear_chans
[5] = {
259 FrontLeft
, FrontRight
, FrontCenter
,
261 }, surround61_chans
[6] = {
262 FrontLeft
, FrontRight
,
263 FrontCenter
, BackCenter
,
265 }, surround71_chans
[7] = {
266 FrontLeft
, FrontRight
, FrontCenter
,
270 ChannelMap chanmap
[MAX_OUTPUT_CHANNELS
];
271 const enum Channel
*channels
= NULL
;
272 const char *layout
= NULL
;
273 ALfloat ambiscale
= 1.0f
;
279 switch(device
->FmtChans
)
283 channels
= mono_chans
;
284 count
= COUNTOF(mono_chans
);
288 channels
= stereo_chans
;
289 count
= COUNTOF(stereo_chans
);
293 channels
= quad_chans
;
294 count
= COUNTOF(quad_chans
);
297 layout
= "surround51";
298 channels
= surround51_chans
;
299 count
= COUNTOF(surround51_chans
);
302 layout
= "surround51rear";
303 channels
= surround51rear_chans
;
304 count
= COUNTOF(surround51rear_chans
);
307 layout
= "surround61";
308 channels
= surround61_chans
;
309 count
= COUNTOF(surround61_chans
);
312 layout
= "surround71";
313 channels
= surround71_chans
;
314 count
= COUNTOF(surround71_chans
);
316 case DevFmtBFormat3D
:
328 snprintf(name
, sizeof(name
), "%s/type", layout
);
329 if(!ConfigValueStr(al_string_get_cstr(device
->DeviceName
), "layouts", name
, &type
))
332 if(sscanf(type
, " %31[^: ] : %d%c", name
, &order
, &eol
) != 2)
334 ERR("Invalid type value '%s' (expected name:order) for layout %s\n", type
, layout
);
338 if(strcasecmp(name
, "fuma") == 0)
340 else if(strcasecmp(name
, "n3d") == 0)
344 ERR("Unhandled type name '%s' (expected FuMa or N3D) for layout %s\n", name
, layout
);
349 ambiscale
= THIRD_ORDER_SCALE
;
351 ambiscale
= SECOND_ORDER_SCALE
;
353 ambiscale
= FIRST_ORDER_SCALE
;
355 ambiscale
= ZERO_ORDER_SCALE
;
358 ERR("Unhandled type order %d (expected 0, 1, 2, or 3) for layout %s\n", order
, layout
);
363 for(i
= 0;i
< count
;i
++)
365 float coeffs
[MAX_AMBI_COEFFS
] = {0.0f
};
366 const char *channame
;
373 chanmap
[i
].ChanName
= channels
[i
];
374 channame
= GetLabelFromChannel(channels
[i
]);
376 snprintf(chanlayout
, sizeof(chanlayout
), "%s/%s", layout
, channame
);
377 if(!ConfigValueStr(al_string_get_cstr(device
->DeviceName
), "layouts", chanlayout
, &value
))
379 ERR("Missing channel %s\n", channame
);
383 props
= sscanf(value
, " %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %c",
384 &coeffs
[0], &coeffs
[1], &coeffs
[2], &coeffs
[3],
385 &coeffs
[4], &coeffs
[5], &coeffs
[6], &coeffs
[7],
386 &coeffs
[8], &coeffs
[9], &coeffs
[10], &coeffs
[11],
387 &coeffs
[12], &coeffs
[13], &coeffs
[14], &coeffs
[15],
391 props
= sscanf(value
, " %f %f %f %f %f %f %f %f %f %c",
392 &coeffs
[0], &coeffs
[1], &coeffs
[2],
393 &coeffs
[3], &coeffs
[4], &coeffs
[5],
394 &coeffs
[6], &coeffs
[7], &coeffs
[8],
398 props
= sscanf(value
, " %f %f %f %f %c",
399 &coeffs
[0], &coeffs
[1],
400 &coeffs
[2], &coeffs
[3],
404 props
= sscanf(value
, " %f %c", &coeffs
[0], &eol
);
407 ERR("Failed to parse option %s properties\n", chanlayout
);
411 if(props
> (order
+1)*(order
+1))
413 ERR("Excess elements in option %s (expected %d)\n", chanlayout
, (order
+1)*(order
+1));
417 for(j
= 0;j
< MAX_AMBI_COEFFS
;++j
)
418 chanmap
[i
].Config
[j
] = coeffs
[j
];
420 SetChannelMap(device
->ChannelName
, device
->AmbiCoeffs
, chanmap
, count
,
421 &device
->NumChannels
, isfuma
);
422 device
->AmbiScale
= ambiscale
;
426 ALvoid
aluInitPanning(ALCdevice
*device
)
428 /* NOTE: These decoder coefficients are using FuMa channel ordering and
429 * normalization, since that's what was produced by the Ambisonic Decoder
430 * Toolbox. SetChannelMap will convert them to N3D.
432 static const ChannelMap MonoCfg
[1] = {
433 { FrontCenter
, { 1.414213562f
} },
435 { FrontLeft
, { 0.707106781f
, 0.0f
, 0.5f
, 0.0f
} },
436 { FrontRight
, { 0.707106781f
, 0.0f
, -0.5f
, 0.0f
} },
438 { FrontLeft
, { 0.353553f
, 0.306184f
, 0.306184f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.000000f
, 0.117186f
} },
439 { FrontRight
, { 0.353553f
, 0.306184f
, -0.306184f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.000000f
, -0.117186f
} },
440 { BackLeft
, { 0.353553f
, -0.306184f
, 0.306184f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.000000f
, -0.117186f
} },
441 { BackRight
, { 0.353553f
, -0.306184f
, -0.306184f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.000000f
, 0.117186f
} },
443 { 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
} },
444 { 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
} },
445 { 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
} },
446 { 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
} },
447 { 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
} },
449 { 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
} },
450 { 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
} },
451 { 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
} },
452 { 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
} },
453 { 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
} },
455 { 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
} },
456 { 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
} },
457 { 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
} },
458 { 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
} },
459 { 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
} },
460 { 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
} },
462 { 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
} },
463 { 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
} },
464 { 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
} },
465 { 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
} },
466 { 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
} },
467 { 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
} },
468 { 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
} },
470 { BFormatW
, { 1.0f
, 0.0f
, 0.0f
, 0.0f
} },
471 { BFormatX
, { 0.0f
, 1.0f
, 0.0f
, 0.0f
} },
472 { BFormatY
, { 0.0f
, 0.0f
, 1.0f
, 0.0f
} },
473 { BFormatZ
, { 0.0f
, 0.0f
, 0.0f
, 1.0f
} },
475 const ChannelMap
*chanmap
= NULL
;
476 ALfloat ambiscale
= 1.0f
;
479 device
->AmbiScale
= 1.0f
;
480 memset(device
->AmbiCoeffs
, 0, sizeof(device
->AmbiCoeffs
));
481 device
->NumChannels
= 0;
485 ALfloat (*coeffs_list
[4])[2];
486 ALuint
*delay_list
[4];
489 count
= COUNTOF(BFormat3D
);
493 for(i
= 0;i
< count
;i
++)
494 device
->ChannelName
[i
] = chanmap
[i
].ChanName
;
495 for(;i
< MAX_OUTPUT_CHANNELS
;i
++)
496 device
->ChannelName
[i
] = InvalidChannel
;
497 SetChannelMap(device
->ChannelName
, device
->AmbiCoeffs
, chanmap
, count
,
498 &device
->NumChannels
, AL_TRUE
);
499 device
->AmbiScale
= ambiscale
;
503 static const enum Channel inputs
[4] = { BFormatW
, BFormatX
, BFormatY
, BFormatZ
};
504 int chan
= GetChannelIdxByName(device
, inputs
[i
]);
505 coeffs_list
[i
] = device
->Hrtf_Params
[chan
].Coeffs
;
506 delay_list
[i
] = device
->Hrtf_Params
[chan
].Delay
;
508 GetBFormatHrtfCoeffs(device
->Hrtf
, 4, coeffs_list
, delay_list
);
513 if(LoadChannelSetup(device
))
516 switch(device
->FmtChans
)
519 count
= COUNTOF(MonoCfg
);
521 ambiscale
= ZERO_ORDER_SCALE
;
525 count
= COUNTOF(StereoCfg
);
527 ambiscale
= FIRST_ORDER_SCALE
;
531 count
= COUNTOF(QuadCfg
);
533 ambiscale
= SECOND_ORDER_SCALE
;
537 count
= COUNTOF(X51SideCfg
);
538 chanmap
= X51SideCfg
;
539 ambiscale
= THIRD_ORDER_SCALE
;
543 count
= COUNTOF(X51RearCfg
);
544 chanmap
= X51RearCfg
;
545 ambiscale
= THIRD_ORDER_SCALE
;
549 count
= COUNTOF(X61Cfg
);
551 ambiscale
= THIRD_ORDER_SCALE
;
555 count
= COUNTOF(X71Cfg
);
557 ambiscale
= THIRD_ORDER_SCALE
;
560 case DevFmtBFormat3D
:
561 count
= COUNTOF(BFormat3D
);
567 SetChannelMap(device
->ChannelName
, device
->AmbiCoeffs
, chanmap
, count
,
568 &device
->NumChannels
, AL_TRUE
);
569 device
->AmbiScale
= ambiscale
;
572 void aluInitEffectPanning(ALeffectslot
*slot
)
574 static const ChannelMap FirstOrderN3D
[4] = {
575 { BFormatW
, { 1.0f
, 0.0f
, 0.0f
, 0.0f
} },
576 { BFormatY
, { 0.0f
, 1.0f
, 0.0f
, 0.0f
} },
577 { BFormatZ
, { 0.0f
, 0.0f
, 1.0f
, 0.0f
} },
578 { BFormatX
, { 0.0f
, 0.0f
, 0.0f
, 1.0f
} },
580 static const enum Channel AmbiChannels
[MAX_OUTPUT_CHANNELS
] = {
581 BFormatW
, BFormatY
, BFormatZ
, BFormatX
, InvalidChannel
584 memset(slot
->AmbiCoeffs
, 0, sizeof(slot
->AmbiCoeffs
));
585 slot
->NumChannels
= 0;
587 SetChannelMap(AmbiChannels
, slot
->AmbiCoeffs
, FirstOrderN3D
, COUNTOF(FirstOrderN3D
),
588 &slot
->NumChannels
, AL_FALSE
);