Deluge Firmware 1.3.0
Build date: 2025.04.16
Loading...
Searching...
No Matches
util.hpp
1/*
2 * Copyright © 2015-2023 Synthstrom Audible Limited
3 *
4 * This file is part of The Synthstrom Audible Deluge Firmware.
5 *
6 * The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software Foundation,
8 * either version 3 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with this program.
15 * If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19#include "deluge/util/fixedpoint.h"
20#include "deluge/util/functions.h"
21#include <cmath>
22
23namespace deluge::dsp {
27constexpr q31_t FOLD_MIN = 0.1 * ONE_Q31;
28constexpr q31_t THREE_FOURTHS = 0.75 * ONE_Q31;
29inline q31_t fold(q31_t input, q31_t level) {
30 // no folding occurs if max is 0 or if max is greater than input
31 // to keep the knob range consistent fold starts from 0 and
32 // increases, decreasing would lead to a large deadspace until
33 // suddenly clipping occured
34 // note 9db loss
35 q31_t extra = 0;
36 q31_t max = level >> 8;
37 if (input > max) {
38 extra = input - max;
39 }
40 else if (input < -max) {
41 extra = input + max;
42 }
43 // this avoids inverting the wave
44 return 2 * extra - input;
45}
50inline q31_t polynomialOscillatorApproximation(q31_t x) {
51 // requires 1 to be ONE_Q31
52
53 q31_t x2 = 2 * multiply_32x32_rshift32(x, x);
54 q31_t x3 = 2 * multiply_32x32_rshift32(x2, x);
55 // this is 4(3*x/4 - x^3) which is a nice shape
56 q31_t r1 = 8 * (multiply_32x32_rshift32(THREE_FOURTHS, x) - x3);
57
58 q31_t r2 = 2 * multiply_32x32_rshift32(r1, r1);
59 q31_t r3 = 2 * multiply_32x32_rshift32(r2, r1);
60 // at this point we've applied the polynomial twice
61 q31_t out = 8 * (multiply_32x32_rshift32(THREE_FOURTHS, r1) - r3);
62
63 return out;
64}
65
66inline void foldBufferPolyApproximation(q31_t* startSample, q31_t* endSample, q31_t level) {
67 q31_t* currentSample = startSample;
68 q31_t fold_level = add_saturate(level, FOLD_MIN);
69
70 do {
71 q31_t c = *currentSample;
72
73 q31_t x = lshiftAndSaturateUnknown(multiply_32x32_rshift32(fold_level, c), 8);
74
75 // volume compensation
76 *currentSample = polynomialOscillatorApproximation(x) >> 7;
77
78 currentSample += 1;
79 } while (currentSample < endSample);
80}
84inline void foldBuffer(q31_t* startSample, q31_t* endSample, q31_t foldLevel) {
85 q31_t* currentSample = startSample;
86 do {
87 q31_t outs = fold(*currentSample, foldLevel);
88 // volume compensation
89 *currentSample = outs + 4 * multiply_32x32_rshift32(outs, foldLevel);
90
91 currentSample += 1;
92 } while (currentSample < endSample);
93}
94} // namespace deluge::dsp