Real-time

Moving avg

rectified mean
time-domainlow-latencysingle-carriermean-rect ≈ 0.637×

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

Moving avg
level 0.521280 samples
Hilbert refMoving avg
Window16 samp (0.3 ms)

Score card

Causality
low-latency
Signal model
single-carrier
Reads
mean-rect ≈ 0.637×
Latency
½ window
Cost
cheap
Domain
time
Reads (measured on a steady sine)0.63×

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

Temporal
14%
Robust
33%
Spectral
10%
Boundary
34%

How it works

Linear-phase smoothing with perfectly predictable behavior. Rectify with |x|, then average over a fixed window — a boxcar FIR. Every sample in the window counts equally, so the ripple and the response are completely deterministic.

The price is latency equal to half the window, and it reports the mean-rectified level (≈0.637·A for a sine of amplitude A). A wider window is smoother and laggier; there is no attack/release asymmetry.

Key terms

Boxcar / moving average (FIR)
Averaging a fixed window of samples where every sample counts equally — a finite-impulse-response filter whose output is just the mean of the last N values.
Linear phase
Every frequency is delayed by the same amount — half the window — so the curve's shape isn't distorted, just shifted. Nothing smears or rings; the envelope arrives late but faithful.
Mean-rectified level
The average of |x|. For a sine of amplitude A this settles at ≈0.637·A — the mean of a rectified sine, not its crest.

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 an average settles toward the amplitude instead of cancelling back to zero.

  3. Step 3Boxcar average

    Slide a fixed-width window across |x| and average it. Every sample in the window counts equally, so the output is an evenly smoothed mean that lags by half the window — the moving-average 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>

/* Moving-average envelope: rectify, then a trailing boxcar of width W.
   acc holds the running sum of the last W rectified samples; during
   warm-up (i < W) fewer samples are in, so divide by (i + 1). */
void movavg_envelope(const double *x, double *env, int n, int W) {
    if (W < 1) W = 1;
    double acc = 0.0;
    for (int i = 0; i < n; i++) {
        acc += fabs(x[i]);
        if (i >= W) acc -= fabs(x[i - W]);   /* drop the sample leaving the window */
        int count = (i + 1 < W) ? (i + 1) : W;
        env[i] = acc / count;
    }
}