26 if (device == Device::silicon)
return oversampled ?
"fuzz.silicon.x4" :
"fuzz.silicon.x1";
27 return oversampled ?
"fuzz.germanium.x4" :
"fuzz.germanium.x1";
42 return static_cast<float>(probe.
loop_gain());
47 t.type_id =
type_id(device, oversampled);
49 t.num_input_ports = t.num_output_ports = 1;
50 t.default_name = device == Device::silicon ?
"Fuzz (Silicon)" :
"Fuzz (Germanium)";
52 t.latency_samples = [oversampled](
double sample_rate) {
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) {
63 f.set_oversampling_enabled(oversampled);
65 f.set_drift_enabled(
false);
68 t.reset = [](
void* p) {
static_cast<Instance*
>(p)->
fuzz.reset(); };
69 t.baked_params = {{
kFuzz, 0.0f, 1.0f, 0.65f},
73 {
kMix, 0.0f, 1.0f, 1.0f},
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)]);
107 "Transistor-style fuzz with selectable device chemistry, bias starvation, "
108 "and source-impedance interaction.";
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}}},
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"}}},
128 {
"fuzz",
kFuzz,
"Fuzz",
"",
129 "Nonlinear intensity — how hard the pair is driven into its fuzz region.",
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.",
139 "Output trim applied after the nonlinearity.",
141 {
"mix",
kMix,
"Mix",
"%",
142 "Blend between the dry input and the fuzz output.",
145 "Slow deterministic component drift, modelling a circuit that is not "
148 {{
"off",
"Off", 0.0f}, {
"on",
"On", 1.0f}}},
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