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

The diode bridge as a gain element: an exact 1/(1 + x) divider plus the audio-path curvature that divider's diodes actually impose. More...

#include <diode_bridge_compressor.hpp>

Public Member Functions

 DiodeBridgeGainT ()
void prepare (double)
 Present for lifecycle symmetry with the rest of the catalog.
void reset ()
void set_character (double character01)
 0..1 colour depth.
void set_adaa (bool on)
 Off is for measurement only — it is what the alias-reduction test compares against.
double drive () const
 The internal operating amplitude full-scale audio is mapped to.
double control_drive_for_current (double amperes) const
 The control drive produced by a physical bias current, in amps.
double dynamic_resistance (double amperes) const
 The bridge's small-signal dynamic resistance at a bias current, in ohms.
SampleType process (SampleType input, double control_drive)
 One sample.

Static Public Member Functions

static double gain_for_control_drive (double control_drive)
 g = 1/(1 + x).
static double control_drive_for_gain_db (double gain_reduction_db)
 x = 10^(|GR|/20) − 1, the drive that realises a given (negative) gain reduction in dB.
static double curvature (double control_drive)
 β(x) = β0·(1 + κ·x) — the curvature in force at a given control drive.
static double shape (double s, double beta)
 The odd cubic the balanced bridge imposes, with slope exactly 1 at the origin: shape(s) = s − β·s³/3.
static double shape_antiderivative (double s, double beta)
 ∫shape ds = s²/2 − β·s⁴/12.
static double max_operating_amplitude (double beta)
 Where the cubic stops being monotonic, less the safety margin.
static double third_harmonic_ratio (double s, double beta)
 Closed-form third-harmonic ratio of the shaper for a sine of amplitude s at curvature β, from the identity sin³θ = (3sinθ − sin3θ)/4:

Static Public Attributes

static constexpr double kIdeality = 1.9
 Emission coefficient of the bridge diodes.
static constexpr double kSaturationCurrent = 1e-14
 Reverse saturation current of one bridge diode.
static constexpr double kSeriesResistance = 1000.0
 Series reference resistance the bridge's variable resistance divides against.
static constexpr double kBaseCurvature = 0.5
 Base audio-path curvature, at rest.
static constexpr double kDriveCurvature = 0.6
 How fast curvature grows with control drive — the smooth-at-rest → overdriven-when-driven slope, as a slope rather than an adjective: β(x) = β0·(1 + κ·x).
static constexpr double kDriveBridgeMax = 0.20
 Internal operating amplitude at character = 1: full-scale audio maps to |s| ≤ kDriveBridgeMax, comfortably inside the monotonic region.
static constexpr double kDriveBridgeFloor = 0.3
 Fraction of kDriveBridgeMax still applied at character = 0.
static constexpr double kMaxControlDrive = 30.62
 Assumed worst-case control drive, used only to size the monotonicity guard's headroom claim.
static constexpr double kMonotonicMargin = 0.98
 Fraction of the 1/√β monotonicity limit the input clamp uses.
static constexpr double kAdaaEpsilon = 1e-5
 ADAA ill-conditioning guard on |s[n] − s[n−1]|.

Detailed Description

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

The diode bridge as a gain element: an exact 1/(1 + x) divider plus the audio-path curvature that divider's diodes actually impose.

The gain magnitude is not where the colour lives. That is deliberate and it is the point of the topology: the divider realises the requested gain reduction to within floating-point, and the harmonics come from a separate, separately-scaled shaper. A caller that wants gain reduction with no colour sets character low; a caller that wants colour at unity gain drives the shaper with control_drive = 0.

Small-signal gain is exactly g (series law 1). The shaper is applied to s = drive·u and divided back by drive, so its contribution to the input→output slope at the origin is shape'(0) = 1 identically, at every character setting. Without that normalisation the character knob would be a hidden level control of up to −24 dB, which is precisely the defect series law 1 exists to prevent.

Constructor & Destructor Documentation

◆ DiodeBridgeGainT()

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

Member Function Documentation

◆ control_drive_for_current()

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::control_drive_for_current ( double amperes) const
inline

The control drive produced by a physical bias current, in amps.

This is the one place (Is, n, V_T, Rs) are visible, and it is computed THROUGH the shared junction law rather than by restating Shockley's equation: the bias point is the junction's own conduction knee at that current, and 1/r_d is the junction's own incremental conductance there. x = Rs/r_d follows. Exposed because "resistance is inversely proportional to bias current" is the claim the whole topology rests on, and a claim a test can check is worth more than one it cannot.

◆ control_drive_for_gain_db()

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::control_drive_for_gain_db ( double gain_reduction_db)
inlinestatic

x = 10^(|GR|/20) − 1, the drive that realises a given (negative) gain reduction in dB.

◆ curvature()

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::curvature ( double control_drive)
inlinestatic

β(x) = β0·(1 + κ·x) — the curvature in force at a given control drive.

◆ drive()

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::drive ( ) const
inline

The internal operating amplitude full-scale audio is mapped to.

◆ dynamic_resistance()

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::dynamic_resistance ( double amperes) const
inline

The bridge's small-signal dynamic resistance at a bias current, in ohms.

n·V_T/(I + Is) — inverted from the same junction, not restated.

◆ gain_for_control_drive()

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::gain_for_control_drive ( double control_drive)
inlinestatic

g = 1/(1 + x).

The exact inverse of control_drive_for_gain_db(), so a sidechain that computes gain reduction in dB and inverts it gets that reduction back to within floating-point.

◆ max_operating_amplitude()

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::max_operating_amplitude ( double beta)
inlinestatic

Where the cubic stops being monotonic, less the safety margin.

◆ prepare()

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

Present for lifecycle symmetry with the rest of the catalog.

The shaper is memoryless, so there is no rate-dependent coefficient to compute; this only clears state. Never allocates.

◆ process()

template<typename SampleType = float>
SampleType pulp::signal::DiodeBridgeGainT< SampleType >::process ( SampleType input,
double control_drive )
inline

One sample.

control_drive is x; the gain 1/(1 + x) is DERIVED from it rather than passed alongside it.

The spec's signature takes a linear gain target AND a control drive. They are exact inverses of one another by §3.2, so accepting both admits an inconsistent pair — a caller that smooths one and not the other gets a gain law that silently stops matching its own gain reduction. One argument cannot disagree with itself.

◆ reset()

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

◆ set_adaa()

template<typename SampleType = float>
void pulp::signal::DiodeBridgeGainT< SampleType >::set_adaa ( bool on)
inline

Off is for measurement only — it is what the alias-reduction test compares against.

◆ set_character()

template<typename SampleType = float>
void pulp::signal::DiodeBridgeGainT< SampleType >::set_character ( double character01)
inline

0..1 colour depth.

Scales the internal operating amplitude only — it is not a level control and does not touch the gain law.

◆ shape()

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::shape ( double s,
double beta )
inlinestatic

The odd cubic the balanced bridge imposes, with slope exactly 1 at the origin: shape(s) = s − β·s³/3.

◆ shape_antiderivative()

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::shape_antiderivative ( double s,
double beta )
inlinestatic

∫shape ds = s²/2 − β·s⁴/12.

Even, as the antiderivative of an odd function must be — a sign error here would produce a waveform that is wrong on half of each cycle and still reads as "the distortion working".

◆ third_harmonic_ratio()

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::third_harmonic_ratio ( double s,
double beta )
inlinestatic

Closed-form third-harmonic ratio of the shaper for a sine of amplitude s at curvature β, from the identity sin³θ = (3sinθ − sin3θ)/4:

shape(s·sinθ) = s(1 − β·s²/4)·sinθ + (β·s³/12)·sin3θ
THD3 = (β·s³/12) / (s(1 − β·s²/4)) = β·s²/12 / (1 − β·s²/4)
static double shape(double s, double beta)
The odd cubic the balanced bridge imposes, with slope exactly 1 at the origin: shape(s) = s − β·s³/3.
Definition diode_bridge_compressor.hpp:293

Stated as a shipped function, not as a test-side literal, so the acceptance suite compares the measurement against the model rather than against a number someone typed. (The spec's worked example gives β·s²/3, which drops the factor of 4 from the sin³ expansion — see the module's defect log.)

Member Data Documentation

◆ kAdaaEpsilon

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::kAdaaEpsilon = 1e-5
staticconstexpr

ADAA ill-conditioning guard on |s[n] − s[n−1]|.

Must sit far below a typical sample-to-sample increment of the drive-scaled signal (at 1 kHz, full scale, character = 1, that increment is ~2.6e-2) and far above float epsilon. [design parameter] default 1e-5, range 1e-7 .. 1e-4.

◆ kBaseCurvature

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::kBaseCurvature = 0.5
staticconstexpr

Base audio-path curvature, at rest.

Tuned to the documented "low distortion by design" regime — see third_harmonic_ratio() for what it buys in measurable terms. Honest gap: no public measured THD-vs-drive curve for this bridge exists at citable precision. This, kDriveCurvature and kDriveBridgeMax are original engineering tuned to the documented QUALITATIVE behaviour, not lifted from hardware. [design parameter] default 0.5, range 0.0 .. 1.5.

◆ kDriveBridgeFloor

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::kDriveBridgeFloor = 0.3
staticconstexpr

Fraction of kDriveBridgeMax still applied at character = 0.

Nonzero so the block never becomes a bit-exact pass-through — the bridge is always in the audio path in hardware, and a character knob that reaches literal zero invites callers to use it as a bypass. [design parameter] default 0.3, range 0.0 .. 1.0.

◆ kDriveBridgeMax

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::kDriveBridgeMax = 0.20
staticconstexpr

Internal operating amplitude at character = 1: full-scale audio maps to |s| ≤ kDriveBridgeMax, comfortably inside the monotonic region.

[design parameter] default 0.20, range 0.05 .. 0.40.

◆ kDriveCurvature

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::kDriveCurvature = 0.6
staticconstexpr

How fast curvature grows with control drive — the smooth-at-rest → overdriven-when-driven slope, as a slope rather than an adjective: β(x) = β0·(1 + κ·x).

[design parameter] default 0.6, range 0.0 .. 2.0.

◆ kIdeality

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::kIdeality = 1.9
staticconstexpr

Emission coefficient of the bridge diodes.

Sets how many volts of bias buy a decade of current, and therefore the current scale of the control law — but it folds entirely into the dimensionless x, so no test can see it except through control_drive_for_current(). [design parameter] default 1.9, range 1.0 .. 2.0 (silicon signal-diode).

◆ kMaxControlDrive

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::kMaxControlDrive = 30.62
staticconstexpr

Assumed worst-case control drive, used only to size the monotonicity guard's headroom claim.

x = 30.62 is 30 dB of gain reduction. [design parameter] default 30.62, range 14.85 .. 99.0 (24 .. 40 dB).

◆ kMonotonicMargin

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::kMonotonicMargin = 0.98
staticconstexpr

Fraction of the 1/√β monotonicity limit the input clamp uses.

The cubic folds back beyond 1/√β; this keeps a margin so the fold is unreachable rather than merely unlikely. [design parameter] default 0.98, range 0.90 .. 0.99.

◆ kSaturationCurrent

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::kSaturationCurrent = 1e-14
staticconstexpr

Reverse saturation current of one bridge diode.

Order-of-magnitude for the device CLASS, never a measured part; like kIdeality it is visible only through the current→drive conversion. [design parameter] default 1e-14 A, range 1e-15 .. 1e-12 A.

◆ kSeriesResistance

template<typename SampleType = float>
double pulp::signal::DiodeBridgeGainT< SampleType >::kSeriesResistance = 1000.0
staticconstexpr

Series reference resistance the bridge's variable resistance divides against.

Fixes the control CURRENT that produces a given x; the gain law itself is independent of it. [design parameter] default 1e3 Ω, range 100 Ω .. 100 kΩ.


The documentation for this class was generated from the following file: