Use virtual functions for the decoder
[openal-soft.git] / core / uhjfilter.h
blob73be7d1711987677a77552b710cba74ba6cfeda4
1 #ifndef CORE_UHJFILTER_H
2 #define CORE_UHJFILTER_H
4 #include <array>
6 #include "almalloc.h"
7 #include "alspan.h"
8 #include "bufferline.h"
9 #include "resampler_limits.h"
12 struct DecoderBase {
13 virtual ~DecoderBase() = default;
15 virtual void setWidth(float width) noexcept = 0;
17 virtual void decode(const al::span<float*> samples, const size_t samplesToDo,
18 const size_t forwardSamples) = 0;
22 struct UhjFilterBase {
23 /* The filter delay is half it's effective size, so a delay of 128 has a
24 * FIR length of 256.
26 static constexpr size_t sFilterDelay{128};
29 struct UhjEncoder : public UhjFilterBase {
30 /* Delays and processing storage for the unfiltered signal. */
31 alignas(16) std::array<float,BufferLineSize+sFilterDelay> mS{};
32 alignas(16) std::array<float,BufferLineSize+sFilterDelay> mD{};
34 /* History for the FIR filter. */
35 alignas(16) std::array<float,sFilterDelay*2 - 1> mWXHistory{};
37 alignas(16) std::array<float,BufferLineSize + sFilterDelay*2> mTemp{};
39 /**
40 * Encodes a 2-channel UHJ (stereo-compatible) signal from a B-Format input
41 * signal. The input must use FuMa channel ordering and UHJ scaling (FuMa
42 * with an additional +3dB boost).
44 void encode(float *LeftOut, float *RightOut, const al::span<const float*const,3> InSamples,
45 const size_t SamplesToDo);
47 DEF_NEWDEL(UhjEncoder)
51 struct UhjDecoder : public DecoderBase, public UhjFilterBase {
52 alignas(16) std::array<float,BufferLineSize+MaxResamplerEdge+sFilterDelay> mS{};
53 alignas(16) std::array<float,BufferLineSize+MaxResamplerEdge+sFilterDelay> mD{};
54 alignas(16) std::array<float,BufferLineSize+MaxResamplerEdge+sFilterDelay> mT{};
56 alignas(16) std::array<float,sFilterDelay-1> mDTHistory{};
57 alignas(16) std::array<float,sFilterDelay-1> mSHistory{};
59 alignas(16) std::array<float,BufferLineSize+MaxResamplerEdge + sFilterDelay*2> mTemp{};
61 void setWidth(float) noexcept override { }
63 /**
64 * Decodes a 3- or 4-channel UHJ signal into a B-Format signal with FuMa
65 * channel ordering and UHJ scaling. For 3-channel, the 3rd channel may be
66 * attenuated by 'n', where 0 <= n <= 1. So to decode 2-channel UHJ, supply
67 * 3 channels with the 3rd channel silent (n=0). The B-Format signal
68 * reconstructed from 2-channel UHJ should not be run through a normal
69 * B-Format decoder, as it needs different shelf filters.
71 void decode(const al::span<float*> samples, const size_t samplesToDo,
72 const size_t forwardSamples) override;
74 DEF_NEWDEL(UhjDecoder)
77 struct UhjStereoDecoder : public UhjDecoder {
78 float mCurrentWidth{-1.0f};
80 /**
81 * The width factor for Super Stereo processing. Can be changed in between
82 * calls to decodeStereo, with valid values being between 0...0.7.
84 float mWidthControl{0.593f};
86 void setWidth(float width) noexcept override
87 { mWidthControl = width; }
89 /**
90 * Applies Super Stereo processing on a stereo signal to create a B-Format
91 * signal with FuMa channel ordering and UHJ scaling. The samples span
92 * should contain 3 channels, the first two being the left and right stereo
93 * channels, and the third left empty.
95 void decode(const al::span<float*> samples, const size_t samplesToDo,
96 const size_t forwardSamples) override;
98 DEF_NEWDEL(UhjStereoDecoder)
101 #endif /* CORE_UHJFILTER_H */