aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2022-08-31 08:29:55 -0700
committerChris Robinson <[email protected]>2022-08-31 09:06:53 -0700
commitbf3f63fb4c5faa45784d7433d68b7013e29ee2c1 (patch)
tree14067933535ae809ab42c62e8c53d993df756fc7 /core
parent042c3d4a4241d03f7a2368d8744f93a3a4fb7565 (diff)
Don't apply the HF scaling for "upsampling" ambisonics
Not sure if this is best, but it fixes the issue of upsampling lower orders to higher orders multiple times (mixing lower order to higher order, cutting back to lower order by dropping the extra channels, then upsampling again, applying the HF scale multiple times and messing up the high frequencies/energy vector), as well as having too-strong high frequencies of upsampled content in general. As it is, with the new upsampling method, the lower order signal contributes to some higher order channels, which helps offset the high frequency scaling difference (except first- to second-order, which adds nothing).
Diffstat (limited to 'core')
-rw-r--r--core/ambidefs.cpp19
-rw-r--r--core/ambidefs.h14
-rw-r--r--core/voice.cpp56
3 files changed, 12 insertions, 77 deletions
diff --git a/core/ambidefs.cpp b/core/ambidefs.cpp
index a7248974..87df1932 100644
--- a/core/ambidefs.cpp
+++ b/core/ambidefs.cpp
@@ -370,22 +370,3 @@ const std::array<AmbiChannelFloatArray,9> AmbiScale::SecondOrder2DUp{CalcSecondO
const std::array<AmbiChannelFloatArray,16> AmbiScale::ThirdOrderUp{CalcThirdOrderUp()};
const std::array<AmbiChannelFloatArray,16> AmbiScale::ThirdOrder2DUp{CalcThirdOrder2DUp()};
const std::array<AmbiChannelFloatArray,25> AmbiScale::FourthOrder2DUp{CalcFourthOrder2DUp()};
-
-const std::array<float,MaxAmbiOrder+1> AmbiScale::DecoderHFScale1O{{
- 2.000000000e+00f, 1.154700538e+00f
-}};
-const std::array<float,MaxAmbiOrder+1> AmbiScale::DecoderHFScale1O2D{{
- 1.414213562e+00f, 1.000000000e+00f
-}};
-const std::array<float,MaxAmbiOrder+1> AmbiScale::DecoderHFScale2O{{
- 1.972026594e+00f, 1.527525232e+00f, 7.888106377e-01f
-}};
-const std::array<float,MaxAmbiOrder+1> AmbiScale::DecoderHFScale2O2D{{
- 1.414213562e+00f, 1.224744871e+00f, 7.071067812e-01f
-}};
-const std::array<float,MaxAmbiOrder+1> AmbiScale::DecoderHFScale3O{{
- 1.865086714e+00f, 1.606093894e+00f, 1.142055301e+00f, 5.683795528e-01f
-}};
-const std::array<float,MaxAmbiOrder+1> AmbiScale::DecoderHFScale3O2D{{
- 1.414213562e+00f, 1.306562965e+00f, 1.000000000e+00f, 5.411961001e-01f
-}};
diff --git a/core/ambidefs.h b/core/ambidefs.h
index 7f0f14ad..70fa23c5 100644
--- a/core/ambidefs.h
+++ b/core/ambidefs.h
@@ -113,20 +113,6 @@ struct AmbiScale {
return ret;
}
- /* Retrieves per-order HF scaling factors for "upsampling" ambisonic data. */
- static std::array<float,MaxAmbiOrder+1> GetHFOrderScales(const uint order, const bool is3D) noexcept
- {
- if(order >= 3) return is3D ? DecoderHFScale3O : DecoderHFScale3O2D;
- if(order == 2) return is3D ? DecoderHFScale2O : DecoderHFScale2O2D;
- return is3D ? DecoderHFScale1O : DecoderHFScale1O2D;
- }
-
- static const std::array<float,MaxAmbiOrder+1> DecoderHFScale1O;
- static const std::array<float,MaxAmbiOrder+1> DecoderHFScale1O2D;
- static const std::array<float,MaxAmbiOrder+1> DecoderHFScale2O;
- static const std::array<float,MaxAmbiOrder+1> DecoderHFScale2O2D;
- static const std::array<float,MaxAmbiOrder+1> DecoderHFScale3O;
- static const std::array<float,MaxAmbiOrder+1> DecoderHFScale3O2D;
static const std::array<std::array<float,MaxAmbiChannels>,4> FirstOrderUp;
static const std::array<std::array<float,MaxAmbiChannels>,4> FirstOrder2DUp;
diff --git a/core/voice.cpp b/core/voice.cpp
index 5263202e..15330012 100644
--- a/core/voice.cpp
+++ b/core/voice.cpp
@@ -892,52 +892,20 @@ void Voice::prepare(DeviceBase *device)
/* Make sure the sample history is cleared. */
std::fill(mPrevSamples.begin(), mPrevSamples.end(), HistoryLine{});
- /* Don't need to set the VoiceIsAmbisonic flag if the device is not higher
- * order than the voice. No HF scaling is necessary to mix it.
+ /* 2-channel UHJ needs different shelf filters. However, we can't just use
+ * different shelf filters after mixing it, given any old speaker setup the
+ * user has. To make this work, we apply the expected shelf filters for
+ * decoding UHJ2 to quad (only needs LF scaling), and act as if those 4
+ * quad channels are encoded right back into B-Format.
+ *
+ * This isn't perfect, but without an entirely separate and limited UHJ2
+ * path, it's better than nothing.
+ *
+ * Do not apply the shelf filter with UHJ output. UHJ2->B-Format->UHJ2 is
+ * identity, so don't mess with it.
*/
- if(mAmbiOrder && device->mAmbiOrder > mAmbiOrder)
+ if(mFmtChannels == FmtUHJ2 && !device->mUhjEncoder)
{
- const uint8_t *OrderFromChan{Is2DAmbisonic(mFmtChannels) ?
- AmbiIndex::OrderFrom2DChannel().data() : AmbiIndex::OrderFromChannel().data()};
- const auto scales = AmbiScale::GetHFOrderScales(mAmbiOrder, !Is2DAmbisonic(mFmtChannels));
-
- const BandSplitter splitter{device->mXOverFreq / static_cast<float>(device->Frequency)};
- for(auto &chandata : mChans)
- {
- chandata.mAmbiHFScale = scales[*(OrderFromChan++)];
- chandata.mAmbiLFScale = 1.0f;
- chandata.mAmbiSplitter = splitter;
- chandata.mDryParams = DirectParams{};
- chandata.mDryParams.NFCtrlFilter = device->mNFCtrlFilter;
- std::fill_n(chandata.mWetParams.begin(), device->NumAuxSends, SendParams{});
- }
- /* 2-channel UHJ needs different shelf filters. However, we can't just
- * use different shelf filters after mixing it and with any old speaker
- * setup the user has. To make this work, we apply the expected shelf
- * filters for decoding UHJ2 to quad (only needs LF scaling), and act
- * as if those 4 quad channels are encoded right back onto higher-order
- * B-Format.
- *
- * This isn't perfect, but without an entirely separate and limited
- * UHJ2 path, it's better than nothing.
- */
- if(mFmtChannels == FmtUHJ2)
- {
- mChans[0].mAmbiHFScale = 1.0f;
- mChans[0].mAmbiLFScale = UhjDecoder<UhjLengthStd>::sWLFScale;
- mChans[1].mAmbiHFScale = 1.0f;
- mChans[1].mAmbiLFScale = UhjDecoder<UhjLengthStd>::sXYLFScale;
- mChans[2].mAmbiHFScale = 1.0f;
- mChans[2].mAmbiLFScale = UhjDecoder<UhjLengthStd>::sXYLFScale;
- }
- mFlags.set(VoiceIsAmbisonic);
- }
- else if(mFmtChannels == FmtUHJ2 && !device->mUhjEncoder)
- {
- /* 2-channel UHJ with first-order output also needs the shelf filter
- * correction applied, except with UHJ output (UHJ2->B-Format->UHJ2 is
- * identity, so don't mess with it).
- */
const BandSplitter splitter{device->mXOverFreq / static_cast<float>(device->Frequency)};
for(auto &chandata : mChans)
{