aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)