Struct CompiledPedal
pub struct CompiledPedal {Show 49 fields
pub stages: Vec<Stage>,
pub stage_route_plan: StageRoutePlan,
pub push_pull_stages: Vec<PushPullStage>,
pub pre_gain: f64,
pub output_gain: f64,
pub rail_saturation: RailSaturation,
pub rail_sat_oversampler: Oversampler,
pub sample_rate: f64,
pub controls: Vec<ControlBinding>,
pub gain_range: (f64, f64),
pub supply_voltage: f64,
pub lfos: Vec<LfoBinding>,
pub envelopes: Vec<EnvelopeBinding>,
pub bbds: Vec<BbdDelayLine>,
pub delay_lines: Vec<DelayLineBinding>,
pub springs: Vec<SpringBinding>,
pub vcos: Vec<VcoBinding>,
pub vcas: Vec<VcaBinding>,
pub thermal: Option<ThermalModel>,
pub tolerance_seed: u64,
pub oversampling: OversamplingFactor,
pub opamp_stages: Vec<OpAmpStage>,
pub power_supply: Option<PowerSupply>,
pub metrics_accumulator: Option<MetricsAccumulator>,
pub metrics_buffer: Option<Arc<MetricsRingBuffer>>,
pub input_loading: Option<InterstageLoading>,
pub output_loading: Option<InterstageLoading>,
pub output_dc_block: Option<(f64, f64, f64, f64)>,
pub sidechains: Vec<SidechainProcessor>,
pub subcircuit_processors: Vec<SubcircuitProcessor>,
pub subcircuit_routing: Vec<RoutingStep>,
pub subcircuit_output_idx: Option<usize>,
pub subcircuit_outputs: Vec<f64>,
pub pot_smoothers: Vec<SmoothedParam>,
pub wiper_dividers: Vec<WiperDivider>,
pub pot_mirrors: HashMap<String, Vec<MirrorPot>>,
pub base_grid_bias: f64,
pub multi_nl_recompute_counter: u32,
pub node_signals: Vec<(usize, f64)>,
pub bbd_wet_mix: f64,
pub bbd_mix_pot_id: Option<String>,
pub triggers: Vec<TriggerState>,
pub original_passive_values: HashMap<String, (&'static str, f64)>,
pub ports: Vec<NamedPortBinding>,
pub port_values: Vec<f64>,
pub internal_ports: Vec<InternalPortBinding>,
pub boundary_loads: Vec<BoundaryLoadBinding>,
pub detector_led_coupling: Option<DetectorLedCoupling>,
pub initialized: bool,
}Expand description
A pedal processor compiled from a .pedal file’s netlist.
Each .pedal file produces a unique processor with its own WDF tree topology,
component values, and diode models — no hardcoded processor selection.
Fields§
§stages: Vec<Stage>All processing stages in signal-flow order. One vec, no index indirection.
stage_route_plan: StageRoutePlanRuntime execution plan derived from stage-owned boundary bindings.
push_pull_stages: Vec<PushPullStage>Push-pull differential stages (e.g., Fairchild 670 gain cell). These are processed after regular stages.
pre_gain: f64§output_gain: f64Auto-calibrated output gain scalar (1.0 = no calibration).
rail_saturation: RailSaturation§rail_sat_oversampler: OversamplerOversampler for rail saturation to anti-alias harmonics generated by the nonlinear clipping at supply rails.
sample_rate: f64§controls: Vec<ControlBinding>§gain_range: (f64, f64)§supply_voltage: f64Supply voltage in volts (default 9.0).
lfos: Vec<LfoBinding>LFO modulators.
envelopes: Vec<EnvelopeBinding>Envelope follower modulators.
bbds: Vec<BbdDelayLine>BBD delay lines for delay/chorus/flanger effects.
delay_lines: Vec<DelayLineBinding>Generic delay lines (tape echo, digital delay, Karplus-Strong, etc.).
springs: Vec<SpringBinding>Spring reverb tanks (dispersive electromechanical reverb islands).
vcos: Vec<VcoBinding>VCO audio-rate oscillator bindings (inject audio at circuit nodes).
vcas: Vec<VcaBinding>VCA amplitude modulation bindings (scale audio by envelope).
thermal: Option<ThermalModel>Thermal model for temperature-dependent behavior. When present, modulates diode Is and BJT gain over time.
tolerance_seed: u64Tolerance engine seed (stored for diagnostics).
oversampling: OversamplingFactorOversampling factor used for this pedal’s nonlinear stages.
opamp_stages: Vec<OpAmpStage>Op-amp stages for unity-gain buffers and gain stages. Each op-amp is modeled as a VCVS with the OpAmpRoot element.
power_supply: Option<PowerSupply>Power supply sag model.
When present, computes instantaneous B+ droop based on signal current draw
and feeds the sagged voltage into set_supply_voltage() each sample.
metrics_accumulator: Option<MetricsAccumulator>Metrics accumulator for real-time UI visualization.
Accumulates per-sample data and reduces to UiMetrics every block.
metrics_buffer: Option<Arc<MetricsRingBuffer>>Ring buffer for sending metrics to the UI thread (shared via Arc). Skipped for serde: AtomicUsize inside MetricsRingBuffer is not serializable, and the ring buffer is a runtime-only construct (not needed on M7 firmware).
input_loading: Option<InterstageLoading>Input loading model — models source impedance interaction at circuit input. Applies DC attenuation and frequency-dependent rolloff based on the source (e.g., guitar pickup, upstream pedal) driving this circuit.
output_loading: Option<InterstageLoading>Output loading model — models load impedance interaction at circuit output. Applies DC attenuation and frequency-dependent rolloff based on what this circuit is driving (e.g., downstream pedal, amp input).
output_dc_block: Option<(f64, f64, f64, f64)>Output DC blocker — first-order HPF at ~5 Hz to remove subsonic drift from integrator DC tails and opamp offset accumulation. Format: (a1, b0, y_prev, x_prev) for IIR highpass.
sidechains: Vec<SidechainProcessor>Sidechain processors for feedback compression loops. Each sidechain taps audio, extracts an envelope, and modulates the push-pull grid bias. Multiple sidechains are supported (e.g., one per channel in a stereo compressor like the 670).
subcircuit_processors: Vec<SubcircuitProcessor>Subcircuit processors (for equipment with subcircuit blocks).
When non-empty, process() delegates to process_subcircuits() and
the normal WDF stage pipeline is bypassed.
subcircuit_routing: Vec<RoutingStep>Routing steps defining signal flow between subcircuits (topological order).
subcircuit_output_idx: Option<usize>Index of the subcircuit whose output is the equipment output.
subcircuit_outputs: Vec<f64>Per-subcircuit output buffer (indexed by subcircuit_idx).
pot_smoothers: Vec<SmoothedParam>Smoothed parameters for zipper-free pot control. One per pot in the circuit that needs smoothing.
wiper_dividers: Vec<WiperDivider>Inter-stage wiper dividers for output Level/Volume pots. Applied in the serial stage chain after the specified stage index.
pot_mirrors: HashMap<String, Vec<MirrorPot>>Mirrored pot mappings: source_comp_id → list of mirrored pots. When a source pot is updated, each mirror gets position = 1.0 - source.
base_grid_bias: f64Base (unmodulated) grid bias for push-pull stages. Stored so sidechain CV can be subtracted without accumulation.
multi_nl_recompute_counter: u32Sample counter for throttling multi-NL scattering recomputes. When a pot inside a multi-NL R-type adaptor changes, the O(n³) matrix inversion is deferred and flushed every 32 samples (~0.7 ms at 48 kHz).
node_signals: Vec<(usize, f64)>Node-based signal routing buffer for parallel-path topologies. Maps circuit graph node IDs to signal values. When non-empty, multi-NL stages read from their injection_node_id and write to their output_node_id, enabling correct parallel channel processing (e.g., 670 sidechain).
bbd_wet_mix: f64BBD wet/dry mix (0.0 = fully dry, 1.0 = fully wet). Controlled by “Blend”/“Mix” knobs on BBD delay pedals.
bbd_mix_pot_id: Option<String>Component ID of the pot controlling BBD wet/dry mix. When set, the pot position is read directly after pot updates.
triggers: Vec<TriggerState>Trigger impulse sources for drum/percussion circuits.
original_passive_values: HashMap<String, (&'static str, f64)>Original passive component values for reset support.
Maps comp_id -> (kind_str, original_value).
Skipped for serde: &'static str cannot be deserialized from owned data.
Reconstructed on the M7 target if needed.
ports: Vec<NamedPortBinding>Named voltage port bindings (audio I/O, CV, gates, envelope outputs).
Ports inject/extract voltage at circuit nodes at audio rate without
impedance recompute. Declared in the .pedal ports {} section.
port_values: Vec<f64>Dense port value buffer — indexed by NamedPortBinding::index. Input ports: written by external code via set_port() before process(). Output ports: written by process(), read via get_port() after.
internal_ports: Vec<InternalPortBinding>Compiler-synthesized INTERNAL delayed ports (Phase 2b) — the z⁻¹ carry
table for de-fused sub-networks (e.g. the LA-2A detector taps + EL_drive).
Not user-overridable; written/read entirely inside process().
boundary_loads: Vec<BoundaryLoadBinding>Compile-time boundary-load decision table (analysis + policy outcome
per analyzed stage boundary). Purely descriptive — the runtime never
reads it; dashboards and triage tooling do. Empty when no boundary was
analyzed (currently only the output boundary of multi-BJT DC-feedback
MNA stages is analyzed; see compiler/boundary_load.rs).
detector_led_coupling: Option<DetectorLedCoupling>Compiler-synthesized DETECTOR → photocoupler-LED coupling (Phase 3) — the
gain-reduction loop closure for a cross-network feedback detector
(LA-2A). None for every other circuit (envelope-follower opto levelers
drive the LED via ModulationTarget::PhotocouplerLed, unchanged).
initialized: boolAuto-init flag: cache_all_vs_pointers runs once on first process() call.
Implementations§
§impl CompiledPedal
impl CompiledPedal
pub fn set_supply_voltage(&mut self, voltage: f64)
pub fn set_supply_voltage(&mut self, voltage: f64)
Set the supply voltage and update all voltage-dependent models.
This affects:
- Headroom for rail saturation modeling
- Op-amp output swing (v_max)
- Triode/pentode plate voltage limits (v_max = B+)
- BJT collector-emitter voltage limits (v_max = Vcc)
For single-supply pedals biased at Vsupply/2, the op-amp can swing from about 1.5V to (Vsupply - 1.5V), giving v_max ≈ (Vsupply/2) - 1.5V.
For tube circuits, the plate voltage can swing from 0V to B+ (supply). For BJT circuits, Vce can swing from ~0V to Vcc (supply).
pub fn cache_all_vs_pointers(&mut self)
pub fn cache_all_vs_pointers(&mut self)
Resolve and cache runtime-only state for all stages.
Must be called once after construction (or deserialization) and before
the first process() call. This:
- Caches raw pointers to VS leaves (eliminates per-sample tree walking)
- Precomputes K-table inverse scales (eliminates per-sample division)
- Precomputes StateSpace v_rail (eliminates per-sample division)
pub fn tolerance_seed(&self) -> u64
pub fn tolerance_seed(&self) -> u64
Get the tolerance seed for this pedal unit (for diagnostics/UI).
pub fn oversampling(&self) -> OversamplingFactor
pub fn oversampling(&self) -> OversamplingFactor
Get the oversampling factor used for this pedal.
pub fn wdf_element_counts(&self) -> (u32, u32)
pub fn wdf_element_counts(&self) -> (u32, u32)
Get the number of WDF stages and op-amp stages. Returns (stage_count, opamp_count).
pub fn opamp_debug_info(&self) -> Vec<(usize, f64, Option<String>)>
pub fn opamp_debug_info(&self) -> Vec<(usize, f64, Option<String>)>
Debug: return opamp gains and feedback pot IDs for all stages.
pub fn multi_nl_debug_info(
&self,
) -> Vec<(usize, usize, Vec<f64>, f64, Vec<f64>)>
pub fn multi_nl_debug_info( &self, ) -> Vec<(usize, usize, Vec<f64>, f64, Vec<f64>)>
Debug: return multi-NL stage scattering info.
pub fn supply_voltage(&self) -> f64
pub fn supply_voltage(&self) -> f64
Get the supply voltage.
pub fn input_impedance(&self) -> f64
pub fn input_impedance(&self) -> f64
Get the input impedance of this pedal (Ω).
Returns the WDF port resistance seen looking into the input. This is the impedance of the first WDF stage’s tree. If the pedal has no stages, returns high impedance (1MΩ).
pub fn output_impedance(&self) -> f64
pub fn output_impedance(&self) -> f64
Get the output impedance of this pedal (Ω).
Returns the WDF port resistance seen looking back into the output. This is the impedance of the last WDF stage’s tree. If the pedal has no stages, returns low impedance (1kΩ).
pub fn set_source_impedance(&mut self, resistance: f64, capacitance: f64)
pub fn set_source_impedance(&mut self, resistance: f64, capacitance: f64)
Set the source impedance driving this circuit’s input.
This models the electrical interaction between whatever is driving this circuit (guitar pickup, upstream pedal, preamp output) and the circuit’s input stage. The interaction produces:
- DC attenuation: voltage divider formed by source and load impedance
- Frequency-dependent rolloff: combined source/load capacitance creates a low-pass filter that rolls off high frequencies
§Arguments
resistance- Source resistance in Ohms (e.g., 7000 for guitar pickup)capacitance- Source capacitance in Farads (e.g., 500e-12 for cable)
§Example
// Guitar pickup through 15ft cable
pedal.set_source_impedance(7000.0, 500e-12);
// Buffered pedal output
pedal.set_source_impedance(1000.0, 50e-12);pub fn set_load_impedance(&mut self, resistance: f64, capacitance: f64)
pub fn set_load_impedance(&mut self, resistance: f64, capacitance: f64)
Set the load impedance this circuit drives.
This models the electrical interaction between this circuit’s output stage and whatever it’s driving (downstream pedal, amp input, mixer). The interaction produces:
- DC attenuation: if the load impedance is low relative to output impedance
- Frequency-dependent rolloff: if significant capacitance is present
§Arguments
resistance- Load resistance in Ohms (e.g., 1_000_000 for tube amp)capacitance- Load capacitance in Farads (e.g., 50e-12 for Miller cap)
§Example
// Driving a tube amp input
pedal.set_load_impedance(1_000_000.0, 50e-12);
// Driving a Fuzz Face (low impedance!)
pedal.set_load_impedance(10_000.0, 50e-12);pub fn clear_source_impedance(&mut self)
pub fn clear_source_impedance(&mut self)
Clear source impedance modeling (use ideal voltage source).
pub fn clear_load_impedance(&mut self)
pub fn clear_load_impedance(&mut self)
Clear load impedance modeling (use ideal open-circuit load).
pub fn has_source_impedance(&self) -> bool
pub fn has_source_impedance(&self) -> bool
Check if source impedance modeling is active.
pub fn has_load_impedance(&self) -> bool
pub fn has_load_impedance(&self) -> bool
Check if load impedance modeling is active.
pub fn set_debug_enabled(&self, _enabled: bool)
pub fn set_debug_enabled(&self, _enabled: bool)
Enable or disable debug mode.
pub fn enable_metering(&mut self, block_size: usize)
pub fn enable_metering(&mut self, block_size: usize)
Enable metering for real-time UI visualization.
Creates a metrics accumulator and ring buffer. Call this before starting
audio processing, then retrieve the ring buffer with metrics_buffer()
to read metrics in the UI thread.
block_size: Number of samples between metric reductions (typically 128 or 256).
pub fn metrics_buffer(&self) -> Option<Arc<MetricsRingBuffer>>
pub fn metrics_buffer(&self) -> Option<Arc<MetricsRingBuffer>>
Get a reference to the metrics ring buffer for UI thread reading.
Returns None if metering is not enabled.
pub fn read_metrics(&self) -> UiMetrics
pub fn read_metrics(&self) -> UiMetrics
Read the latest metrics (convenience method for the UI thread).
Returns default metrics if metering is not enabled.
pub fn list_editable_components(&self) -> Vec<(String, &'static str, f64)>
pub fn list_editable_components(&self) -> Vec<(String, &'static str, f64)>
List all editable passive components across all stages.
pub fn set_passive(&mut self, comp_id: &str, value: f64) -> bool
pub fn set_passive(&mut self, comp_id: &str, value: f64) -> bool
Set a passive component’s value by comp_id across all stages. Automatically determines component type from original_passive_values. After setting, recomputes all affected WDF tree coefficients.
pub fn reset_passive(&mut self, comp_id: &str) -> bool
pub fn reset_passive(&mut self, comp_id: &str) -> bool
Reset a passive component to its original value.
pub fn snapshot_original_values(&mut self)
pub fn snapshot_original_values(&mut self)
Populate original_passive_values from all stages’ current editable leaves. Should be called once after compilation is complete.
pub fn resolve_control(&self, label: &str) -> Vec<usize>
pub fn resolve_control(&self, label: &str) -> Vec<usize>
Set a control by its label (e.g., “Drive”, “Level”, “Rate”).
Resolve a control label to its binding indices. Call once at init,
then use [set_control_indexed] at audio rate to skip string matching.
Returns a vec of control indices that match the label (there may be multiple bindings for the same label, e.g., ganged pots).
pub fn set_control_indexed(&mut self, control_idx: usize, value: f64)
pub fn set_control_indexed(&mut self, control_idx: usize, value: f64)
Set a control by pre-resolved index. No string matching — O(1).
Use [resolve_control] at init to get the index, then call this
at audio rate for envelope-modulated parameters.
pub fn set_control(&mut self, label: &str, value: f64)
pub fn set_control_immediate(&mut self, label: &str, value: f64)
pub fn debug_stage_count(&self) -> usize
pub fn debug_stage_count(&self) -> usize
Debug dump: print complete pedal structure for debugging.
Number of WDF stages (for debug reporting).
pub fn debug_push_pull_count(&self) -> usize
pub fn debug_push_pull_count(&self) -> usize
Number of push-pull stages (for debug reporting).
pub fn debug_multi_nl_count(&self) -> usize
pub fn debug_multi_nl_count(&self) -> usize
Number of multi-NL stages (for debug reporting).
pub fn diag_snapshot(&self, pedal_name: &str, source_path: &str) -> DiagSnapshot
pub fn diag_snapshot(&self, pedal_name: &str, source_path: &str) -> DiagSnapshot
Shows gain structure, all WDF stages with their trees, and control bindings.
Build a read-only compile-time diagnostics snapshot of every MultiNl
stage (MNA scattering matrix, per-NL-port gm/companion, adapted port
resistances, extraction coefficients, VS injection) plus a coarse stage
listing. Derived on demand; behavior-preserving.
pedal_name/source_path are set by the caller (the std host knows the
source path; the rt crate does not).
pub fn debug_dump(&self) -> String
pub fn stage_graph_json(&self) -> String
pub fn stage_graph_json(&self) -> String
Machine-readable structured dump of the compiled stage structure.
This is the structured counterpart to debug_dump:
instead of prose it emits a JSON StageGraph so tooling (the tracing
IDE, structure diagnostics) can reason about the compiled pipeline.
Schema:
{
"schema": "pedalkernel.stage_graph/1",
"sample_rate": 48000.0,
"supply_voltage": 12.0,
"stage_count": 3,
"nodes": [
{ "id": 0, "kind": "MultiNl", "label": "...",
"flow_order": 1, "feedback_ports": 0, "nl_root_count": 3,
"nl_port_count": 6, "bypass_serial": false }
],
"edges": [
{ "from": 0, "to": 1, "kind": "Flow" }
]
}Edges (Phase 1b) are inter-stage Flow edges derived from the
flow-distance ordering of audio-path (non-bypass_serial) stages.