aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2016-03-15 08:00:03 -0700
committerChris Robinson <[email protected]>2016-03-15 08:00:03 -0700
commit3a26d853ba02d970b3e31db85c8b4b32c14417b7 (patch)
tree2ffd47609948f07007f4e3fcdfc3dc27a7851a11
parent23bce59c663ad9227767d53325a33977675896d6 (diff)
Replace the custom layout options with an ambdec loader
The ambisonic layout options were never very good for clarity or flexibility. Hopefully using ambdec files will prove to be better.
-rw-r--r--Alc/panning.c216
1 files changed, 87 insertions, 129 deletions
diff --git a/Alc/panning.c b/Alc/panning.c
index df504292..e090461e 100644
--- a/Alc/panning.c
+++ b/Alc/panning.c
@@ -62,10 +62,31 @@ static const ALuint FuMa2ACN[MAX_AMBI_COEFFS] = {
9, /* Q */
};
-/* NOTE: These are scale factors as applied to Ambisonics content. FuMa
- * decoder coefficients should be divided by these values to get N3D decoder
- * coefficients.
+/* NOTE: These are scale factors as applied to Ambisonics content. Decoder
+ * coefficients should be divided by these values to get proper N3D scalings.
*/
+static const ALfloat UnitScale[MAX_AMBI_COEFFS] = {
+ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
+};
+static const ALfloat SN3D2N3DScale[MAX_AMBI_COEFFS] = {
+ 1.000000000f, /* ACN 0 (W), sqrt(1) */
+ 1.732050808f, /* ACN 1 (Y), sqrt(3) */
+ 1.732050808f, /* ACN 2 (Z), sqrt(3) */
+ 1.732050808f, /* ACN 3 (X), sqrt(3) */
+ 2.236067978f, /* ACN 4 (V), sqrt(5) */
+ 2.236067978f, /* ACN 5 (T), sqrt(5) */
+ 2.236067978f, /* ACN 6 (R), sqrt(5) */
+ 2.236067978f, /* ACN 7 (S), sqrt(5) */
+ 2.236067978f, /* ACN 8 (U), sqrt(5) */
+ 2.645751311f, /* ACN 9 (Q), sqrt(7) */
+ 2.645751311f, /* ACN 10 (O), sqrt(7) */
+ 2.645751311f, /* ACN 11 (M), sqrt(7) */
+ 2.645751311f, /* ACN 12 (K), sqrt(7) */
+ 2.645751311f, /* ACN 13 (L), sqrt(7) */
+ 2.645751311f, /* ACN 14 (N), sqrt(7) */
+ 2.645751311f, /* ACN 15 (P), sqrt(7) */
+};
static const ALfloat FuMa2N3DScale[MAX_AMBI_COEFFS] = {
1.414213562f, /* ACN 0 (W), sqrt(2) */
1.732050808f, /* ACN 1 (Y), sqrt(3) */
@@ -338,73 +359,37 @@ static bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALuint spe
static bool LoadChannelSetup(ALCdevice *device)
{
- static const enum Channel mono_chans[1] = {
- FrontCenter
- }, stereo_chans[2] = {
- FrontLeft, FrontRight
- }, quad_chans[4] = {
- FrontLeft, FrontRight,
- BackLeft, BackRight
- }, surround51_chans[5] = {
- FrontLeft, FrontRight, FrontCenter,
- SideLeft, SideRight
- }, surround51rear_chans[5] = {
- FrontLeft, FrontRight, FrontCenter,
- BackLeft, BackRight
- }, surround61_chans[6] = {
- FrontLeft, FrontRight,
- FrontCenter, BackCenter,
- SideLeft, SideRight
- }, surround71_chans[7] = {
- FrontLeft, FrontRight, FrontCenter,
- BackLeft, BackRight,
- SideLeft, SideRight
- };
ChannelMap chanmap[MAX_OUTPUT_CHANNELS];
- const enum Channel *channels = NULL;
+ ALuint speakermap[MAX_OUTPUT_CHANNELS];
+ const ALfloat *coeff_scale = UnitScale;
const char *layout = NULL;
ALfloat ambiscale = 1.0f;
- size_t count = 0;
- int isfuma;
- int order;
+ const char *fname;
+ AmbDecConf conf;
size_t i;
switch(device->FmtChans)
{
case DevFmtMono:
layout = "mono";
- channels = mono_chans;
- count = COUNTOF(mono_chans);
break;
case DevFmtStereo:
layout = "stereo";
- channels = stereo_chans;
- count = COUNTOF(stereo_chans);
break;
case DevFmtQuad:
layout = "quad";
- channels = quad_chans;
- count = COUNTOF(quad_chans);
break;
case DevFmtX51:
layout = "surround51";
- channels = surround51_chans;
- count = COUNTOF(surround51_chans);
break;
case DevFmtX51Rear:
layout = "surround51rear";
- channels = surround51rear_chans;
- count = COUNTOF(surround51rear_chans);
break;
case DevFmtX61:
layout = "surround61";
- channels = surround61_chans;
- count = COUNTOF(surround61_chans);
break;
case DevFmtX71:
layout = "surround71";
- channels = surround71_chans;
- count = COUNTOF(surround71_chans);
break;
case DevFmtBFormat3D:
break;
@@ -412,108 +397,81 @@ static bool LoadChannelSetup(ALCdevice *device)
if(!layout)
return false;
- else
+
+ if(!ConfigValueStr(al_string_get_cstr(device->DeviceName), "layouts", layout, &fname))
+ return false;
+
+ ambdec_init(&conf);
+ if(!ambdec_load(&conf, fname))
{
- char name[32] = {0};
- const char *type;
- char eol;
+ ERR("Failed to load layout file %s\n", fname);
+ goto fail;
+ }
- snprintf(name, sizeof(name), "%s/type", layout);
- if(!ConfigValueStr(al_string_get_cstr(device->DeviceName), "layouts", name, &type))
- return false;
+ if(conf.FreqBands != 1)
+ {
+ ERR("AmbDec layout file must be single-band (freq_bands = %u)\n", conf.FreqBands);
+ goto fail;
+ }
- if(sscanf(type, " %31[^: ] : %d%c", name, &order, &eol) != 2)
- {
- ERR("Invalid type value '%s' (expected name:order) for layout %s\n", type, layout);
- return false;
- }
+ if(!MakeSpeakerMap(device, &conf, speakermap))
+ goto fail;
- if(strcasecmp(name, "fuma") == 0)
- isfuma = 1;
- else if(strcasecmp(name, "n3d") == 0)
- isfuma = 0;
- else
- {
- ERR("Unhandled type name '%s' (expected FuMa or N3D) for layout %s\n", name, layout);
- return false;
- }
+ if(conf.ChanMask > 0x1ff)
+ ambiscale = THIRD_ORDER_SCALE;
+ else if(conf.ChanMask > 0xf)
+ ambiscale = SECOND_ORDER_SCALE;
+ else if(conf.ChanMask > 0x1)
+ ambiscale = FIRST_ORDER_SCALE;
+ else
+ ambiscale = 0.0f;
- if(order == 3)
- ambiscale = THIRD_ORDER_SCALE;
- else if(order == 2)
- ambiscale = SECOND_ORDER_SCALE;
- else if(order == 1)
- ambiscale = FIRST_ORDER_SCALE;
- else if(order == 0)
- ambiscale = ZERO_ORDER_SCALE;
- else
- {
- ERR("Unhandled type order %d (expected 0, 1, 2, or 3) for layout %s\n", order, layout);
- return false;
- }
- }
+ if(conf.CoeffScale == ADS_SN3D)
+ coeff_scale = SN3D2N3DScale;
+ else if(conf.CoeffScale == ADS_FuMa)
+ coeff_scale = FuMa2N3DScale;
- for(i = 0;i < count;i++)
+ for(i = 0;i < conf.NumSpeakers;i++)
{
- float coeffs[MAX_AMBI_COEFFS] = {0.0f};
- const char *channame;
- char chanlayout[32];
- const char *value;
- int props = 0;
- char eol = 0;
- int j;
-
- chanmap[i].ChanName = channels[i];
- channame = GetLabelFromChannel(channels[i]);
-
- snprintf(chanlayout, sizeof(chanlayout), "%s/%s", layout, channame);
- if(!ConfigValueStr(al_string_get_cstr(device->DeviceName), "layouts", chanlayout, &value))
+ ALuint chan = speakermap[i];
+ ALuint j, k = 0;
+
+ for(j = 0;j < MAX_AMBI_COEFFS;j++)
+ chanmap[i].Config[j] = 0.0f;
+
+ chanmap[i].ChanName = device->RealOut.ChannelName[chan];
+ for(j = 0;j < 1;j++)
{
- ERR("Missing channel %s\n", channame);
- return false;
+ if((conf.ChanMask&(1<<j)))
+ chanmap[i].Config[j] = conf.HFMatrix[i][k++] / coeff_scale[j] * conf.HFOrderGain[0];
}
- if(order == 3)
- props = sscanf(value, " %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %c",
- &coeffs[0], &coeffs[1], &coeffs[2], &coeffs[3],
- &coeffs[4], &coeffs[5], &coeffs[6], &coeffs[7],
- &coeffs[8], &coeffs[9], &coeffs[10], &coeffs[11],
- &coeffs[12], &coeffs[13], &coeffs[14], &coeffs[15],
- &eol
- );
- else if(order == 2)
- props = sscanf(value, " %f %f %f %f %f %f %f %f %f %c",
- &coeffs[0], &coeffs[1], &coeffs[2],
- &coeffs[3], &coeffs[4], &coeffs[5],
- &coeffs[6], &coeffs[7], &coeffs[8],
- &eol
- );
- else if(order == 1)
- props = sscanf(value, " %f %f %f %f %c",
- &coeffs[0], &coeffs[1],
- &coeffs[2], &coeffs[3],
- &eol
- );
- else if(order == 0)
- props = sscanf(value, " %f %c", &coeffs[0], &eol);
- if(props == 0)
+ for(;j < 4;j++)
{
- ERR("Failed to parse option %s properties\n", chanlayout);
- return false;
+ if((conf.ChanMask&(1<<j)))
+ chanmap[i].Config[j] = conf.HFMatrix[i][k++] / coeff_scale[j] * conf.HFOrderGain[1];
}
-
- if(props > (order+1)*(order+1))
+ for(;j < 9;j++)
{
- ERR("Excess elements in option %s (expected %d)\n", chanlayout, (order+1)*(order+1));
- return false;
+ if((conf.ChanMask&(1<<j)))
+ chanmap[i].Config[j] = conf.HFMatrix[i][k++] / coeff_scale[j] * conf.HFOrderGain[2];
+ }
+ for(;j < 16;j++)
+ {
+ if((conf.ChanMask&(1<<j)))
+ chanmap[i].Config[j] = conf.HFMatrix[i][k++] / coeff_scale[j] * conf.HFOrderGain[3];
}
-
- for(j = 0;j < MAX_AMBI_COEFFS;++j)
- chanmap[i].Config[j] = coeffs[j];
}
- SetChannelMap(device->Dry.ChannelName, device->Dry.AmbiCoeffs, chanmap, count,
- &device->Dry.NumChannels, isfuma);
+
+ SetChannelMap(device->Dry.ChannelName, device->Dry.AmbiCoeffs, chanmap, conf.NumSpeakers,
+ &device->Dry.NumChannels, AL_FALSE);
device->Dry.AmbiScale = ambiscale;
+
+ ambdec_deinit(&conf);
return true;
+
+fail:
+ ambdec_deinit(&conf);
+ return false;
}
ALvoid aluInitPanning(ALCdevice *device, const AmbDecConf *conf)