Sound Atom Composer — User Guide
Builds a descriptor-indexed corpus of pitched source moments, selects and reorders those atoms, then resynthesizes a new stereo texture by reading the actual source audio at variable speed with per-atom pan and right-channel timing jitter.
What this does
Sound Atom Composer analyzes a folder of WAV files, identifies voiced moments that satisfy pitch and intensity criteria, stores those moments as a descriptor table, and then uses the selected table rows to read short pieces of the actual source waveform from a concatenated mono SourceBank.
What is an atom here?
An atom is a qualifying analysis frame plus a fixed requested read duration. The dictionary contains four numeric descriptors:
| Column | Meaning | Used in synthesis? |
|---|---|---|
| time | Absolute time inside the concatenated SourceBank. | Yes — source-read start. |
| duration | max(Time_step × Atom_duration_multiplier, 2/maxSR). | Yes — nominal source-grain duration. |
| frequency | Detected voiced F0 in Hz. | Used for selection and visualization, not as an oscillator frequency. |
| amplitude | Praat Intensity value at the analysis time. | Used for selection/visualization only; it does not multiply grain gain. |
Quick start
- Prepare a folder containing lowercase
*.wavfiles. - Run
Sound_atom_composer.praat; no Sound selection is required. - Type a folder path, or leave Folder blank to use Praat's folder chooser.
- Choose Custom, Time Stretch, Pitch Shifted Cloud, or Shuffle Texture.
- Set analysis thresholds, pitch range, atom limit, transposition, output duration and amplitude scale.
- Run. The output object is named
Granular_Output.
Corpus preparation
Folder discovery
The script searches the selected folder with the pattern *.wav. If no matching files are found, it exits.
Mono conversion
Every loaded file is converted to mono before corpus assembly. Stereo and multichannel spatial information from the source files is therefore discarded before analysis and synthesis.
Common sample rate
The target sample rate is the highest sample rate among all loaded files. Lower-rate files are resampled to that value with Praat precision 50.
SourceBank order
The files are concatenated explicitly in the order returned by Praat's file list. The script builds fresh accumulator copies so later resampling cannot accidentally reorder the bank through Object-list IDs.
The resulting mono SourceBank is shifted to start at time 0. Per-file start/end positions are retained internally so candidate atoms can be checked against file boundaries.
Analysis & atom dictionary
Pitch analysis
The effective Pitch ceiling is:
The lower bound is Min_freq. If the resulting usable range is invalid, the script exits instead of running Pitch outside the corpus Nyquist range.
Intensity analysis
Praat Intensity is calculated with Min_freq as its minimum-pitch parameter and Time_step as the time step. Min_energy is compared directly with Praat Intensity values.
Acceptance test
A frame becomes an atom only when all of the following are true:
Unvoiced Pitch frames are skipped; they are not replaced by a fallback frequency.
File-boundary protection
The nominal source read extends forward from the analysis time by:
If that interval would cross from one original file into the next within SourceBank, the candidate is rejected. A rendered grain therefore never splices two corpus files inside one atom.
Selection & randomization
After analysis, the table contains all qualifying atoms in SourceBank/time order.
Randomize_order = off
The table remains sequential. If more rows exist than Max_atoms, the first Max_atoms rows are used.
Randomize_order = on
Praat Randomize rows is called before the Max_atoms limit is applied.
Max_atoms is a positive real field for API compatibility, but the engine uses floor(Max_atoms) and enforces an internal minimum of 1.
There is no random-seed control, so row randomization, stereo pan and right-channel jitter can vary between runs.
True granular synthesis
The engine creates two silent mono buffers, Left and Right, each exactly Output_duration long at the SourceBank sample rate.
Destination timing
Selected atoms are distributed uniformly across the requested output timeline:
The final atom therefore begins one spacing interval before Output_duration rather than exactly at the endpoint.
Actual source audio
For each output sample, the engine reads SourceBank with Praat's object() function:
This is sample-based corpus resynthesis. No sine oscillator is created.
Gaussian-like edge-zeroed window
The nominal Gaussian uses width = renderedDuration / 4. Because a Gaussian at ±2 widths equals exp(-2), the script subtracts that edge value and renormalizes:
This makes the window reach zero at the rendered interval edges rather than ending at approximately 0.135.
Output-edge clipping
If an atom begins before time 0 because of right-channel jitter, or extends beyond Output_duration, only its intersection with the legal output domain is rendered. The complete atom is not discarded.
Transpose & atom duration
Transposition uses a source-read-rate ratio:
The rendered atom duration is:
- positive semitones: source is read faster → higher pitch and shorter atom;
- 0 semitones: original pitch and nominal atom duration;
- negative semitones: source is read slower → lower pitch and longer atom.
Stereo field
Source spatial information has already been removed by mono conversion. A new stereo field is created independently for every selected atom.
Random balance
This is a linear balance law, not constant-power panning. At pan=0.5, each side receives 0.5 × Amplitude_scale.
Right-channel timing jitter
Left begins at the regular destination time. Right begins at destinationTime + jitter. Jitter can be positive or negative and is safely clipped at output time 0 when necessary.
atomPan value shown in the Stereo Field visualization is this random 0…1 balance parameter. The right-channel timing jitter is not shown as a separate horizontal offset in that panel; both visualization panels use the unjittered destination time on the x-axis.
Three named presets + Custom
The presets overwrite only Time_step, Max_atoms, Transpose_semitones, Randomize_order, Output_duration and Atom_duration_multiplier. They do not overwrite Min_energy, Min_freq, Max_freq, Amplitude_scale, Draw_visualization, Play_result or Folder.
| Preset | Time step | Max atoms | Transpose | Randomize | Output | Duration mult. |
|---|---|---|---|---|---|---|
| Time Stretch | 50 ms | 1000 | 0 st | No | 20 s | 2.0 |
| Pitch Shifted Cloud | 30 ms | 600 | +12 st | Yes | 8 s | 1.0 |
| Shuffle Texture | 100 ms | 200 | −5 st | Yes | 10 s | 1.0 |
Parameters & limits
| Parameter | Default | Exact role |
|---|---|---|
| Folder | blank | Typed WAV-folder path; blank opens a directory chooser. |
| Preset_style | Custom | Custom plus three named strategies. |
| Time_step | 0.05 s | Pitch/Intensity analysis step and base atom-duration unit. |
| Min_energy | 30 | Minimum Praat Intensity value required for atom acceptance. |
| Min_freq | 50 Hz | Pitch-analysis floor and atom-selection lower bound. |
| Max_freq | 4000 Hz | Requested Pitch ceiling/selection upper bound; analysis is capped below Nyquist. |
| Max_atoms | 400 | Floored to an integer ≥1 after optional table randomization. |
| Transpose_semitones | 0 | Varispeed read-rate transposition; no explicit public range clamp. |
| Randomize_order | On | Randomizes dictionary rows before Max_atoms truncation. |
| Output_duration | 10 s | Exact duration of the L/R synthesis buffers. |
| Atom_duration_multiplier | 1.5 | Dictionary duration = Time_step × multiplier, with a two-sample minimum. |
| Amplitude_scale | 1.0 | Global multiplier applied through per-atom L/R gains. |
| Draw_visualization | On | Draw SourceBank, Result, Atom Distribution, Stereo Field and Summary. |
| Play_result | On | Play Granular_Output after completion. |
Min_freq must be smaller than Max_freq. Most numeric fields are positive at the Praat-form level. Amplitude_scale and Transpose_semitones are real fields and are not otherwise clamped by the script.
Amplitude scale & final peak safety
Amplitude_scale directly affects the atom gains. It is not cancelled by unconditional normalization.
After L/R are combined to stereo, the script measures the Sinc70 absolute extremum:
This is an attenuate-only safety ceiling, not target normalization. A quiet result stays quiet; only an over-ceiling result is globally reduced.
Visualization
The v1.3.6 Picture view contains:
- Source Bank waveform — concatenated mono corpus.
- Result waveform — stereo Granular_Output.
- Atom Distribution — selected atom frequency versus destination time; color represents stored Intensity amplitude from quiet to loud.
- Stereo Field — random pan parameter versus destination time; color represents atom frequency from low to high.
- Summary — atom count, average frequency, transpose, duration, corpus size, analysis range, time step and randomization state.
Shared waveform scale
SourceBank and Result use one shared amplitude scale based on the larger Sinc70 peak plus 5% headroom, so their plotted levels are directly comparable.
Selected frequency display range
The Atom Distribution y-axis zooms to the actually selected frequency range with padding, constrained by Min_freq/Max_freq, rather than always displaying the entire requested analysis range.
Output behavior
- Name:
Granular_Output. - Channels: always stereo.
- Source spatial image: not preserved; all corpus files are mono-folded first.
- Sample rate: highest sample rate among the corpus WAV files.
- Duration: Output_duration.
- Source material: real waveform grains read from SourceBank.
- Pitch change: varispeed source reading.
- Randomness: optional row shuffle, per-atom pan, per-atom Gaussian right-channel jitter.
- Random seed: no user control.
- Playback: controlled by Play_result.
The temporary SourceBank and atomDictionary are removed after synthesis; the final Granular_Output Sound remains selected.