The Snob's Guide to Noise

Designing a psychoacoustic sleep aid for infants, weary parents, and mathematical purists.

I'm a noise snob. As an electrical engineer, I learned that white, pink, and brown noise are all VERY specific things, with fascinating properties and behavior. Each is a mathematical function, and each has really interesting use cases.

When I became a parent I was horrified at the PERVERSE! LIARS! who dared to post things on youtube like "ten hours of pink noise, guaranteed to make baby sleep", and then in fact post ****** recordings of the ******* ocean. In a perfect society, (as we all agree), they would be hung and the only thing keeping that from happening is collusion between Youtube and Soros DAs. Which is cool and all. I'm a big fan of Soros DAs and Youtube.

I went to great length as an early dad to find a true source of noise, and literally nobody could provide this. Spotify and youtube would serve something called "pink noise" and it would have literal bird sounds, every time. I ended up buying a signal generator app, and my son was able to go to sleep in the mathematically defined embrace of equal power amplitude across the frequency spectrum.

Today, I was listening to a shepard tone and it hit me that an infinite downward sweep would be beautiful to fall asleep to, if it were coupled with a noiselike function.

So, I built it. Here's the math. Take a gander, and enjoy!

1. The Math of Noise and Psychoacoustics

Let's define our terms cleanly. The "colors" of noise are determined by their **Power Spectral Density (PSD)**—how energy is spread across the frequency domain.

2. The Shepard Illusion and Dynamic Sweeps

A classic Shepard tone uses a bank of sine wave oscillators separated by octaves. As they sweep upward or downward, a Gaussian amplitude envelope fades them in at the hearing extremes (low and high) and peaks them in the middle of our hearing range. When the sweep resets, the transition is hidden because the resetting oscillator is silent.

To do this with noise, we stack bandpass filters. If the base frequency of the lowest octave is $f_{\text{min}}$ and the sweep period is $T$, the center frequency $f_n(t)$ of the $n$-th band is: \[ f_n(t) = f_{\text{min}} \cdot 2^{s(t) + n} \] where $s(t)$ is the sweep driver. For a continuous downward sweep, we calculate: \[ s(t) = 1.0 - \frac{t \pmod{T}}{T} \]

3. The Whistle Problem: The Constant-Q Solution

If you filter a noise source using standard filters with a fixed bandwidth (e.g., $50\text{ Hz}$ wide), you run into a physical limitation of human hearing. At $100\text{ Hz}$, a $50\text{ Hz}$ bandwidth is wide ($0.5$ octaves), sounding like a rumble. But at $10\text{ kHz}$, a $50\text{ Hz}$ bandwidth is microscopically narrow ($0.007$ octaves). The noise loses its chaotic nature and becomes a whistle.

To solve this, the bandwidth of each band must scale proportionally with its center frequency: \[ \text{Bandwidth}(t) = \text{bandwidth\_ratio} \cdot f_n(t) \] We achieve this constant relative bandwidth (constant Q) by generating a single reference low-pass noise stream $w(\tau)$ and mapping it to a warped time index $u(t)$ that scales with the cumulative instantaneous frequency of the band: \[ u(t) = \text{bandwidth\_ratio} \cdot \int_0^t f_inst(z) \, dz \] By interpolating our reference noise at $w(u(t))$, the modulation speed scales dynamically. The low-frequency rumble remains a rumble, and the high-frequency bands stay broad, rushing noise instead of turning into distinct whistles.

4. Adding Acoustic Chaos (FM Jitter)

To make the sweep sound organic, we introduce frequency modulation (FM) jitter. We apply a slow, low-pass filtered random walk $\text{jitter}(t)$ to the frequency driver itself: \[ f_{\text{jittered}}(t) = f_n(t) \cdot (1.0 + \text{fm\_jitter} \cdot \text{jitter}(t)) \] This continually scatters the phase of the carrier waves. It mimics natural wind gusts and tape flutter, preventing the brain from locking onto any single pitch and encouraging deep, slow-wave sleep.

5. Phase Decoupling and Long-Window Loops

When implementing a real-time noise generator, we must account for two major psychoacoustic pitfalls. First, if the source noise buffer is too short (e.g., 2 seconds), the brain's auditory cortex quickly locks onto the repeating micro-structure of the static loop, creating an artificial, rhythmic "pulsing" or "swishing" sensation. To resolve this, we utilize a 15-second noise buffer, pushing the repetition window well past the short-term pattern recognition capacity of human hearing.

Second, if a single noise source is fed into all 9 bandpass filters, their overlapping filter slopes create constructive and destructive phase interference as they sweep past each other. This results in comb filtering and prominent acoustic beating (pulsing volumes). We eliminate this by generating 9 completely independent 15-second noise buffers—one dedicated to each band. By decoupling the phase relationships between bands, the sweep remains a lush, beating-free, continuous acoustic roar.

6. Verification Plots

Downward Sweep & Jitter Spectrogram
Figure 1: Downward Sweep & Jitter Spectrogram. The top-right panel (Improved: Constant-Q) shows the downward slope of the bands. The bands are visibly wider and have wavy, organic outlines from the FM jitter, which is exactly what makes them sound "noisier" and more natural. The bottom-right panel (Relative Bandwidth) confirms the stable relative bandwidth of the constant-Q method under the downward sweep.
Downward Mix PSD Colors
Figure 2: Power Spectral Density (PSD) of Shepard Noise Colors. This plot shows that the spectral slopes are perfectly maintained for the downward sweep, preserving the relative 3 dB/octave offsets between White, Pink, and Brown noise colors.

7. Browser Implementation (Web Audio API)

Rather than serving giant static audio files, we can generate this entire DSP engine inside the browser in real time. The Web Audio API provides native node structures that run on the device's audio chip. Here is the core loop that manages the active filter sweep:

// Dynamic tick running in the browser
function tick() {
  const t = audioCtx.currentTime;
  const t_cycle = t % sweep_period;
  
  // Calculate downward sweep driver
  const sweep_driver = 1.0 - (t_cycle / sweep_period);
  const alpha = -0.5; // -6dB/octave slope for Brown noise
  
  for (let i = 0; i < numBands; i++) {
    const filter = filterBank[i];
    const gainNode = bandGains[i];
    
    const current_octave = sweep_driver + i;
    const f_inst = f_min * Math.pow(2, current_octave);
    
    // Smooth random walk frequency jitter
    bandJitters[i] = bandJitters[i] * 0.95 + (Math.random() - 0.5) * 0.05;
    const f_jittered = f_inst * (1.0 + fmJitterDepth * bandJitters[i]);
    
    // Clamp frequency to Nyquist limit to prevent browser console warnings
    const max_f = audioCtx.sampleRate ? (audioCtx.sampleRate / 2) - 100 : 22000;
    const f_clamped = Math.max(10, Math.min(max_f, f_jittered));
    
    // Update active bandpass parameters
    filter.frequency.setTargetAtTime(f_clamped, t, 0.02);
    filter.Q.setTargetAtTime(target_Q, t, 0.02);
    
    // Gaussian envelope + color gain tilt
    const amp_env = Math.exp(-0.5 * Math.pow((current_octave - center_octave) / sigma, 2));
    const color_scale = Math.pow(f_inst / f_center_ref, alpha);
    
    gainNode.gain.setTargetAtTime(amp_env * color_scale, t, 0.02);
  }
  requestAnimationFrame(tick);
}

The resulting implementation is hosted live right here: Shepard Sleep Noise Generator. It features full interactive controls for noisiness (bandwidth) and speed, as well as a specialized low-luminance "Crib Mode" to protect nursery melatonin levels in the middle of the night.