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
36 extern inline void CalcXYZCoeffs(ALfloat x
, ALfloat y
, ALfloat z
, ALfloat coeffs
[MAX_AMBI_COEFFS
]);
39 #define ZERO_ORDER_SCALE 0.0f
40 #define FIRST_ORDER_SCALE 1.0f
41 #define SECOND_ORDER_SCALE (1.0f / 1.22474f)
42 #define THIRD_ORDER_SCALE (1.0f / 1.30657f)
45 static const ALuint FuMa2ACN
[MAX_AMBI_COEFFS
] = {
64 /* NOTE: These are scale factors as applied to Ambisonics content. FuMa
65 * decoder coefficients should be divided by these values to get N3D decoder
68 static const ALfloat FuMa2N3DScale
[MAX_AMBI_COEFFS
] = {
69 1.414213562f
, /* ACN 0 (W), sqrt(2) */
70 1.732050808f
, /* ACN 1 (Y), sqrt(3) */
71 1.732050808f
, /* ACN 2 (Z), sqrt(3) */
72 1.732050808f
, /* ACN 3 (X), sqrt(3) */
73 1.936491673f
, /* ACN 4 (V), sqrt(15)/2 */
74 1.936491673f
, /* ACN 5 (T), sqrt(15)/2 */
75 2.236067978f
, /* ACN 6 (R), sqrt(5) */
76 1.936491673f
, /* ACN 7 (S), sqrt(15)/2 */
77 1.936491673f
, /* ACN 8 (U), sqrt(15)/2 */
78 2.091650066f
, /* ACN 9 (Q), sqrt(35/8) */
79 1.972026594f
, /* ACN 10 (O), sqrt(35)/3 */
80 2.231093404f
, /* ACN 11 (M), sqrt(224/45) */
81 2.645751311f
, /* ACN 12 (K), sqrt(7) */
82 2.231093404f
, /* ACN 13 (L), sqrt(224/45) */
83 1.972026594f
, /* ACN 14 (N), sqrt(35)/3 */
84 2.091650066f
, /* ACN 15 (P), sqrt(35/8) */
88 void CalcDirectionCoeffs(const ALfloat dir
[3], ALfloat coeffs
[MAX_AMBI_COEFFS
])
90 /* Convert from OpenAL coords to Ambisonics. */
96 coeffs
[0] = 1.0f
; /* ACN 0 = 1 */
98 coeffs
[1] = 1.732050808f
* y
; /* ACN 1 = sqrt(3) * Y */
99 coeffs
[2] = 1.732050808f
* z
; /* ACN 2 = sqrt(3) * Z */
100 coeffs
[3] = 1.732050808f
* x
; /* ACN 3 = sqrt(3) * X */
102 coeffs
[4] = 3.872983346f
* x
* y
; /* ACN 4 = sqrt(15) * X * Y */
103 coeffs
[5] = 3.872983346f
* y
* z
; /* ACN 5 = sqrt(15) * Y * Z */
104 coeffs
[6] = 1.118033989f
* (3.0f
*z
*z
- 1.0f
); /* ACN 6 = sqrt(5)/2 * (3*Z*Z - 1) */
105 coeffs
[7] = 3.872983346f
* x
* z
; /* ACN 7 = sqrt(15) * X * Z */
106 coeffs
[8] = 1.936491673f
* (x
*x
- y
*y
); /* ACN 8 = sqrt(15)/2 * (X*X - Y*Y) */
108 coeffs
[9] = 2.091650066f
* y
* (3.0f
*x
*x
- y
*y
); /* ACN 9 = sqrt(35/8) * Y * (3*X*X - Y*Y) */
109 coeffs
[10] = 10.246950766f
* z
* x
* y
; /* ACN 10 = sqrt(105) * Z * X * Y */
110 coeffs
[11] = 1.620185175f
* y
* (5.0f
*z
*z
- 1.0f
); /* ACN 11 = sqrt(21/8) * Y * (5*Z*Z - 1) */
111 coeffs
[12] = 1.322875656f
* z
* (5.0f
*z
*z
- 3.0f
); /* ACN 12 = sqrt(7)/2 * Z * (5*Z*Z - 3) */
112 coeffs
[13] = 1.620185175f
* x
* (5.0f
*z
*z
- 1.0f
); /* ACN 13 = sqrt(21/8) * X * (5*Z*Z - 1) */
113 coeffs
[14] = 5.123475383f
* z
* (x
*x
- y
*y
); /* ACN 14 = sqrt(105)/2 * Z * (X*X - Y*Y) */
114 coeffs
[15] = 2.091650066f
* x
* (x
*x
- 3.0f
*y
*y
); /* ACN 15 = sqrt(35/8) * X * (X*X - 3*Y*Y) */
117 void CalcAngleCoeffs(ALfloat angle
, ALfloat elevation
, ALfloat coeffs
[MAX_AMBI_COEFFS
])
120 sinf(angle
) * cosf(elevation
),
122 -cosf(angle
) * cosf(elevation
)
124 CalcDirectionCoeffs(dir
, coeffs
);
128 void ComputeAmbientGains(const ChannelConfig
*chancoeffs
, ALuint numchans
, ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
])
132 for(i
= 0;i
< numchans
;i
++)
134 // The W coefficients are based on a mathematical average of the
135 // output. The square root of the base average provides for a more
136 // perceptual average volume, better suited to non-directional gains.
137 gains
[i
] = sqrtf(chancoeffs
[i
][0]) * ingain
;
139 for(;i
< MAX_OUTPUT_CHANNELS
;i
++)
143 void ComputePanningGains(const ChannelConfig
*chancoeffs
, ALuint numchans
, const ALfloat coeffs
[MAX_AMBI_COEFFS
], ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
])
147 for(i
= 0;i
< numchans
;i
++)
150 for(j
= 0;j
< MAX_AMBI_COEFFS
;j
++)
151 gain
+= chancoeffs
[i
][j
]*coeffs
[j
];
152 gains
[i
] = gain
* ingain
;
154 for(;i
< MAX_OUTPUT_CHANNELS
;i
++)
158 void ComputeBFormatGains(const ChannelConfig
*chancoeffs
, ALuint numchans
, const ALfloat mtx
[4], ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
])
162 for(i
= 0;i
< numchans
;i
++)
166 gain
+= chancoeffs
[i
][j
] * mtx
[j
];
167 gains
[i
] = gain
* ingain
;
169 for(;i
< MAX_OUTPUT_CHANNELS
;i
++)
174 DECL_CONST
static inline const char *GetLabelFromChannel(enum Channel channel
)
178 case FrontLeft
: return "front-left";
179 case FrontRight
: return "front-right";
180 case FrontCenter
: return "front-center";
181 case LFE
: return "lfe";
182 case BackLeft
: return "back-left";
183 case BackRight
: return "back-right";
184 case BackCenter
: return "back-center";
185 case SideLeft
: return "side-left";
186 case SideRight
: return "side-right";
188 case BFormatW
: return "bformat-w";
189 case BFormatX
: return "bformat-x";
190 case BFormatY
: return "bformat-y";
191 case BFormatZ
: return "bformat-z";
193 case InvalidChannel
: break;
199 typedef struct ChannelMap
{
200 enum Channel ChanName
;
201 ChannelConfig Config
;
204 static void SetChannelMap(const enum Channel
*devchans
, ChannelConfig
*ambicoeffs
,
205 const ChannelMap
*chanmap
, size_t count
, ALuint
*outcount
,
211 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
&& devchans
[i
] != InvalidChannel
;i
++)
213 if(devchans
[i
] == LFE
)
215 for(j
= 0;j
< MAX_AMBI_COEFFS
;j
++)
216 ambicoeffs
[i
][j
] = 0.0f
;
220 for(j
= 0;j
< count
;j
++)
222 if(devchans
[i
] != chanmap
[j
].ChanName
)
227 /* Reformat FuMa -> ACN/N3D */
228 for(k
= 0;k
< MAX_AMBI_COEFFS
;++k
)
230 ALuint acn
= FuMa2ACN
[k
];
231 ambicoeffs
[i
][acn
] = chanmap
[j
].Config
[k
] / FuMa2N3DScale
[acn
];
236 for(k
= 0;k
< MAX_AMBI_COEFFS
;++k
)
237 ambicoeffs
[i
][k
] = chanmap
[j
].Config
[k
];
242 ERR("Failed to match %s channel (%u) in channel map\n", GetLabelFromChannel(devchans
[i
]), i
);
247 static bool LoadChannelSetup(ALCdevice
*device
)
249 static const enum Channel mono_chans
[1] = {
251 }, stereo_chans
[2] = {
252 FrontLeft
, FrontRight
254 FrontLeft
, FrontRight
,
256 }, surround51_chans
[5] = {
257 FrontLeft
, FrontRight
, FrontCenter
,
259 }, surround51rear_chans
[5] = {
260 FrontLeft
, FrontRight
, FrontCenter
,
262 }, surround61_chans
[6] = {
263 FrontLeft
, FrontRight
,
264 FrontCenter
, BackCenter
,
266 }, surround71_chans
[7] = {
267 FrontLeft
, FrontRight
, FrontCenter
,
271 ChannelMap chanmap
[MAX_OUTPUT_CHANNELS
];
272 const enum Channel
*channels
= NULL
;
273 const char *layout
= NULL
;
274 ALfloat ambiscale
= 1.0f
;
280 switch(device
->FmtChans
)
284 channels
= mono_chans
;
285 count
= COUNTOF(mono_chans
);
289 channels
= stereo_chans
;
290 count
= COUNTOF(stereo_chans
);
294 channels
= quad_chans
;
295 count
= COUNTOF(quad_chans
);
298 layout
= "surround51";
299 channels
= surround51_chans
;
300 count
= COUNTOF(surround51_chans
);
303 layout
= "surround51rear";
304 channels
= surround51rear_chans
;
305 count
= COUNTOF(surround51rear_chans
);
308 layout
= "surround61";
309 channels
= surround61_chans
;
310 count
= COUNTOF(surround61_chans
);
313 layout
= "surround71";
314 channels
= surround71_chans
;
315 count
= COUNTOF(surround71_chans
);
317 case DevFmtBFormat3D
:
329 snprintf(name
, sizeof(name
), "%s/type", layout
);
330 if(!ConfigValueStr(al_string_get_cstr(device
->DeviceName
), "layouts", name
, &type
))
333 if(sscanf(type
, " %31[^: ] : %d%c", name
, &order
, &eol
) != 2)
335 ERR("Invalid type value '%s' (expected name:order) for layout %s\n", type
, layout
);
339 if(strcasecmp(name
, "fuma") == 0)
341 else if(strcasecmp(name
, "n3d") == 0)
345 ERR("Unhandled type name '%s' (expected FuMa or N3D) for layout %s\n", name
, layout
);
350 ambiscale
= THIRD_ORDER_SCALE
;
352 ambiscale
= SECOND_ORDER_SCALE
;
354 ambiscale
= FIRST_ORDER_SCALE
;
356 ambiscale
= ZERO_ORDER_SCALE
;
359 ERR("Unhandled type order %d (expected 0, 1, 2, or 3) for layout %s\n", order
, layout
);
364 for(i
= 0;i
< count
;i
++)
366 float coeffs
[MAX_AMBI_COEFFS
] = {0.0f
};
367 const char *channame
;
374 chanmap
[i
].ChanName
= channels
[i
];
375 channame
= GetLabelFromChannel(channels
[i
]);
377 snprintf(chanlayout
, sizeof(chanlayout
), "%s/%s", layout
, channame
);
378 if(!ConfigValueStr(al_string_get_cstr(device
->DeviceName
), "layouts", chanlayout
, &value
))
380 ERR("Missing channel %s\n", channame
);
384 props
= sscanf(value
, " %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %c",
385 &coeffs
[0], &coeffs
[1], &coeffs
[2], &coeffs
[3],
386 &coeffs
[4], &coeffs
[5], &coeffs
[6], &coeffs
[7],
387 &coeffs
[8], &coeffs
[9], &coeffs
[10], &coeffs
[11],
388 &coeffs
[12], &coeffs
[13], &coeffs
[14], &coeffs
[15],
392 props
= sscanf(value
, " %f %f %f %f %f %f %f %f %f %c",
393 &coeffs
[0], &coeffs
[1], &coeffs
[2],
394 &coeffs
[3], &coeffs
[4], &coeffs
[5],
395 &coeffs
[6], &coeffs
[7], &coeffs
[8],
399 props
= sscanf(value
, " %f %f %f %f %c",
400 &coeffs
[0], &coeffs
[1],
401 &coeffs
[2], &coeffs
[3],
405 props
= sscanf(value
, " %f %c", &coeffs
[0], &eol
);
408 ERR("Failed to parse option %s properties\n", chanlayout
);
412 if(props
> (order
+1)*(order
+1))
414 ERR("Excess elements in option %s (expected %d)\n", chanlayout
, (order
+1)*(order
+1));
418 for(j
= 0;j
< MAX_AMBI_COEFFS
;++j
)
419 chanmap
[i
].Config
[j
] = coeffs
[j
];
421 SetChannelMap(device
->ChannelName
, device
->AmbiCoeffs
, chanmap
, count
,
422 &device
->NumChannels
, isfuma
);
423 device
->AmbiScale
= ambiscale
;
427 ALvoid
aluInitPanning(ALCdevice
*device
)
429 /* NOTE: These decoder coefficients are using FuMa channel ordering and
430 * normalization, since that's what was produced by the Ambisonic Decoder
431 * Toolbox. SetChannelMap will convert them to N3D.
433 static const ChannelMap MonoCfg
[1] = {
434 { FrontCenter
, { 1.414213562f
} },
436 { FrontLeft
, { 0.707106781f
, 0.0f
, 0.5f
, 0.0f
} },
437 { FrontRight
, { 0.707106781f
, 0.0f
, -0.5f
, 0.0f
} },
439 { FrontLeft
, { 0.353553f
, 0.306184f
, 0.306184f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.000000f
, 0.117186f
} },
440 { FrontRight
, { 0.353553f
, 0.306184f
, -0.306184f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.000000f
, -0.117186f
} },
441 { BackLeft
, { 0.353553f
, -0.306184f
, 0.306184f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.000000f
, -0.117186f
} },
442 { BackRight
, { 0.353553f
, -0.306184f
, -0.306184f
, 0.0f
, 0.0f
, 0.0f
, 0.0f
, 0.000000f
, 0.117186f
} },
444 { 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
} },
445 { 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
} },
446 { 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
} },
447 { 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
} },
448 { 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
} },
450 { 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
} },
451 { 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
} },
452 { 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
} },
453 { 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
} },
454 { 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
} },
456 { 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
} },
457 { 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
} },
458 { 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
} },
459 { 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
} },
460 { 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
} },
461 { 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
} },
463 { 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
} },
464 { 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
} },
465 { 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
} },
466 { 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
} },
467 { 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
} },
468 { 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
} },
469 { 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
} },
471 { BFormatW
, { 1.0f
, 0.0f
, 0.0f
, 0.0f
} },
472 { BFormatX
, { 0.0f
, 1.0f
, 0.0f
, 0.0f
} },
473 { BFormatY
, { 0.0f
, 0.0f
, 1.0f
, 0.0f
} },
474 { BFormatZ
, { 0.0f
, 0.0f
, 0.0f
, 1.0f
} },
476 const ChannelMap
*chanmap
= NULL
;
477 ALfloat ambiscale
= 1.0f
;
480 device
->AmbiScale
= 1.0f
;
481 memset(device
->AmbiCoeffs
, 0, sizeof(device
->AmbiCoeffs
));
482 device
->NumChannels
= 0;
486 ALfloat (*coeffs_list
[4])[2];
487 ALuint
*delay_list
[4];
490 count
= COUNTOF(BFormat3D
);
494 for(i
= 0;i
< count
;i
++)
495 device
->ChannelName
[i
] = chanmap
[i
].ChanName
;
496 for(;i
< MAX_OUTPUT_CHANNELS
;i
++)
497 device
->ChannelName
[i
] = InvalidChannel
;
498 SetChannelMap(device
->ChannelName
, device
->AmbiCoeffs
, chanmap
, count
,
499 &device
->NumChannels
, AL_TRUE
);
500 device
->AmbiScale
= ambiscale
;
504 static const enum Channel inputs
[4] = { BFormatW
, BFormatX
, BFormatY
, BFormatZ
};
505 int chan
= GetChannelIdxByName(device
, inputs
[i
]);
506 coeffs_list
[i
] = device
->Hrtf_Params
[chan
].Coeffs
;
507 delay_list
[i
] = device
->Hrtf_Params
[chan
].Delay
;
509 GetBFormatHrtfCoeffs(device
->Hrtf
, 4, coeffs_list
, delay_list
);
514 if(LoadChannelSetup(device
))
517 switch(device
->FmtChans
)
520 count
= COUNTOF(MonoCfg
);
522 ambiscale
= ZERO_ORDER_SCALE
;
526 count
= COUNTOF(StereoCfg
);
528 ambiscale
= FIRST_ORDER_SCALE
;
532 count
= COUNTOF(QuadCfg
);
534 ambiscale
= SECOND_ORDER_SCALE
;
538 count
= COUNTOF(X51SideCfg
);
539 chanmap
= X51SideCfg
;
540 ambiscale
= THIRD_ORDER_SCALE
;
544 count
= COUNTOF(X51RearCfg
);
545 chanmap
= X51RearCfg
;
546 ambiscale
= THIRD_ORDER_SCALE
;
550 count
= COUNTOF(X61Cfg
);
552 ambiscale
= THIRD_ORDER_SCALE
;
556 count
= COUNTOF(X71Cfg
);
558 ambiscale
= THIRD_ORDER_SCALE
;
561 case DevFmtBFormat3D
:
562 count
= COUNTOF(BFormat3D
);
568 SetChannelMap(device
->ChannelName
, device
->AmbiCoeffs
, chanmap
, count
,
569 &device
->NumChannels
, AL_TRUE
);
570 device
->AmbiScale
= ambiscale
;