aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--al/buffer.cpp1
-rw-r--r--al/source.cpp2
-rw-r--r--alc/alu.cpp9
-rw-r--r--alc/effects/convolution.cpp9
-rw-r--r--alc/panning.cpp2
-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
9 files changed, 40 insertions, 21 deletions
diff --git a/al/buffer.cpp b/al/buffer.cpp
index 26fe863e..e9c1f76b 100644
--- a/al/buffer.cpp
+++ b/al/buffer.cpp
@@ -317,6 +317,7 @@ ALenum EnumFromAmbiScaling(AmbiScaling scale)
case AmbiScaling::FuMa: return AL_FUMA_SOFT;
case AmbiScaling::SN3D: return AL_SN3D_SOFT;
case AmbiScaling::N3D: return AL_SN3D_SOFT;
+ case AmbiScaling::UHJ: break;
}
throw std::runtime_error{"Invalid AmbiScaling: "+std::to_string(int(scale))};
}
diff --git a/al/source.cpp b/al/source.cpp
index b8278fed..ef70a86d 100644
--- a/al/source.cpp
+++ b/al/source.cpp
@@ -499,7 +499,7 @@ void InitVoice(Voice *voice, ALsource *source, ALbufferQueueItem *BufferList, AL
voice->mAmbiLayout = (buffer->mChannels == FmtUHJ2 || buffer->mChannels == FmtUHJ3
|| voice->mFmtChannels == FmtUHJ4) ? AmbiLayout::FuMa : buffer->mAmbiLayout;
voice->mAmbiScaling = (buffer->mChannels == FmtUHJ2 || buffer->mChannels == FmtUHJ3
- || voice->mFmtChannels == FmtUHJ4) ? AmbiScaling::FuMa : buffer->mAmbiScaling;
+ || voice->mFmtChannels == FmtUHJ4) ? AmbiScaling::UHJ : buffer->mAmbiScaling;
voice->mAmbiOrder = buffer->mAmbiOrder;
if(buffer->mCallback) voice->mFlags |= VoiceIsCallback;
diff --git a/alc/alu.cpp b/alc/alu.cpp
index 2ab4dcbc..fa362586 100644
--- a/alc/alu.cpp
+++ b/alc/alu.cpp
@@ -347,8 +347,13 @@ inline uint dither_rng(uint *seed) noexcept
inline auto& GetAmbiScales(AmbiScaling scaletype) noexcept
{
- if(scaletype == AmbiScaling::FuMa) return AmbiScale::FromFuMa();
- if(scaletype == AmbiScaling::SN3D) return AmbiScale::FromSN3D();
+ switch(scaletype)
+ {
+ case AmbiScaling::FuMa: return AmbiScale::FromFuMa();
+ case AmbiScaling::SN3D: return AmbiScale::FromSN3D();
+ case AmbiScaling::UHJ: return AmbiScale::FromUHJ();
+ case AmbiScaling::N3D: break;
+ }
return AmbiScale::FromN3D();
}
diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp
index ca5a7321..300ddb17 100644
--- a/alc/effects/convolution.cpp
+++ b/alc/effects/convolution.cpp
@@ -91,8 +91,13 @@ void LoadSamples(double *RESTRICT dst, const al::byte *src, const size_t srcstep
inline auto& GetAmbiScales(AmbiScaling scaletype) noexcept
{
- if(scaletype == AmbiScaling::FuMa) return AmbiScale::FromFuMa();
- if(scaletype == AmbiScaling::SN3D) return AmbiScale::FromSN3D();
+ switch(scaletype)
+ {
+ case AmbiScaling::FuMa: return AmbiScale::FromFuMa();
+ case AmbiScaling::SN3D: return AmbiScale::FromSN3D();
+ case AmbiScaling::UHJ: return AmbiScale::FromUHJ();
+ case AmbiScaling::N3D: break;
+ }
return AmbiScale::FromN3D();
}
diff --git a/alc/panning.cpp b/alc/panning.cpp
index 2c99d978..d5fb1cf5 100644
--- a/alc/panning.cpp
+++ b/alc/panning.cpp
@@ -844,7 +844,7 @@ void InitUhjPanning(ALCdevice *device)
auto acnmap_begin = AmbiIndex::FromFuMa().begin();
std::transform(acnmap_begin, acnmap_begin + count, std::begin(device->Dry.AmbiMap),
[](const uint8_t &acn) noexcept -> BFChannelConfig
- { return BFChannelConfig{1.0f/AmbiScale::FromFuMa()[acn], acn}; });
+ { return BFChannelConfig{1.0f/AmbiScale::FromUHJ()[acn], acn}; });
AllocChannels(device, count, device->channelsFromFmt());
}
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).
*/