Use the AmbiUpsampler with higher order basic and custom panning

Also allocate the BFormatDec and AmbiUpsampler where they're (re)set.
This commit is contained in:
Chris Robinson
2018-12-17 07:29:55 -08:00
parent 59013b5cb5
commit 5243516149
2 changed files with 47 additions and 96 deletions
-17
View File
@@ -9,23 +9,6 @@
struct AmbDecConf;
/* These are the necessary scales for first-order HF responses to play over
* higher-order 2D (non-periphonic) decoders.
*/
#define W_SCALE_2H0P 1.224744871f /* sqrt(1.5) */
#define XYZ_SCALE_2H0P 1.0f
#define W_SCALE_3H0P 1.414213562f /* sqrt(2) */
#define XYZ_SCALE_3H0P 1.082392196f
/* These are the necessary scales for first-order HF responses to play over
* higher-order 3D (periphonic) decoders.
*/
#define W_SCALE_2H2P 1.341640787f /* sqrt(1.8) */
#define XYZ_SCALE_2H2P 1.0f
#define W_SCALE_3H3P 1.695486018f
#define XYZ_SCALE_3H3P 1.136697713f
class BFormatDec {
public:
static constexpr size_t sNumBands{2};
+47 -79
View File
@@ -435,6 +435,7 @@ void InitPanning(ALCdevice *device)
device->FOAOut.CoeffCount = 0;
device->FOAOut.NumChannels = 4;
device->AmbiUp.reset(new AmbiUpsampler{});
device->AmbiUp->reset(device);
}
@@ -453,20 +454,25 @@ void InitPanning(ALCdevice *device)
chanmap, count, &device->Dry.NumChannels);
device->Dry.CoeffCount = coeffcount;
const ALfloat w_scale{(device->Dry.CoeffCount > 9) ? W_SCALE_3H0P :
(device->Dry.CoeffCount > 4) ? W_SCALE_2H0P : 1.0f};
const ALfloat xyz_scale{(device->Dry.CoeffCount > 9) ? XYZ_SCALE_3H0P :
(device->Dry.CoeffCount > 4) ? XYZ_SCALE_2H0P : 1.0f};
device->FOAOut.Ambi = AmbiConfig{};
for(ALsizei i{0};i < device->Dry.NumChannels;i++)
if(coeffcount <= 4)
{
device->FOAOut.Ambi.Coeffs[i][0] = device->Dry.Ambi.Coeffs[i][0] * w_scale;
for(ALsizei j{1};j < 4;j++)
device->FOAOut.Ambi.Coeffs[i][j] = device->Dry.Ambi.Coeffs[i][j] * xyz_scale;
device->FOAOut.Ambi = device->Dry.Ambi;
device->FOAOut.CoeffCount = device->Dry.CoeffCount;
device->FOAOut.NumChannels = 0;
}
else
{
device->FOAOut.Ambi = AmbiConfig{};
auto acnmap_end = std::begin(AmbiIndex::ACN2ACN) + 4;
std::transform(std::begin(AmbiIndex::ACN2ACN), acnmap_end, std::begin(device->FOAOut.Ambi.Map),
[](const ALsizei &acn) noexcept { return BFChannelConfig{1.0f, acn}; }
);
device->FOAOut.CoeffCount = 0;
device->FOAOut.NumChannels = 4;
device->AmbiUp.reset(new AmbiUpsampler{});
device->AmbiUp->reset(device);
}
device->FOAOut.CoeffCount = 4;
device->FOAOut.NumChannels = 0;
}
device->RealOut.NumChannels = 0;
}
@@ -477,34 +483,6 @@ void InitCustomPanning(ALCdevice *device, const AmbDecConf *conf, const ALsizei
ERR("Basic renderer uses the high-frequency matrix as single-band (xover_freq = %.0fhz)\n",
conf->XOverFreq);
ALfloat w_scale{1.0f}, xyz_scale{1.0f};
if((conf->ChanMask&AMBI_PERIPHONIC_MASK))
{
if(conf->ChanMask > AMBI_2ORDER_MASK)
{
w_scale = W_SCALE_3H3P;
xyz_scale = XYZ_SCALE_3H3P;
}
else if(conf->ChanMask > AMBI_1ORDER_MASK)
{
w_scale = W_SCALE_2H2P;
xyz_scale = XYZ_SCALE_2H2P;
}
}
else
{
if(conf->ChanMask > AMBI_2ORDER_MASK)
{
w_scale = W_SCALE_3H0P;
xyz_scale = XYZ_SCALE_3H0P;
}
else if(conf->ChanMask > AMBI_1ORDER_MASK)
{
w_scale = W_SCALE_2H0P;
xyz_scale = XYZ_SCALE_2H0P;
}
}
const ALfloat (&coeff_scale)[MAX_AMBI_COEFFS] = GetAmbiScales(conf->CoeffScale);
ChannelMap chanmap[MAX_OUTPUT_CHANNELS]{};
for(size_t i{0u};i < conf->Speakers.size();i++)
@@ -528,15 +506,27 @@ void InitCustomPanning(ALCdevice *device, const AmbDecConf *conf, const ALsizei
device->Dry.CoeffCount = (conf->ChanMask > AMBI_2ORDER_MASK) ? 16 :
(conf->ChanMask > AMBI_1ORDER_MASK) ? 9 : 4;
device->FOAOut.Ambi = AmbiConfig{};
for(ALsizei i{0};i < device->Dry.NumChannels;i++)
if(conf->ChanMask <= AMBI_1ORDER_MASK)
{
device->FOAOut.Ambi.Coeffs[i][0] = device->Dry.Ambi.Coeffs[i][0] * w_scale;
for(ALsizei j{1};j < 4;j++)
device->FOAOut.Ambi.Coeffs[i][j] = device->Dry.Ambi.Coeffs[i][j] * xyz_scale;
device->FOAOut.Ambi = device->Dry.Ambi;
device->FOAOut.CoeffCount = device->Dry.CoeffCount;
device->FOAOut.NumChannels = 0;
}
else
{
static constexpr int map[4] = { 0, 1, 2, 3 };
static constexpr ALsizei count{4};
device->FOAOut.Ambi = AmbiConfig{};
std::transform(std::begin(map), std::begin(map)+count, std::begin(device->FOAOut.Ambi.Map),
[](const ALsizei &index) noexcept { return BFChannelConfig{1.0f, index}; }
);
device->FOAOut.CoeffCount = 0;
device->FOAOut.NumChannels = count;
device->AmbiUp.reset(new AmbiUpsampler{});
device->AmbiUp->reset(device);
}
device->FOAOut.CoeffCount = 4;
device->FOAOut.NumChannels = 0;
device->RealOut.NumChannels = 0;
@@ -576,6 +566,7 @@ void InitHQPanning(ALCdevice *device, const AmbDecConf *conf, const ALsizei (&sp
(conf->ChanMask > AMBI_1ORDER_MASK) ? "second" : "first",
(conf->ChanMask&AMBI_PERIPHONIC_MASK) ? " periphonic" : ""
);
device->AmbiDecoder.reset(new BFormatDec{});
device->AmbiDecoder->reset(conf, count, device->Frequency, speakermap);
if(conf->ChanMask <= AMBI_1ORDER_MASK)
@@ -702,8 +693,13 @@ void InitHrtfPanning(ALCdevice *device)
static_assert(COUNTOF(AmbiPoints) == COUNTOF(AmbiMatrixFOA), "FOA Ambisonic HRTF mismatch");
static_assert(COUNTOF(AmbiPoints) == COUNTOF(AmbiMatrixHOA), "HOA Ambisonic HRTF mismatch");
if(device->AmbiUp)
/* Don't bother with HOA when using full HRTF rendering. Nothing needs it,
* and it eases the CPU/memory load.
*/
if(device->Render_Mode != HrtfRender)
{
device->AmbiUp.reset(new AmbiUpsampler{});
AmbiMatrix = AmbiMatrixHOA;
AmbiOrderHFGain = AmbiOrderHFGainHOA;
count = static_cast<ALsizei>(COUNTOF(IndexMap));
@@ -909,6 +905,8 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, HrtfRequestMode hrtf_appr
device->AvgSpeakerDist = 0.0f;
device->ChannelDelay.clear();
device->AmbiDecoder = nullptr;
device->AmbiUp = nullptr;
device->Stablizer = nullptr;
if(device->FmtChans != DevFmtStereo)
@@ -956,24 +954,9 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, HrtfRequestMode hrtf_appr
}
}
if(pconf && GetConfigValueBool(devname, "decoder", "hq-mode", 0))
{
device->AmbiUp = nullptr;
if(!device->AmbiDecoder)
device->AmbiDecoder.reset(new BFormatDec{});
}
else
{
device->AmbiDecoder = nullptr;
if(device->FmtChans != DevFmtAmbi3D || device->mAmbiOrder < 2)
device->AmbiUp = nullptr;
else if(!device->AmbiUp)
device->AmbiUp.reset(new AmbiUpsampler{});
}
if(!pconf)
InitPanning(device);
else if(device->AmbiDecoder)
else if(GetConfigValueBool(devname, "decoder", "hq-mode", 0))
InitHQPanning(device, pconf, speakermap);
else
InitCustomPanning(device, pconf, speakermap);
@@ -1108,19 +1091,6 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, HrtfRequestMode hrtf_appr
ERR("Unexpected hrtf-mode: %s\n", mode);
}
if(device->Render_Mode == HrtfRender)
{
/* Don't bother with HOA when using full HRTF rendering. Nothing
* needs it, and it eases the CPU/memory load.
*/
device->AmbiUp = nullptr;
}
else
{
if(!device->AmbiUp)
device->AmbiUp.reset(new AmbiUpsampler{});
}
TRACE("%s HRTF rendering enabled, using \"%s\"\n",
((device->Render_Mode == HrtfRender) ? "Full" : "Basic"), device->HrtfName.c_str()
);
@@ -1137,8 +1107,6 @@ no_hrtf:
device->Render_Mode = StereoPair;
device->AmbiUp = nullptr;
int bs2blevel{((headphones && hrtf_appreq != Hrtf_Disable) ||
(hrtf_appreq == Hrtf_Enable)) ? 5 : 0};
if(device->Type != Loopback)