Allpass Diffuser — User Guide

Spreads transients and reshapes temporal detail with a cascade of Schroeder allpass sections while keeping the magnitude response essentially flat. The result can range from light phase dispersion to a dense cloud, a long smear, or an intentionally metallic echo pattern.

Author: Shai Cohen Affiliation: Department of Music, Bar-Ilan University, Israel Version: 0.2.0 (2026) Implementation: Pure Praat Category: Phase / allpass processing
Contents:

What this does

Allpass Diffuser sends the selected Sound through a cascade of delayed allpass sections. An ideal allpass filter has unit magnitude at every frequency: it does not intentionally boost or cut spectral bands. What it changes is phase. In the time domain, that phase redistribution turns an impulse or sharp transient into a pattern of echoes whose density grows as more sections are cascaded.

Core idea: this tool is about time and phase rather than spectral colour. The script measures the magnitude spread of the actual composite impulse response on every run, so the user can verify how close the finite implementation remains to the allpass ideal.

Key features:

Flat magnitude does not mean perceptual neutrality. A sparse or periodic echo pattern can sound metallic or fluttery even when the frequency-response magnitude is flat. The Metallic comb preset is deliberately designed to demonstrate this distinction.

Quick start

  1. In Praat, select exactly one Sound.
  2. Run AllpassDiffuser.praat.
  3. Choose a preset. Custom is the form default and starts at 6 sections, g = 0.70, Size = 1.0 and fully wet output.
  4. Leave Normalize = none for the neutral allpass result.
  5. Leave Draw_visualization enabled if you want to inspect the temporal spreading and measured flatness.
  6. Enable Play_impulse_response if you want to hear the diffuser itself as an impulse response.
  7. Click OK. The result appears as originalName_apdiff.
Recommended first comparison: try Light dispersion, Dense cloud and Metallic comb on the same short percussive sound. All three aim at a flat magnitude response, but their temporal echo patterns are very different.

Presets

The preset changes Sections, Diffusion_g, Size and Dry_wet. It does not override your normalization, visualization or playback choices.

PresetSectionsgSizeDry/WetMeasured composite IR*Character
Custom (default)60.701.01.0≈2.26 sDense general-purpose diffuser; already highly diffuse within the first tens of milliseconds.
Light dispersion30.500.60.6≈0.18 sShort phase dispersion that preserves more of the direct attack.
Phase halo50.622.20.8≈2.52 sSparse near the attack, then increasingly diffuse — a halo around transients rather than an immediate cloud.
Dense cloud80.751.01.0≈5.74 sStrong click-to-cloud transformation with a dense echo field.
Long smear80.851.61.0≈16.25 sLong, slower-building temporal smear with a very extended tail.
Metallic comb20.851.51.0≈1.04 sIntentionally under-diffused and periodic; demonstrates that flat magnitude can still sound coloured.

*Values reported in the script's measured 44.1 kHz preset tests. The exact duration in a run is computed from the actual sampling rate and quantized delay lengths.

Echo-density behavior from the script's 44.1 kHz tests: Custom measured about 13,700 non-zero taps/s around 20 ms and 39,100 taps/s around 100 ms; Phase halo starts much sparser (about 1,150 taps/s at 20 ms) and becomes substantially denser later (about 15,200 taps/s at 100 ms). This is why the two presets can have similar total IR lengths yet very different attacks.

Allpass theory

One delayed Schroeder allpass section

The recursive section described by the script is:

v[n] = x[n] + g · v[n-M] y[n] = -g · v[n] + v[n-M] H(z) = (z^-M - g) / (1 - g z^-M)

For real |g| < 1, the numerator is the reversed/conjugate counterpart of the denominator on the unit circle, so the ideal magnitude response satisfies |H(e)| = 1. Frequency-dependent phase — not magnitude shaping — produces the audible transformation.

Closed-form impulse response

Rather than evaluating the recursion sample by sample in Praat script code, each section is expanded into its sparse impulse response:

h[0] = -g h[kM] = (1 - g²) · g^(k-1), k = 1, 2, 3, ... h[n] = 0 at all other samples

The echoes occur only at integer multiples of the section delay M, while their amplitudes follow a geometric decay. Cascading several sections convolves these sparse patterns together, rapidly increasing temporal density.

What Sections, g and Size actually change

Sections

More sections combine more mutually different delay patterns. This usually raises echo density and makes individual repeats harder to hear as separate events.

Diffusion_g

g controls the geometric decay inside every section. Higher values retain significant taps for longer, lengthening the effective section IR and increasing the amount of delayed energy.

Size

Size multiplies all section delays. Larger values move echoes farther apart and lengthen the composite tail without changing the ideal allpass magnitude law.

How it is implemented

The processing is entirely inside Praat and follows this sequence:

  1. Validate the controls. Sections is capped at 8, g at 0.05–0.95, Size at 0.1–8 and Dry_wet at 0–1.
  2. Scale the section delays. The fixed base delays are 149, 211, 353, 457, 631, 823, 1123 and 1523 samples at a 44.1 kHz reference. Each is multiplied by Size and converted to the Sound's actual sampling rate, keeping the intended delay in seconds approximately sample-rate independent.
  3. Choose the geometric-series length. The script keeps enough taps for g^k to fall below about 10-6, with a minimum of four taps.
  4. Build one sparse IR per section. Only samples at 0, M, 2M, 3M… contain non-zero values.
  5. Cascade the IRs first. The section IRs are convolved together into one composite allpass IR.
  6. Convolve the Sound once. The selected Sound is convolved with that composite IR, producing the full tail.
  7. Apply equal-power dry/wet mixing. The dry signal stops at its original end; the remaining tail is therefore wet only.
  8. Apply the selected normalization.
  9. Measure the actual magnitude spread. Praat derives an LTAS from the composite IR and reports max-minus-min dB over 80 Hz to the smaller of 16 kHz or Nyquist minus 1 kHz.
Why one final convolution matters: mathematically, convolving the Sound successively with each section IR is equivalent to first convolving all section IRs together and then applying the composite IR once. The latter avoids repeatedly processing an increasingly long Sound and reuses the same composite IR needed for visualization.

Finite-tail safeguard

An ideal recursive allpass has an infinite impulse response. This implementation realizes it as a long but finite FIR approximation. Each section is normally limited to a maximum target of 40 seconds. If an extreme combination of high g and large Size truncates a still-significant next tap, the script reports the amplitude of that first dropped tap.

Trust the measured spread on extreme Custom settings. If the first dropped tap exceeds 0.001, the script explicitly warns that the finite chain is no longer strictly allpass. Lower Diffusion_g or Size until the warning disappears if flat magnitude is important.

Parameters

ParameterDefaultEffective range / optionsMeaning
PresetCustomCustom + 5 presetsLoads a predefined combination of Sections, g, Size and Dry_wet.
Sections61–8Number of allpass sections in the cascade. More sections usually produce greater echo density.
Diffusion_g0.700.05–0.95Feedback coefficient used by every section. Higher values create longer geometric tails.
Size1.00.1–8Global multiplier for all delay lengths.
Dry_wet1.00–1Equal-power blend between the original Sound and the diffused result.
Normalizenonenone / peak / rms (loudness compensation)Optional post-scaling. See the section below; none is the neutral default.
Draw_visualizationonon/offDraw diagnostic panels in the Praat Picture window.
Play_impulse_responseoffon/offAudition the composite diffuser IR before it is removed.
Play_resultonon/offPlay the processed Sound after completion.
All presets retain your Normalize choice. If you switch from Custom to Long smear while Normalize is set to RMS, the preset changes the diffuser parameters but the final RMS compensation remains enabled.

Dry/wet mixing and normalization

Equal-power dry/wet law

dryGain = cos(Dry_wet · π/2) wetGain = sin(Dry_wet · π/2) output = wet · wetGain + dry · dryGain

This gives the familiar equal-power crossfade law: Dry_wet = 0 is dry, 1 is wet, and 0.5 assigns both paths a gain of approximately 0.707. Because dry and wet signals are related rather than statistically independent, this should be understood as a mixing law, not a guarantee of constant measured loudness at every setting.

Normalize = none

No post-scaling is applied. For a non-truncated, fully wet allpass chain, this is the setting that best preserves the intended energy behavior. The output is longer because the IR tail is retained, so RMS computed across the whole output duration is naturally lower even when total energy is preserved.

Normalize = peak

The finished output is scaled so its absolute peak matches the input peak. This is useful as a level-safety or comparison option, but it changes the natural gain of the allpass result.

Normalize = rms (loudness compensation)

The finished output is scaled so its whole-file RMS matches the input RMS. Because temporal diffusion spreads energy over a longer duration, this can raise the result substantially — especially with Long smear. The script therefore labels RMS normalization explicitly as loudness compensation, not neutral normalization.

Visualization and Info report

With Draw_visualization enabled, the Picture window contains five coordinated areas:

PanelWhat it showsHow to read it
Input waveformOriginal selected Sound.Uses the same Y range as the output, so peak spreading is visible rather than hidden by separate auto-scaling.
Diffused outputProcessed waveform including the convolution tail.Compare attack concentration, peak height and temporal spread directly with the input.
Composite allpass IRThe actual FIR approximation used for the one final convolution.Shows how quickly the echo pattern becomes dense and how long the tail extends.
Magnitude responseLTAS of the composite IR in a fixed 12 dB vertical window.An ideal result appears essentially horizontal; the title reports the measured max-minus-min spread in dB.
SummaryPreset, sections, g, Size, dry/wet, normalization, IR length, magnitude spread, duration, channels, peak/RMS values and section delays.If the finite-tail cap becomes significant, the warning is repeated here in red.
Shared waveform scaling is deliberate. Input and output use one common amplitude range, so a lower output peak caused by temporal spreading remains visible instead of being normalized away by the drawing itself.

Applications

Diffuse attacks without intentional EQ

Use Light dispersion for a modest phase blur or Dense cloud for a stronger transformation. Percussion, plucked strings and short synthetic impulses make the temporal redistribution especially clear.

Create a phase halo around a gesture

Phase halo uses fewer sections but longer delays than the default. The early response is comparatively sparse and the density builds later, allowing the original attack to remain more legible before the cloud develops.

Turn a short event into a long temporal smear

Long smear combines eight sections, high g and enlarged delays. The full convolution tail is retained, so a short source can produce an output many seconds longer than the original.

Demonstrate temporal colouration

Metallic comb intentionally uses only two high-g sections. Its sparse periodic structure can sound strongly coloured even though its magnitude response remains close to flat — useful both compositionally and pedagogically.

Use the diffuser as an impulse-response object

Enable Play_impulse_response to audition the composite allpass IR itself. The script does not leave that IR in the Object List after processing, but the visualization displays the exact IR used for the Sound convolution.

Troubleshooting

“Select exactly one Sound.” The script requires one and only one selected Sound object. Other selected object types do not substitute for it.
The result is much longer than the input. This is expected. Praat's convolution retains the composite IR tail. Long smear in particular can add a very long decay after the original Sound ends.
The result is quieter with Normalize = none. Check both peak and RMS. Temporal spreading lowers peak concentration and, because the output is longer, whole-file RMS can fall even when the fully wet allpass is preserving energy as intended.
RMS normalization makes the tail unexpectedly loud. That mode compensates whole-output RMS and can add substantial gain to a long diffuser tail. Use none for neutral processing or peak if you only need peak matching.
The Info window says the chain is not strictly allpass. A high-g, large-Size Custom configuration has reached the finite 40-second-per-section design limit while a significant tap is still being discarded. Lower Diffusion_g or Size and rerun.
The magnitude response is flat but the sound is metallic. This is not contradictory. Allpass flatness describes spectral magnitude, while the ear is also sensitive to the temporal pattern of echoes. Use more Sections, lower Size, or a denser preset if you want the individual delay structure to become less audible.