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.

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

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.

What is a "causal model"? The polynomial is a causal-model reading, not causal identification from observational audio alone. "Lawful" and "anomalous" therefore mean close to / far from this chosen intensity-to-centroid model, not proof of a physical cause. The script sorts grains by how well they conform to the model's prediction — grains with small residuals are "lawful" (brightness follows intensity), grains with large residuals are "anomalous" (deviate from the expected relationship).

Key Features:

Synthesis method: The synthesis stage does not filter or synthesise new spectra. A mono source grain pool is extracted with a rectangular window, then only splice edges are gain-tapered for overlap-add. Left and right contain the same grain pool but can place nearby-ranked grains in a slightly different order. Where grains overlap, samples are mixed and normalised by the same window sum. Stereo divergence is NOT a delay effect — both sides share the same stable causal order; only the closest adjacent key pairs can be swapped in one channel.

Quick start

  1. In Praat, select exactly one Sound object.
  2. Run script…Causal_Recomposer.praat.
  3. Choose a preset from the dropdown (3 options, plus Custom).
  4. Select Sort_key (Model residual magnitude / Predicted brightness / Signed model residual / Intensity).
  5. Select Sort_direction (Ascending / Descending).
  6. Set Grain_size_ms and Analysis_overlap (segmentation).
  7. Set Synthesis_overlap and Crossfade_ms (resynthesis).
  8. Adjust Stereo_divergence_percent (0–100%) for L/R local swaps.
  9. Click OK — the script analyses, fits the model, sorts grains, and recomposes stereo output.
Quick tip: Start with Lawful to Anomalous — grains that follow the intensity→centroid law are placed first, anomalies later. Anomalous to Lawful reverses the order. Brightness Sweep sorts by predicted brightness, creating a smooth spectral sweep. Increase Stereo_divergence_percent (20–40%) for more L/R difference. The visualisation shows the model fit, reordering map, and spectral shape comparison.
Important: This script is a grain re-ordering processor, not a spectral filter or resynthesizer. It does not create new spectral content — it reorders existing grains from the source. The polynomial model is fitted to the source's own intensity and centroid values; a well-fitting model (high R²) means the source has a strong intensity→centroid relationship, and sorting by residual will produce a perceptually meaningful reordering. If R² is low, sorting by residual may be less effective — try sorting by predicted brightness or intensity instead.

3 Presets

PresetSort KeyDirectionGrain (ms)Analysis OverlapSynth OverlapCrossfade (ms)Character
Lawful to AnomalousModel residual magnitudeAscending7050%40%20Grains that fit the law first, anomalies last
Anomalous to LawfulModel residual magnitudeDescending7050%40%20Anomalies first, lawful grains last
Brightness SweepPredicted brightness (Ĉ)Ascending9050%50%25Dark 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.

Sort keys available:
  • 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: Both channels receive the exact same primary sort. Then, 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.
Interpretation note: The polynomial is a causal-model reading, not causal identification from observational audio alone. A high R² means the source has a strong intensity→centroid relationship — but this is a statistical description, not a proof of physical causation. "Lawful" and "anomalous" should be understood as "close to / far from the chosen model's prediction."

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 and local swaps: The script first computes a stable base sort using the chosen key. Then, 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.

Troubleshooting:
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)

When Draw_visualization is enabled, the script generates:
  • 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.
The model fit panel (A) is the key diagnostic: it shows the intensity→centroid law and which grains are "lawful" vs "anomalous."