Spectral Noise Shaping — User Guide

Analyses a folder of audio files, learns their spectral profile and temporal envelope, then generates new stereo audio by shaping white noise to match. No neural networks, no training – finishes in seconds. Perfect for creating synthetic textures, ambient drones, or randomised soundscapes from a corpus.

Author: Shai Cohen Affiliation: Department of Music, Bar‑Ilan University, Israel Version: 1.1 (2026) License: MIT License Repo: GitHub
Contents:

What this does

Spectral Noise Shaping is a fast, neural‑free generative synthesis tool. It analyses a folder of audio files (your “corpus”), learns their spectral character, and generates new stereo audio by shaping white noise to match that profile.

How it works:
  1. Load all audio files in the corpus folder (WAV, FLAC, AIFF).
  2. Compute STFT of every file, building a bank of spectral magnitude profiles (per‑frame).
  3. Compute the mean temporal envelope (RMS over time) across all files.
  4. Generate white noise of the target duration.
  5. For each STFT frame of the noise, replace its magnitude with a randomly selected corpus profile (blended with a second profile for variation). Keep the noise’s random phase – this preserves the “noise” character while imposing the spectral shape.
  6. Inverse STFT → shaped noise.
  7. Apply the learned temporal envelope to shape the amplitude over time.
  8. Normalise and save as stereo WAV (left and right channels use different random seeds for decorrelation).

The result genuinely starts from noise but inherits the spectral character and dynamic contour of the corpus. The output is a new, unique sound every run – perfect for generating ambient drones, textural beds, randomised soundscapes, or training data for other systems.

Quick start

  1. Prepare a folder of audio files (e.g., recordings of rain, speech, instruments, field recordings).
  2. In Praat, run the script Spectral_Noise_Shaping.praat.
  3. Set Input_folder to the path of your corpus folder.
  4. Set Duration (seconds) for the generated output.
  5. Choose a Chunk_preset – controls the grain texture:
    • 1024 (~23 ms) – grainy / fluttery.
    • 2048 (~46 ms) – balanced (default).
    • 4096 (~93 ms) – smooth / sustained.
    • 8192 (~186 ms) – slow / washy.
    • Same as N_fft – uses the FFT size as the chunk size.
  6. Adjust Variation (0 = pure mean spectrum, 1 = max variation between profiles).
  7. Optionally set a fixed Seed (0 = random).
  8. Click OK. Python analyses the corpus, generates audio, and imports the result as spectral_noise_shaped.
Tip: For a first test, use a small folder (5–10 files) and duration 5 s. The analysis phase prints progress in the Info window. The output is stereo – left and right channels are generated independently with different random seeds, creating a wide, decorrelated stereo image.
Important: Python dependencies: numpy, scipy, soundfile. The script uses a fast STFT‑based pipeline and finishes in seconds even for large corpora. The chunk size must be a power of two and at least 2× the hop length – the script validates this and provides clear error messages.

5‑stage pipeline

Stage 1 – Load corpus (Python)
Recursively scan the input folder for audio files (WAV, FLAC, AIFF). Load each file, convert to mono, resample to target sample rate, normalise peak to 0.95. Skip files shorter than 0.2 s.

Stage 2 – Analyse spectra
For each file, compute STFT with Hann window, chunk_size (frame size), hop_length, and n_fft (FFT size). Extract magnitude spectra per frame. Also compute RMS per frame for temporal envelope. Build a bank of all magnitude profiles across all frames of all files.

Stage 3 – Compute mean envelope
Resample each file’s RMS envelope to a common length (200 points), average them, normalise peak to 1.

Stage 4 – Generate stereo noise
Generate white noise of target duration (plus padding for overlap‑add). For each STFT frame:
  • Window the noise frame with Hann window.
  • Pick a random corpus profile (and optionally a second for blending).
  • Apply variation (blend + jitter).
  • Reconstruct: magnitude from corpus, phase from noise.
  • Inverse FFT → overlap‑add.
Left and right channels use different random seeds for decorrelation.

Stage 5 – Apply envelope & normalise
Apply the mean temporal envelope (smoothed with 20 ms kernel). Apply 10 ms fade‑in/out. Normalise peak to 0.9. Write stereo WAV.

The chunk size controls the temporal grain of the synthesis – smaller chunks create fluttery, grainy textures; larger chunks create smooth, sustained textures. The variation parameter controls how much the output deviates from the mean spectrum.

Parameters & defaults

Input

ParameterDefaultDescription
Input_folderD:\sounds\corpus

Output

ParameterRangeDefaultDescription Duration0.5–603.0。 Seed0 = random0。

Spectral settings

ParameterRangeDefaultDescription N_fft512–81922048。 Hop_length≤ n_fft512。 Chunk_preset1024 / 2048 / 4096 / 8192 / Same as N_fft2048。 Variation0–10.5。<0 = pure mean spectrum, 1 = max variation between profiles.

Audio

ParameterDefaultDescription
Sample_rate44100

Output options

ParameterDefaultDescription Draw_visualizationyes。 Play_resultyes。

Chunk size & grain texture

The chunk size (synthesis frame size) determines the temporal resolution of the generated audio. Smaller chunks produce grainier, more fluttery textures; larger chunks produce smoother, more sustained sounds.

。<~23 ms。 。<~46 ms。 。<~93 ms。 。<~186 ms。
Chunk sizeDuration at 44.1 kHzTextureUse case
1024
2048
4096
8192

The chunk size must be a power of two and at least 2× the hop length. The script validates this and provides an error message with the nearest valid value if violated.

Visualization (Praat picture)

When Draw_visualization = 1, the script draws a 3‑panel figure:

Tip: The spectrogram reveals the timbral quality of the output. If it looks too uniform, increase Variation to blend more diverse corpus profiles. If it sounds too noisy, reduce Variation or use a larger chunk size.

FAQ / troubleshooting

“chunk_size must be a power of 2”

The chunk size (synthesis frame size) must be a power of two (e.g., 512, 1024, 2048, 4096, 8192). The script prints the nearest valid value. Choose a preset or manually set Chunk_preset = Same as N_fft if your n_fft is already a power of two.

“chunk_size must be at least 2 × hop_length”

If the chunk size is too small relative to the hop length, there will be gaps in the overlap‑add synthesis, resulting in silence or clicks. Increase the chunk size or decrease the hop length. The default hop length is 512 samples; the default chunk size (2048) is 4× hop, which is safe.

Output is mono / left and right identical

The script generates left and right channels independently with different random seeds (seed_L = user seed, seed_R = user seed + 1). If you set a fixed seed, the two channels will still be different because the seeds differ. If the output sounds mono, check that your playback system is stereo.

Corpus analysis is slow for many files

The script loads all files into memory. For very large corpora (hundreds of files, gigabytes of data), reduce the number of files or increase the hop length to analyse fewer frames per file. The script prints progress – be patient.

Why keep the noise phase?

Replacing the noise’s magnitude with corpus profiles while keeping the random noise phase preserves the “noise” character – the output sounds like shaped noise, not a copy of the corpus. If you replaced the phase as well, you’d get a granular reconstruction of the corpus itself, which is not the goal.

Stereo decorrelation

Left and right channels are generated independently with different random seeds. This creates a wide, immersive stereo image. The two channels have the same spectral character but different fine‑grain noise structure.

Temporal envelope smoothing

The mean envelope is smoothed with a 20 ms kernel to avoid amplitude pumping. This is especially important for short chunk sizes, where the envelope would otherwise track the noise’s instantaneous amplitude.

```