HomeSound & MusicNoise Colors — White, Pink & Brown

📻 Noise Colors — White, Pink & Brown

White noise has equal power at every frequency, pink noise falls off as 1/f (equal energy per octave), brown noise falls off as 1/f² — the same randomness, filtered differently.

Sound & Music2DEasy60 FPS
noise-colors ↗ Open standalone

How it Works

A random signal's "color" is defined entirely by its power spectral density S(f) — how its average power is distributed across frequency. White noise has a flat PSD (equal power per hertz), which is trivial to generate: draw a fresh independent random value every tick. Pink and brown noise need a shaping process, because simply filtering white noise with an arbitrary low-pass filter does not reproduce the precise 1/f or 1/f² power-law slope that defines them.

Pink noise here is generated with the Voss-McCartney algorithm: a small bank of independent random generators ("rows") is updated at octave-spaced rates — row 0 every sample, row 1 every 2 samples, row 2 every 4, and so on — and summed together, which is efficiently implemented by refreshing the row indicated by the trailing-zero-bit count of an incrementing counter. Brown noise is generated as the running sum (discrete integral) of white noise, clamped to stay bounded — the same process as a one-dimensional random walk, which is why it is also called Brownian noise. The canvas periodically re-computes an approximate power spectral density from the recent sample buffer using a direct discrete Fourier transform evaluated at log-spaced frequencies (a periodogram), so you can see the flat, -3 dB/octave, and -6 dB/octave trends directly instead of only hearing them.

White: S(f) ∝ f⁰ (flat spectrum, independent samples)
Pink: S(f) ∝ f⁻¹ (Voss-McCartney: octave-spaced generators summed)
Brown: S(f) ∝ f⁻² (running sum / random walk of white noise)
Blue: S(f) ∝ f⁺¹ (first difference of white noise, optional)

Frequently Asked Questions

What is power spectral density (PSD) and why does it define a noise's "color"?

Power spectral density describes how the average power of a random signal is distributed across frequency, S(f). Noise "colors" are simply names for characteristic PSD shapes: flat S(f) is white, S(f) ∝ 1/f is pink, and S(f) ∝ 1/f² is brown. Two signals with the same PSD shape sound the same "color" even though the exact random samples differ every time you generate them.

Why is white noise called "white"?

The name is an analogy to white light, which contains roughly equal intensity across all visible wavelengths. White noise likewise has equal power per hertz at every audible frequency — its power spectral density is flat, S(f) ∝ f⁰. It is generated here simply by drawing a new independent random sample every tick, with no correlation between samples.

Why does pink noise sound "duller" or warmer than white noise, even though it has more low-frequency energy per hertz?

Human hearing groups frequencies into octave bands, and each octave spans a doubling of frequency, so higher octaves contain far more individual hertz than lower ones. White noise has equal energy per hertz, so equal-width octaves at high frequencies collect much more total energy than low ones — it sounds hiss-heavy and bright. Pink noise instead has equal energy per octave, matching how we perceive pitch, which removes that high-frequency emphasis and makes it sound warmer and duller despite carrying real energy at every hertz.

How does the Voss-McCartney algorithm actually generate pink noise?

The Voss-McCartney method keeps a small bank of independent random "rows," each updated at a different rate: row 0 changes every sample, row 1 every 2 samples, row 2 every 4 samples, and so on in octave steps. Summing all the rows produces a signal whose spectrum falls off close to 1/f, because slower rows contribute more low-frequency content and faster rows contribute more high-frequency content in octave-balanced proportions. A cheap way to pick which row to refresh each step is to count the trailing zero bits of an incrementing counter, which naturally updates row 0 half the time, row 1 a quarter of the time, and so on.

Why do white noise machines help people sleep or mask sound?

White noise's flat, broadband spectrum covers essentially all audible frequencies at once, so it is very effective at raising the auditory masking threshold across the whole hearing range — quieter, more variable sounds like a door closing or traffic get buried under a constant, unchanging hiss. Because it has no distinctive pitch or rhythm, the brain also habituates to it quickly instead of continually flagging it as a novel, attention-grabbing sound.

Why does pink noise (1/f noise) show up so often in nature and biological systems?

1/f spectra are extremely common in physical and biological time series: heartbeat interval variability, neural firing rates, river flow, and even music show approximately pink spectra. This seems to arise whenever a system has many interacting processes operating across a wide range of timescales, each contributing roughly equally per octave rather than per hertz — no single mechanism fully explains it, but the ubiquity of multi-scale, weakly coupled processes in nature is the leading explanation.

What does brown (Brownian) noise sound like, and why?

Brown noise sounds like a deep, rumbling roar — like a waterfall or heavy rain heard from a distance — because its power falls off steeply (1/f²) as frequency rises, so almost all of its energy sits in the low end of the spectrum and very little reaches the highs. It is named for Brownian motion, not the color brown; the name is a pun on Robert Brown, the botanist who described the random jittering of pollen grains in water.

What is the mathematical relationship between brown noise and a random walk?

Brown noise is literally the running sum (discrete integral) of white noise, which is exactly the definition of a one-dimensional random walk or discrete Brownian motion: at every step you add a new independent random increment to your current position. Integrating in time is equivalent to dividing by frequency in the spectral domain, so integrating white noise (flat spectrum) once produces a 1/f² spectrum — the extra factor of f compared to pink noise's single 1/f comes from that doubled effect of integration.

What is blue noise, and how is it different from the other colors?

Blue noise has power that rises with frequency, S(f) ∝ f, the mirror image of pink noise. It is generated here by differencing successive white noise samples, the discrete equivalent of differentiation, which boosts high frequencies while suppressing low ones. It sounds thin, hissy, and sharp, and is used in fields like dithering and stippling where evenly spread high-frequency energy without low-frequency clumping is desirable.

About this simulation

This simulator generates three genuine noise colors sample-by-sample and lets you both hear and see the difference: white noise from independent random samples, pink noise from the classic Voss-McCartney algorithm (octave-spaced random generators summed together), and brown noise from a clamped running sum — a discrete random walk — of white noise. A live scrolling waveform and a log-log power spectral density plot, computed with a direct discrete Fourier transform over the recent sample buffer, show the flat, -3 dB/octave, and -6 dB/octave slopes directly, while Web Audio plays the actual selected algorithm's samples through your speakers in real time.

🔬 What it shows

A scrolling time-domain waveform of the currently selected noise color, paired with an approximate power spectral density plot computed via a direct DFT periodogram over a Hann-windowed buffer, so the characteristic flat / -3 dB/octave / -6 dB/octave power-law slopes are visible on a log-frequency axis, not just audible.

🎮 How to use

Pick a noise type from the dropdown, press Play to hear it rendered live through Web Audio, and drag the Gain slider to adjust loudness. The canvas keeps animating independently of playback — P pauses the visualization, R resets the sample buffer and PSD plot.

💡 Did you know?

Pink noise carries more raw energy per hertz at low frequencies than white noise does anywhere, yet it sounds "duller" — because human hearing (and most spectrum displays) naturally groups frequencies by octave, and pink noise is defined by having equal energy per octave rather than per hertz.

Frequently asked questions

Why does switching noiseType to "pink" call makeVossPink() instead of just running white noise through a filter?

makeVossPink() builds a closure holding twelve independent random "rows" plus a running sum, and each call to the returned generator refreshes exactly one row (chosen via trailingZeroBits(counter)) before returning the updated sum divided by the row count. A single low-pass filter can only approximate a 1/f slope over a narrow band, while stacking octave-spaced generators reproduces the correct power-law slope across the whole audible range, which is why the algorithm is used instead of simple filtering.

What does trailingZeroBits(counter) actually control in the pink noise generator?

trailingZeroBits(counter) counts how many low-order bits of the incrementing counter are zero, and that count (modulo the number of rows) selects which row gets a fresh random value on this call. Because trailing-zero counts of 0 occur on half of all integers, counts of 1 on a quarter, counts of 2 on an eighth, and so on, row 0 refreshes every sample, row 1 every second sample, row 2 every fourth sample — exactly the octave-spaced update rates the Voss-McCartney method requires.

Why is the brown noise generator's running total clamped to [-1, 1] instead of left to accumulate freely?

The brown noise closure adds a small scaled white noise increment to brownState on every call, which is a genuine unbounded random walk and would otherwise drift arbitrarily far from zero over time (a well-known property of Brownian motion). Clamping brownState back into [-1, 1] each step keeps the waveform and the Web Audio output within a safe, audible amplitude range without altering the 1/f² shape of its spectrum.

How does computePSD() turn a buffer of samples into the log-log plot on the canvas?

computePSD() applies a Hann window to the most recent 1024-sample visBuffer, then evaluates a direct discrete Fourier transform — a plain sum of cosine and sine terms — at a fixed set of log-spaced frequency bins rather than computing every possible frequency, which keeps the per-frame cost manageable while still tracing out the flat, -3 dB/octave, or -6 dB/octave trend for the selected noise type.

Why does moving the Gain slider change gainNode.gain.value but not the shape of the PSD plot?

The Gain slider only updates gainNode.gain.value, a multiplier applied after the noise samples are generated, so it changes loudness uniformly across all frequencies without altering the underlying sample sequence that visBuffer and computePSD() analyze. Scaling every sample by the same constant shifts the whole PSD curve up or down by a fixed number of decibels but leaves its characteristic slope — flat, -3, or -6 dB per octave — completely unchanged.

⚙ Under the hood

White noise has equal power at every frequency, pink noise falls off as 1/f (equal energy per octave), brown noise falls off as 1/f² — the same randomness, filtered differently.

noisespectrumaudiosignal processingrandomness

2D · HTML5 Canvas 2D · 60 FPS target · runs fully client-side, no install

What did you find?

Add reproduction steps (optional)