1 #ifndef CORE_UHJFILTER_H
2 #define CORE_UHJFILTER_H
7 #include "bufferline.h"
8 #include "resampler_limits.h"
11 struct UhjFilterBase
{
12 /* The filter delay is half it's effective size, so a delay of 128 has a
15 static constexpr size_t sFilterDelay
{128};
18 struct UhjEncoder
: public UhjFilterBase
{
19 /* Delays and processing storage for the unfiltered signal. */
20 alignas(16) std::array
<float,BufferLineSize
+sFilterDelay
> mS
{};
21 alignas(16) std::array
<float,BufferLineSize
+sFilterDelay
> mD
{};
23 /* History for the FIR filter. */
24 alignas(16) std::array
<float,sFilterDelay
*2 - 1> mWXHistory
{};
26 alignas(16) std::array
<float,BufferLineSize
+ sFilterDelay
*2> mTemp
{};
29 * Encodes a 2-channel UHJ (stereo-compatible) signal from a B-Format input
30 * signal. The input must use FuMa channel ordering and UHJ scaling (FuMa
31 * with an additional +3dB boost).
33 void encode(float *LeftOut
, float *RightOut
, const FloatBufferLine
*InSamples
,
34 const size_t SamplesToDo
);
36 DEF_NEWDEL(UhjEncoder
)
40 struct UhjDecoder
: public UhjFilterBase
{
41 static constexpr size_t sLineSize
{BufferLineSize
+MaxResamplerPadding
+sFilterDelay
};
42 using BufferLine
= std::array
<float,sLineSize
>;
44 alignas(16) std::array
<float,BufferLineSize
+MaxResamplerEdge
+sFilterDelay
> mS
{};
45 alignas(16) std::array
<float,BufferLineSize
+MaxResamplerEdge
+sFilterDelay
> mD
{};
46 alignas(16) std::array
<float,BufferLineSize
+MaxResamplerEdge
+sFilterDelay
> mT
{};
48 alignas(16) std::array
<float,sFilterDelay
-1> mDTHistory
{};
49 alignas(16) std::array
<float,sFilterDelay
-1> mSHistory
{};
51 alignas(16) std::array
<float,BufferLineSize
+MaxResamplerEdge
+ sFilterDelay
*2> mTemp
{};
53 float mCurrentWidth
{-1.0f
};
56 * The width factor for Super Stereo processing. Can be changed in between
57 * calls to decodeStereo, with valid values being between 0...0.7.
59 float mWidthControl
{0.593f
};
62 * Decodes a 3- or 4-channel UHJ signal into a B-Format signal with FuMa
63 * channel ordering and UHJ scaling. For 3-channel, the 3rd channel may be
64 * attenuated by 'n', where 0 <= n <= 1. So to decode 2-channel UHJ, supply
65 * 3 channels with the 3rd channel silent (n=0). The B-Format signal
66 * reconstructed from 2-channel UHJ should not be run through a normal
67 * B-Format decoder, as it needs different shelf filters.
69 void decode(const al::span
<float*> samples
, const size_t samplesToDo
,
70 const size_t forwardSamples
);
73 * Applies Super Stereo processing on a stereo signal to create a B-Format
74 * signal with FuMa channel ordering and UHJ scaling. The samples span
75 * should contain 3 channels, the first two being the left and right stereo
76 * channels, and the third left empty.
78 void decodeStereo(const al::span
<float*> samples
, const size_t samplesToDo
,
79 const size_t forwardSamples
);
81 using DecoderFunc
= void (UhjDecoder::*)(const al::span
<float*> samples
,
82 const size_t samplesToDo
, const size_t forwardSamples
);
84 DEF_NEWDEL(UhjDecoder
)
87 #endif /* CORE_UHJFILTER_H */