Evolving Granular — User Guide

Granular resynthesis with time-varying event density, pitch trajectory, grain duration statistics, source-position scatter, amplitude variation, and stereo decorrelation.

Author: Shai Cohen Affiliation: Department of Music, Bar-Ilan University, Israel Version: 0.5.2 (2026) License: MIT License Repo: https://github.com/ShaiCohen-ops/Praat-plugin_AudioTools
Contents:

What this does

Evolving Granular creates a new granular texture from the selected Sound. The source is converted to mono for grain extraction, but the result is always a new stereo Sound. Each grain is a short Hanning-windowed excerpt of the source. Its source position, output time, duration, pitch shift, amplitude, and right-channel deviations are determined before rendering.

The three evolution modes do not vary the same parameters. Density Growth changes event density over output time. Pitch Sweep uses an approximately constant mean event density while pitch follows output time. Statistical Shift divides the output into three statistical regions with different duration, pitch, pitch-randomness, and amplitude distributions.

Source-position randomness and output timing are separate. Position_randomness perturbs where a grain is read from the source. It does not jitter the left-channel event time. This keeps the requested temporal evolution readable.

What is a grain?

A grain is a short excerpt of the source waveform used as one synthesis event. In this script, each grain is extracted with Praat's Hanning window, multiplied by a per-grain amplitude factor, optionally pitch-shifted by varispeed resampling, and added into the stereo output at a scheduled start time.

grain = Hanning-windowed source excerpt × per-grain amplitude × optional varispeed pitch transformation

Many grains can overlap in the same output region. Their samples are added rather than concatenated, so increasing density increases the amount of overlap and changes the resulting texture.

Quick start

  1. Select exactly one Sound object in Praat.
  2. Run Evolving_Granular.praat.
  3. Choose one of the eight presets or keep Custom.
  4. For Custom, set the density values and grain-duration range.
  5. Choose Density growth, Pitch sweep, or Statistical shift.
  6. Set source-position, pitch, and amplitude randomness.
  7. Set Stereo_width; 0 creates identical L/R channels, while larger values increase right-channel decorrelation.
  8. Enable or disable pitch shifting, visualization, and automatic playback.
  9. Run the script. The result is named <source>_<presetName>.

Presets

Named presets replace the grain, evolution, and randomization settings shown below. Stereo_width, Draw_visualization, and Play_result remain at the values chosen in the form.

PresetDensityGrain durationModePitch targetPosition rand.Pitch rand.Amp rand.Pitch
Dense Cloud20 → 40/s40–100 msDensity Growth3 st*0.401.5 st0.25On
Sparse Texture5 → 12/s80–200 msDensity Growth2 st*0.201.0 st0.15On
Rising Pitch Sweep15 / 3050–120 msPitch Sweep+12 st0.252.0 st0.20On
Falling Pitch Sweep15 / 3050–120 msPitch Sweep−12 st0.252.0 st0.20On
Three Region Evolution18 / 3530–150 msStatistical Shift8 st0.352.5 st0.25On
Gentle Growth8 → 20/s60–160 msDensity Growth2 st*0.151.0 st0.10On
Extreme Density Build10 → 60/s30–80 msDensity Growth5 st*0.503.0 st0.30On
Micro Grains30 → 50/s20–50 msDensity Growth7 st*0.304.0 st0.25Off
*Density Growth does not use Pitch_shift_semitones as a base pitch target. Its grain pitch is centred at 0 semitones and comes only from Pitch_randomness. The preset still assigns a Pitch_shift value, but that value has no effect while the mode remains Density Growth.

Evolution modes

1. Density Growth

The requested density is a linear function of normalized output time:

λ(u) = Initial_density + (Final_density − Initial_density) × u

The total requested grain count is:

N = round(duration × (Initial_density + Final_density) / 2)

Instead of generating candidates and rejecting some of them, v0.5.2 places deterministic quantiles of the cumulative density law. For each grain, it inverts the cumulative integral of λ(u). This avoids the saturation problem that occurs when an acceptance probability exceeds 1.

The selected grain duration is uniformly random between the minimum and effective maximum. Its legal start interval is therefore 0 ... duration − grainDuration, and the density-law position is mapped into that range. Pitch is 0 + Gaussian pitch randomness; amplitude is 1 + Gaussian amplitude randomness, clamped to 0.3–1.5.

2. Pitch Sweep

Here, Initial_density and Final_density are used only through their average to determine N. Grain centres are drawn uniformly across the output, so the expected event rate is approximately constant at that mean density.

normalizedTime = actual grain centre / duration basePitch = Pitch_shift_semitones × normalizedTime pitch = basePitch + Gaussian(0, Pitch_randomness)

A positive target rises from 0 toward that interval; a negative target falls. The base amplitude also changes with time:

baseAmplitude = 1.2 − 0.4 × normalizedTime amplitude = clamp(baseAmplitude + Gaussian randomness, 0.3, 1.5)

3. Statistical Shift

Grain centres are drawn uniformly in time. As in Pitch Sweep, the two density fields determine only the total grain count through their average. The output is divided at normalized times 0.33 and 0.66:

RegionDuration range within user's min–max spanBase pitchPitch randomness σBase amplitude
First third55%–100%−0.5 × target1.0 × Pitch_randomness0.9
Middle third25%–65%+0.25 × target1.5 × Pitch_randomness0.7
Final third0%–35%+1.0 × target2.0 × Pitch_randomness0.5

Amplitude randomness is added to the regional base and then clamped to 0.2–1.3.

Pitch shifting & grain duration

Pitch shifting is implemented by varispeed resampling, not by PSOLA. For a per-grain pitch shift s in semitones:

factor = 2^(s / 12) Override sampling frequency = sourceRate × factor Resample back to sourceRate

This changes both pitch and duration: positive shifts shorten the rendered grain, while negative shifts lengthen it. The output placement procedure uses the transformed grain's actual duration and truncates its contribution at the end of the output canvas if necessary.

Pitch processing is skipped only when |shift| ≤ 0.005 semitone, or when Enable_pitch_shifting is off. When pitch shifting is disabled, stored pitch values are set to zero so the visualization matches the rendered audio.

Stereo construction

The synthesis source is mono. Every planned grain is rendered once into the left channel and again into the right channel. The right copy receives three small independent deviations controlled by Stereo_width:

right detune σ = Stereo_width × 0.06 semitone right source jitter σ = Stereo_width × 0.002 s right timing jitter σ = Stereo_width × 0.0005 s

The right channel uses the same grain amplitude as the left. At Stereo_width = 0, all three deviations are zero, so the output is a stereo object with identical L/R channels. At larger values the two channels carry the same granular plan but are increasingly decorrelated.

Parameters

ParameterDefaultActual role
PresetCustomCustom plus eight named parameter sets.
Initial_density10.0Start density in Density Growth; otherwise contributes only to mean grain count.
Final_density25.0End density in Density Growth; otherwise contributes only to mean grain count.
Grain_duration_min0.05 sMinimum planned grain duration.
Grain_duration_max0.15 sMaximum planned duration; clipped internally to the source duration.
Evolution_typeDensity growthDensity Growth, Pitch Sweep, or Statistical Shift.
Pitch_shift_semitones7.0Pitch endpoint/range control for Pitch Sweep and Statistical Shift; unused as a base target in Density Growth.
Position_randomness0.3Source-read scatter in seconds. Density/Statistical use σ = 0.5 × value; Pitch Sweep uses σ = 0.3 × value.
Pitch_randomness2.0 stGaussian pitch standard deviation; Statistical Shift multiplies it by 1, 1.5, or 2 by region.
Amplitude_randomness0.2Gaussian variation around each mode's base amplitude.
Stereo_width0.30–1 scaling of right-channel detune, source jitter, and timing jitter.
Enable_pitch_shiftingOnEnables varispeed pitch processing.
Draw_visualizationOnDraws Source → Grain evolution map → Output → Summary.
Play_resultOnAutomatically plays the result.

Visualization

The Picture window is organized as Source → Grain evolution map → Output → Summary.

Source and Output use the same amplitude scale. Dot size changes automatically with grain count so both sparse and dense clouds remain readable.

The central map describes the planned left-channel grain events. The small right-channel source, timing, and detune deviations are not drawn individually.

Output & limits

Final level

After all grains are mixed, the script measures the output extremum. If the result is non-silent, it performs peak normalization to 0.95. This can attenuate or amplify the complete texture; it is not an attenuate-only safety ceiling.

Output name

The result is renamed <source name>_<presetName>, for example voice_RisingPitch or field_Custom.