Causal Recomposer — Grain Reordering Processor
A grain re-ordering processor that fits a compact predictive law between local intensity and spectral centroid, then uses the residual from that model as a stable sort key. The source is reduced to one protected mono grain pool and recomposed twice — left and right use the same primary causal sort plus a few channel-specific local swaps to create stereo from recomposition itself.
What this does
This script implements a grain re-ordering processor — it is not a spectral filter or resynthesizer. It analyses overlapping source grains, fits a compact predictive law between local intensity I and spectral centroid C:
Ĉ(t) = f( z(I(t)) ) — polynomial order 1–3
R(t) = C(t) - Ĉ(t)
and uses one quantity derived from that model as a stable sort key. The source is then reduced to one protected mono grain pool and recomposed twice: left and right use the same primary causal sort plus a few channel-specific local swaps. That controlled difference creates stereo from recomposition itself.
Key Features:
- 3 Presets — Lawful to Anomalous, Anomalous to Lawful, Brightness Sweep
- 4 Sort Keys — Model residual magnitude, Predicted brightness, Signed model residual, Intensity
- Polynomial model fitting — order 1–3 with automatic rank reduction
- Stereo from recomposition — both channels share the same primary sort, with local swaps for spatial divergence
- Cancellation-safe mono fold — averages channels; falls back to strongest channel if anti-phase cancellation occurs
- Overlap-add resynthesis — raised-cosine crossfade, dual-channel overlap-add
- Visualisation — intensity→centroid model, L/R reordering map, splice window, spectral shape comparison
Quick start
- In Praat, select exactly one Sound object.
- Run script… →
Causal_Recomposer.praat. - Choose a preset from the dropdown (3 options, plus Custom).
- Select Sort_key (Model residual magnitude / Predicted brightness / Signed model residual / Intensity).
- Select Sort_direction (Ascending / Descending).
- Set Grain_size_ms and Analysis_overlap (segmentation).
- Set Synthesis_overlap and Crossfade_ms (resynthesis).
- Adjust Stereo_divergence_percent (0–100%) for L/R local swaps.
- Click OK — the script analyses, fits the model, sorts grains, and recomposes stereo output.
3 Presets
| Preset | Sort Key | Direction | Grain (ms) | Analysis Overlap | Synth Overlap | Crossfade (ms) | Character |
|---|---|---|---|---|---|---|---|
| Lawful to Anomalous | Model residual magnitude | Ascending | 70 | 50% | 40% | 20 | Grains that fit the law first, anomalies last |
| Anomalous to Lawful | Model residual magnitude | Descending | 70 | 50% | 40% | 20 | Anomalies first, lawful grains last |
| Brightness Sweep | Predicted brightness (Ĉ) | Ascending | 90 | 50% | 50% | 25 | Dark to bright spectral sweep |
Theory — Model Fitting and Residual Sorting
Feature extraction per grain
Each grain is analysed for:
- Intensity I — RMS amplitude in dB (from Intensity object)
- Spectral centroid C — centre of gravity of the spectrum
Standardised polynomial model
z(I) = (I - μI) / σI
Ĉ(z) = a₀ + a₁·z + a₂·z² + a₃·z³ (order 1–3)
The standardisation improves numerical conditioning of higher-order polynomial fitting. The model is fitted using ordinary least squares with automatic rank reduction (if the requested order is singular, it falls back to a lower order or a constant model).
Residual
R = C - Ĉ
Positive residual = brighter than predicted; negative = darker than predicted.
- Residual magnitude |R| — lawful (small) to anomalous (large)
- Predicted brightness Ĉ — dark to bright (sweep)
- Signed residual R — darker-than-predicted to brighter-than-predicted
- Intensity I — quiet to loud
Stereo_divergence_percent controls how many adjacent pairs with the smallest primary-key gaps are swapped. The swap is applied to either the left or right channel based on a secondary feature (signed residual or intensity). This creates subtle stereo differences while preserving the global causal order.
4 Sort Keys
Model residual magnitude lawful → anomalous
|C - Ĉ| — how far the grain deviates from the intensity→centroid model. Small residuals = lawful (predictable); large residuals = anomalous (unexpected).
Best for: Exploring the "lawfulness" gradient of the source.
Predicted brightness (Ĉ) dark → bright
The model's predicted centroid based on the grain's intensity. Sorts by the model's estimate of brightness, not the measured value.
Best for: Creating a smooth spectral sweep while maintaining the intensity→centroid relationship.
Signed model residual darker → brighter
C - Ĉ — positive = brighter than predicted, negative = darker than predicted. Sorts from negative to positive.
Best for: Exploring the direction of the deviation, not just its magnitude.
Intensity quiet → loud
The grain's measured RMS amplitude in dB. Sorts from quiet to loud (or reverse).
Best for: Simple amplitude-based reordering, without the model.
Stereo_divergence_percent controls how many adjacent pairs (with the smallest key gaps) are swapped. The swap is applied to either the left or right channel based on a secondary feature (signed residual or standardised intensity), ensuring that the same grain can appear at slightly different positions in L/R. This creates a perceptually coherent stereo image from a mono grain pool.
Applications
Lawful to Anomalous / Anomalous to Lawful
Use case: Reorder a sound so that the most "predictable" grains play first, followed by the most "unexpected" grains — or vice versa. This can create a narrative arc from stable to unstable.
Settings: Lawful to Anomalous preset. The output is a recomposition that starts with grains that follow the intensity→centroid law and ends with the anomalies.
Brightness sweep
Use case: Create a smooth spectral sweep from dark to bright (or bright to dark) using the model's predicted brightness.
Settings: Brightness Sweep preset. The output progresses from low-predicted-centroid grains to high-predicted-centroid grains.
Generated stereo from mono sources
Use case: Create a stereo output from a mono input using controlled L/R divergence.
Settings: Any preset, increase Stereo_divergence_percent (20–40%). The L and R channels share the same primary sort but have slightly different local orderings, creating a subtle stereo image.
Workflow: Voice recording → Lawful to Anomalous
Source: Spoken word or sung phrase.
Settings: Lawful to Anomalous preset, grain=70 ms, stereo_divergence=20%.
Result: The voice is recomposed: stable, predictable grains (steady pitch, consistent brightness) play first, followed by the more unusual moments (pitch jumps, spectral oddities). The stereo divergence creates a subtle widening.
Workflow: Instrumental recording → Brightness sweep
Source: Instrumental solo (guitar, piano, synth).
Settings: Brightness Sweep preset, grain=90 ms, synthesis_overlap=50%.
Result: The output progresses from dark, low-centroid grains to bright, high-centroid grains — a timbral sweep across the duration.
Workflow: Mono field recording → Stereo recomposition
Source: Mono field recording (birds, water, wind).
Settings: Custom, sort_key=Model residual magnitude, stereo_divergence=30%.
Result: The mono recording is recomposed into stereo using the causal sort — the L and R channels are subtly different, creating a wider, more spatial texture.
• Model fit R² is very low (<0.1): The source has a weak intensity→centroid relationship. Sorting by residual may produce a random-sounding result. Try sorting by Intensity or Predicted brightness instead.
• Output is mono or has very little stereo: Increase Stereo_divergence_percent (30–50%). The script only swaps adjacent pairs with the smallest key gaps; if the source has very few near-equal pairs, the stereo divergence will be limited.
• Output has clicks at grain boundaries: Increase Crossfade_ms (15–30 ms) or synthesis_overlap. The raised-cosine taper should eliminate clicks if the overlap is sufficient.
• Channel average nearly cancels: The script detects severe anti-phase cancellation and falls back to the strongest channel. This is reported in the Info window. The mono grain pool is protected.
• Visualisation shows "model order reduced": The requested polynomial was singular (insufficient intensity variation). The script automatically reduces the order or falls back to a constant model. The fit R² will reflect the reduced model.
Visualisation (4-panel process view)
- Panel A (Model): Intensity (dB) vs spectral centroid (Hz) scatter plot with the fitted polynomial curve. Shows which grains follow the law (close to curve) and which are anomalous (far from curve).
- Panel B (Order): L/R reordering map — output position vs source position. Blue = Left, Red = Right. Grey diagonal = unchanged chronology. Differences between L and R are the stereo divergence.
- Panel C (Splice): One grain's gain envelope (blue) and the overlap-add normalisation weight (red). Shows the crossfade and overlap geometry.
- Panel D (Check): Spectral shape difference between the mono source and the stereo MID channel. Also reports SIDE/MID ratio (stereoness).
- Summary bar: Sort key, direction, grain count, stereo divergence, mono pool method, side/mid ratio.