72 case Shape::atan_soft:
74 case Shape::cubic_soft:
78 case Shape::tanh_soft:
86 case Shape::atan_soft:
87 return "Saturator (Arctan)";
88 case Shape::cubic_soft:
89 return "Saturator (Cubic)";
91 return "Saturator (Sinh-Arc)";
92 case Shape::tanh_soft:
94 return "Saturator (Tanh)";
100 case AliasPolicy::oversample_2x:
102 case AliasPolicy::off:
104 case AliasPolicy::adaa:
112 case Shape::tanh_soft:
113 case Shape::atan_soft:
114 case Shape::cubic_soft:
115 case Shape::sinh_arc:
118 return Shape::tanh_soft;
124 case AliasPolicy::adaa:
125 case AliasPolicy::oversample_2x:
126 case AliasPolicy::off:
129 return AliasPolicy::adaa;
158 if (fixed_alias_policy != AliasPolicy::adaa)
161 t.num_input_ports = 1;
162 t.num_output_ports = 1;
165 t.latency_samples = [fixed_shape, fixed_alias_policy](
double sample_rate) {
175 t.prepare = [fixed_shape, fixed_alias_policy](
void* p,
double sr,
int ) {
177 s->saturator.set_shape(fixed_shape);
178 s->saturator.set_alias_policy(fixed_alias_policy);
179 s->saturator.prepare(sr);
187 t.baked_params.push_back({
kDriveDb,
static_cast<float>(Sat::kDriveDbMin),
188 static_cast<float>(Sat::kDriveDbMax),
189 static_cast<float>(Sat::kDriveDbDefault)});
190 t.baked_params.push_back({
kBias, -1.0f, 1.0f, 0.0f});
191 t.baked_params.push_back({
kTonePreHz, 0.0f,
static_cast<float>(Sat::kTonePreHzMax),
192 static_cast<float>(Sat::kTonePreHzDefault)});
193 t.baked_params.push_back({
kMix, 0.0f, 1.0f, 1.0f});
194 t.baked_params.push_back({
kOutputTrimDb, -
static_cast<float>(Sat::kOutputTrimDbMax),
195 static_cast<float>(Sat::kOutputTrimDbMax), 0.0f});
197 t.baked_params.push_back({
kToneDeHz, 0.0f,
static_cast<float>(Sat::kTonePreHzMax),
198 static_cast<float>(Sat::kTonePreHzDefault)});
199 t.baked_params.push_back({
kPreBoostDb, 0.0f,
static_cast<float>(Sat::kPreBoostDbMax),
200 static_cast<float>(Sat::kPreBoostDbDefault)});
206 const float* input = in.channel_ptr(0);
207 float* output = out.channel_ptr(0);
214 for (
int k = 0; k < n; ++k) {
215 const auto offset =
static_cast<std::int32_t
>(k);
216 s->saturator.set_drive_db(params.value_at(
kDriveDb, offset));
217 s->saturator.set_bias(params.value_at(
kBias, offset));
218 s->saturator.set_tone_pre_hz(params.value_at(
kTonePreHz, offset));
219 s->saturator.set_tone_tracking(params.value_at(
kToneTracking, offset) >= 0.5f);
220 s->saturator.set_tone_de_hz(params.value_at(
kToneDeHz, offset));
221 s->saturator.set_pre_boost_db(params.value_at(
kPreBoostDb, offset));
222 s->saturator.set_mix(params.value_at(
kMix, offset));
223 s->saturator.set_output_trim_db(params.value_at(
kOutputTrimDb, offset));
224 output[
static_cast<std::size_t
>(k)] =
225 s->saturator.process(input[
static_cast<std::size_t
>(k)]);
235 "Memoryless waveshaping with four harmonic curves and a construction-time "
236 "anti-aliasing policy.",
239 "Selects the fixed transfer curve and harmonic character.",
240 {{
"tanh",
"Tanh", 0.0f},
241 {
"atan",
"Arctan", 1.0f},
242 {
"cubic",
"Cubic", 2.0f},
243 {
"sinh_arc",
"Sinh-Arc", 3.0f}}},
246 "Selects antiderivative anti-aliasing, two-times oversampling, or the raw curve.",
247 {{
"adaa",
"ADAA", 0.0f}, {
"x2",
"2x Oversampling", 1.0f}, {
"off",
"Off", 2.0f}}}},
248 {{
"tanh_adaa",
"saturator.tanh", {{
"shape",
"tanh"}, {
"alias_policy",
"adaa"}}},
249 {
"tanh_x2",
"saturator.tanh.x2", {{
"shape",
"tanh"}, {
"alias_policy",
"x2"}}},
250 {
"tanh_off",
"saturator.tanh.off", {{
"shape",
"tanh"}, {
"alias_policy",
"off"}}},
251 {
"atan_adaa",
"saturator.atan", {{
"shape",
"atan"}, {
"alias_policy",
"adaa"}}},
252 {
"atan_x2",
"saturator.atan.x2", {{
"shape",
"atan"}, {
"alias_policy",
"x2"}}},
253 {
"atan_off",
"saturator.atan.off", {{
"shape",
"atan"}, {
"alias_policy",
"off"}}},
254 {
"cubic_adaa",
"saturator.cubic", {{
"shape",
"cubic"}, {
"alias_policy",
"adaa"}}},
255 {
"cubic_x2",
"saturator.cubic.x2", {{
"shape",
"cubic"}, {
"alias_policy",
"x2"}}},
256 {
"cubic_off",
"saturator.cubic.off", {{
"shape",
"cubic"}, {
"alias_policy",
"off"}}},
258 "saturator.sinh_arc",
259 {{
"shape",
"sinh_arc"}, {
"alias_policy",
"adaa"}}},
261 "saturator.sinh_arc.x2",
262 {{
"shape",
"sinh_arc"}, {
"alias_policy",
"x2"}}},
264 "saturator.sinh_arc.off",
265 {{
"shape",
"sinh_arc"}, {
"alias_policy",
"off"}}}},
270 "Input gain applied before the transfer curve.",
279 "Offsets the transfer curve to introduce asymmetric harmonics.",
288 "Sets the pre-emphasis corner; zero disables the stage.",
297 "Blends the latency-aligned dry and saturated signals.",
306 "Applies gain after the wet/dry blend.",
315 "Makes the de-emphasis corner track the pre-emphasis corner.",
318 {{
"off",
"Off", 0.0f}, {
"on",
"On", 1.0f}},
324 "Sets the independent post-shaper de-emphasis corner when tracking is off.",
333 "Boosts the pre-emphasis stage before nonlinear shaping.",
Non-owning view over multi-channel audio sample data.
Definition buffer.hpp:30
Definition custom_node_type.hpp:51
void set_alias_policy(AliasPolicy policy)
Select the alias policy.
Definition saturator.hpp:548
void prepare(double sample_rate)
Sizes the oversampler and the dry-path alignment delay. May allocate.
Definition saturator.hpp:465
void set_bias(double normalized)
Bias as a normalised [-1, +1].
Definition saturator.hpp:507
void set_shape(Shape shape)
Definition saturator.hpp:490
double worst_case_gain() const
The supremum of |shaped(x) / x| over every input, at the current shape and bias — the bound Forge's r...
Definition saturator.hpp:670
int latency_samples() const noexcept
The integer delay the host should compensate, matched on the dry path.
Definition saturator.hpp:574
Definition forge_saturator_catalog.hpp:44
constexpr const char * kTanhTypeId
Definition forge_saturator_catalog.hpp:50
constexpr state::ParamID kTonePreHz
Definition forge_saturator_catalog.hpp:59
AliasPolicy normalized_alias_policy(AliasPolicy policy) noexcept
Definition forge_saturator_catalog.hpp:122
constexpr state::ParamID kPreBoostDb
Definition forge_saturator_catalog.hpp:64
signal::SaturatorShape Shape
Definition forge_saturator_catalog.hpp:46
signal::SaturatorAliasPolicy AliasPolicy
Definition forge_saturator_catalog.hpp:47
constexpr state::ParamID kMix
Definition forge_saturator_catalog.hpp:60
CustomNodeType make_saturator_node(Shape shape, AliasPolicy alias_policy=AliasPolicy::adaa)
One factory, four registered realizations.
Definition forge_saturator_catalog.hpp:152
const char * alias_policy_id(AliasPolicy policy) noexcept
Definition forge_saturator_catalog.hpp:98
constexpr state::ParamID kDriveDb
Definition forge_saturator_catalog.hpp:57
constexpr const char * kSinhArcTypeId
Definition forge_saturator_catalog.hpp:53
constexpr state::ParamID kOutputTrimDb
Definition forge_saturator_catalog.hpp:61
float saturator_worst_case_gain(Shape shape)
The largest gain this realization can present, for the Forge registry's worst_case_gain row (series l...
Definition forge_saturator_catalog.hpp:141
constexpr const char * kAtanTypeId
Definition forge_saturator_catalog.hpp:51
constexpr const char * kCubicTypeId
Definition forge_saturator_catalog.hpp:52
Shape normalized_shape(Shape shape) noexcept
Definition forge_saturator_catalog.hpp:110
constexpr state::ParamID kToneDeHz
Definition forge_saturator_catalog.hpp:63
ForgeNodeDescriptor saturator_descriptor()
Definition forge_saturator_catalog.hpp:231
constexpr state::ParamID kToneTracking
Definition forge_saturator_catalog.hpp:62
constexpr state::ParamID kBias
Definition forge_saturator_catalog.hpp:58
const char * saturator_type_id(Shape shape)
Definition forge_saturator_catalog.hpp:70
const char * saturator_default_name(Shape shape)
Definition forge_saturator_catalog.hpp:84
@ stepped
Definition forge_param_descriptor.hpp:25
@ continuous
Definition forge_param_descriptor.hpp:25
@ logarithmic
Definition forge_param_descriptor.hpp:29
@ linear
Definition forge_param_descriptor.hpp:29
SaturatorShape
Which member of the waveshaper family a SaturatorT evaluates.
Definition saturator.hpp:136
SaturatorAliasPolicy
How a SaturatorT keeps the harmonics it generates from folding back.
Definition saturator.hpp:144
SaturatorT< float > Saturator
Definition saturator.hpp:844
uint32_t ParamID
Unique parameter identifier, stable across plugin versions.
Definition parameter.hpp:55
The memoryless saturation stage every drive, fuzz, tube and tape-warmth block in the catalog composes...
Definition custom_node_type.hpp:90
Definition forge_param_descriptor.hpp:127
Definition forge_saturator_catalog.hpp:66
signal::Saturator saturator
Definition forge_saturator_catalog.hpp:67