Tabula Sonora 0.1.0
A native C++20 implementation of the Roland Sound Canvas VA synth voice
Loading...
Searching...
No Matches
send_effects.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <array>
6#include <cstdint>
7#include <optional>
8#include <span>
9#include <vector>
10
11namespace ts {
12
14class Effect {
15public:
16 virtual ~Effect() = default;
17
19 virtual void
20 process(std::span<const float> input, std::span<float> left, std::span<float> right) = 0;
21
23 virtual void reset() = 0;
24};
25
32class DcBlocker {
33public:
34 static constexpr double input_coefficient = 0.99804;
35 static constexpr double state_coefficient = -0.003919;
36
37 void reset() noexcept { state_ = 0.0; }
38
39 [[nodiscard]] double process(double input) noexcept
40 {
41 const double output = (input * input_coefficient) + state_;
42 state_ += output * state_coefficient;
43 return output;
44 }
45
46private:
47 double state_ = 0.0;
48};
49
57class Reverb final : public Effect {
58public:
60 static constexpr int ring_size = 65536;
61
62 explicit Reverb(const ReverbPreset& preset) : preset_(preset) {}
63
65 [[nodiscard]] static Reverb for_type(std::optional<int> type);
66
68 [[nodiscard]] static double send_gain(int controller) noexcept
69 {
70 return ReverbPresets::send_at_full_scale * (controller / 127.0);
71 }
72
73 void reset() override;
74
75 void
76 process(std::span<const float> input, std::span<float> left, std::span<float> right) override;
77
79 void process(std::span<const float> input,
80 std::span<const float> chorus_left,
81 std::span<const float> chorus_right,
82 std::span<float> left,
83 std::span<float> right);
84
85private:
86 static constexpr int ring_mask = ring_size - 1;
87 static constexpr int input_tap = 0x1000;
88
89 void run_tank(const TankTaps& taps,
90 const ReverbTank& tank,
91 const AllpassStage& first,
92 const AllpassStage& second,
93 double carry,
94 double feedback,
95 double& state) noexcept;
96
97 ReverbPreset preset_;
98 std::vector<double> ring_ = std::vector<double>(ring_size, 0.0);
99
100 double dc_state_ = 0.0;
101 double damp_ = 0.0;
102 double tank_state_a_ = 0.0;
103 double tank_state_b_ = 0.0;
104 int write_cursor_ = 0;
105};
106
112class Chorus final : public Effect {
113public:
115 static constexpr int ring_size = 65536;
116
117 explicit Chorus(const ChorusPreset& preset) : preset_(preset) {}
118
120 [[nodiscard]] static Chorus for_type(std::optional<int> type);
121
123 [[nodiscard]] static double send_gain(int controller) noexcept
124 {
125 return ChorusPresets::send_at_full_scale * (controller / 127.0);
126 }
127
128 void reset() override;
129
130 void
131 process(std::span<const float> input, std::span<float> left, std::span<float> right) override;
132
133private:
134 static constexpr int ring_mask = ring_size - 1;
135 static constexpr int phase_sign = 1 << 24;
136 static constexpr int phase_half = 1 << 23;
137
138 [[nodiscard]] double read_tap(int depth, int base_delay, int triangle) const noexcept;
139
140 ChorusPreset preset_;
141 std::vector<double> ring_ = std::vector<double>(ring_size, 0.0);
142
143 int phase_ = 0;
144 double dc_state_ = 0.0;
145 double lowpass_ = 0.0;
146 double feedback_ = 0.0;
147 int write_cursor_ = 0;
148};
149
155 double centre_gain = 0.0;
156 double left_gain = 0.0;
157 double right_gain = 0.0;
158 double feedback = 0.0;
160 double send_to_reverb = 0.0;
161};
162
164class SystemDelay final : public Effect {
165public:
167 static constexpr int ring_size = 1 << 17;
168
169 explicit SystemDelay(const DelayParameters& parameters);
170
172 [[nodiscard]] static SystemDelay for_type(int type);
173
177 [[nodiscard]] static double send_gain(int send) noexcept
178 {
179 return DelayPresets::send_at_full_scale * (send / 127.0);
180 }
181
183 [[nodiscard]] static double time_milliseconds(int raw);
184
186 [[nodiscard]] static double ratio_percent(int raw);
187
189 [[nodiscard]] static DelayParameters compile(std::span<const int> raw, int sample_rate = 32000);
190
191 void reset() override;
192
193 void
194 process(std::span<const float> input, std::span<float> left, std::span<float> right) override;
195
196private:
197 static constexpr int ring_mask = ring_size - 1;
198
199 DelayParameters parameters_;
200 std::vector<double> ring_ = std::vector<double>(ring_size, 0.0);
201
202 int pre_delay_ = DelayPresets::pre_delay_samples;
203 double pre_low_pass_coefficient_ = 0.0;
204 std::vector<float> pending_left_;
205 std::vector<float> pending_right_;
206 int pending_ = 0;
207 double lowpass_ = 0.0;
208 int write_cursor_ = 0;
209};
210
211} // namespace ts
static Chorus for_type(std::optional< int > type)
Creates a chorus for a GS type 0–7, or the default when none is given.
static double send_gain(int controller) noexcept
The send-bus gain for CC#93.
Definition send_effects.hpp:123
void process(std::span< const float > input, std::span< float > left, std::span< float > right) override
Processes a block.
Chorus(const ChorusPreset &preset)
Definition send_effects.hpp:117
static constexpr int ring_size
Size of the delay ring.
Definition send_effects.hpp:115
void reset() override
Clears all internal state.
The engine's DC blocker: one design, instantiated once on each effect input.
Definition send_effects.hpp:32
static constexpr double state_coefficient
Definition send_effects.hpp:35
static constexpr double input_coefficient
Definition send_effects.hpp:34
void reset() noexcept
Definition send_effects.hpp:37
double process(double input) noexcept
Definition send_effects.hpp:39
A stereo send effect fed from one mono bus.
Definition send_effects.hpp:14
virtual void process(std::span< const float > input, std::span< float > left, std::span< float > right)=0
Processes a block.
virtual void reset()=0
Clears all internal state.
virtual ~Effect()=default
static Reverb for_type(std::optional< int > type)
Creates a reverb for a GS type 0–7, or the default when none is given.
void process(std::span< const float > input, std::span< const float > chorus_left, std::span< const float > chorus_right, std::span< float > left, std::span< float > right)
Processes a block with the chorus feeding into it; either chorus span may be empty.
static double send_gain(int controller) noexcept
The send-bus gain for CC#91. Linear in the controller, unlike the volume law.
Definition send_effects.hpp:68
void reset() override
Clears all internal state.
void process(std::span< const float > input, std::span< float > left, std::span< float > right) override
Processes a block.
Reverb(const ReverbPreset &preset)
Definition send_effects.hpp:62
static constexpr int ring_size
Size of the shared delay ring.
Definition send_effects.hpp:60
static double send_gain(int send) noexcept
The send-bus gain for a part's delay send, 0–127.
Definition send_effects.hpp:177
SystemDelay(const DelayParameters &parameters)
static constexpr int ring_size
Size of the delay ring.
Definition send_effects.hpp:167
void reset() override
Clears all internal state.
static DelayParameters compile(std::span< const int > raw, int sample_rate=32000)
Compiles ten raw GS parameters into DSP coefficients.
static double ratio_percent(int raw)
Converts a raw ratio value, 1–120, to a percentage.
void process(std::span< const float > input, std::span< float > left, std::span< float > right) override
Processes a block.
static SystemDelay for_type(int type)
Creates a delay for a GS type 0–9.
static double time_milliseconds(int raw)
Converts a raw time value, 1–115, to milliseconds.
Definition control_decode.hpp:7
One allpass stage: a read tap, a write tap and the two coefficients around them.
Definition effect_presets.hpp:12
Coefficients for one GS chorus type.
Definition effect_presets.hpp:68
static constexpr double send_at_full_scale
Send-bus gain at controller 127.
Definition effect_presets.hpp:94
Compiled coefficients for one GS delay type.
Definition send_effects.hpp:151
double left_gain
Definition send_effects.hpp:156
double centre_gain
Definition send_effects.hpp:155
double send_to_reverb
Definition send_effects.hpp:160
double right_gain
Definition send_effects.hpp:157
int centre_samples
Definition send_effects.hpp:152
int pre_low_pass
Definition send_effects.hpp:159
int left_samples
Definition send_effects.hpp:153
double feedback
Definition send_effects.hpp:158
int right_samples
Definition send_effects.hpp:154
static constexpr double send_at_full_scale
Send-bus gain at full scale.
Definition effect_presets.hpp:104
static constexpr int pre_delay_samples
Fixed input pre-delay ahead of the feedback line, in samples — 60 ms at 32 kHz.
Definition effect_presets.hpp:109
Coefficients for one GS reverb type.
Definition effect_presets.hpp:53
static constexpr double send_at_full_scale
Send-bus gain at controller 127.
Definition effect_presets.hpp:84
One reverb tank.
Definition effect_presets.hpp:38
One reverb tank's eight ring offsets, resolved from their names once.
Definition effect_presets.hpp:26