Commit e65e3a87 by PLN (Algolia)

fix(sc): swap PV_Freeze for PV_MagFreeze — JoshPVUGens took the server down mid-set

Sudden silence while changing track, an "audio server died" notification, then
crackle and no sound while Ardour's faders still moved. Four scsynth SIGSEGVs in
four minutes (14:01:58, 14:02:55, 14:03:52, 14:04:53), each ~57s apart, until the
watchdog hit its bound: "GIVING UP: 3 restarts in 600s and scsynth will not stay
up." sclang stayed alive throughout, so the systemd unit read active (running)
the entire time — green unit, no sound, exactly the supervision trap.

WHERE IT DIED
Every coredump carries the same frame #1: JoshPVUGens.so, on the audio callback
thread (libpipewire -> libspa -> libjack -> libscsynth -> JoshPVUGens). The only
route into that library from this rig is SuperDirt's `spectral-freeze` module in
default-effects-extra.scd, i.e. Tidal's `# freeze`. Eight live tracks carry it,
including cafe_glace.tidal:44 — the track being played when it started.

WHY IT DIED
The server was starving before it fell over: `LocalBuf_allocBuffer: alloc failed`,
18x `Buffer UGen: no buffer data`, and `late` values of 6-13 SECONDS. SuperDirt
builds one spectral-freeze synth PER EVENT, each allocating FFT(LocalBuf(2048))
per channel, so a dense pattern under `# freeze` drains the RT pool even at the
configured memSize of 256 MB.

The difference that matters, measured in NRT with 120 overlapping synths and a
starved pool (both survive non-realtime, but their behaviour diverges):

    PV_Freeze     LocalBuf_allocBuffer: alloc failed        <- and then nothing
    PV_MagFreeze  PV_MagFreeze_next: alloc failed x6        <- detects it, bails

The core UGen guards its buffer. Josh's does not — it proceeds with the failed
allocation. Single-threaded NRT survives that; the realtime callback does not.

THE FIX
Re-`.add` "spectral-freeze2" after ~dirt.start, identical but for PV_MagFreeze —
the core-SC sibling JoshUGens' own help file compares itself to, with the same
trigger semantics (freeze > 0 freezes magnitudes). Slightly more static, since
PV_Freeze also advances phase between frames; in exchange it cannot take the
server down. Verified live: boot prints "[boot] spectral-freeze overridden",
scsynth stable, 96 SC->Ardour links re-made by the autoroute unit.

Pre-existing and NOT caused by this change: `SynthDef global_mi_verb2 not found`
appears from 14:02:31, in a boot that predates the edit. Filed separately.
parent 113d9c57
......@@ -285,6 +285,36 @@ s.waitForBoot {
}, [\ir, \ir]).add;
};
// =============================================
// spectral-freeze override: PV_Freeze -> PV_MagFreeze
// =============================================
// 2026-08-15: scsynth SIGSEGV'd four times in four minutes mid-session,
// every coredump with the same frame #1 -- JoshPVUGens.so, on the JACK/
// PipeWire audio callback thread. The only route into that library from
// this rig is SuperDirt's `spectral-freeze` module (default-effects-extra
// .scd), i.e. Tidal's `# freeze`, which 8 live tracks carry.
//
// The server was already starving when it died: `LocalBuf_allocBuffer:
// alloc failed` and 18x `Buffer UGen: no buffer data` in the log, plus
// `late` values of 6-13 SECONDS. SuperDirt builds one of these synths PER
// EVENT, each allocating FFT(LocalBuf(2048)) per channel, so a dense
// pattern under `# freeze` drains the RT pool -- and Josh's PV_Freeze does
// not survive being handed the resulting null buffer.
//
// PV_MagFreeze is the core-SC sibling (JoshUGens' own help file compares
// the two) with identical trigger semantics: freeze > 0 freezes magnitudes.
// It is slightly more static -- PV_Freeze also advances phase between
// frames -- but it is in libscsynth, null-checks its buffer, and cannot
// take the server down. Re-`.add` replaces SuperDirt's definition by name.
SynthDef("spectral-freeze" ++ ~dirt.numChannels, { |out, freeze|
var signal, chain;
signal = In.ar(out, ~dirt.numChannels);
chain = signal.asArray.collect { |x| FFT(LocalBuf(2048), x) };
signal = IFFT(PV_MagFreeze(chain, freeze));
ReplaceOut.ar(out, signal)
}, [\ir]).add;
"[boot] spectral-freeze overridden: PV_MagFreeze (JoshPVUGens crashed scsynth 2026-08-15)".postln;
// Register global effects on all orbits
~dirt.orbits.do { |x|
var verb = GlobalDirtEffect(\global_mi_verb, [\verbwet, \verbtime, \verbdamp, \verbhp, \verbfreeze, \verbdiff, \verbgain]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment