Stereo and surround placement
.pan(p) places a voice in the stereo field, −1 (hard left) to 1 (hard right), and like most controls it takes a mini-notation string. For real multichannel rigs, .channels([...]) sets raw per-speaker gains in FL, FR, C, LFE, SL, SR, RL, RR order, and .surround(angleDegrees) is the friendlier form — equal-power placement at an angle on the 7.1 speaker ring (0° front-centre, ±90° sides, ±180° dead behind). channels/surround take precedence over pan when both are set.
By default a destination stays stereo and multichannel placements fold down automatically. To address real surround speakers, opt the context in once:
import { enableMultichannel, note } from '@liminal-hq/undertone';
const ctx = new AudioContext();
enableMultichannel(ctx); // widens the destination to the hardware's channel count
note('c4(5,8)').sound('triangle').surround(135).loop({ ctx, bpm: 120 });On plain stereo hardware the same code still sounds right — the fold-down is automatic — so surround placement is safe to ship speculatively.