diff options
author | Chris Robinson <[email protected]> | 2021-07-13 06:31:13 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2021-07-13 06:31:13 -0700 |
commit | d998c03a2761920b1edc4f1da09a04072af83d7e (patch) | |
tree | ede3bda406061fe8b47072b3d459b0ead2e879e8 /core | |
parent | fb2cb2bd064c681defda5f1019faa5189ec3bb34 (diff) |
Add a UHJ-specific coefficient scaling array
Diffstat (limited to 'core')
-rw-r--r-- | core/ambidefs.h | 12 | ||||
-rw-r--r-- | core/buffer_storage.h | 1 | ||||
-rw-r--r-- | core/uhjfilter.cpp | 20 | ||||
-rw-r--r-- | core/uhjfilter.h | 5 |
4 files changed, 23 insertions, 15 deletions
diff --git a/core/ambidefs.h b/core/ambidefs.h index 22739359..3339c28f 100644 --- a/core/ambidefs.h +++ b/core/ambidefs.h @@ -97,6 +97,18 @@ struct AmbiScale { }}; return ret; } + static auto& FromUHJ() noexcept + { + static constexpr const std::array<float,MaxAmbiChannels> ret{{ + 1.000000000f, /* ACN 0 (W), sqrt(1) */ + 1.224744916f, /* ACN 1 (Y), sqrt(3/2) */ + 1.224744916f, /* ACN 2 (Z), sqrt(3/2) */ + 1.224744916f, /* ACN 3 (X), sqrt(3/2) */ + /* Higher orders not relevant for UHJ. */ + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + }}; + return ret; + } /* Retrieves per-order HF scaling factors for "upsampling" ambisonic data. */ static std::array<float,MaxAmbiOrder+1> GetHFOrderScales(const uint in_order, diff --git a/core/buffer_storage.h b/core/buffer_storage.h index 59280354..64943453 100644 --- a/core/buffer_storage.h +++ b/core/buffer_storage.h @@ -40,6 +40,7 @@ enum class AmbiScaling : unsigned char { FuMa, SN3D, N3D, + UHJ, }; uint BytesFromFmt(FmtType type) noexcept; diff --git a/core/uhjfilter.cpp b/core/uhjfilter.cpp index f1af4b94..f4ef61f8 100644 --- a/core/uhjfilter.cpp +++ b/core/uhjfilter.cpp @@ -43,9 +43,6 @@ const PhaseShifterT<UhjEncoder::sFilterDelay*2> PShift{}; void UhjEncoder::encode(const FloatBufferSpan LeftOut, const FloatBufferSpan RightOut, const FloatBufferLine *InSamples, const size_t SamplesToDo) { - /* Given FuMa input, a +3dB boost is needed for the expected levels. */ - static constexpr float sqrt2{1.41421356237f}; - ASSUME(SamplesToDo > 0); float *RESTRICT left{al::assume_aligned<16>(LeftOut.data())}; @@ -63,14 +60,14 @@ void UhjEncoder::encode(const FloatBufferSpan LeftOut, const FloatBufferSpan Rig auto miditer = mS.begin() + sFilterDelay; std::transform(winput, winput+SamplesToDo, xinput, miditer, [](const float w, const float x) noexcept -> float - { return 0.9396926f*sqrt2*w + 0.1855740f*sqrt2*x; }); + { return 0.9396926f*w + 0.1855740f*x; }); for(size_t i{0};i < SamplesToDo;++i,++miditer) *miditer += left[i] + right[i]; /* D = 0.6554516*Y */ auto sideiter = mD.begin() + sFilterDelay; std::transform(yinput, yinput+SamplesToDo, sideiter, - [](const float y) noexcept -> float { return 0.6554516f*sqrt2*y; }); + [](const float y) noexcept -> float { return 0.6554516f*y; }); for(size_t i{0};i < SamplesToDo;++i,++sideiter) *sideiter += left[i] - right[i]; @@ -78,7 +75,7 @@ void UhjEncoder::encode(const FloatBufferSpan LeftOut, const FloatBufferSpan Rig auto tmpiter = std::copy(mWXHistory.cbegin(), mWXHistory.cend(), mTemp.begin()); std::transform(winput, winput+SamplesToDo, xinput, tmpiter, [](const float w, const float x) noexcept -> float - { return -0.3420201f*sqrt2*w + 0.5098604f*sqrt2*x; }); + { return -0.3420201f*w + 0.5098604f*x; }); std::copy_n(mTemp.cbegin()+SamplesToDo, mWXHistory.size(), mWXHistory.begin()); PShift.processAccum({mD.data(), SamplesToDo}, mTemp.data()); @@ -113,9 +110,6 @@ void UhjEncoder::encode(const FloatBufferSpan LeftOut, const FloatBufferSpan Rig void UhjDecoder::decode(const al::span<BufferLine> samples, const size_t offset, const size_t samplesToDo, const size_t forwardSamples) { - /* A -3dB attenuation is needed for FuMa output. */ - static constexpr float sqrt1_2{0.707106781187f}; - ASSUME(samplesToDo > 0); { @@ -125,15 +119,15 @@ void UhjDecoder::decode(const al::span<BufferLine> samples, const size_t offset, /* S = Left + Right */ for(size_t i{0};i < samplesToDo+sFilterDelay;++i) - mS[i] = (left[i] + right[i]) * sqrt1_2; + mS[i] = left[i] + right[i]; /* D = Left - Right */ for(size_t i{0};i < samplesToDo+sFilterDelay;++i) - mD[i] = (left[i] - right[i]) * sqrt1_2; + mD[i] = left[i] - right[i]; /* T */ for(size_t i{0};i < samplesToDo+sFilterDelay;++i) - mT[i] = t[i] * sqrt1_2; + mT[i] = t[i]; } float *RESTRICT woutput{al::assume_aligned<16>(samples[0].data() + offset)}; @@ -169,6 +163,6 @@ void UhjDecoder::decode(const al::span<BufferLine> samples, const size_t offset, float *RESTRICT zoutput{samples[3].data() + offset}; /* Z = 1.023332*Q */ for(size_t i{0};i < samplesToDo;++i) - zoutput[i] = 1.023332f*sqrt1_2*zoutput[i]; + zoutput[i] = 1.023332f*zoutput[i]; } } diff --git a/core/uhjfilter.h b/core/uhjfilter.h index c04913b4..e535cfb7 100644 --- a/core/uhjfilter.h +++ b/core/uhjfilter.h @@ -25,7 +25,8 @@ struct UhjEncoder { /** * Encodes a 2-channel UHJ (stereo-compatible) signal from a B-Format input - * signal. The input must use FuMa channel ordering and scaling. + * signal. The input must use FuMa channel ordering and UHJ scaling (FuMa + * with an additional +3dB boost). */ void encode(const FloatBufferSpan LeftOut, const FloatBufferSpan RightOut, const FloatBufferLine *InSamples, const size_t SamplesToDo); @@ -51,7 +52,7 @@ struct UhjDecoder { /** * Decodes a 3- or 4-channel UHJ signal into a B-Format signal with FuMa - * channel ordering and scaling. For 3-channel, the 3rd channel may be + * channel ordering and UHJ scaling. For 3-channel, the 3rd channel may be * attenuated by 'n', where 0 <= n <= 1. So 2-channel UHJ can be decoded by * leaving the 3rd channel input silent (n=0). */ |