@maruaudio/dsp/distortion/triode-stage is a static common-cathode triode gain stage on a resistive load line, an original numerical implementation of Koren's triode equation (Eq. 4, Table 1) with his 12AX7 values: MU 100, EX 1.4, KG1 1060, KP 600, KVB 300. triodePlateCurrent(Vplate, Vgrid) evaluates the plate current; triodePlateVoltage(Vgrid) solves Vplate + 100 kΩ × Iplate = 300 V with a safeguarded Newton method of at most 16 iterations. Per sample:
grid = bias + clamp(x, ±16) × 3 V × drive
y = tone(dcBlock((plate(bias) − plate(grid)) / 150 V)) × outputParameters
configureTriodeStage(state, driveDb, biasVolts, toneHz, outputDb) uses clampFiniteWithFallback (@maru/math-range):
| Argument | Range | Fallback and init |
|---|---|---|
driveDb | 0 to 36 dB (@maru/math-decibels) | 0 dB |
biasVolts | 0.5 to 3, the magnitude of a negative grid bias | 1.5 V |
toneHz | 500 Hz to min(16 kHz, 0.45 × rate) | 16 kHz |
outputDb | −24 to 0 dB | 0 dB |
Lifecycle
initTriodeStage(rate) (8 to 192 kHz, fallback 48 kHz) → configureTriodeStage → triodeStageTick, once per channel → resetTriodeStage, which clears the 10 Hz DC blocker (@maru/filters-dc-block) and the tone filter (@maru/filters-tone) and keeps the controls. Each tick runs the bounded Newton solve. Nothing allocates or does I/O.
When to use it
A single tube-style gain stage on guitar, bass or keys, driven harder for more curvature, inside a larger chain.
Limits
- Mono sample tick. It is a static stage, not a complete or calibrated amplifier: no cathode or supply memory, parasitic capacitance, grid current or oversampling, so high drive at high frequency can alias.
- The grid is clamped to −20 to 0 V; positive-grid current is outside the model.