#include "delay/buffer_multi.hpp" #include #ifndef MIX_HPP #define MIX_HPP #include // Use like `Householder::inPlace(data)` - size must be ≥ 1 template class Householder { static constexpr Sample multiplier{-2.0/size}; public: static void inPlace(Sample *arr) { double sum = 0; for (int i = 0; i < size; ++i) { sum += arr[i]; } sum *= multiplier; for (int i = 0; i < size; ++i) { arr[i] += sum; } }; }; // Use like `Hadamard::inPlace(data)` - size must be a power of 2 template class Hadamard { public: static inline void recursiveUnscaled(Sample * data) { if (size <= 1) { return; } constexpr int hSize = size/2; // Two (unscaled) Hadamards of half the size Hadamard::recursiveUnscaled(data); Hadamard::recursiveUnscaled(data + hSize); // Combine the two halves using sum/difference for (int i = 0; i < hSize; ++i) { double a = data[i]; double b = data[i + hSize]; data[i] = (a + b); data[i + hSize] = (a - b); } } static inline void inPlace(Sample * data) { recursiveUnscaled(data); Sample scalingFactor = std::sqrt(1.0/size); for (int c = 0; c < size; ++c) { data[c] *= scalingFactor; } } }; template class Shuffle { public: static inline void outOfPlace(dsp::Buffer &in, dsp::Buffer &out, dsp::Buffer &shuffle_spec) { for (int c=0; c < shuffle_spec.capacity(); c++) { T sign = 1; int s = (int)shuffle_spec[c]; if (s < 0) { sign = -1; s *= -1; } if (s >= shuffle_spec.capacity()) { s = 0; } out[s] = sign * in[c]; } }; static inline void outOfPlace(dsp::BufferMulti &in, dsp::BufferMulti &out, dsp::Buffer &shuffle_spec) { for (int c=0; c < shuffle_spec.capacity(); c++) { T sign = 1; int s = (int)shuffle_spec[c]; if (s < 0) { sign = -1; s *= -1; } if (s >= shuffle_spec.capacity()) { s = 0; } for (int n=0; n < in.capacity(); n++) { out[c][n] = sign * in[s][n]; } } }; }; #endif