Real-time

Peak

one-pole
time-domainreal-timesingle-carrierpeak ≈ 1.0×

An envelope detector traces the loudness contour of a waveform — the slow outline riding over the fast carrier inside it. Every graph on this page is drawn by the method's real algorithm, and the sliders at the top drive all of them at once.

The whole method, live

Peak
level 0.701280 samples
Hilbert refPeak
Attack4 samp (0.1 ms)
Release32 samp (0.7 ms)

Score card

Causality
real-time
Signal model
single-carrier
Reads
peak ≈ 1.0×
Latency
attack/release
Cost
trivial
Domain
time
Reads (measured on a steady sine)0.86×

Tracking error vs the true envelope, by challenge axis — longer bar is a tighter fit. Computed live across the oracle generators.

Temporal
14%
Robust
26%
Spectral
10%
Boundary
13%

How it works

The default smoother: cheap, causal, and endlessly tunable. Rectify with |x|, then run a one-pole low-pass with separate attack and release coefficients so the curve can rise fast and fall slow — exactly the attack/release shape a compressor or gate wants.

Watch out: it settles toward the average of the rectified signal, not the true peak, and if you set either time shorter than the carrier period it starts tracking individual cycles and ripples.

Key terms

Rectifier
The |x| step that folds the negative half of the waveform upward, the way a diode does in an analog detector. Every sample becomes positive so a smoother can settle toward amplitude instead of averaging back to zero.
One-pole low-pass
A single-coefficient smoother: y += k · (x − y). Each output is nudged a fraction k of the way toward the new input — a leaky integrator that melts ripple into a smooth line.
Attack / release
The two time constants of the smoother: attack sets how fast the curve rises onto a louder section, release how slowly it falls back. Splitting them is what gives the envelope its fast-up, slow-down shape.

Building the envelope, step by step

Each step adds one idea and shows a graph with only that principle applied — drawn by the real algorithm on the page's own input, working up to the finished curve.

  1. Step 1The carrier

    Start with the raw waveform — a fast carrier whose height swells and fades. The envelope is the slow outline we want, not the fast wiggle inside it.

  2. Step 2Rectify

    Fold the negative half upward with |x|, the way a diode does in an analog detector. Every sample is now positive, so a smoother can settle toward the amplitude instead of averaging back to zero.

  3. Step 3One-pole smoothing

    Low-pass the rectified signal with a one-pole filter — rising on a fast attack, falling on a slow release. The ripple melts into a smooth line that hugs the swell: the envelope.

The code

Six readable forms of the exact algorithm that draws the curves above — C, JS and Python ports, an optimized C, a fixed-coefficient version, and a user-controlled one whose parameters match the sliders.

#include <math.h>

/* exp(-1/tau): the one-pole coefficient for a time constant of
   tau samples. Clamped at 1 so a tiny tau can't blow up. */
static double decay_coeff(double tau) {
    return exp(-1.0 / (tau < 1.0 ? 1.0 : tau));
}

/* Peak envelope: rectify, then a one-pole low-pass that rises on the
   attack coefficient and falls on the (slower) release coefficient. */
void peak_envelope(const double *x, double *env, int n,
                   double attack_samples, double release_samples) {
    double ca = decay_coeff(attack_samples);
    double cr = decay_coeff(release_samples);
    double e = 0.0;
    for (int i = 0; i < n; i++) {
        double r = fabs(x[i]);
        double c = (r > e) ? ca : cr;   /* faster when rising */
        e = c * e + (1.0 - c) * r;
        env[i] = e;
    }
}