diff options
-rw-r--r-- | Alc/ALc.c | 15 | ||||
-rw-r--r-- | Alc/panning.c | 57 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 12 | ||||
-rw-r--r-- | alsoftrc.sample | 5 |
4 files changed, 63 insertions, 26 deletions
@@ -3427,6 +3427,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) device->FmtType = DevFmtTypeDefault; device->Frequency = DEFAULT_OUTPUT_RATE; device->IsHeadphones = AL_FALSE; + device->AmbiFmt = AmbiFormat_Default; device->NumUpdates = 4; device->UpdateSize = 1024; @@ -3544,6 +3545,18 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) } almtx_init(&device->BackendLock, almtx_plain); + if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt)) + { + if(strcasecmp(fmt, "fuma") == 0) + device->AmbiFmt = AmbiFormat_FuMa; + else if(strcasecmp(fmt, "acn+sn3d") == 0) + device->AmbiFmt = AmbiFormat_ACN_SN3D; + else if(strcasecmp(fmt, "acn+n3d") == 0) + device->AmbiFmt = AmbiFormat_ACN_N3D; + else + ERR("Unsupported ambi-format: %s\n", fmt); + } + if(DefaultEffect.type != AL_EFFECT_NULL) { device->DefaultSlot = (ALeffectslot*)device->_slot_mem; @@ -3706,6 +3719,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, return NULL; } device->IsHeadphones = AL_FALSE; + device->AmbiFmt = AmbiFormat_Default; device->UpdateSize = samples; device->NumUpdates = 1; @@ -3903,6 +3917,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN device->FmtChans = DevFmtChannelsDefault; device->FmtType = DevFmtTypeDefault; device->IsHeadphones = AL_FALSE; + device->AmbiFmt = AmbiFormat_Default; ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax); if(device->SourcesMax == 0) device->SourcesMax = 256; diff --git a/Alc/panning.c b/Alc/panning.c index 80909564..685c3de6 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -63,6 +63,10 @@ static const ALuint FuMa2ACN[MAX_AMBI_COEFFS] = { 15, /* P */ 9, /* Q */ }; +static const ALuint ACN2ACN[MAX_AMBI_COEFFS] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15 +}; /* NOTE: These are scale factors as applied to Ambisonics content. Decoder * coefficients should be divided by these values to get proper N3D scalings. @@ -596,44 +600,45 @@ static void InitPanning(ALCdevice *device) device->FOAOut.Ambi = device->Dry.Ambi; device->FOAOut.CoeffCount = device->Dry.CoeffCount; } - else if(device->FmtChans == DevFmtAmbi1) + else if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) { - count = 4; - for(i = 0;i < count;i++) - { - device->Dry.Ambi.Map[i].Scale = 1.0f/SN3D2N3DScale[i]; - device->Dry.Ambi.Map[i].Index = i; - } - device->Dry.CoeffCount = 0; - device->Dry.NumChannels = count; + const ALuint *acnmap = (device->AmbiFmt == AmbiFormat_FuMa) ? FuMa2ACN : ACN2ACN; + const ALfloat *n3dcale = (device->AmbiFmt == AmbiFormat_FuMa) ? FuMa2N3DScale : + (device->AmbiFmt == AmbiFormat_ACN_SN3D) ? SN3D2N3DScale : + /*(device->AmbiFmt == AmbiFormat_ACN_N3D) ?*/ UnitScale; - device->FOAOut.Ambi = device->Dry.Ambi; - device->FOAOut.CoeffCount = device->Dry.CoeffCount; - } - else if(device->FmtChans == DevFmtAmbi2 || device->FmtChans == DevFmtAmbi3) - { count = (device->FmtChans == DevFmtAmbi3) ? 16 : - (device->FmtChans == DevFmtAmbi2) ? 9 : 1; + (device->FmtChans == DevFmtAmbi2) ? 9 : + (device->FmtChans == DevFmtAmbi1) ? 4 : 1; for(i = 0;i < count;i++) { - device->Dry.Ambi.Map[i].Scale = 1.0f/SN3D2N3DScale[i]; - device->Dry.Ambi.Map[i].Index = i; + ALuint acn = acnmap[i]; + device->Dry.Ambi.Map[i].Scale = 1.0f/n3dcale[acn]; + device->Dry.Ambi.Map[i].Index = acn; } device->Dry.CoeffCount = 0; device->Dry.NumChannels = count; - /* FOA output is always ACN+N3D for higher-order ambisonic output. The - * upsampler expects this and will convert it for output. - */ - memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi)); - for(i = 0;i < 4;i++) + if(device->FmtChans == DevFmtAmbi1) { - device->FOAOut.Ambi.Map[i].Scale = 1.0f; - device->FOAOut.Ambi.Map[i].Index = i; + device->FOAOut.Ambi = device->Dry.Ambi; + device->FOAOut.CoeffCount = device->Dry.CoeffCount; } - device->FOAOut.CoeffCount = 0; + else + { + /* FOA output is always ACN+N3D for higher-order ambisonic output. + * The upsampler expects this and will convert it for output. + */ + memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi)); + for(i = 0;i < 4;i++) + { + device->FOAOut.Ambi.Map[i].Scale = 1.0f; + device->FOAOut.Ambi.Map[i].Index = i; + } + device->FOAOut.CoeffCount = 0; - ambiup_reset(device->AmbiUp, device); + ambiup_reset(device->AmbiUp, device); + } } else { diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index d07cb589..dff94487 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -463,6 +463,14 @@ inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType typ return ChannelsFromDevFmt(chans) * BytesFromDevFmt(type); } +enum AmbiFormat { + AmbiFormat_FuMa, /* FuMa channel order and normalization */ + AmbiFormat_ACN_SN3D, /* ACN channel order and SN3D normalization */ + AmbiFormat_ACN_N3D, /* ACN channel order and N3D normalization */ + + AmbiFormat_Default = AmbiFormat_ACN_SN3D +}; + extern const struct EffectList { const char *name; @@ -557,6 +565,10 @@ struct ALCdevice_struct enum DevFmtChannels FmtChans; enum DevFmtType FmtType; ALboolean IsHeadphones; + /* For DevFmtAmbi* output only, specifies the channel order and + * normalization. + */ + enum AmbiFormat AmbiFmt; al_string DeviceName; diff --git a/alsoftrc.sample b/alsoftrc.sample index ae965fba..444ebc6f 100644 --- a/alsoftrc.sample +++ b/alsoftrc.sample @@ -97,6 +97,11 @@ # disabled. #stereo-panning = uhj +## ambi-format: +# Specifies the channel order and normalization for the "ambi*" set of channel +# configurations. Valid settings are: fuma, acn+sn3d, acn+n3d +#ambi-format = acn+sn3d + ## hrtf: # Controls HRTF processing. These filters provide better spatialization of # sounds while using headphones, but do require a bit more CPU power. The |