Fractal Convolution Matrix — User Guide
A cascade of sparse causal FIR delay kernels whose base delay is halved at each depth. The repeated 2:1 scaling creates a self-similar, fractal-like echo structure while preserving the source channel count.
What this does
Fractal Convolution Matrix processes the selected Sound through a sequence of feed-forward delay stages. Each stage contains one dry tap plus several delayed copies of the previous stage. The delayed taps are causal — they read earlier samples only — and every stage uses a fixed snapshot of its input, so the process is an FIR cascade rather than feedback.
The base delay at depth d is derived from the original source length:
Depth 1 therefore has the longest base delay. Every deeper level approximately halves that delay. Repeating a similar sparse tap pattern at these 2:1 scales creates the fractal-like temporal organization.
What is “fractal” here?
The term refers to self-similar organization across temporal scales. The same tap layout is reused at each depth, while the delay unit changes geometrically:
where T is the original source duration, apart from sample rounding. The script does not calculate a fractal dimension and does not claim that the resulting waveform is a mathematical fractal. “Fractal” describes the repeated 2:1 delay hierarchy.
Quick start
- Select exactly one Sound object.
- Run
Fractal_Convolution_Matrix.praat. - Choose Custom, Subtle, Medium, Heavy, or Extreme.
- For Custom, set Tail_duration_s, Fractal_depth, Convolution_width, Kernel_divisor, and Amplitude_reduction.
- Set Scale_peak and Fadeout_duration_s.
- Run the script. The result is named
<source>_fractal_<preset>.
The sparse FIR kernel
At each active depth, the script first snapshots the complete result from the previous depth. It then rebuilds the current result from that snapshot plus delayed copies read from the same fixed snapshot.
Dry path
Delayed taps
For tap k = 1 ... Convolution_width:
Samples before the beginning of the stage are treated as zero. There are no future-sample taps and no zero-delay tap duplicated inside the wet bank.
weightSum, increasing Convolution_width adds more delay taps and changes their distribution without automatically multiplying the total delayed-layer gain. At one depth, the delayed taps together sum to depthGain.
What Amplitude_reduction means
Amplitude_reduction controls only the newly added delayed layer:
For example, with reduction = 0.15, the delayed-bank gains are approximately 0.85, 0.72, 0.61, 0.52... across successive depths. The dry path of each stage is not multiplied by this value.
Depth & delay scale
The base delay is tied to the original source length, not to the extended source-plus-tail canvas:
Sample rounding makes the exact value:
The farthest tap at one depth is:
Because the depth kernels are cascaded, their delays can accumulate. The script reports the theoretical maximum cumulative span:
If a requested depth rounds to a base delay below one sample, that depth is skipped and reported. Depth is limited to 30.
Tail & fadeout
Tail duration
Tail_duration_s appends digital silence before the FIR cascade. Its purpose is to provide output space into which delayed copies can arrive. It does not participate in the base-delay calculation.
If the tail is shorter than the theoretical cumulative delay span, the late part of the cascade is truncated by the finite output canvas. The script reports this condition rather than changing the requested delay scales.
Fadeout
The final portion of the complete output receives a half-cosine fade:
effectiveFadeout = min(Fadeout_duration_s, outputDuration). A value of 0 disables the fade. The fade always acts on the end of the whole result; if no tail is used, it therefore fades the end of the original-duration signal.
Presets
| Preset | Tail | Depth | Width | Divisor | Reduction | Peak | Fade |
|---|---|---|---|---|---|---|---|
| Subtle | 1.5 s | 3 | 2 | 12 | 0.12 | 0.92 | 0.8 s |
| Medium | 2.0 s | 5 | 3 | 10 | 0.15 | 0.90 | 1.0 s |
| Heavy | 2.8 s | 7 | 4 | 8 | 0.18 | 0.88 | 1.4 s |
| Extreme | 4.0 s | 10 | 5 | 6 | 0.22 | 0.86 | 1.8 s |
| Custom | 2.0 s | 5 | 3 | 10 | 0.15 | 0.90 | 1.0 s |
Named presets overwrite the synthesis parameters shown above. Draw_visualization and Play_result remain under the user's control.
Parameters & limits
| Parameter | Default | Meaning / validation |
|---|---|---|
| Preset | Custom | Custom or four named presets. |
| Tail_duration_s | 2.0 | Extra silent canvas after the source; must be ≥ 0. |
| Fractal_depth | 5 | Requested cascade depth, 1–30. Very deep sub-sample delays are skipped. |
| Convolution_width | 3 | Number of causal delayed taps per active depth, 1–64. |
| Kernel_divisor | 10 | Sets the depth-1 delay scale; must be > 0 and must leave at least a one-sample delay at depth 1. |
| Amplitude_reduction | 0.15 | Controls geometric decay of each depth's delayed bank; valid range 0 ≤ value < 1. |
| Scale_peak | 0.90 | Peak-normalization target before the final fadeout; valid range (0, 1]. |
| Fadeout_duration_s | 1.0 | Requested final half-cosine fade; must be ≥ 0. |
| Draw_visualization | On | Draws Source → Fractal delay matrix → Output → Summary. |
| Play_result | On | Plays the result after processing. |
Visualization
The Picture window directly shows the implemented FIR structure:
- Source: original waveform. Delay-scale annotation shows that timing derives from the source length.
- Fractal delay matrix: one row per active depth. Gray marks the dry path; orange circles are causal delayed taps; marker radius represents tap gain.
- Horizontal delay axis: uses
log10(1 + delay_ms)so the repeated 2:1 scale changes remain readable. Labels at 1, 10, 100, and 1000 ms report physical delay values. - Output: final waveform after normalization and fadeout.
- Summary: preset, active/requested depth, width, divisor, reduction, peak target, theoretical span, tail status, and source/output duration.
Source and Output use a shared amplitude scale. Multichannel Sounds are folded to mono only for visualization; the rendered audio retains its channels.
Output behavior
Channel count
The FIR formulas operate independently on every channel, so the output retains the input channel count.
Peak scaling
After the cascade, the script measures the absolute peak with Sinc70. Any non-silent result is peak-scaled to Scale_peak. This is true normalization and can increase a quiet result.
Duration and naming
The result duration is the original duration plus the requested tail. It is named:
The original Sound is left unchanged and temporary processing objects are removed.