diff options
author | Chris Robinson <[email protected]> | 2016-03-15 08:00:03 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2016-03-15 08:00:03 -0700 |
commit | 3a26d853ba02d970b3e31db85c8b4b32c14417b7 (patch) | |
tree | 2ffd47609948f07007f4e3fcdfc3dc27a7851a11 | |
parent | 23bce59c663ad9227767d53325a33977675896d6 (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.c | 216 |
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) |