Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
forge_fuzz_catalog.hpp
Go to the documentation of this file.
1#pragma once
2
3// FuzzPair bake catalog. Device chemistry and oversampling are realizations:
4// both are circuit identity, and oversampling changes reported latency.
5
9
10#include <cstdint>
11
13
15inline constexpr state::ParamID kFuzz = 1;
16inline constexpr state::ParamID kBiasStarve = 2;
17inline constexpr state::ParamID kSourceKohm = 3;
18inline constexpr state::ParamID kOutputDb = 4;
19inline constexpr state::ParamID kMix = 5;
20inline constexpr state::ParamID kDriftEnabled = 6;
21inline constexpr std::uint32_t kDeterministicDriftSeed = 0x46555a5au;
22
24
25inline const char* type_id(Device device, bool oversampled) noexcept {
26 if (device == Device::silicon) return oversampled ? "fuzz.silicon.x4" : "fuzz.silicon.x1";
27 return oversampled ? "fuzz.germanium.x4" : "fuzz.germanium.x1";
28}
29
36inline float worst_case_gain() {
37 signal::FuzzPair probe;
38 probe.set_device(Device::silicon);
39 probe.set_fuzz(1.0);
40 probe.set_bias_starve(0.0);
42 return static_cast<float>(probe.loop_gain());
43}
44
45inline CustomNodeType make_fuzz_node(Device device, bool oversampled = true) {
47 t.type_id = type_id(device, oversampled);
48 t.version = 1;
49 t.num_input_ports = t.num_output_ports = 1;
50 t.default_name = device == Device::silicon ? "Fuzz (Silicon)" : "Fuzz (Germanium)";
51 t.lowerable = true;
52 t.latency_samples = [oversampled](double sample_rate) {
53 signal::FuzzPair probe;
54 probe.set_oversampling_enabled(oversampled);
55 probe.prepare(sample_rate);
56 return probe.latency_samples();
57 };
58 t.create = []() -> void* { return new Instance{}; };
59 t.destroy = [](void* p) { delete static_cast<Instance*>(p); };
60 t.prepare = [device, oversampled](void* p, double sr, int) {
61 auto& f = static_cast<Instance*>(p)->fuzz;
62 f.set_device(device);
63 f.set_oversampling_enabled(oversampled);
64 f.set_seed(kDeterministicDriftSeed);
65 f.set_drift_enabled(false);
66 f.prepare(sr);
67 };
68 t.reset = [](void* p) { static_cast<Instance*>(p)->fuzz.reset(); };
69 t.baked_params = {{kFuzz, 0.0f, 1.0f, 0.65f},
70 {kBiasStarve, 0.0f, 1.0f, 0.0f},
71 {kSourceKohm, 0.1f, 1000.0f, 10.0f},
72 {kOutputDb, -24.0f, 24.0f, 0.0f},
73 {kMix, 0.0f, 1.0f, 1.0f},
74 {kDriftEnabled, 0.0f, 1.0f, 0.0f}};
75 t.process_instance_baked_param = [](void* p, audio::BufferView<float>& out,
76 const audio::BufferView<const float>& in, int n,
77 const BakedParamView& params) {
78 auto& f = static_cast<Instance*>(p)->fuzz;
79 const float* input = in.channel_ptr(0);
80 float* output = out.channel_ptr(0);
81 for (int i = 0; i < n; ++i) {
82 const auto offset = static_cast<std::int32_t>(i);
83 f.set_fuzz(params.value_at(kFuzz, offset));
84 f.set_bias_starve(params.value_at(kBiasStarve, offset));
85 f.set_source_impedance_kohm(params.value_at(kSourceKohm, offset));
86 f.set_output_level_db(params.value_at(kOutputDb, offset));
87 f.set_mix(params.value_at(kMix, offset));
88 f.set_drift_enabled(params.value_at(kDriftEnabled, offset) >= 0.5f);
89 output[static_cast<std::size_t>(i)] = f.process(input[static_cast<std::size_t>(i)]);
90 }
91 };
92 return t;
93}
94
95inline int latency_samples(bool oversampled, double sample_rate = 48000.0) {
96 signal::FuzzPair probe;
97 probe.set_oversampling_enabled(oversampled);
98 probe.prepare(sample_rate);
99 return probe.latency_samples();
100}
101
104 d.key = "fuzz";
105 d.label = "Fuzz";
106 d.description =
107 "Transistor-style fuzz with selectable device chemistry, bias starvation, "
108 "and source-impedance interaction.";
109 d.axes = {
110 {"device", "Device", "Transistor chemistry. Germanium is softer and more "
111 "temperature-dependent; silicon is harder and more stable.",
112 {{"silicon", "Silicon", 0.0f}, {"germanium", "Germanium", 1.0f}}},
113 {"oversampling", "Oversampling",
114 "Four-times oversampling trades reported latency for reduced aliasing.",
115 {{"x1", "Off", 0.0f}, {"x4", "4x", 1.0f}}},
116 };
117 d.realizations = {
118 {"silicon_x1", type_id(Device::silicon, false),
119 {{"device", "silicon"}, {"oversampling", "x1"}}},
120 {"silicon_x4", type_id(Device::silicon, true),
121 {{"device", "silicon"}, {"oversampling", "x4"}}},
122 {"germanium_x1", type_id(Device::germanium, false),
123 {{"device", "germanium"}, {"oversampling", "x1"}}},
124 {"germanium_x4", type_id(Device::germanium, true),
125 {{"device", "germanium"}, {"oversampling", "x4"}}},
126 };
127 d.params = {
128 {"fuzz", kFuzz, "Fuzz", "",
129 "Nonlinear intensity — how hard the pair is driven into its fuzz region.",
131 {"bias_starve", kBiasStarve, "Bias Starve", "",
132 "Starves the bias supply, producing gating, splatter, and note dropout.",
134 {"source_kohm", kSourceKohm, "Source Impedance", "kOhm",
135 "Impedance of the source feeding the input, which loads the circuit and "
136 "changes both gain and brightness.",
138 {"output_db", kOutputDb, "Output", "dB",
139 "Output trim applied after the nonlinearity.",
141 {"mix", kMix, "Mix", "%",
142 "Blend between the dry input and the fuzz output.",
144 {"drift_enabled", kDriftEnabled, "Drift", "",
145 "Slow deterministic component drift, modelling a circuit that is not "
146 "perfectly stable.",
148 {{"off", "Off", 0.0f}, {"on", "On", 1.0f}}},
149 };
150 return d;
151}
152
153} // namespace pulp::host::fuzz
Non-owning view over multi-channel audio sample data.
Definition buffer.hpp:30
Definition custom_node_type.hpp:51
void set_oversampling_enabled(bool on)
Test-only escape hatch: runs the nonlinearity at the base rate so the aliasing the oversampler remove...
Definition fuzz_pair.hpp:385
void set_bias_starve(double starve01)
0 = healthy supply, 1 = fully starved.
Definition fuzz_pair.hpp:355
int latency_samples() const noexcept
Reported exactly, never estimated (series law 5).
Definition fuzz_pair.hpp:471
void set_fuzz(double amount01)
Feedback-network engagement, 0..1.
Definition fuzz_pair.hpp:347
void set_device(Device device)
Definition fuzz_pair.hpp:338
double loop_gain() const
The linearised small-signal loop gain at the CURRENT operating point.
Definition fuzz_pair.hpp:455
void set_source_impedance_kohm(double kohm)
The Thévenin source impedance at the input jack: pickup, cable and — the part that matters — whatever...
Definition fuzz_pair.hpp:367
void prepare(double sample_rate)
Builds the oversampler's filter state. May allocate.
Definition fuzz_pair.hpp:307
The two-transistor direct-coupled feedback pair — the fuzz circuit whose character comes from its FEE...
Definition forge_fuzz_catalog.hpp:12
constexpr state::ParamID kMix
Definition forge_fuzz_catalog.hpp:19
constexpr state::ParamID kFuzz
Definition forge_fuzz_catalog.hpp:15
float worst_case_gain()
Tested small-signal feedback bound for the Forge registry.
Definition forge_fuzz_catalog.hpp:36
constexpr state::ParamID kSourceKohm
Definition forge_fuzz_catalog.hpp:17
constexpr state::ParamID kOutputDb
Definition forge_fuzz_catalog.hpp:18
constexpr std::uint32_t kDeterministicDriftSeed
Definition forge_fuzz_catalog.hpp:21
constexpr state::ParamID kBiasStarve
Definition forge_fuzz_catalog.hpp:16
const char * type_id(Device device, bool oversampled) noexcept
Definition forge_fuzz_catalog.hpp:25
constexpr state::ParamID kDriftEnabled
Definition forge_fuzz_catalog.hpp:20
CustomNodeType make_fuzz_node(Device device, bool oversampled=true)
Definition forge_fuzz_catalog.hpp:45
ForgeNodeDescriptor descriptor()
Definition forge_fuzz_catalog.hpp:102
int latency_samples(bool oversampled, double sample_rate=48000.0)
Definition forge_fuzz_catalog.hpp:95
signal::FuzzDevice Device
Definition forge_fuzz_catalog.hpp:14
@ 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
FuzzDevice
The two device families. They differ only in (n, Is).
Definition fuzz_pair.hpp:130
FuzzPairT< float > FuzzPair
Definition fuzz_pair.hpp:914
uint32_t ParamID
Unique parameter identifier, stable across plugin versions.
Definition parameter.hpp:55
Definition custom_node_type.hpp:90
Definition forge_param_descriptor.hpp:127
Definition forge_fuzz_catalog.hpp:23
signal::FuzzPair fuzz
Definition forge_fuzz_catalog.hpp:23