#ifndef CORE_BFORMATDEC_H #define CORE_BFORMATDEC_H #include #include #include #include #include "almalloc.h" #include "alspan.h" #include "ambidefs.h" #include "bufferline.h" #include "devformat.h" #include "filters/splitter.h" struct FrontStablizer; using ChannelDec = std::array; class BFormatDec { static constexpr size_t sHFBand{0}; 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{}; /* NOTE: BandSplitter filter is unused with single-band decoding. */ BandSplitter mXOver; }; alignas(16) std::array mSamples; const std::unique_ptr 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 mChannelDec; public: BFormatDec(const size_t inchans, const al::span coeffs, const al::span coeffslf, const float xover_f0norm, std::unique_ptr stablizer); bool hasStablizer() const noexcept { return mStablizer != nullptr; } /* Decodes the ambisonic input to the given output channels. */ void process(const al::span OutBuffer, const FloatBufferLine *InSamples, const size_t SamplesToDo); /* Decodes the ambisonic input to the given output channels with stablization. */ void processStablize(const al::span OutBuffer, const FloatBufferLine *InSamples, const size_t lidx, const size_t ridx, const size_t cidx, const size_t SamplesToDo); static std::unique_ptr Create(const size_t inchans, const al::span coeffs, const al::span coeffslf, const float xover_f0norm, std::unique_ptr stablizer); DEF_NEWDEL(BFormatDec) }; #endif /* CORE_BFORMATDEC_H */