Apply a Pinking Tilt Filter in FFmpeg

This guide explains how to apply a pinking tilt filter to white noise using FFmpeg. Although FFmpeg does not feature a standalone filter named tilt, you can achieve the exact -3 dB per octave spectral tilt required for pinking by using FFmpeg's firequalizer filter, or by manipulating FFT frequency bins directly with afftfilt.

Understanding the Pinking Filter

White noise contains equal energy per Hertz across the entire frequency spectrum. Pink noise requires equal energy per octave, which translates to a power spectral density roll-off of 3 dB per octave (approximately 10 dB per decade) as frequency increases. A pinking filter is a spectral tilt filter configured to impose this continuous -3 dB/octave attenuation curve across the audible frequency range (20 Hz to 20,000 Hz).

The firequalizer filter applies an arbitrary equalizer curve using a Fast Fourier Transform finite impulse response (FIR). You can define the -3 dB/octave slope mathematically using the gain parameter.

ffmpeg -f lavfi -i anoisesrc=color=white:sample_rate=48000:duration=10 \
-af "firequalizer=gain='-3*log2(clip(f,20,20000)/20)':scale=log" \
pink_noise.wav

How the Command Works:

  • -f lavfi -i anoisesrc=color=white:sample_rate=48000:duration=10: Generates 10 seconds of pure white noise at a 48 kHz sample rate.
  • firequalizer: Employs FIR-based equalization.
  • gain='-3*log2(...): Computes the attenuation dynamically. For every octave (doubling of frequency \(f\)) above 20 Hz, the output is attenuated by 3 dB.
  • clip(f,20,20000): Restricts calculation to the standard audible band to prevent invalid low-frequency or sub-audible calculations.
  • scale=log: Sets logarithmic frequency spacing, matching human hearing and filter behavior.

Method 2: Using afftfilt (Frequency-Domain Tilt)

Pink noise amplitude follows a \(1/\sqrt{f}\) relationship relative to frequency. The afftfilt filter allows direct manipulation of frequency magnitudes using mathematical formulas applied to real and imaginary FFT components.

ffmpeg -f lavfi -i anoisesrc=color=white:sample_rate=48000:duration=10 \
-af "afftfilt=real='re*sqrt(1000/clip(f,20,20000))':imag='im*sqrt(1000/clip(f,20,20000))'" \
pink_noise_afft.wav

In this command, each frequency bin above 20 Hz is scaled by \(1/\sqrt{f}\) (anchored at 1000 Hz for reference gain), achieving the pinking tilt directly in the spectral domain.

Applying the Tilt to Existing White Noise Files

If you have an existing white noise file rather than generating one, pass it as the standard input -i:

ffmpeg -i white_noise.wav \
-af "firequalizer=gain='-3*log2(clip(f,20,20000)/20)':scale=log" \
output_pink.wav

Direct Generation Alternative

If your goal is simply to produce pink noise rather than demonstrating the transformation of white noise via a tilt filter, FFmpeg's anoisesrc filter can generate pink noise natively:

ffmpeg -f lavfi -i anoisesrc=color=pink:sample_rate=48000:duration=10 pink_noise_native.wav