Skip to content

Sag

Tier: Color | ComponentType: 23 | Params: 4

Power supply voltage sag simulation -- models the dynamic compression that occurs when a tube amplifier's power supply cannot keep up with the signal demand.

Overview

Sag simulates the behavior of an under-rated power supply in a tube amplifier. When the amplifier draws more current than the power supply can deliver (during loud passages or hard transients), the supply voltage droops, reducing the amplifier's headroom. This creates a natural, signal-dependent compression that responds to the energy content of the music rather than just peak levels. The effect is most noticeable on percussive transients: the initial attack passes through at full voltage, then the supply sags under sustained load, compressing the sustain portion of the signal.

The sag behavior is controlled by four parameters that shape the energy tracking and voltage response envelope. The energy window sets how quickly the circuit responds to changes in signal level. The droop speed controls how fast the voltage drops under load -- shorter values create a tighter, more responsive sag that follows individual note attacks. The recovery speed controls how slowly the voltage returns to full -- longer values create the "breathing" compression feel of vintage amplifiers with large filter capacitors.

The asymmetric envelope (fast droop, slow recovery) is the key characteristic that distinguishes power supply sag from conventional compression. A compressor responds to peak or RMS levels with attack/release controls. Sag responds to the integral of energy over time, with an inherently asymmetric response that creates the "bloom" effect heard in cranked Fender and Vox amplifiers.

File Locations

Path
Header Sources/FolioDSP/include/FolioDSP/Color/Sag.h
Implementation Sources/FolioDSP/src/Color/Sag.cpp
Tests Tests/FolioDSPTests/SagTests.swift
Bridge Sources/FolioDSPBridge/src/FolioDSPBridge.mm (SagBridge)

Parameters

Index Name Description Min Max Default Min Default Max Default Unit
0 Sag Amount How much the supply voltage drops under load 0.0 1.0 0.0 0.8 0.5
1 Droop Speed Time constant for voltage to drop under load 0.1 50 0.5 10 5 ms
2 Recovery Speed Time constant for voltage to recover after load decreases 10 2000 50 500 200 ms
3 Energy Window Averaging window for input energy tracking 1 500 10 100 50 ms

Processing Algorithm

The process() function executes these steps for each input sample:

1. Energy Tracking

A one-pole lowpass filter tracks the squared input signal, accumulating a smoothed energy estimate:

\[\alpha_e = 1 - e^{-2\pi / (W \cdot f_s / 1000)}\]
\[E_n = E_{n-1} + \alpha_e \cdot (x^2 - E_{n-1})\]

Where \(W\) is the energy window in milliseconds. This produces a smoothed estimate of the signal's instantaneous power.

2. Target Voltage

The target supply voltage is derived from the square root of accumulated energy, scaled by the sag amount:

\[V_{\text{target}} = 1 - S \cdot \sqrt{\max(0,\; E_n)}\]
\[V_{\text{target}} = \text{clamp}(V_{\text{target}},\; 0.01,\; 1.0)\]

Where \(S\) is the sag amount. The square root compresses the energy response, preventing the voltage from collapsing too aggressively on loud signals. The minimum clamp of 0.01 prevents complete silence.

3. Asymmetric Envelope

The supply voltage follows the target with different time constants for drooping (fast) and recovering (slow):

\[\alpha = \begin{cases} 1 - e^{-2\pi / (T_d \cdot f_s / 1000)} & \text{if } V_{\text{target}} < V_n \text{ (droop)} \\ 1 - e^{-2\pi / (T_r \cdot f_s / 1000)} & \text{if } V_{\text{target}} \geq V_n \text{ (recovery)} \end{cases}\]
\[V_{n+1} = V_n + \alpha \cdot (V_{\text{target}} - V_n)\]

Where \(T_d\) is droop speed and \(T_r\) is recovery speed, both in milliseconds.

4. Apply Voltage

The output is simply the input scaled by the current supply voltage:

\[y = x \cdot V_n\]

5. Gain Reduction

For monitoring purposes, gain reduction is computed in decibels:

\[\text{GR} = 20 \cdot \log_{10}(V_n)\]

Clamped to \(-60\) dB when \(V_n\) approaches zero.

Core Equations

\[E_n = \text{LP}(x^2, \alpha_e)\]
\[V_{\text{target}} = \text{clamp}(1 - S\sqrt{E_n},\; 0.01,\; 1)\]
\[V_{n+1} = V_n + \alpha_{\text{asym}} \cdot (V_{\text{target}} - V_n)\]
\[y = x \cdot V_n\]

Snapshot Fields

Field Type Range Unit Description
Input Level Float 0--1 Smoothed absolute input level
Output Level Float 0--1 Smoothed absolute output level
Supply Voltage Float 0--1 Current simulated supply voltage
Energy Level Float 0--1 Smoothed energy accumulator value
Sag Amount Float 0--1 Current sag amount parameter value
Gain Reduction Float -60--0 dB Gain reduction in decibels

Implementation Notes

  • currentHeadroom() method: Exposes the current supply voltage for external monitoring. The bridge exposes this as a separate method on SagBridge.
  • Energy accumulator: Uses \(x^2\) (instantaneous power) rather than \(|x|\) (peak level), making the sag respond to sustained energy rather than transient peaks. This more accurately models how a power supply capacitor discharges.
  • Minimum voltage clamp: The target is clamped to 0.01 (not 0.0) to prevent the output from going completely silent, which would also prevent the energy tracker from ever recovering.
  • Level tracking uses exponential smoothing with coefficient 0.01 for display-rate visualization.
  • All parameters are marked as smoothed in ParamInfo for bridge-level interpolation.
  • Snapshot emission is decimated to ~60 fps (every 735 samples at 44.1 kHz).

Equation Summary

y = x ยท sag(energy(x))