Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::signal::DiodeClipperT< SampleType > Class Template Reference

The diode-to-ground clipper: series resistor, shunt diode network, optional shunt capacitor. More...

#include <distortion.hpp>

Public Types

using Model = DiodeModel

Public Member Functions

 DiodeClipperT ()
void prepare (double sample_rate)
void set_diode_model (Model model)
void set_symmetry (double symmetry)
 −1 = single diode (half-wave), 0 = matched pair, +1 = mismatched pair.
void set_resistance (double ohms)
void set_capacitance (double farads)
 Zero is the degenerate memoryless configuration: a solver limit case for tests, not a shipped preset.
void reset ()
 Antiderivative antialiasing is NOT offered on this class, deliberately.
int last_iteration_count () const
 Iterations the last solve took.
SampleType process (SampleType input)
double voltage () const
 The node voltage without advancing — for tests that check the ODE's residual directly.
double resistive_residual (double vin, double v) const
 (vin − v)/R − i_D(v), the residual the memoryless (C = 0) solution must drive to zero.

Static Public Attributes

static constexpr double kResistanceDefault = 10000.0
 Series input resistor.
static constexpr double kCapacitanceDefault = 51e-12
 Shunt capacitor — the memory element.

Detailed Description

template<typename SampleType = float>
class pulp::signal::DiodeClipperT< SampleType >

The diode-to-ground clipper: series resistor, shunt diode network, optional shunt capacitor.

C·dv/dt = (vin − v)/R − i_D(v), solved by TR-BDF2 with safeguarded Newton-Raphson inner solves.

Member Typedef Documentation

◆ Model

template<typename SampleType = float>
using pulp::signal::DiodeClipperT< SampleType >::Model = DiodeModel

Constructor & Destructor Documentation

◆ DiodeClipperT()

template<typename SampleType = float>
pulp::signal::DiodeClipperT< SampleType >::DiodeClipperT ( )
inline

Member Function Documentation

◆ last_iteration_count()

template<typename SampleType = float>
int pulp::signal::DiodeClipperT< SampleType >::last_iteration_count ( ) const
inline

Iterations the last solve took.

Exposed so the RT-safety cap can be asserted rather than assumed.

◆ prepare()

template<typename SampleType = float>
void pulp::signal::DiodeClipperT< SampleType >::prepare ( double sample_rate)
inline

◆ process()

template<typename SampleType = float>
SampleType pulp::signal::DiodeClipperT< SampleType >::process ( SampleType input)
inline

◆ reset()

template<typename SampleType = float>
void pulp::signal::DiodeClipperT< SampleType >::reset ( )
inline

Antiderivative antialiasing is NOT offered on this class, deliberately.

It was, and it diverged: a 440 Hz full-scale sine reached 5.8e25, growing geometrically at roughly 3300x per sample, on every diode model and at 8/48/192 kHz. It never reported failure because every value stayed finite, and no test saw it because the only ADAA assertion compared two renders for equality — which a deterministic divergence passes.

The cause is structural, not a bug to patch. ADAA replaces the diode term with its MEAN over [v(n-1), v(n)], but trapezoidal rule is already averaging the nonlinearity across the timestep. Stacking the two double-counts the averaging, so the residual's root moves outside the bracket [min(0, v(n-1), vin), max(...)] that makes the safeguarded solve safe; the solver then clamps to an endpoint and the state ratchets away. Matching the Jacobian to the residual (which was ALSO wrong here — it used the plain conductance) is necessary and not sufficient: with a finite-difference-verified derivative it still diverges.

Doing this properly means antialiasing the explicit output shaping rather than the implicit term, which is a different design and wants its own validation. Until then the honest position is that the x1 path has no antialiasing and the oversampled tiers are how you get it.

JunctionPair::adaa_current remains, and remains correct: it is sound for a MEMORYLESS shaper, which is how diode_bridge_compressor.hpp uses it. The unsoundness is specific to putting it inside this implicit solve.

◆ resistive_residual()

template<typename SampleType = float>
double pulp::signal::DiodeClipperT< SampleType >::resistive_residual ( double vin,
double v ) const
inline

(vin − v)/R − i_D(v), the residual the memoryless (C = 0) solution must drive to zero.

◆ set_capacitance()

template<typename SampleType = float>
void pulp::signal::DiodeClipperT< SampleType >::set_capacitance ( double farads)
inline

Zero is the degenerate memoryless configuration: a solver limit case for tests, not a shipped preset.

◆ set_diode_model()

template<typename SampleType = float>
void pulp::signal::DiodeClipperT< SampleType >::set_diode_model ( Model model)
inline

◆ set_resistance()

template<typename SampleType = float>
void pulp::signal::DiodeClipperT< SampleType >::set_resistance ( double ohms)
inline

◆ set_symmetry()

template<typename SampleType = float>
void pulp::signal::DiodeClipperT< SampleType >::set_symmetry ( double symmetry)
inline

−1 = single diode (half-wave), 0 = matched pair, +1 = mismatched pair.

◆ voltage()

template<typename SampleType = float>
double pulp::signal::DiodeClipperT< SampleType >::voltage ( ) const
inline

The node voltage without advancing — for tests that check the ODE's residual directly.

Member Data Documentation

◆ kCapacitanceDefault

template<typename SampleType = float>
double pulp::signal::DiodeClipperT< SampleType >::kCapacitanceDefault = 51e-12
staticconstexpr

Shunt capacitor — the memory element.

Rolls the generated harmonics off before they alias and softens the clip corners. [design parameter] default 51 pF, range 0 .. 500 pF.

◆ kResistanceDefault

template<typename SampleType = float>
double pulp::signal::DiodeClipperT< SampleType >::kResistanceDefault = 10000.0
staticconstexpr

Series input resistor.

Sets the ODE's time-constant scale jointly with C. Not a reproduction of any pedal's input resistor. [design parameter] default 10 kΩ, range 1 kΩ .. 100 kΩ.


The documentation for this class was generated from the following file:
  • /home/runner/work/pulp/pulp/core/signal/include/pulp/signal/distortion.hpp