Adaptive Grain Cloud Synthesis — User Guide
Granular resynthesis with sample-quantized event scheduling, stochastic source-position and pitch variation, optional content-adaptive grain duration, random grain reversal, and multi-track overlap-add rendering.
What this does
Adaptive Grain Cloud Synthesis resynthesizes the selected Sound as a cloud of short, overlapping grains. The source is converted to mono, grains are read from positions that follow the source from beginning to end (or remain fixed for the Spectral Freeze preset), and each grain is placed on an exact sample-quantized output event grid.
The cloud can vary in density, overlap, source-position scatter, pitch scatter, grain duration, and direction. When Adaptive_duration is enabled, grain duration responds to the source's spectral-centroid profile: relatively darker regions produce longer grains and relatively brighter regions produce shorter grains. This adaptation affects duration only; pitch scatter remains controlled separately by Pitch_scatter_semitones.
What is a grain cloud?
A grain is a short excerpt of sound. A grain cloud is a collection of many such excerpts whose start times, source positions, durations, pitch shifts, and directions can vary. When grains overlap densely, the individual fragments merge perceptually into a continuous texture; with lower density or larger spacing, the individual events remain more audible.
Grain anatomy in this script
Source interval: a short Hanning-windowed excerpt from the mono source.
Output event: a sample-quantized onset on the cloud timeline.
Optional transformations: adaptive duration, Gaussian pitch scatter, source-position scatter, and 50% random reversal when enabled.
Cloud rendering: grains are distributed over several non-overlapping tracks and the tracks are summed.
Quick start
- In Praat, select exactly one Sound object.
- Run
Adaptive_Grain_Cloud_Synthesis.praat. - Choose a preset, or keep Custom.
- Set Grain_size_ms, Grain_overlap, and Density.
- Use Pitch_scatter_semitones for random per-grain pitch variation and Position_scatter for random variation of the source read position.
- Enable Adaptive_duration if you want spectral centroid to control grain duration.
- Enable Reverse_random if approximately half of the grains should be reversed.
- Set Output_duration_factor to define the requested cloud duration relative to the source.
- Click OK. The output is created as
<source>_grainCloud.
Presets
Choosing a named preset overrides the grain, scatter, processing, and output-duration values shown below. The preset does not change Draw_visualization or Play_result.
| Preset | Grain | Overlap | Density | Pitch σ | Position scatter | Adaptive | Reverse | Duration |
|---|---|---|---|---|---|---|---|---|
| Dense Cloud | 40 ms | 0.7 | 3.0 | 0.0 st | 0.1 | On | Off | 1.0× |
| Sparse Cloud | 100 ms | 0.4 | 0.5 | 0.5 st | 0.3 | On | On | 1.0× |
| Micro-Grains | 10 ms | 0.5 | 5.0 | 1.0 st | 0.1 | Off | Off | 1.0× |
| Long Grains | 200 ms | 0.8 | 1.5 | 0.0 st | 0.05 | On | Off | 1.0× |
| Spectral Freeze | 80 ms | 0.9 | 2.0 | 0.0 st | 0.0 | Off | Off | 2.0× |
| Rhythmic Scatter | 30 ms | 0.0 | 2.0 | 0.2 st | 0.5 | Off | Off | 1.0× |
| Chaotic Swarm | 25 ms | 0.6 | 4.0 | 2.0 st | 0.8 | On | On | 1.5× |
| Time Stretch 2x | 60 ms | 0.75 | 1.0 | 0.0 st | 0.0 | On | Off | 2.0× |
| Time Compress 0.5x | 40 ms | 0.7 | 1.0 | 0.0 st | 0.0 | On | Off | 0.5× |
Adaptive duration
When Adaptive_duration is enabled, the script divides the source into a small number of analysis windows: 20 for files of at least 1 second, 10 for files shorter than 1 second, and 5 for files shorter than 0.25 seconds. Each window is Hanning-windowed, transformed to a Spectrum, and measured with Get centre of gravity: 2.
The mapping is relative to the spectral-centroid range of the selected source, not to a fixed brightness threshold such as 2000 Hz. A source with little centroid variation uses the neutral 1.0× duration multiplier.
Scheduling & rendering
Event rate
Density therefore changes the actual event rate. At density 2, the requested event hop is half the base hop; at density 0.5 it is twice the base hop.
Sample-quantized scheduler
The requested event hop is rounded to an integer number of samples. A minimum event hop of 1 ms is enforced. The scheduler may further increase the hop when necessary to respect two internal safety limits: at most 10,000 grains and at most 24 tracks. If this happens, the Info window reports that the effective density was reduced.
Source traversal and position scatter
Outside Spectral Freeze, the nominal source read position travels linearly from the beginning toward the last valid base-grain start as output time advances. Position_scatter adds Gaussian displacement to that source read position:
The result is clamped to the valid source range. Position scatter does not jitter output event times.
Pitch scatter
Each grain receives a Gaussian random pitch shift with standard deviation Pitch_scatter_semitones. The draw is bounded to ±3σ and also to an absolute maximum of ±24 semitones. Shifts whose absolute value is 0.1 semitone or less are left unchanged.
Pitch shifting is implemented by overriding the grain sampling frequency by 2^(shift/12) and resampling back to the source rate. Because this method changes the grain's sample count, pitch shifting also changes grain duration.
Tracks and mixing
Scheduled grains are interleaved over enough tracks that grains assigned to the same track do not overlap. Each grain is followed by silence to fill one exact track slot, every track is forced to the exact requested output sample count, and all tracks are then summed. Before summing, each track is scaled by 1 / sqrt(number_of_tracks).
Parameters
| Parameter | Default | Behavior |
|---|---|---|
| Preset | Custom | Selects Custom or one of nine named parameter sets. |
| Grain_size_ms | 50 | Base grain duration. Must fit inside the source. |
| Grain_overlap | 0.5 | Range 0–0.9. Defines base hop before Density is applied. |
| Density | 2.0 | Divides the base hop. Positive value; effective density may be reduced by safety limits. |
| Pitch_scatter_semitones | 0.0 | Gaussian σ in semitones; must be non-negative. |
| Position_scatter | 0.2 | Range 0–1. Gaussian scatter of the source read position. |
| Adaptive_duration | On | Maps regional spectral centroid to 0.6×–1.4× grain duration. |
| Reverse_random | Off | When enabled, each grain has a 50% chance of reversal. |
| Output_duration_factor | 1.0 | Requested output sample count = round(source samples × factor). |
| Draw_visualization | On | Draw source, grain time map, output, and summary. |
| Play_result | On | Automatically plays the resulting Sound. |
Visualization
When Draw_visualization is enabled, the Picture window shows four components:
- Source: the mono analysis/render source waveform, shown on a fixed ±1 amplitude scale.
- Grain time map: every scheduled grain is drawn as a mapping from its source interval on the horizontal axis to its output interval on the vertical axis. Blue upward mappings are forward grains; purple downward mappings are reversed grains. A pale reference line shows the nominal linear source traversal, or a vertical line in Spectral Freeze.
- Output: the final mono grain cloud on a fixed ±1 amplitude scale.
- Summary: grain count, base grain size, overlap, track count, requested/effective density, position scatter, pitch σ, duration, adaptive-duration state, and random-reverse state.
The Source and Output waveform panels use the same amplitude scale, so their displayed heights can be compared directly.
Output, limits & behavior
- The source must be at least as long as the base grain size.
- Grain overlap must be between 0 and 0.9.
- Position scatter must be between 0 and 1.
- Pitch scatter must be zero or positive.
- Output duration factor must be positive.
- The scheduler uses a minimum event hop of 1 ms, at most 10,000 grains, and at most 24 tracks.
- The output duration is sample-quantized from
round(sourceSamples × Output_duration_factor). - The final cloud is unconditionally peak-normalized to 0.9 when non-silent.
- A 10 ms fade-in and fade-out are applied; for outputs shorter than 40 ms, each fade is reduced to one quarter of the output duration.
- The output object is named
<source>_grainCloud.