Layered snapshot bug: one layer's preset Program Change hijacks another layer's sound (cause + fix)

Sharing a tricky one I just chased down on my Pi 5 / V5, in case it helps anyone running layered setups.

Setup: A 4-layer snapshot, all chains on the same MIDI channel so my keyboard plays them together:

  • JE8086 (JP-8000) – “Tiny bells”
  • LinuxSampler – Salamander Grand
  • Pianoteq
  • FluidSynth – an “FM Piano” SF2

One of these is my own modified/improved JE8086 integration that loads both individual panel patches and Performances spanning both panels — full write-up + preset bundles here: https://github.com/smatheusale/zynthian-custom/blob/main/JE8086.md

Symptom: After loading the snapshot, the FluidSynth layer played violin/strings even though the screen correctly said “FM Piano”. Re-selecting the preset by hand fixed it — until the next snapshot load.

Cause: The JE8086 layer selects patches via MIDI Bank Select + Program Change (Tiny bells = bank [0,1], PC 40). That PC was being sent on the MIDI channel, so every chain on that channel received it — including FluidSynth. FM Piano.sf2 has no bank 1, so FluidSynth fell back to the GM soundfont, where program 40 = Violin. FluidSynth’s own channels output gave it away:

Instrument not found on channel 0 [bank=1 prog=40], substituted [bank=0 prog=40]
chan 0 … preset 40, Violin

A second issue: loading a snapshot didn’t re-trigger the engines’ set_preset, so they started on their default patch despite the right name showing.

Fix: Send the preset Bank Select + PC through the chain’s own zmop (zmop_send_program_change / zmop_send_ccontrol_change) instead of a global channel send — that confines it to the originating chain. Plus re-fire set_preset after restore for engines that load their patch there. Both layers now restore perfectly, and manual preset changes still work.

Filed upstream: Layered snapshot: a chain's preset Program Change leaks to layer-mates on the same MIDI channel (and restore doesn't re-fire set_preset) · Issue #1705 · zynthian/zynthian-issue-tracking · GitHub

Hope it saves someone the headache! :musical_keyboard:

2 Likes