aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/bformatdec.cpp64
-rw-r--r--core/bformatdec.h22
2 files changed, 47 insertions, 39 deletions
diff --git a/core/bformatdec.cpp b/core/bformatdec.cpp
index 129b9976..a308e185 100644
--- a/core/bformatdec.cpp
+++ b/core/bformatdec.cpp
@@ -16,33 +16,45 @@
#include "opthelpers.h"
+namespace {
+
+template<typename... Ts>
+struct overloaded : Ts... { using Ts::operator()...; };
+
+template<typename... Ts>
+overloaded(Ts...) -> overloaded<Ts...>;
+
+} // namespace
+
BFormatDec::BFormatDec(const size_t inchans, const al::span<const ChannelDec> coeffs,
const al::span<const ChannelDec> coeffslf, const float xover_f0norm,
std::unique_ptr<FrontStablizer> stablizer)
- : mStablizer{std::move(stablizer)}, mDualBand{!coeffslf.empty()}, mChannelDec{inchans}
+ : mStablizer{std::move(stablizer)}
{
- if(!mDualBand)
+ if(coeffslf.empty())
{
- for(size_t j{0};j < mChannelDec.size();++j)
+ auto &decoder = mChannelDec.emplace<std::vector<ChannelDecoderSingle>>(inchans);
+ for(size_t j{0};j < decoder.size();++j)
{
- float *outcoeffs{mChannelDec[j].mGains.Single};
+ float *outcoeffs{decoder[j].mGains};
for(const ChannelDec &incoeffs : coeffs)
*(outcoeffs++) = incoeffs[j];
}
}
else
{
- mChannelDec[0].mXOver.init(xover_f0norm);
- for(size_t j{1};j < mChannelDec.size();++j)
- mChannelDec[j].mXOver = mChannelDec[0].mXOver;
+ auto &decoder = mChannelDec.emplace<std::vector<ChannelDecoderDual>>(inchans);
+ decoder[0].mXOver.init(xover_f0norm);
+ for(size_t j{1};j < decoder.size();++j)
+ decoder[j].mXOver = decoder[0].mXOver;
- for(size_t j{0};j < mChannelDec.size();++j)
+ for(size_t j{0};j < decoder.size();++j)
{
- float *outcoeffs{mChannelDec[j].mGains.Dual[sHFBand]};
+ float *outcoeffs{decoder[j].mGains[sHFBand]};
for(const ChannelDec &incoeffs : coeffs)
*(outcoeffs++) = incoeffs[j];
- outcoeffs = mChannelDec[j].mGains.Dual[sLFBand];
+ outcoeffs = decoder[j].mGains[sLFBand];
for(const ChannelDec &incoeffs : coeffslf)
*(outcoeffs++) = incoeffs[j];
}
@@ -55,30 +67,32 @@ void BFormatDec::process(const al::span<FloatBufferLine> OutBuffer,
{
ASSUME(SamplesToDo > 0);
- if(mDualBand)
+ auto decode_dualband = [=](std::vector<ChannelDecoderDual> &decoder)
{
+ auto *input = InSamples;
const al::span<float> hfSamples{mSamples[sHFBand].data(), SamplesToDo};
const al::span<float> lfSamples{mSamples[sLFBand].data(), SamplesToDo};
- for(auto &chandec : mChannelDec)
+ for(auto &chandec : decoder)
{
- chandec.mXOver.process({InSamples->data(), SamplesToDo}, hfSamples.data(),
+ chandec.mXOver.process({input->data(), SamplesToDo}, hfSamples.data(),
lfSamples.data());
- MixSamples(hfSamples, OutBuffer, chandec.mGains.Dual[sHFBand],
- chandec.mGains.Dual[sHFBand], 0, 0);
- MixSamples(lfSamples, OutBuffer, chandec.mGains.Dual[sLFBand],
- chandec.mGains.Dual[sLFBand], 0, 0);
- ++InSamples;
+ MixSamples(hfSamples, OutBuffer, chandec.mGains[sHFBand], chandec.mGains[sHFBand],0,0);
+ MixSamples(lfSamples, OutBuffer, chandec.mGains[sLFBand], chandec.mGains[sLFBand],0,0);
+ ++input;
}
- }
- else
+ };
+ auto decode_singleband = [=](std::vector<ChannelDecoderSingle> &decoder)
{
- for(auto &chandec : mChannelDec)
+ auto *input = InSamples;
+ for(auto &chandec : decoder)
{
- MixSamples({InSamples->data(), SamplesToDo}, OutBuffer, chandec.mGains.Single,
- chandec.mGains.Single, 0, 0);
- ++InSamples;
+ MixSamples({input->data(), SamplesToDo}, OutBuffer, chandec.mGains, chandec.mGains,
+ 0, 0);
+ ++input;
}
- }
+ };
+
+ std::visit(overloaded{decode_dualband, decode_singleband}, mChannelDec);
}
void BFormatDec::processStablize(const al::span<FloatBufferLine> OutBuffer,
diff --git a/core/bformatdec.h b/core/bformatdec.h
index 42024bd9..3bb7f544 100644
--- a/core/bformatdec.h
+++ b/core/bformatdec.h
@@ -4,6 +4,7 @@
#include <array>
#include <cstddef>
#include <memory>
+#include <variant>
#include <vector>
#include "almalloc.h"
@@ -23,27 +24,20 @@ class BFormatDec {
static constexpr size_t sLFBand{1};
static constexpr size_t sNumBands{2};
- struct ChannelDecoder {
- union MatrixU {
- float Dual[sNumBands][MAX_OUTPUT_CHANNELS];
- float Single[MAX_OUTPUT_CHANNELS];
- } mGains{};
+ struct ChannelDecoderSingle {
+ float mGains[MAX_OUTPUT_CHANNELS];
+ };
- /* NOTE: BandSplitter filter is unused with single-band decoding. */
+ struct ChannelDecoderDual {
BandSplitter mXOver;
+ float mGains[sNumBands][MAX_OUTPUT_CHANNELS];
};
alignas(16) std::array<FloatBufferLine,2> mSamples;
const std::unique_ptr<FrontStablizer> mStablizer;
- const bool mDualBand{false};
-
- /* TODO: This should ideally be a FlexArray, since ChannelDecoder is rather
- * small and only a few are needed (3, 4, 5, 7, typically). But that can
- * only be used in a standard layout struct, and a std::unique_ptr member
- * (mStablizer) causes GCC and Clang to warn it's not.
- */
- std::vector<ChannelDecoder> mChannelDec;
+
+ std::variant<std::vector<ChannelDecoderSingle>,std::vector<ChannelDecoderDual>> mChannelDec;
public:
BFormatDec(const size_t inchans, const al::span<const ChannelDec> coeffs,