aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2021-07-13 06:31:13 -0700
committerChris Robinson <[email protected]>2021-07-13 06:31:13 -0700
commitd998c03a2761920b1edc4f1da09a04072af83d7e (patch)
treeede3bda406061fe8b47072b3d459b0ead2e879e8 /core
parentfb2cb2bd064c681defda5f1019faa5189ec3bb34 (diff)
Add a UHJ-specific coefficient scaling array
Diffstat (limited to 'core')
-rw-r--r--core/ambidefs.h12
-rw-r--r--core/buffer_storage.h1
-rw-r--r--core/uhjfilter.cpp20
-rw-r--r--core/uhjfilter.h5
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).
*/