Rhythmic Fractal Granulator — User Guide
Generates a mirrored, recursively subdivided event-time pattern, extracts source grains by random or sequential reading, applies generation-dependent amplitude envelopes, and overlap-adds the grains at their target times into a fixed-duration output buffer.
What this does
Rhythmic Fractal Granulator separates two ideas that should not be conflated:
- When grains occur is determined by a recursively subdivided timing pattern with bounded jitter and exact left/right mirroring.
- What each grain contains is determined independently by Random Offset or Sequential Scan through the selected source.
What “fractal” means here
The script uses a recursive dyadic-subdivision-inspired timing rule. Each generation introduces a smaller temporal shift, approximately half the previous generation's scale. This creates a hierarchy of event spacings.
After the left-half pattern is generated, every event is copied to the corresponding mirrored time on the right:
The mirrored half therefore preserves the exact jittered timing relationships of the generated left half under temporal reflection.
Quick start
- Select exactly one Sound object.
- Run
Rhythmic_Fractal_Granulator.praat. - Choose Custom or one of the five named presets.
- Set output duration, grain duration and number of generations.
- Choose Bell (Hanning) or Plateau (Trapezoid).
- Choose Random Offset or Sequential Scan.
- Choose whether a mono source should be duplicated to stereo and whether the final output should be peak-normalized.
- Run. The output is automatically played at the end.
Event-time generation
Output geometry
The historical 50 ms center reserve and 100 ms seed offset are therefore retained for normal output durations, but both scale down safely for very short custom renders.
Generation rule
The left half begins with one Generation-0 seed event at seedOffset. For generation g = 1...Generations:
The script snapshots the number of events that already exist at the beginning of that generation. Every one of those existing events is then eligible to spawn one new child:
The child is retained only if it remains inside the legal left-half region.
Event count
If every eligible parent successfully produces a child, the left-half population doubles at each generation:
Actual counts can be lower because children that fall beyond halfDuration are rejected. Generations are limited to 0–11 and the arrays are additionally guarded at 5000 events.
Mirroring and sorting
After the left half is complete, every event is mirrored around the output midpoint with its generation number unchanged. The complete event list is then sorted chronologically before source reading and synthesis.
Source reading
The source is never time-stretched or pitch-shifted. Each event simply extracts one rectangular grain of the effective grain duration from some location in the source.
Effective grain duration
The requested grain duration is internally clamped so that it:
- does not exceed the available source duration;
- contains at least two source samples when possible.
This protects both the legal source-read range and the Hanning denominator N-1.
Random Offset
A new random source position is drawn independently for every output event.
Sequential Scan
After the fractal events have been sorted by output time, source positions progress linearly through the entire legal read-start range:
The first event reads from source time 0; when there is more than one event, the last event reaches exactly sourceDuration - effectiveGrainDuration.
Non-zero source time domains
All synthesis reads use 0…sourceDuration coordinates. If the selected Sound does not start at time 0, the script creates a temporary zero-based processing copy. The user's original Sound is unchanged.
Grain amplitude & envelopes
Generation amplitude
Amplitude decreases by a fixed 15% multiplier per generation:
This value is hard-coded in v0.5.1; it is not a public parameter.
Bell (Hanning)
The sample-domain bell is:
The grain is multiplied by 0.85^g × w[n]. The first and final samples are zero.
Plateau (Trapezoid)
The current implementation is a genuine linear trapezoid:
The same generation amplitude multiplier is applied throughout the envelope.
True overlap-add
A silent output Sound of exactly Total_duration is created before any grain is rendered. It has the source sample rate and the source channel count.
For event time t:
The windowed grain samples are then added directly into the corresponding output sample range:
If multiple grains overlap, their samples add. There is no voice stealing, overlap limit, automatic gain compensation, or per-overlap normalization.
Output-edge clipping
If a grain begins near the end of the fixed output buffer, only the portion that fits before Total_duration is added. The event is not shifted earlier and the output is not extended to accommodate the grain tail.
Five named presets + Custom
Named presets overwrite only Total_duration, Grain_duration, Generations, Window_shape and Read_mode. They do not overwrite Stereo, Normalize or Draw_visualization.
| Preset | Total | Grain | Generations | Window | Read mode |
|---|---|---|---|---|---|
| Dense Texture | 6.0 s | 50 ms | 6 | Bell | Random |
| Sparse Rhythmic | 8.0 s | 200 ms | 3 | Trapezoid | Sequential |
| Glitchy | 3.0 s | 20 ms | 7 | Bell | Random |
| Ambient Cloud | 10.0 s | 150 ms | 4 | Bell | Random |
| Percussive | 4.0 s | 80 ms | 3 | Trapezoid | Sequential |
Parameters & effective limits
| Parameter | Default | Exact behavior |
|---|---|---|
| Preset | Custom | Custom plus five named configurations. |
| Total_duration_(s) | 4.0 | Must be >0. Defines the output-buffer duration and timing scale. |
| Grain_duration_(s) | 0.1 | Must be >0; internally clamped to source duration and at least two source samples when possible. |
| Generations | 5 | Integer 0–11; controls recursive subdivision depth. |
| Window_shape | Plateau | Bell/Hanning or linear trapezoid. |
| Read_mode | Random Offset | Independent random source positions or full-range sequential scan. |
| Stereo | On | If source is mono, duplicate final mono output to stereo. Does not pan or spatialize. |
| Normalize | On | Target Sinc70 peak scaling to 0.95 when non-silent. |
| Draw_visualization | On | Draw the v0.5.1 fractal-timing visualization. |
Source minimum
The source must contain at least two samples. There is no fixed minimum duration such as 0.5 seconds.
Channels & the Stereo option
Grain extraction and overlap-add operate on all source channels independently. The initial output buffer is created with the same channel count as the source.
| Source | Stereo off | Stereo on |
|---|---|---|
| Mono | Mono output | Mono result duplicated to two identical channels |
| Stereo | Stereo preserved | Stereo preserved; no additional conversion |
| 3+ channels | Channel count preserved | Channel count preserved; not reduced to stereo |
Normalization
When Normalize is enabled, the completed result is measured with Praat's Sinc70 absolute extremum. A non-silent result then receives:
This is target peak normalization, not an attenuate-only ceiling. A quiet output can be amplified to the 0.95 target.
When Normalize is off, overlapping grains are left at their raw additive level. No limiter or clipping-prevention stage follows.
Visualization
The v0.5.1 Picture view preserves the tool's distinctive timing analysis while aligning the waveform geometry and color semantics.
- Source waveform — original selected Sound.
- Recursive Subdivision — event positions arranged by generation, with the mirror axis marked.
- IOI distribution — 24-bin logarithmic histogram of successive event intervals.
- Radial clock — angular position = normalized event time; radius = generation.
- Output waveform — completed result.
- Summary — event count, mirrored count, generations, effective grain duration, window, read mode and output duration.
Shared waveform scale
Source and Output share one amplitude range based on the larger Sinc70 peak, with 8% visual headroom. They can therefore be compared directly in level as well as shape.
Generation color
Color has one semantic meaning: generation. Generation 0 begins warm and later generations move through the palette toward cooler colors. Generations above 7 share the final color and are labeled 7+ in the legend.
Recursive Subdivision connectors
IOI log-histogram
Bars show the measured intervals between chronologically adjacent events. The dotted reference lines show the ideal dyadic scales:
Jitter, mirroring and the interaction among multiple generations can broaden or redistribute the actual histogram relative to those reference positions.
Radial clock
The inner viewport is explicitly square, so the clock is physically circular. Event angle follows time across Total_duration; radial distance follows generation. The vertical diameter marks the mirror axis.
Output behavior
- Name:
Fractal_Granular_<random 5-digit ID>. - Duration: exactly the requested Total_duration buffer, subject to Praat's sample grid.
- Sample rate: source sample rate.
- Source pitch: unchanged; no transposition is performed.
- Original source: unchanged.
- Randomness: timing jitter always; random source positions in Random Offset mode; random 5-digit output ID.
- Random seed: no user control.
- Playback: always performed at the end of the script.