🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
3.3 KiB

  1. #ifndef CORE_UHJFILTER_H
  2. #define CORE_UHJFILTER_H
  3. #include <array>
  4. #include "almalloc.h"
  5. #include "alspan.h"
  6. #include "bufferline.h"
  7. #include "resampler_limits.h"
  8. struct DecoderBase {
  9. virtual ~DecoderBase() = default;
  10. virtual void decode(const al::span<float*> samples, const size_t samplesToDo,
  11. const size_t forwardSamples) = 0;
  12. /**
  13. * The width factor for Super Stereo processing. Can be changed in between
  14. * calls to decode, with valid values being between 0...0.7.
  15. */
  16. float mWidthControl{0.593f};
  17. float mCurrentWidth{-1.0f};
  18. };
  19. struct UhjFilterBase {
  20. /* The filter delay is half it's effective size, so a delay of 128 has a
  21. * FIR length of 256.
  22. */
  23. static constexpr size_t sFilterDelay{128};
  24. };
  25. struct UhjEncoder : public UhjFilterBase {
  26. /* Delays and processing storage for the unfiltered signal. */
  27. alignas(16) std::array<float,BufferLineSize+sFilterDelay> mS{};
  28. alignas(16) std::array<float,BufferLineSize+sFilterDelay> mD{};
  29. /* History for the FIR filter. */
  30. alignas(16) std::array<float,sFilterDelay*2 - 1> mWXHistory{};
  31. alignas(16) std::array<float,BufferLineSize + sFilterDelay*2> mTemp{};
  32. /**
  33. * Encodes a 2-channel UHJ (stereo-compatible) signal from a B-Format input
  34. * signal. The input must use FuMa channel ordering and UHJ scaling (FuMa
  35. * with an additional +3dB boost).
  36. */
  37. void encode(float *LeftOut, float *RightOut, const al::span<const float*const,3> InSamples,
  38. const size_t SamplesToDo);
  39. DEF_NEWDEL(UhjEncoder)
  40. };
  41. struct UhjDecoder : public DecoderBase, public UhjFilterBase {
  42. /* For 2-channel UHJ, shelf filters should use these LF responses. */
  43. static constexpr float sWLFScale{0.661f};
  44. static constexpr float sXYLFScale{1.293f};
  45. alignas(16) std::array<float,BufferLineSize+MaxResamplerEdge+sFilterDelay> mS{};
  46. alignas(16) std::array<float,BufferLineSize+MaxResamplerEdge+sFilterDelay> mD{};
  47. 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{};
  50. alignas(16) std::array<float,BufferLineSize+MaxResamplerEdge + sFilterDelay*2> mTemp{};
  51. /**
  52. * Decodes a 3- or 4-channel UHJ signal into a B-Format signal with FuMa
  53. * channel ordering and UHJ scaling. For 3-channel, the 3rd channel may be
  54. * attenuated by 'n', where 0 <= n <= 1. So to decode 2-channel UHJ, supply
  55. * 3 channels with the 3rd channel silent (n=0). The B-Format signal
  56. * reconstructed from 2-channel UHJ should not be run through a normal
  57. * B-Format decoder, as it needs different shelf filters.
  58. */
  59. void decode(const al::span<float*> samples, const size_t samplesToDo,
  60. const size_t forwardSamples) override;
  61. DEF_NEWDEL(UhjDecoder)
  62. };
  63. struct UhjStereoDecoder : public UhjDecoder {
  64. /**
  65. * Applies Super Stereo processing on a stereo signal to create a B-Format
  66. * signal with FuMa channel ordering and UHJ scaling. The samples span
  67. * should contain 3 channels, the first two being the left and right stereo
  68. * channels, and the third left empty.
  69. */
  70. void decode(const al::span<float*> samples, const size_t samplesToDo,
  71. const size_t forwardSamples) override;
  72. DEF_NEWDEL(UhjStereoDecoder)
  73. };
  74. #endif /* CORE_UHJFILTER_H */