diff options
author | Chris Robinson <[email protected]> | 2022-08-31 08:29:55 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2022-08-31 09:06:53 -0700 |
commit | bf3f63fb4c5faa45784d7433d68b7013e29ee2c1 (patch) | |
tree | 14067933535ae809ab42c62e8c53d993df756fc7 /core | |
parent | 042c3d4a4241d03f7a2368d8744f93a3a4fb7565 (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.cpp | 19 | ||||
-rw-r--r-- | core/ambidefs.h | 14 | ||||
-rw-r--r-- | core/voice.cpp | 56 |
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) { |