Spatial Panner — v1.0 User Guide

2D circular trajectory editor for multi‑channel spatialisation using DBAP (Distance‑Based Amplitude Panning). Draw a moving source path inside a circle, assign time stamps, and render to N‑channel audio (default 8 speakers in a ring).

Author: Shai Cohen Affiliation: Department of Music, Bar‑Ilan University, Israel Version: 1.0 (2025) License: MIT License Repo: GitHub
Contents:

What this does

Spatial Panner lets you draw a moving sound source trajectory on a 2D circular stage. The source position at each moment is converted to gains for an arbitrary number of loudspeakers using Distance‑Based Amplitude Panning (DBAP). The result is a multi‑channel audio file (e.g., 8‑channel WAV) that you can play back on a multichannel system or further process in Praat.

Key features:
  • Draw trajectories by left‑clicking in the circle – points are added with automatically assigned times.
  • Drag points to reposition; right‑click to delete (start/end anchors are protected).
  • Double‑click a point to manually edit its time (in seconds).
  • Switch speaker layouts on the fly: 4, 6, or 8 speakers equally spaced around the ring.
  • Real‑time preview of trajectory points in a side panel and on a time ruler below the stage.
  • DBAP with RMS normalisation ensures equal perceived loudness regardless of position.

Quick start

  1. In Praat, select exactly one Sound object (mono or stereo). Stereo will be downmixed to mono for spatial rendering.
  2. Run script…Spatial_Panner.praat.
  3. The Python GUI opens with a circular stage. Two anchor points already exist: at the centre at time 0 and at the centre at the sound’s duration.
  4. To add a trajectory point: left‑click anywhere inside the circle. The point is given a time halfway between the previous point and the end anchor.
  5. To move a point: left‑click and drag. Points are constrained to the circle.
  6. To delete a point: right‑click on it (anchors cannot be deleted).
  7. To edit a point’s time: double‑click it and enter a new time within the allowed range.
  8. You can change the number of speakers using the buttons in the right panel (4, 6, 8). The speaker layout is displayed in the listbox.
  9. When satisfied, click Apply. The engine computes DBAP gains, renders an N‑channel WAV, and imports it back into Praat as originalname_spatial.
Tip: The time ruler below the stage shows the temporal distribution of your points. Use double‑click to adjust times if points are too crowded or too sparse.
Important: Python dependencies: numpy, soundfile, scipy. Tkinter is included with Python. The output is a multichannel WAV (32‑bit float). Praat can read up to 250 channels, but for playback you will need a multichannel audio interface or a player that can downmix.

GUI & trajectory editing

Interface preview (dark theme)

┌──────────────────────────────────────────────────────┐
│ sound.wav 3.45s 44100Hz mono → 8-ch output L-click: add/drag R-click: delete Double-click: edit time │
├───────────────────────┬──────────────────────────────┤
│ ┌───────────┐ │ Speaker Layout │
│ / \ │ [4 spk] [6 spk] [8 spk] │
│ │ ● │ │ │
│ │ ● ● │ │ Sp1 0.0° r=1.00 │
│ \ / │ Sp2 45.0° r=1.00 │
│ └───────────┘ │ Sp3 90.0° r=1.00 │
⚓0.00s •0.85s │ Sp4 135.0° r=1.00 │
⚓3.45s │ ... │
├───────────────────────┴──────────────────────────────┤
│ ══╤══╤══╤══╤══╤══╤══╤══╤══
│ 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 s │
├──────────────────────────────────────────────────────┤
│ Ready. │
├──────────────────────────────────────────────────────┤
│ [ Reset ] [ Cancel ] [ ▶ Apply ] │
└──────────────────────────────────────────────────────┘

Stage elements

Editing operations

ActionResult
Left‑click empty areaAdd a new trajectory point at that position. Time is automatically assigned halfway between previous point and end anchor.
Left‑click + drag pointMove the point (constrained to circle).
Right‑click pointDelete point (anchors cannot be deleted).
Double‑click pointOpen dialog to manually edit time (range enforced by neighbours).
Click speaker buttonsSwitch to 4, 6, or 8 equally spaced speakers.

Speaker layouts

The default speaker arrangement is 8 speakers equally spaced around a circle of radius 1.0, starting at top (0°) and going clockwise. You can switch between 4, 6, and 8 speakers using the buttons in the right panel.

NumberAngles (degrees, clockwise from top)
40°, 90°, 180°, 270°
60°, 60°, 120°, 180°, 240°, 300°
80°, 45°, 90°, 135°, 180°, 225°, 270°, 315°

The speaker positions are fixed to the edge of the circle (radius 1.0). DBAP gains are computed based on Euclidean distance from the source position to each speaker.

Custom layouts: To use a different speaker arrangement, edit the make_ring_speakers call in the Python script. You can change the radius, add an offset, or define completely arbitrary positions by modifying the DEFAULT_SPEAKERS list.

DBAP (Distance‑Based Amplitude Panning)

Gain calculation:
For source at position (sx, sy) and speaker i at (spk_x, spk_y):
d_i = distance(s, spk_i) + ε
raw_i = 1 / (d_i^k)
gain_i = raw_i / √(∑ raw_j²)

Parameters:
k (rolloff exponent) = 1.0 (default)
ε (minimum distance) = 0.02
Normalisation: √(∑ gain_i²) = 1 (RMS‑preserving)

DBAP has several advantages over traditional VBAP:

The current implementation uses vectorised numpy operations for speed, computing gains for all samples at once. The trajectory is linearly interpolated between breakpoints.

FAQ / troubleshooting

“Python not found” or missing packages

Install: pip install numpy scipy soundfile. On Windows, the script uses py (Python launcher).

GUI opens but output is silent or has wrong channel count

Check the Info window in Praat – the Python engine prints detailed debug info. Look for “Output shape” and “Gains shape”. If the number of channels doesn’t match your expected speaker count, verify that the speaker layout was set correctly.

Trajectory points snap to circle edge when dragged

That’s intentional – the stage is the unit circle. Points cannot go outside because they represent positions inside the listening area. If you need positions outside (e.g., for extra‑loudspeaker effects), you would need to modify the stage radius and speaker positions in the script.

“Edit time” dialog prevents going beyond neighbours

This ensures the trajectory remains monotonic in time (no backwards jumps). If you need a point to come before a previous point, you must delete and re‑add in the correct order.

Debug log

If processing fails, a debug file (output_spatial_debug.txt) is saved alongside the output WAV. It contains the trajectory, gain statistics, and any error tracebacks.

Playing multichannel audio in Praat

Praat can play multichannel sounds, but it will downmix to stereo on most systems. To hear the full spatial effect, you need a multichannel audio interface and a player like Ardour, Reaper, or a custom Python script with soundfile + pyaudio.

Modifying the speaker layout

To change the default speaker arrangement, edit the line:

DEFAULT_SPEAKERS = make_ring_speakers(8, radius=1.0, offset_deg=0.0)

You can also define an explicit list, e.g.:

DEFAULT_SPEAKERS = [
    ("L", 90.0, 1.0),
    ("R", 270.0, 1.0),
    ("C", 0.0, 0.5),
]

Angles are in degrees, 0° = top, increasing clockwise. Radius can be less than 1.0 for speakers inside the circle.