Deluge Firmware 1.3.0
Build date: 2026.10.14
Loading...
Searching...
No Matches
digital.hpp
1/*
2 * Copyright © 2024 Katherine Whitlock
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#pragma once
18#include "definitions_cxx.hpp"
19#include "mutable.hpp"
20
21namespace deluge::dsp::reverb {
22
25class Digital : public Mutable {
26 constexpr static float kRatio = 29761.f / kSampleRate; // Lexicon sample rate to Deluge sample rate
27
29 constexpr static size_t max_excursion = 16.f * kRatio;
30
34 constexpr static size_t kInterpolationGuard = 1;
35
39 constexpr static float kDecayMin = 0.1f;
40 constexpr static float kDecayMax = 0.9f;
41
42public:
43 void process(std::span<q31_t> in, std::span<StereoSample> output) override {
44 typename FxEngine::Context c;
45
46 typename FxEngine::AllPass ap1(142 * kRatio);
47 typename FxEngine::AllPass ap2(107 * kRatio);
48 typename FxEngine::AllPass ap3(379 * kRatio);
49 typename FxEngine::AllPass ap4(277 * kRatio);
50
51 typename FxEngine::AllPass dap1a((672 * kRatio) + max_excursion + kInterpolationGuard);
52 typename FxEngine::DelayLine del1a(4453 * kRatio);
53 typename FxEngine::AllPass dap1b(1800 * kRatio);
54 typename FxEngine::DelayLine del1b(3720 * kRatio);
55
56 typename FxEngine::AllPass dap2a((908 * kRatio) + max_excursion + kInterpolationGuard);
57 typename FxEngine::DelayLine del2a(4217 * kRatio);
58 typename FxEngine::AllPass dap2b(2656 * kRatio);
59 typename FxEngine::DelayLine del2b(3163 * kRatio);
60
61 FxEngine::ConstructTopology(engine_, {&ap1, &ap2, &ap3, &ap4, //<
62 &dap1a, &del1a, &dap1b, &del1b, //<
63 &dap2a, &del2a, &dap2b, &del2b});
64
65 const float kdecay = reverb_time_; // 0.5f
66 const float kid1 = 0.750f; // input diffusion 1
67 const float kid2 = 0.625f; // input diffusion 2
68 const float kdd1 = 0.70f; // decay diffusion 1
69 const float kdd2 = std::clamp(kdecay + 0.15f, 0.25f, 0.5f); // decay diffusion 2
70
71 const float kdamp = lp_; // 1.f - 0.0005f; // damping
72 const float kbandwidth = 0.9995f;
73
74 float lp_1 = lp_decay_1_;
75 float lp_2 = lp_decay_2_;
76 float lp_band = lp_band_;
77
78 for (size_t frame = 0; frame < in.size(); ++frame) {
79 engine_.Advance();
80
81 const float input_sample = in[frame] / static_cast<float>(std::numeric_limits<int32_t>::max());
82 c.Set(input_sample);
83
84 c.Lp(lp_band, kbandwidth);
85
86 // Diffuse through 4 allpasses.
87 ap1.Process(c, kid1);
88 ap2.Process(c, kid1);
89 ap3.Process(c, kid2);
90 ap4.Process(c, kid2);
91 float apout = c.Get();
92
93 // Main reverb loop: a figure of eight, where each branch's tail feeds the other's
94 // head. del2b's output is already a delayed read, so branch one can close the loop
95 // on it here and branch two simply carries on from branch one's accumulator.
96 c.Set(apout);
97 c.Add(kdecay * del2b.Read(del2b.length));
98 dap1a.ProcessInterpolate(c, 672.0f * kRatio, LFO_2, max_excursion, -kdd1);
99 del1a.Process(c);
100 c.Lp(lp_1, kdamp); // damping
101 c.Multiply(kdecay);
102 dap1b.Process(c, kdd2);
103 del1b.Process(c);
104
105 c.Multiply(kdecay);
106 c.Add(apout);
107 dap2a.ProcessInterpolate(c, 908.0f * kRatio, LFO_1, max_excursion, -kdd1);
108 del2a.Process(c);
109 c.Lp(lp_2, kdamp); // damping
110 c.Multiply(kdecay);
111 dap2b.Process(c, kdd2);
112 del2b.Process(c);
113
114 float left_sum = 0;
115 left_sum += 0.6f * del2a.at(266 * kRatio);
116 left_sum += 0.6f * del2a.at(2974 * kRatio);
117 left_sum -= 0.6f * dap2b.at(1913 * kRatio);
118 left_sum += 0.6f * del2b.at(1996 * kRatio);
119 left_sum -= 0.6f * del1a.at(1990 * kRatio);
120 left_sum -= 0.6f * dap1b.at(187 * kRatio);
121 left_sum -= 0.6f * del1b.at(1066 * kRatio);
122 left_sum = left_sum - dsp::OnePole(hp_l_, left_sum, hp_cutoff_);
123 left_sum = dsp::OnePole(lp_l_, left_sum, lp_cutoff_);
124
125 float right_sum = 0;
126 right_sum += 0.6f * del1a.at(353 * kRatio);
127 right_sum += 0.6f * del1a.at(3627 * kRatio);
128 right_sum -= 0.6f * dap1b.at(1228 * kRatio);
129 right_sum += 0.6f * del1b.at(2673 * kRatio);
130 right_sum -= 0.6f * del2a.at(2111 * kRatio);
131 right_sum -= 0.6f * dap2b.at(335 * kRatio);
132 right_sum -= 0.6f * del2b.at(121 * kRatio);
133 right_sum = right_sum - dsp::OnePole(hp_r_, right_sum, hp_cutoff_);
134 right_sum = dsp::OnePole(lp_r_, right_sum, lp_cutoff_);
135
136 q31_t output_left = dsp::toQ31Saturating(left_sum * kOutputGain);
137 q31_t output_right = dsp::toQ31Saturating(right_sum * kOutputGain);
138
139 // Mix
140 output[frame].l += multiply_32x32_rshift32_rounded(output_left, getPanLeft());
141 output[frame].r += multiply_32x32_rshift32_rounded(output_right, getPanRight());
142 }
143
144 lp_decay_1_ = lp_1;
145 lp_decay_2_ = lp_2;
146 lp_band_ = lp_band;
147 }
148
149 // Reverb Base Overrides
150 void setRoomSize(float value) override { reverb_time_ = util::map(value, 0.f, 1.f, kDecayMin, kDecayMax); }
151 [[nodiscard]] float getRoomSize() const override {
152 return util::map(reverb_time_, kDecayMin, kDecayMax, 0.f, 1.f);
153 };
154
155private:
156 float lp_band_{0.f};
157};
158} // namespace deluge::dsp::reverb
The Griesinger topology model from Part 1 of Effect Design by John Dattorro, classically based on the...
Definition digital.hpp:25
static constexpr size_t max_excursion
Dattorro's +/-16 samples of tank modulation, rescaled to our sample rate.
Definition digital.hpp:29
static constexpr size_t kInterpolationGuard
Definition digital.hpp:34
static constexpr float kDecayMin
Definition digital.hpp:39
Definition fx_engine.hpp:98
static constexpr float kOutputGain
Definition mutable.hpp:115
Definition fx_engine.hpp:168
Definition fx_engine.hpp:116