circuit.h
A nodal circuit engine (the DK method).
#include <sonore/circuit.h>- 1type
- Guides: Getting started, MIDI and MPE
On this page
Design notes
Every pedal and preamp in this SDK so far was derived by hand: write the ODE, discretise, solve. That is the right thing for a circuit with one nonlinearity and it is the wrong thing for a Fuzz Face, whose two transistors, four capacitors and a feedback loop make a hand derivation a week of algebra that is wrong somewhere. This is the general machine: a netlist goes in, and every sample the circuit's node voltages come out.
The method is Yeh's nodal DK (D. T. Yeh, "Automated physical modeling of nonlinear audio circuits for real-time audio effects", IEEE TASLP 2010, and the generalisation in Holters & Zölzer, DAFx 2015):
1. Modified nodal analysis stamps the linear elements into a conductance matrix A. Capacitors and inductors become trapezoidal COMPANION models -- a conductance plus a history current -- so the linear part of the circuit is one constant matrix per sample rate. 2. The nonlinear elements are pulled out as PORTS. With A inverted once, the circuit reduces to p = p0 - K i(p): the port voltages are an affine function of the port currents through a small matrix K. 3. That small system is solved by Newton's method every sample, warm- started from the previous sample, which is why it converges in two or three iterations at audio rates.
The cost per sample is the reduced system, not the whole matrix: for a Fuzz Face, a 4x4 Newton and one matrix-vector product.
Devices: resistor, capacitor, inductor, voltage source (the input signal and the supply are both sources), Shockley diode, Ebers-Moll BJT (NPN or PNP, transport form), Shichman-Hodges JFET (the phaser's variable resistor), and an IDEAL op-amp -- the MNA nullor: the solver enforces v+ == v- exactly, which is the op-amp of every pedal analysis in the literature (Yeh's Tube Screamer treatment assumes it; the pedal's clipping is its feedback diodes, not the chip). A circuit that relies on op-amp RAIL clipping needs a clipper stage after it, and a nullor with no feedback path makes the matrix singular, exactly like a real op-amp wired open-loop. Resistors and sources may change at run time -- a potentiometer is a resistor that moves -- and a resistor change re- factorises the linear part, so move pots at control rate, not per sample.
Two SPICE habits are kept because they are what makes a nodal solver robust: a gmin conductance from every node to ground (a node that only touches a capacitor is otherwise floating at DC), and junction voltage LIMITING in the Newton step (an unlimited step through an exponential overflows before it converges). The operating point at reset() is solved with the capacitors open, so the circuit starts settled instead of spending a quarter-second charging its coupling capacitors on air.
Everything is double: a 100k resistor next to a 1e-7 saturation current is eleven orders of magnitude, which float cannot carry through an inverse.
Included by dsp.h.
Types 1
No comment on this one in the header yet; the source says the rest.