19#include "deluge/util/fixedpoint.h"
20#include "deluge/util/functions.h"
21#include "dsp/stereo_sample.h"
25namespace deluge::dsp {
29constexpr q31_t FOLD_MIN = 0.1 * ONE_Q31;
30constexpr q31_t THREE_FOURTHS = 0.75 * ONE_Q31;
31inline q31_t fold(q31_t input, q31_t level) {
38 q31_t max = level >> 8;
42 else if (input < -max) {
46 return 2 * extra - input;
52inline q31_t polynomialOscillatorApproximation(q31_t x) {
55 q31_t x2 = 2 * multiply_32x32_rshift32(x, x);
56 q31_t x3 = 2 * multiply_32x32_rshift32(x2, x);
58 q31_t r1 = 8 * (multiply_32x32_rshift32(THREE_FOURTHS, x) - x3);
60 q31_t r2 = 2 * multiply_32x32_rshift32(r1, r1);
61 q31_t r3 = 2 * multiply_32x32_rshift32(r2, r1);
63 q31_t out = 8 * (multiply_32x32_rshift32(THREE_FOURTHS, r1) - r3);
68inline void foldBufferPolyApproximation(std::span<q31_t> buffer, q31_t level) {
69 q31_t fold_level = add_saturate(level, FOLD_MIN);
70 for (
auto& sample : buffer) {
71 q31_t x = lshiftAndSaturateUnknown(multiply_32x32_rshift32(fold_level, sample), 8);
73 sample = polynomialOscillatorApproximation(x) >> 7;
77inline void foldBufferPolyApproximation(std::span<StereoSample> buffer, q31_t level) {
78 foldBufferPolyApproximation(std::span<q31_t>{
reinterpret_cast<q31_t*
>(buffer.data()), buffer.size() * 2}, level);
84inline void foldBuffer(std::span<q31_t> buffer, q31_t foldLevel) {
85 for (
auto& sample : buffer) {
86 auto out = fold(sample, foldLevel);
88 sample = out + 4 * multiply_32x32_rshift32(out, foldLevel);