static void SetChannelMap(ALCdevice *device, const ChannelMap *chanmap, size_t count, ALfloat ambiscale) { size_t i, j, k; device->AmbiScale = ambiscale; for(i = 0;i < MAX_OUTPUT_CHANNELS && device->ChannelName[i] != InvalidChannel;i++) { if(device->ChannelName[i] == LFE) { for(j = 0;j < MAX_AMBI_COEFFS;j++) device->AmbiCoeffs[i][j] = 0.0f; continue; } for(j = 0;j < count;j++) { if(device->ChannelName[i] == chanmap[j].ChanName) { for(k = 0;k < MAX_AMBI_COEFFS;++k) device->AmbiCoeffs[i][k] = chanmap[j].Config[k]; break; } } if(j == count) ERR("Failed to match %s channel ("SZFMT") in config\n", GetLabelFromChannel(device->ChannelName[i]), i); } device->NumChannels = i; }
static void SetChannelMap(const enum Channel *devchans, ChannelConfig *ambicoeffs, const ChannelMap *chanmap, size_t count, ALuint *outcount, ALboolean isfuma) { size_t j, k; ALuint i; for(i = 0;i < MAX_OUTPUT_CHANNELS && devchans[i] != InvalidChannel;i++) { if(devchans[i] == LFE) { for(j = 0;j < MAX_AMBI_COEFFS;j++) ambicoeffs[i][j] = 0.0f; continue; } for(j = 0;j < count;j++) { if(devchans[i] != chanmap[j].ChanName) continue; if(isfuma) { /* Reformat FuMa -> ACN/N3D */ for(k = 0;k < MAX_AMBI_COEFFS;++k) { ALuint acn = FuMa2ACN[k]; ambicoeffs[i][acn] = chanmap[j].Config[k] / FuMa2N3DScale[acn]; } } else { for(k = 0;k < MAX_AMBI_COEFFS;++k) ambicoeffs[i][k] = chanmap[j].Config[k]; } break; } if(j == count) ERR("Failed to match %s channel (%u) in channel map\n", GetLabelFromChannel(devchans[i]), i); } *outcount = i; }
static void SetChannelMap(ALCdevice *device, const ChannelMap *chanmap, size_t count, ALfloat ambiscale, ALboolean isfuma) { size_t j, k; ALuint i; device->AmbiScale = ambiscale; for(i = 0;i < MAX_OUTPUT_CHANNELS && device->ChannelName[i] != InvalidChannel;i++) { if(device->ChannelName[i] == LFE) { for(j = 0;j < MAX_AMBI_COEFFS;j++) device->AmbiCoeffs[i][j] = 0.0f; continue; } for(j = 0;j < count;j++) { if(device->ChannelName[i] == chanmap[j].ChanName) { if(isfuma) { /* Reformat FuMa -> ACN/N3D */ for(k = 0;k < MAX_AMBI_COEFFS;++k) { ALuint acn = FuMa2ACN[k]; device->AmbiCoeffs[i][acn] = chanmap[j].Config[k] / FuMa2N3DScale[acn]; } } else { for(k = 0;k < MAX_AMBI_COEFFS;++k) device->AmbiCoeffs[i][k] = chanmap[j].Config[k]; } break; } } if(j == count) ERR("Failed to match %s channel (%u) in config\n", GetLabelFromChannel(device->ChannelName[i]), i); } device->NumChannels = i; }
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; const char *layout = NULL; ALfloat ambiscale = 1.0f; size_t count = 0; int isfuma; int order; 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; } if(!layout) return false; else { char name[32] = {0}; const char *type; char eol; snprintf(name, sizeof(name), "%s/type", layout); if(!ConfigValueStr(al_string_get_cstr(device->DeviceName), "layouts", name, &type)) return false; 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(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(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; } } for(i = 0;i < count;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)) { ERR("Missing channel %s\n", channame); return false; } 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) { ERR("Failed to parse option %s properties\n", chanlayout); return false; } if(props > (order+1)*(order+1)) { ERR("Excess elements in option %s (expected %d)\n", chanlayout, (order+1)*(order+1)); return false; } if(isfuma) { /* Reorder FuMa -> ACN */ for(j = 0;j < MAX_AMBI_COEFFS;++j) chanmap[i].Config[FuMa2ACN[j]] = coeffs[j]; } else { /* Rescale N3D -> FuMa */ for(j = 0;j < MAX_AMBI_COEFFS;++j) chanmap[i].Config[j] = coeffs[j] * N3D2FuMaScale[j]; } } SetChannelMap(device, chanmap, count, ambiscale); return true; }