Skip to main content

CompiledPedal

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: StageRoutePlan

Runtime 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: f64

Auto-calibrated output gain scalar (1.0 = no calibration).

§rail_saturation: RailSaturation§rail_sat_oversampler: Oversampler

Oversampler 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: f64

Supply 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: u64

Tolerance engine seed (stored for diagnostics).

§oversampling: OversamplingFactor

Oversampling 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: f64

Base (unmodulated) grid bias for push-pull stages. Stored so sidechain CV can be subtracted without accumulation.

§multi_nl_recompute_counter: u32

Sample 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: f64

BBD 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: bool

Auto-init flag: cache_all_vs_pointers runs once on first process() call.

Implementations§

§

impl CompiledPedal

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)

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

Get the tolerance seed for this pedal unit (for diagnostics/UI).

pub fn oversampling(&self) -> OversamplingFactor

Get the oversampling factor used for this pedal.

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>)>

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>)>

Debug: return multi-NL stage scattering info.

pub fn supply_voltage(&self) -> f64

Get the supply voltage.

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

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)

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)

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)

Clear source impedance modeling (use ideal voltage source).

pub fn clear_load_impedance(&mut self)

Clear load impedance modeling (use ideal open-circuit load).

pub fn has_source_impedance(&self) -> bool

Check if source impedance modeling is active.

pub fn has_load_impedance(&self) -> bool

Check if load impedance modeling is active.

pub fn set_debug_enabled(&self, _enabled: bool)

Enable or disable debug mode.

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>>

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

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)>

List all editable passive components across all stages.

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

Reset a passive component to its original value.

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>

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)

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 note_on(&mut self, note: u8, _velocity: u8)

Handle MIDI note-on by firing all trigger inputs.

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

Number of push-pull stages (for debug reporting).

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

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

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.

Trait Implementations§

§

impl PedalProcessor for CompiledPedal

§

fn process(&mut self, input: f64) -> f64

Process a single sample.
§

fn set_sample_rate(&mut self, rate: f64)

Set sample rate (call before processing).
§

fn reset(&mut self)

Reset all internal state.
§

fn set_control(&mut self, label: &str, value: f64)

Set a named control parameter (0.0-1.0). Default: no-op.
§

fn set_supply_voltage(&mut self, voltage: f64)

Set supply voltage in volts (default 9.0).
§

fn list_editable_components(&self) -> Vec<(String, &'static str, f64)>

List all editable passive components (R, C, L with comp_ids). Returns (comp_id, kind_str, current_value) for each editable leaf.
§

fn set_passive(&mut self, comp_id: &str, value: f64) -> bool

Set a passive component’s value by comp_id. Returns true if found.
§

fn reset_passive(&mut self, comp_id: &str) -> bool

Reset a passive component to its original value. Returns true if found.
§

fn control_debug_info(&self) -> Vec<(String, f64, f64)>

Debug: return current control state as (label, target_value, smoothed_value).
§

fn resolve_port(&self, name: &str) -> Option<usize>

Resolve a port name to its index in the ports slice. Call once at init to cache indices.
§

fn port_count(&self) -> usize

Number of declared ports (for allocating the ports slice).
§

fn process_ports(&mut self, ports: &mut [f64])

Process one sample with named port I/O. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more