How a single memoryless curve — a piece of glowing glass, a pair of diodes, a strip of magnetic tape, or three lines of code — bends a waveform, breeds harmonics, and, if you are not careful, folds ghosts back down from beyond Nyquist.
Every distortion, overdrive, fuzz, saturator and amp-simulator you have ever heard is, at heart, a single idea: pass each sample through a nonlinear function and keep whatever new frequencies come out. A clean amplifier obeys superposition — double the input, double the output, and never a frequency that was not already there. A distortion deliberately breaks that promise.
The distinction we care about is between a linear system and a nonlinear one. A linear time-invariant system — an equaliser, a delay, an ideal reverb — can only change the amplitude and phase of frequencies that already exist in the signal. It can boost 3 kHz, cut 100 Hz, smear things across time, but it can never create a partial at a frequency the input did not contain. A nonlinear system can and does. Feed it a pure sine and you get back a sine plus a family of harmonics at integer multiples of the fundamental. That newly-minted harmonic energy is the sound of distortion: the warmth of a slightly-pushed valve, the grind of a fuzz box, the glue of a saturating console.
The simplest and most important class of distortion is memoryless waveshaping: the output sample depends only on the current input sample, through a fixed curve $y=f(x)$. No filters, no state, no history — just a lookup. It is astonishing how much musical territory this single equation covers, from the gentle third-harmonic sheen of tape to the square-wave brutality of a hard clipper. This page builds that theory carefully, then hands you a working multi-algorithm saturator, written in real DSP, so the mathematics on the screen is literally the code making the sound in your speakers.
The curve
A memoryless nonlinearity $y=f(x)$. Its shape decides the harmonic recipe: symmetric curves give odd harmonics, asymmetric curves add even ones.
The harmonics
Chebyshev polynomials tell us exactly which harmonics a given power of $x$ produces. Distortion is harmonic synthesis by geometry.
The catch
Those harmonics can land above half the sample rate and fold back as inharmonic aliases. Oversampling is the cure.
Throughout, we assume a normalised signal in which full scale is $|x|=1$. Real converters and plug-ins scale to this internally; it keeps the shaper equations clean and lets a single "drive" gain do the work of pushing the signal into the interesting part of the curve.
02Memoryless waveshaping
A memoryless waveshaper is defined by one static transfer function applied sample by sample:
$$ y[n] = f\big(g\cdot x[n]\big) $$
where $x[n]$ is the input, $g$ is the drive (a pre-gain that decides how hard we push into the curve), and $f(\cdot)$ is the shaper. Because there is no dependence on $x[n-1]$ or on any internal state, the whole processor is captured by a single one-dimensional function — you could implement it as a lookup table. This is what makes waveshaping so cheap and so ubiquitous.
Two properties of $f$ dominate the sound:
Symmetry. If $f(-x) = -f(x)$ (an odd function) the shaper treats the positive and negative halves of the wave identically. If it does not, the two halves are compressed differently and the output acquires a DC-like asymmetry. As we will see, symmetry controls whether the harmonics are odd-only or a full odd-and-even set.
Curvature and saturation. How sharply $f$ bends from its linear region into its flat region sets the harmonic slope — a soft, gradual knee (tape, a lightly-driven valve) generates mostly low-order harmonics that fall away quickly; a hard corner (a clipper) generates a long tail of high-order harmonics.
Near the origin every well-behaved shaper looks like a straight line — that is the "clean" region where the effect is nearly transparent. Push harder with $g$ and the signal spends more of its excursion out on the curved, saturating flanks, so the timbre grows richer as you turn up the drive. This is exactly the behaviour of a guitar amplifier: quiet passages stay clean, loud notes bloom into overdrive, and it is the same curve doing both.
The Taylor picture
Expand a smooth shaper as a power series about the origin:
The linear term $a_1x$ is the clean, undistorted signal. Every higher term is a source of harmonics, and — crucially — the even powers ($x^2, x^4,\dots$) and the odd powers ($x^3, x^5,\dots$) generate different families of harmonics. An odd (symmetric) shaper has only odd powers in its expansion; an even asymmetry switches the even powers on. The next section makes "a power of $x$ generates these harmonics" precise.
03How a curve breeds harmonics
Drive a single cosine $x=\cos\theta$ (with $\theta = 2\pi f_0 t$) into a power of $x$ and ask what frequencies come out. The answer is one of the most elegant results in signal processing, and it is a statement about Chebyshev polynomials. The Chebyshev polynomial of the first kind, $T_n$, is defined by exactly the property we want:
$$ T_n(\cos\theta) = \cos(n\theta) $$
In words: feeding a cosine through $T_n$ produces a pure cosine at the $n$-th harmonic. The Chebyshev polynomials therefore form a "harmonic basis" for waveshaping — if you want to synthesise exactly the $n$-th harmonic and nothing else, shape with $T_n$. The first few are $T_0=1$, $T_1=x$, $T_2=2x^2-1$, $T_3=4x^3-3x$, $T_4=8x^4-8x^2+1$.
Turning this around gives the rule that governs all waveshaping distortion. Any monomial $x^k$ can be written as a sum of Chebyshev polynomials $T_0\ldots T_k$, so:
$$ x^k \;\Longrightarrow\; \text{harmonics } 0,1,2,\dots,k \ \text{(up to the }k\text{-th)} $$
An even power $x^{2m}$ expands into even-order Chebyshev terms only — it produces DC and even harmonics ($2f_0, 4f_0,\dots$).
An odd power $x^{2m+1}$ expands into odd-order Chebyshev terms only — it produces odd harmonics ($f_0, 3f_0, 5f_0,\dots$).
So the symmetry of the shaper maps directly onto the harmonic spectrum. A symmetric (odd) shaper such as $\tanh$ or a hard clipper contains only odd powers in its Taylor series and therefore generates only odd harmonics — the hollow, square-ish, "valve push" or "fuzz" character. Break the symmetry — by adding a bias so the curve clips the top harder than the bottom, or by using a diode-like asymmetric shaper — and the even powers switch on, injecting even harmonics ($2f_0$, an octave up) that many listeners hear as "warm", "tube-like" or "fat".
Derivation — why cubing a cosine makes a third harmonic
Take the simplest nonlinear term, the cube, and feed it a cosine $x=\cos\theta$. Use the triple-angle identity:
The cube has produced the original tone (scaled by $3/4$) and a brand-new component at three times the frequency (scaled by $1/4$). That $\cos 3\theta$ term is the third harmonic. Because the cube is an odd function there is no even harmonic and no DC. This is precisely $x^3 = \tfrac14 T_3(x)+\tfrac34 T_1(x)$ using $T_3=4x^3-3x$.
The square produces a constant (DC, the $\tfrac12$) plus the second harmonic — even harmonics and an offset, no fundamental. This is $x^2 = \tfrac12 T_2(x)+\tfrac12 T_0(x)$. Superpose these building blocks with the Taylor coefficients $a_k$ of any real shaper and you can read its entire harmonic recipe straight off the page.
There is a second, subtler consequence. With a single input tone the new components are exact integer harmonics and sound musical. Feed the same nonlinearity two tones at $f_1$ and $f_2$ and the cross terms produce intermodulation products at sums and differences $|m f_1 \pm n f_2|$. These are generally not harmonically related to either note, which is why heavy distortion on a full chord sounds muddy and "clashy" where distortion on a single note sounds rich. The live demo lets you switch between a single sustained note and a two-note chord to hear exactly this.
04A gallery of shapers
Here are the five curves the demo implements, each written as the exact function that also runs in the audio thread. Drag vertically on the graph below to change the drive and watch the input's excursion sweep across the curve; change the shaper and bias to see the geometry — and therefore the harmonic content — change.
Hard clip
The brute-force limiter: pass the signal untouched until it hits the rails, then hold it flat.
Perfectly symmetric, with an infinitely sharp corner. That corner is a discontinuity in the first derivative, so its Taylor tail never dies away — hard clipping produces a long series of odd harmonics ($f_0,3f_0,5f_0,\dots$) falling off slowly. This is the sound of a fuzz box and of digital clipping: buzzy, square, aggressive.
Soft clip (cubic)
The classic polynomial "soft" clipper rounds the corner using a cubic in its active region:
Between the rails it is the odd cubic $x-\tfrac{x^3}{3}$, so — by the derivation above — its dominant addition is a gentle third harmonic. The knee is smooth (continuous slope), so the harmonic tail dies away far faster than the hard clipper's. It is cheap, musical and the workhorse of "overdrive". We apply a $\times\tfrac32$ make-up so full scale maps to $\pm1$.
Hyperbolic tangent
Physically the most valve-like of the smooth shapers: the input–output law of many transistor and triode stages is very close to a $\tanh$.
Odd and infinitely smooth, with a soft, compressive saturation. Its Taylor series $x-\tfrac{x^3}{3}+\tfrac{2x^5}{15}-\cdots$ is odd, so it produces odd harmonics that roll off quickly at low drive and progressively richer as you push it. This is the default in the demo and a fine general-purpose "warm" saturation.
Arctangent
Very similar in spirit to $\tanh$ but with a slightly slower, more gradual approach to saturation, normalised here for unity small-signal gain and $\pm1$ limits:
Also odd; the softer knee gives a touch less high-harmonic content than $\tanh$ at equal drive — a subtle, "polite" saturation.
Asymmetric (diode / bias)
Real valves and diode clippers are not symmetric — one polarity conducts differently from the other. We model this with a diode-like curve that saturates the two halves with different softness, and separately expose a bias offset that shifts the operating point:
Because the positive and negative halves are now shaped unequally, the even powers switch on and the output gains even harmonics (notably the octave, $2f_0$) — the classic "tube warmth". Asymmetry also introduces a DC offset, which is why the demo runs a DC-blocking high-pass on the output; without it the asymmetry would push the signal off-centre and waste headroom.
drive ×1.0
Transfer curve y = f(g·x + bias). The orange band is the swept input excursion; the moving dot is a live sample tracing the curve. Drag up/down on the graph to change drive.
Choosing a shaper
Shaper
Symmetry
Harmonics
Knee
Character
Hard clip
Symmetric
Odd, slow roll-off
Infinitely sharp
Fuzz, buzz, digital clip
Soft cubic
Symmetric
Odd, mostly 3rd
Smooth
Overdrive, cheap & musical
tanh
Symmetric
Odd, fast roll-off
Soft
Valve-like warmth
arctan
Symmetric
Odd, gentle
Softest
Polite saturation
Asymmetric
Asymmetric
Odd + even
Soft, uneven
Tube "fatness", octave
05The catch: aliasing, and its cure
Distortion manufactures harmonics without asking whether there is room for them. In a digital system there is a hard ceiling — the Nyquist frequency at half the sample rate — and harmonics pushed above it do not vanish. They fold back down into the audible band as inharmonic, dissonant tones. This aliasing is the single biggest quality difference between a cheap distortion and a good one.
Why it happens
Suppose we run at $f_s = 44{,}100$ Hz, so Nyquist is $f_N = 22{,}050$ Hz, and we distort a $5$ kHz tone hard enough to generate strong harmonics. The harmonics sit at $10, 15, 20, 25, 30,\dots$ kHz. The first three are fine, but the fifth harmonic at $25$ kHz is above Nyquist. Sampling cannot represent it; instead it appears mirrored about $f_N$ at
That $19.1$ kHz component is not a harmonic of $5$ kHz — it is inharmonic, it does not track the note musically, and as you play up the neck it slides the "wrong way" down the spectrum. Stack up a chord and every harmonic of every note that crosses Nyquist folds back, producing a smear of unrelated partials. This is the harsh, "digital", metallic edge that afflicts naive software distortion.
Analogue
A valve or diode clipper works at "infinite" sample rate. Its harmonics extend upward forever and are then gently band-limited by circuit capacitance and the speaker — nothing folds back.
Naive digital
Apply $f(x)$ directly at $f_s$ and every harmonic above $f_N$ reflects into the audio band. The higher the drive and the higher the note, the worse the aliasing.
The cure: oversampling
If the problem is that harmonics exceed Nyquist, raise Nyquist. Temporarily run the nonlinearity at $L$ times the sample rate, so there is $L\times$ more room above the audio band before anything folds, then filter and return to the base rate. The standard four-step recipe is:
Upsample by $L$ — insert $L-1$ zeros between every input sample (zero-stuffing), which raises the sample rate to $Lf_s$ but also creates spectral images.
Interpolation low-pass — filter at the original Nyquist $f_N$ (with make-up gain $L$) to remove those images, reconstructing a clean band-limited signal at the higher rate.
Apply the nonlinearity $f(\cdot)$ at $Lf_s$. New harmonics are now generated, but there is far more headroom below the new Nyquist $Lf_N$, so most of them fit without folding.
Decimation low-pass then downsample — low-pass again at $f_N$ to throw away every harmonic above the base-rate Nyquist before discarding samples, then keep every $L$-th sample to return to $f_s$.
$$ x \xrightarrow{\ \uparrow L\ }\ \text{LPF}\ \xrightarrow{\ f(\cdot)\ }\ \text{LPF}\ \xrightarrow{\ \downarrow L\ } y $$
The two low-pass filters are the heart of it. The first removes upsampling images; the second removes the freshly-created high harmonics before they can alias on the way back down. Oversampling does not eliminate aliasing entirely — a harmonic above the oversampled Nyquist still folds — but at $L=4$ the folded energy is pushed so high and so low in level that it is inaudible for all but the most extreme settings. In the demo, hardware permitting, the shaper runs inside an AudioWorklet with a hand-written windowed-sinc half-band-style filter at each stage; toggling oversampling on and off makes the inharmonic alias spikes in the spectrum appear and disappear before your eyes and ears.
Aside — antiderivative anti-aliasing (ADAA), the cheaper cousin
Oversampling is brute force: do the same work $L$ times over. An elegant alternative, developed by Parker, Zavalishin and Le Bivic and by Bilbao and colleagues, is antiderivative anti-aliasing. Instead of raising the rate, you replace the instantaneous shaper $f(x)$ with a value computed from the antiderivative $F$ where $F' = f$:
This is the average of $f$ over the segment between successive samples — a first-order continuous-domain anti-aliasing that dramatically reduces folded energy at only a small extra cost and no change of sample rate (higher orders use further antiderivatives). It has become popular precisely because full oversampling is expensive; the trade is a little high-frequency loss and some complexity near $x[n]\approx x[n-1]$. We mention it as the modern state of the art; the demo uses classical oversampling because it is the clearer thing to hear.
Deliberate aliasing: the bit-crusher
Everything above fights aliasing. Sometimes you want it. A bit-crusher does two lo-fi things on purpose: it quantises the amplitude to a small number of bits, $y=\Delta\,\operatorname{round}(x/\Delta)$ with step $\Delta = 2^{1-B}$ for $B$ bits (adding gritty quantisation-noise harmonics), and it reduces the sample rate by holding each value for several samples (folding a riot of aliases into the band). The demo includes a bit-depth control so you can hear quantisation distortion as the deliberate opposite of the smooth, oversampled saturation beside it.
06The live saturator
Below is a complete, working multi-algorithm saturation plug-in. The shaper, the drive, the DC-blocker, the tone filter, the bit-crusher and the oversampling are all hand-written sample-by-sample DSP running inside an AudioWorklet — the exact source is shown beneath the panel, and it is the very same text compiled into the audio thread, so what you read is what you hear. Choose a source, press play, and turn it up.
◆ Thermionic — SaturatorDSP & MUSIC · WAVESHAPER
Drive
0.0 dB
Bias
0.00
Tone
50%
Output
0.0 dB
Mix
100%
Bits
16
ShaperOversample
Out
built-in saw chord
Tip: choose the Asymmetric shaper and add Bias to hear even harmonics arrive; then push Drive with Oversample Off and watch inharmonic alias spikes appear in the spectrum — switch it to 4× and they collapse away. Double-click any knob to reset it; drag knobs vertically (works on touch too).
What you are seeing
The panel display is the live output spectrum (an AnalyserNode FFT on a log-frequency axis). With a single note you will see a neat comb of harmonics; add drive with oversampling off and extra spikes that do not line up with the comb are aliases. The two graphs below add the transfer curve in motion and a direct comparison of the input and output waveforms.
Input (dim) vs output (orange) waveform. Watch the peaks flatten and square up as drive rises — that flattening is the harmonic generation.
The live transfer curve for the current shaper/drive/bias, with the running signal tracing its path across it.
The processor, in full
This is the complete AudioWorklet source that the demo loads. The per-sample shaper matches the equations in §4 exactly; the oversampler implements the four-step recipe of §5 with hand-written windowed-sinc FIR filters.
(loading…)
worklet — compiled to a Blob URL and added with audioContext.audioWorklet.addModule()
07The same effect in JUCE / C++
In a real plug-in you would build this with the JUCE DSP module. The pattern mirrors the demo one-for-one: a drive gain, a hand-written waveshaper wrapped in juce::dsp::WaveShaper, a tone filter, and — the important part — juce::dsp::Oversampling<float> wrapping the nonlinear stage so aliasing is handled for you. Parameters are exposed through an AudioProcessorValueTreeState (APVTS).
The shaper functions (map these to the JavaScript)
// Shaper.h — memoryless transfer functions, normalised to |x|<=1 full scale.
// These are the exact analogues of the JavaScript in the live demo.
#pragma once
#include <cmath>
namespace shaper
{
inline float hardClip (float x) noexcept
{
return juce::jlimit (-1.0f, 1.0f, x);
}
inline float softCubic (float x) noexcept // odd cubic, x - x^3/3, clamped
{
x = juce::jlimit (-1.0f, 1.0f, x);
return 1.5f * (x - x * x * x / 3.0f); // 1.5x make-up -> full scale +/-1
}
inline float tanhShape (float x) noexcept { return std::tanh (x); }
inline float atanShape (float x) noexcept
{
constexpr float k = juce::MathConstants<float>::halfPi;
return (1.0f / k) * std::atan (k * x); // unity small-signal gain, +/-1 limit
}
inline float asymmetric (float x) noexcept // diode-like: halves shaped unequally
{
return x >= 0.0f ? std::tanh (x) : std::tanh (0.6f * x);
}
// Dispatch by an integer choice parameter.
inline float apply (int type, float x) noexcept
{
switch (type)
{
case 0: return hardClip (x);
case 1: return softCubic (x);
case 2: return tanhShape (x);
case 3: return atanShape (x);
default: return asymmetric(x);
}
}
}
Shaper.h — the five curves, one dispatch function
The processor
// SaturatorProcessor.h
class SaturatorProcessor : public juce::AudioProcessor
{
public:
SaturatorProcessor()
: apvts (*this, nullptr, "PARAMS", createLayout())
{
// 4x oversampling of the nonlinear stage, FIR (steep, linear phase).
oversampler = std::make_unique<juce::dsp::Oversampling<float>> (
2, /*factor 2^2 = 4x*/ 2,
juce::dsp::Oversampling<float>::filterHalfBandFIREquiripple);
}
void prepareToPlay (double sampleRate, int blockSize) override
{
juce::dsp::ProcessSpec spec { sampleRate,
(juce::uint32) blockSize,
(juce::uint32) getTotalNumOutputChannels() };
oversampler->initProcessing ((size_t) blockSize);
driveGain.prepare (spec); driveGain.setRampDurationSeconds (0.02);
outputGain.prepare (spec); outputGain.setRampDurationSeconds (0.02);
tone.prepare (spec);
dcBlocker.prepare (spec);
dcBlocker.coefficients = juce::dsp::IIR::Coefficients<float>::makeHighPass (sampleRate, 15.0f);
}
void processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer&) override
{
juce::ScopedNoDenormals noDenormals;
const int shaperType = (int) *apvts.getRawParameterValue ("shaper");
const float bias = *apvts.getRawParameterValue ("bias");
const float mix = *apvts.getRawParameterValue ("mix");
driveGain.setGainDecibels (*apvts.getRawParameterValue ("drive"));
outputGain.setGainDecibels (*apvts.getRawParameterValue ("output"));
tone.setCutoffFrequency (*apvts.getRawParameterValue ("tone"));
juce::dsp::AudioBlock<float> block (buffer);
dryBuffer.makeCopyOf (buffer, true); // keep the dry signal for the mix
// --- pre-gain (drive) at base rate ---
driveGain.process (juce::dsp::ProcessContextReplacing<float> (block));
// --- oversample -> waveshape -> back down ---
auto up = oversampler->processSamplesUp (block); // 4x block
for (size_t ch = 0; ch < up.getNumChannels(); ++ch)
{
auto* d = up.getChannelPointer (ch);
for (size_t i = 0; i < up.getNumSamples(); ++i)
d[i] = shaper::apply (shaperType, d[i] + bias);
}
oversampler->processSamplesDown (block); // anti-alias + decimate
// --- tone, DC-block, output trim, wet/dry ---
tone.process (juce::dsp::ProcessContextReplacing<float> (block));
dcBlocker.process(juce::dsp::ProcessContextReplacing<float> (block));
outputGain.process(juce::dsp::ProcessContextReplacing<float> (block));
for (int ch = 0; ch < buffer.getNumChannels(); ++ch)
{
auto* wet = buffer.getWritePointer (ch);
auto* dry = dryBuffer.getReadPointer (ch);
for (int i = 0; i < buffer.getNumSamples(); ++i)
wet[i] = mix * wet[i] + (1.0f - mix) * dry[i];
}
}
static juce::AudioProcessorValueTreeState::ParameterLayout createLayout()
{
using P = juce::AudioParameterFloat;
using R = juce::NormalisableRange<float>;
std::vector<std::unique_ptr<juce::RangedAudioParameter>> p;
p.push_back (std::make_unique<P> ("drive", "Drive", R { 0.0f, 36.0f }, 0.0f));
p.push_back (std::make_unique<P> ("bias", "Bias", R { -0.5f, 0.5f }, 0.0f));
p.push_back (std::make_unique<P> ("tone", "Tone", R { 200.0f, 18000.0f, 0.0f, 0.3f }, 12000.0f));
p.push_back (std::make_unique<P> ("output", "Output", R { -24.0f, 12.0f }, 0.0f));
p.push_back (std::make_unique<P> ("mix", "Mix", R { 0.0f, 1.0f }, 1.0f));
p.push_back (std::make_unique<juce::AudioParameterChoice> ("shaper", "Shaper",
juce::StringArray { "Hard", "SoftCubic", "Tanh", "Atan", "Asym" }, 2));
return { p.begin(), p.end() };
}
private:
juce::AudioProcessorValueTreeState apvts;
std::unique_ptr<juce::dsp::Oversampling<float>> oversampler;
juce::dsp::Gain<float> driveGain, outputGain;
juce::dsp::FirstOrderTPTFilter<float> tone; // simple 1-pole low-pass "tone"
juce::dsp::IIR::Filter<float> dcBlocker;
juce::AudioBuffer<float> dryBuffer;
};
Note how juce::dsp::Oversampling collapses steps 1–4 of §5 into processSamplesUp / processSamplesDown around the loop that applies the shaper. That loop is the same arithmetic as the JavaScript worklet; everything else is plumbing. In a real product you would also declare the oversampler's latency via setLatencySamples (roundToInt (oversampler->getLatencyInSamples())) so the host can compensate.
08A short history of making things dirty
Distortion began as a defect — the sound of equipment being driven past its design limits — and became, over sixty years, one of the most deliberately cultivated timbres in music. The through-line is always the same nonlinear curve, realised first in glass and iron, then in silicon, then in software.
1940s–50s
Valve overdrive. Guitarists push tube amplifiers (and occasionally slit the speaker cones) past clean headroom. The soft, even-harmonic-rich saturation of an overdriven triode — close to a biased $\tanh$ — becomes the foundational sound of electric blues and rock 'n' roll.
1962
The first fuzz. A faulty channel on a mixing console gives Marty Robbins' "Don't Worry" its buzzing bass; the Maestro FZ-1 Fuzz-Tone productises the sound, and in 1965 Keith Richards' riff on "(I Can't Get No) Satisfaction" makes hard transistor clipping a household noise.
1960s–70s
Diode and transistor clippers. The Big Muff Pi (cascaded transistor clipping) and later the Ibanez Tube Screamer (op-amp gain with diode clipping in the feedback loop, plus a mid-hump tone stack) define fuzz and overdrive respectively — symmetric and asymmetric clipping made into pedals.
1950s–80s
Tape and transformer colour. Magnetic tape saturates gently and compresses transients; console input/output transformers add subtle low-order harmonics and "glue". Engineers learn to drive these stages musically — saturation as a mix tool, not just a guitar effect.
1990s–2000s
Digital arrives — and aliases. Early software distortion applies $f(x)$ directly at $44.1$ kHz and sounds harsh: the harmonics fold. Oversampling and better anti-aliasing become the mark of quality. Physical valve-circuit modelling (Yeh, Abel and Smith at CCRMA) puts real device equations under the sound.
2000s–2010s
Analogue-modelling plug-ins. SoundToys Decapitator, FabFilter Saturn, and Chris Johnson's free, aggressively-transparent Airwindows saturators bring oversampled, multi-algorithm waveshaping to every DAW. Amp sims (Line 6, later NAM neural captures) model whole signal chains.
2016→
Antiderivative anti-aliasing. Parker, Zavalishin & Le Bivic publish ADAA, reducing aliasing without the full cost of oversampling. Anti-aliasing moves from an afterthought to a design parameter, and the humble memoryless shaper is still at the centre of it all.
09References & further reading
Selected sources
Zölzer, U. (ed.), DAFX: Digital Audio Effects, 2nd ed., Wiley, 2011 — chapters on nonlinear processing and valve simulation; the standard reference for waveshaping and its harmonic analysis.
Smith, J. O., Physical Audio Signal Processing and the CCRMA/JOS online publications — nonlinear elements, memoryless nonlinearities and the aliasing they cause.
Le Brun, M., "Digital Waveshaping Synthesis", Journal of the Audio Engineering Society, 27(4), 1979 — the foundational treatment of Chebyshev-polynomial waveshaping for controlled harmonic synthesis.
Parker, J. D., Zavalishin, V. & Le Bivic, E., "Reducing the Aliasing of Nonlinear Waveshaping Using Continuous-Time Convolution", Proc. DAFx-16, 2016 — antiderivative anti-aliasing (ADAA).
Bilbao, S., Esqueda, F., Parker, J. D. & Välimäki, V., "Antiderivative Antialiasing for Memoryless Nonlinearities", IEEE Signal Processing Letters, 24(7), 2017.
Yeh, D. T., Abel, J. S. & Smith, J. O., "Automated Physical Modeling of Nonlinear Audio Circuits for Real-Time Audio Effects", IEEE Trans. Audio, Speech & Language Processing, 18(4), 2010 — vacuum-tube amplifier modelling.
Pakarinen, J. & Yeh, D. T., "A Review of Digital Techniques for Modeling Vacuum-Tube Guitar Amplifiers", Computer Music Journal, 33(2), 2009.
Välimäki, V. & Huovilainen, A., "Oversampling and antialiasing in nonlinear audio processing" — practical treatments of the upsample–shape–downsample chain.
JUCE documentation — juce::dsp::WaveShaper, juce::dsp::Oversampling, and the AudioProcessorValueTreeState tutorial, ROLI/JUCE.
Mozilla Developer Network — Web Audio API, AudioWorklet and AnalyserNode references.