Delay Array — User Guide

A cascade of two-tap FIR difference filters. Each stage subtracts the current sample from a shifted sample, producing a comb-shaped frequency response whose spacing is determined either by a fraction of the file length or by an explicit millisecond delay.

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

What this does

Delay Array processes the selected Sound with between one and four successive two-tap FIR stages. Every stage uses the same operation:

y[n] = x[n + D] - x[n]

where D is the active delay in samples. Because the current sample is subtracted from a shifted copy, the stage has zero response at DC and a repeating comb-shaped magnitude response. Multiple iterations cascade these responses, multiplying their spectral effects.

This is not a conventional feedback echo. The script does not add a delayed copy to the original and it has no feedback loop. It applies a feed-forward finite-impulse-response difference operator to the whole Sound.

What is a delay-difference filter?

A two-tap difference filter compares two samples separated by D samples. In this script the shifted sample is the future sample x[n+D]:

y[n] = x[n+D] - x[n] frequency response: H(f) = exp(j 2π f D / Fs) - 1 magnitude: |H(f)| = 2 |sin(π f D / Fs)|

The response is zero at DC and repeats zeros at integer multiples of:

comb-zero spacing = Fs / D

The magnitude response is the same as the more familiar delayed-difference form x[n] - x[n-D]; using the future sample changes time alignment and finite-boundary behavior, not the comb magnitude.

Quick start

  1. Select exactly one Sound object.
  2. Run Delay_Array.praat.
  3. Choose one of the six presets or Custom.
  4. Choose how many stages to apply with Number_of_iterations (1–4).
  5. Leave Use_ms_delay off for file-relative delays, or enable it for explicit short delays in milliseconds.
  6. Set Scale_peak for the final peak-normalization target.
  7. Run the script. The result remains the same duration and channel count as the input.
Practical distinction: divisor mode often produces very long delays and therefore very closely spaced comb zeros. Millisecond mode is the direct choice when you want short-delay comb coloration.

Delay modes

File divisor mode — default

With Use_ms_delay = Off, each active delay is derived from the total sample count:

D[k] = floor(totalSamples / divisor[k]) actualDelaySeconds = D[k] / Fs

The delay therefore scales with the duration of the selected Sound. A divisor of 2 is approximately half the file duration; a divisor of 8 is approximately one eighth. Active divisors must be greater than 1.

Millisecond mode

With Use_ms_delay = On:

D[k] = round(delay_ms[k] / 1000 × Fs) D[k] is forced to at least 1 sample

The actual delay is sample-quantized, so the Info window reports both the requested millisecond value and the realized sample/millisecond value.

Cascade behavior

Each stage processes the result of the previous stage:

stage1[n] = x[n+D1] - x[n] stage2[n] = stage1[n+D2] - stage1[n] stage3[n] = stage2[n+D3] - stage2[n] stage4[n] = stage3[n+D4] - stage3[n]

In frequency-domain terms, the stage responses multiply. After K stages:

H_total(f) = Π(k=1..K) [exp(j 2π f Dk/Fs) - 1]

Every stage contributes its own regularly spaced zeros, so combinations of delays create a denser composite notch pattern. The process is linear and time-invariant apart from the finite-length boundary at the end of the Sound.

Presets

Each named preset supplies both divisor values and millisecond values. The active set depends on Use_ms_delay.

PresetDivisorsms delays
Default2, 4, 8, 102, 4, 8, 10 ms
Fine2, 3, 5, 72, 3, 5, 7 ms
Coarse4, 8, 12, 164, 8, 12, 16 ms
Extreme2, 6, 12, 242, 6, 12, 24 ms
Harmonic2, 4, 8, 162, 4, 8, 16 ms
Prime2, 3, 5, 112, 3, 5, 11 ms
CustomUser valuesUser values

Presets do not change Number_of_iterations, Use_ms_delay, Scale_peak, visualization, or playback.

Parameters

ParameterDefaultBehavior
PresetDefaultChooses one of six named arrays or Custom.
Divisor_1…42, 4, 8, 10Used only in divisor mode. Active values must be > 1.
Number_of_iterations4Number of active cascade stages; maximum 4.
Use_ms_delayOffOff = file divisors; On = millisecond delays.
Delay_1_ms…Delay_4_ms3, 5, 7, 11 in the formUsed only for Custom in ms mode; named presets replace them with their preset ms arrays.
Scale_peak0.99Final peak-normalization target. Must be > 0 and ≤ 1.
Draw_visualizationOnDraw Source → Delay cascade map → Output → Summary.
Play_resultOnAutomatically plays the result.

Finite-signal boundary

The formula is evaluated across the full Sound. Near the end, n + D may lie beyond the available samples. Praat returns zero for out-of-range self[index], so the operator becomes:

y[n] = 0 - x[n] = -x[n]

for those tail samples. This is equivalent to zero-padding the shifted branch rather than leaving the tail unprocessed or deleting it.

Visualization

When enabled, the Picture window shows:

Source and Output use a shared amplitude scale, so their displayed amplitudes can be compared directly.

Output behavior

Peak scaling

After all active stages, the script measures the absolute sample extremum. If the result is non-silent, it always executes Scale peak to Scale_peak.

This is normalization, not an attenuate-only safety ceiling. A non-silent result below the target peak will be amplified; a result above it will be attenuated.