Matrix Chain — User Guide

A four-slot AudioTools host for building compound Praat processing chains in series and parallel. Matrix Chain discovers compatible scripts, exposes their form parameters in one interface, renders the active chain through a single headless Praat process, and can optionally include compatible Python-bridge processors.

Author: Shai Cohen Affiliation: Department of Music, Bar-Ilan University, Israel Matrix version: 0.3 (2026) Inspector: 0.4 (2026) License: MIT License Repo: Praat AudioTools
Contents:

What this is

Matrix Chain is a host layer for Praat AudioTools. Instead of running one processing script, returning to the Objects window, selecting its result, and launching the next script manually, Matrix Chain can assemble up to four compatible processors into one reusable routing graph.

The host reads each script's form, recreates its parameters in a single Tk interface, and calls the original script with runScript. The individual AudioTools scripts remain the processors; Matrix Chain is the routing, parameter, compatibility, rendering, and preset layer around them.

One render, one headless Praat process. For every Audition or Apply operation, the host generates one disposable wrapper script for the complete active chain and launches one headless Praat instance. Native Praat Sound objects are then passed from stage to stage in memory rather than saved between slots.
Compatibility is deliberate, not universal. Matrix Chain does not try to force every AudioTools script into a chain. Scripts that require several selected Sounds, depend on interactive windows or mandatory file choosers, produce analysis only, or fail the output contract are excluded rather than being run ambiguously.

Architecture

Selected Praat Sound
32-bit temporary WAV
Python / Tk Matrix host
Generated wrapper + one headless Praat
In-memory script stages
32-bit result WAV
Imported Praat Sound

The launcher Matrix_Chain.praat verifies that exactly one Sound is selected, exports that Sound once as a 32-bit WAV file, writes a small manifest, and starts matrix_chain.py. The host scans the AudioTools library through praat_script_inspector.py, opens the Matrix interface, and waits for a render request.

When rendering, the Python host writes a temporary Praat wrapper containing the routing graph and the current parameter values. That wrapper reads the input once, calls the selected scripts, performs any requested branch mixing and global output processing, and writes one 32-bit result file. The original Praat process imports the result after the Matrix window is closed.

Apply does not immediately close the host. Apply → Praat renders the final result and marks it for return. Close the Matrix window when you are ready to resume the original Praat session; the launcher then imports and selects the rendered Sound.

Quick start

  1. Select exactly one Sound in the Praat Objects window.
  2. Run Matrix_Chain.praat.
  3. In each row, choose a Category, a compatible Script, and a routing Mode.
  4. Click a slot row to edit that script's parameters in the lower panel.
  5. Use Series for sequential processing or consecutive Parallel rows for branches fed from the same stage input.
  6. Use Audition for a scratch render. Use Stop to cancel an active render or stop playback.
  7. When the chain is ready, click Apply → Praat.
  8. Close the Matrix window. The result is imported into Praat as a new Sound named from the source plus _matrix_<duration>s.
The signal-flow line under the slot table updates continuously. Read it before rendering: it is the clearest summary of how the current Series and Parallel rows will be grouped.

Slots & routing

The host provides four rows. Each row has Category, Script, Mode, Branch %, and a status description. A row can be Off, Series, or Parallel.

ModeSignal behaviorBranch %
OffThe row is ignored.Not used.
SeriesThe script receives the current chain Sound. Its output becomes the input to the next stage.Not used.
ParallelConsecutive Parallel rows receive copies of the same stage input. Their outputs are conformed as needed and summed into one new Sound.Linear branch gain in the sum. It is not wet/dry.

Series example

input[1: compressor][2: filter][3: pitch process]output

Parallel example

input[1: series processor] → ( [2: branch A 60%] + [3: branch B 100%] ) → [4: series processor]output

Only consecutive Parallel rows belong to the same branch group. A Series row ends the current parallel group and begins a new sequential stage.

Branch % is a gain, not a crossfade. Two branches at 100% are summed at full level. The combined peak may therefore exceed either branch individually. Use the branch gains intentionally; the optional Safety ceiling or post normalization can reduce excessive peaks afterward.

Format conforming inside a parallel stage

Parallel branches can return different durations, sample rates, or channel counts. The host uses the longest branch duration and the highest branch sample rate as the target. Branches whose sample rate differs are resampled in Praat with precision 50.

Mono/stereo mismatches are conformed to stereo when stereo is the largest format. Mixed channel layouts that extend beyond stereo are treated conservatively; when channel counts differ and the largest layout exceeds stereo, the parallel target is folded to mono.

Matrix Chain is most predictable for mono and stereo work. Treat complex multichannel parallel routing as an advanced case and verify the resulting channel structure before using it as a final render.

Script parameters

When you choose a script, the inspector parses its first Praat form block and the host builds matching widgets in the parameter panel. Numeric and text fields appear as entries, boolean fields as checkboxes, and choice/optionmenu fields as menus.

The host supports both legacy and modern Praat form syntax, including vector fields and multiline text fields. Menu values are passed back to runScript as option text, matching Praat's argument semantics.

ControlBehavior
Reset to defaultsRestores the current script's parsed form defaults.
Force Play offWhen the inspector identifies a playback boolean such as Play, Audition, Preview, Listen, or Play_result, the host sends it as off during chain rendering.
Force Draw offFor recognized boolean drawing/visualization controls, the host sends off during the render.
A script with no form can still be eligible. It then runs with its built-in values and is marked with a warning because there are no exposed parameters for Matrix Chain to control.

Global controls

ControlDefaultMeaning
Dry/Wet %100%Linear amplitude mix between the original input Sound and the complete processed chain. 100% is chain only; 0% is dry only.
Trim / fade / normalizeOffOptional post stage: trims to the detected active region, applies edge fades, then peak-normalizes.
Safety ceilingOnWhen the post stage is off, attenuates only if the output peak exceeds 0.99. If disabled, no host-level gain stage is applied.
Force Play offOnSuppresses recognized script-level playback controls during chain rendering.
Force Draw offOnSuppresses recognized boolean drawing/visualization controls during chain rendering.
Include Python bridges (slower)OffRescans the py/ area and offers Python-backed Praat launchers that pass compatibility checks.
Timeout s300 s when launched from the Praat launcherMaximum render time. Increase it for slow chains and especially for Python bridges.

Post stage details

With Trim / fade / normalize enabled, the host analyses Intensity, uses a threshold 60 dB below the detected peak intensity to define the active region, applies a 20 ms half-cosine fade at each edge (capped at one quarter of the resulting duration), and scales the final peak to 0.98.

With the post stage off and Safety ceiling on, only peaks above 0.99 are attenuated. With both controls off, the chain output is left at its current level.

Compatibility inspector

praat_script_inspector.py statically scans the AudioTools library before scripts are offered in the Matrix. It reads form parameters, estimates the selected-Sound requirement, looks for audio-producing operations, checks common interactive blockers, and classifies Python bridges.

The inspector is a compatibility screen, not formal verification. Static analysis can determine many structural incompatibilities before rendering, while the runtime output contract remains the final check that each active slot actually leaves a usable Sound.

Typical eligible structure

Examples of blockers

Detected conditionWhy it is blocked
Analysis/drawing only; no audio outputThere is no Sound for the next slot.
Requires 2+ selected SoundsA Matrix slot receives one current Sound, not an arbitrary Objects-window selection.
Input requirement unclearThe host cannot safely infer the script's selection contract.
Editor or demo windowHeadless Praat cannot use an interactive editor as part of an unattended render.
Pause inside a loop/procedureWould make the headless execution path interactive or ambiguous.
Mandatory chooserA headless file/folder chooser cannot supply a user selection.
External corpus file-list dependencyThe current Matrix catalog treats external corpus-folder requirements as non-portable.

Runtime output contract

After every slot, the generated wrapper checks the selected Sound objects. A slot that leaves no Sound selected fails the render. If several Sounds are selected, the newest selected Sound is taken and the event is logged. A native script may modify its input Sound in place; a Python bridge is stricter and must produce a new Sound object.

The “newest selected Sound” rule is a deterministic host convention, not proof that a multi-selected script's newest object is musically the intended result. Scripts designed for Matrix use should ideally finish with one clear output Sound selected.

Generators

A script classified as requiring no input is treated as a generator. Generator scripts are offered only in Slot 1 and are intended to be the first active stage in Series mode, because inserting a generator later would discard the signal built before it.

Python bridges

Python-backed AudioTools processors are opt-in. Enable Include Python bridges (slower) to rescan the py/ directory and expose compatible Praat launchers.

A bridge is considered chainable only when:

The inspector looks for common GUI frameworks and blocking calls including Tkinter, Qt/PySide, wx, Kivy, pygame, Streamlit, webview, Gradio, Dear PyGui, PySimpleGUI, mainloop(), input(), plt.show(), and GUI application execution. A backend that returns only an external file without reading it back into Praat is blocked. A bridge that reads its result as a LongSound is also blocked because the chain requires a Sound object.

Nested processing is slower. A bridge effectively runs Python inside the headless Praat render that was launched by the Python Matrix host. Heavy machine-learning, corpus, or resynthesis backends can therefore need a much longer timeout than native Praat slots.
The Matrix host prepends its own Python environment to PATH before launching headless Praat. This helps a bridge's internal python lookup resolve to the same environment that is already running Matrix Chain, reducing “works in the host but packages are missing in the bridge” failures.

Audio fidelity & file I/O

Matrix Chain is designed to avoid unnecessary intermediate quantization. The selected Praat Sound is exported to the host as a 32-bit integer PCM WAV. After the headless wrapper reads that file, native Praat slot outputs are passed in memory until the final result is saved once as another 32-bit WAV and returned to the original Praat session.

Original Praat Sound → 32-bit PCM host input → native Praat stages in memory → 32-bit PCM host result → imported Praat Sound

This removes the 16-bit input/output bottleneck that would otherwise quantize every Matrix render. The host can also read common PCM 8/16/24/32-bit and IEEE float WAV data for Audition, including WAVE_FORMAT_EXTENSIBLE headers.

Do not interpret this as “lossless under all conditions.” A Python bridge may perform its own temporary WAV export/import, resampling, normalization, machine-learning transformation, or other processing internally. Matrix Chain preserves high-resolution transfer at its own boundary; the fidelity of a bridge's internal path depends on that bridge's implementation.

Parallel routing can also introduce deliberate format conversion: branches with different sample rates are resampled to the highest branch rate before mixing. Global Dry/Wet may conform the original dry copy to the final processed format. These are functional routing operations, not hidden file-format conversions.

Level changes are separate from resolution

Safety ceiling and Trim / fade / normalize can change level by design. For a host-transparency A/B test, turn off the post stage and Safety ceiling, use 100% Dry/Wet, and choose processors that themselves make no normalization or sample-rate change.

Saving & restoring chains

Save chain… writes a JSON preset containing the four slot choices, routing modes, branch levels, current script parameters, global Dry/Wet, post setting, Safety ceiling state, and the Python-bridge inclusion state.

Load chain… restores that state. If a saved chain contains a Python bridge, Matrix Chain turns bridge scanning on and rescans before rebuilding the slots.

The host also stores the most recent chain and remembered Praat executable in matrix_chain_config.json next to matrix_chain.py. On the next launch, the previous chain is restored automatically when possible.

Installation & dependencies

ComponentExpected location / role
Matrix_Chain.praatPraat-side launcher. Select one Sound and run this script.
py/matrix_chain.pyPython/Tk host, routing engine, wrapper generator, rendering and preset layer.
py/praat_script_inspector.pyStatic script scanner and compatibility classifier.
py/matrix_chain_config.jsonCreated/updated by the host to remember the Praat executable and last chain.

Required

The launcher tries a configured Python first and then platform-appropriate Python commands. The host can auto-detect common Praat executable locations; the Praat… button lets you select the executable manually, and Test Praat checks that it can run headlessly and write audio.

Optional playback packages

sounddevice, soundfile, and numpy improve Audition support. Rendering itself does not depend on all three. On Windows the host can fall back to the standard winsound API by creating a temporary 16-bit playback copy; that copy is for Audition only and does not replace the 32-bit render.

Python-bridge dependencies

Each bridge can require its own Python packages. Enabling bridge scanning does not install those dependencies; it only makes compatible launchers available to the Matrix.

Praat 7 gates file writing, file deletion, and subprocess launching behind its trust system. The launcher and generated wrapper request trust when running on Praat 7 or later.

Limitations

Troubleshooting

SymptomWhat to check
Praat NOT FOUNDClick Praat…, select the executable, then use Test Praat. The chosen path is remembered.
A script is missing from the listClick Rescan and inspect Log. The script may have an eligibility blocker. Python-backed launchers also require Include Python bridges.
A generator is missing from Slot 2–4This is intentional. Generators ignore their input and are restricted to the first slot/first Series stage.
Argument-count mismatchThe form parser and the target script disagree about the number of fields. Rescan first; persistent cases indicate a form syntax the inspector does not yet parse correctly.
Slot left no Sound selectedThe script did not satisfy the chain output contract. It cannot be used safely as a Matrix effect in its current form.
Python bridge produced no chainable Sound outputThe bridge did not create a new Sound after its external backend returned. Check backend errors and its Praat-side readback step.
Render times outIncrease Timeout s, especially for Python, neural, corpus, or long-duration processors.
Audition renders but does not playThe render itself may be valid. Install an available playback path such as sounddevice, or check the platform fallback reported in the status/log.
Output is much quieterCheck Branch %, script-level dry/wet or normalization, global Dry/Wet, Safety ceiling, and the post stage. The log reports when the host Safety ceiling is applied.

The Log window reports the catalog scan, blockers and warnings, render command, wrapper, stage progress, stdout/stderr, and the last stage reached when a render fails.

Further reading